| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 Label is_assignable, runtime_call; | 311 Label is_assignable, runtime_call; |
| 312 __ cmpq(RAX, raw_null); | 312 __ cmpq(RAX, raw_null); |
| 313 __ j(EQUAL, &is_assignable); | 313 __ j(EQUAL, &is_assignable); |
| 314 | 314 |
| 315 // Generate throw new TypeError() if the type is malformed. | 315 // Generate throw new TypeError() if the type is malformed. |
| 316 if (dst_type.IsMalformed()) { | 316 if (dst_type.IsMalformed()) { |
| 317 const Error& error = Error::Handle(dst_type.malformed_error()); | 317 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 318 const String& error_message = String::ZoneHandle( | 318 const String& error_message = String::ZoneHandle( |
| 319 String::NewSymbol(error.ToErrorCString())); | 319 String::NewSymbol(error.ToErrorCString())); |
| 320 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 320 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 321 const Immediate location = | 321 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location. |
| 322 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | |
| 323 __ pushq(location); // Push the source location. | |
| 324 __ pushq(RAX); // Push the source object. | 322 __ pushq(RAX); // Push the source object. |
| 325 __ PushObject(dst_name); // Push the name of the destination. | 323 __ PushObject(dst_name); // Push the name of the destination. |
| 326 __ PushObject(error_message); | 324 __ PushObject(error_message); |
| 327 GenerateCallRuntime(cid, | 325 GenerateCallRuntime(cid, |
| 328 token_index, | 326 token_index, |
| 329 try_index, | 327 try_index, |
| 330 kMalformedTypeErrorRuntimeEntry); | 328 kMalformedTypeErrorRuntimeEntry); |
| 331 // We should never return here. | 329 // We should never return here. |
| 332 __ int3(); | 330 __ int3(); |
| 333 | 331 |
| 334 __ Bind(&is_assignable); // For a null object. | 332 __ Bind(&is_assignable); // For a null object. |
| 335 return; | 333 return; |
| 336 } | 334 } |
| 337 | 335 |
| 338 // Generate inline type check, linking to runtime call if not assignable. | 336 // Generate inline type check, linking to runtime call if not assignable. |
| 339 GenerateInlineInstanceof(dst_type, &is_assignable, &runtime_call); | 337 GenerateInlineInstanceof(dst_type, &is_assignable, &runtime_call); |
| 340 | 338 |
| 341 __ Bind(&runtime_call); | 339 __ Bind(&runtime_call); |
| 342 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 340 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 343 const Immediate location = | 341 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location. |
| 344 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 342 __ pushq(Immediate(Smi::RawValue(cid))); // Computation id. |
| 345 const Immediate cid_as_smi = | |
| 346 Immediate(reinterpret_cast<int64_t>(Smi::New(cid))); | |
| 347 __ pushq(location); // Push the source location. | |
| 348 __ pushq(cid_as_smi); // node-id. | |
| 349 __ pushq(RAX); // Push the source object. | 343 __ pushq(RAX); // Push the source object. |
| 350 __ PushObject(dst_type); // Push the type of the destination. | 344 __ PushObject(dst_type); // Push the type of the destination. |
| 351 if (!dst_type.IsInstantiated()) { | 345 if (!dst_type.IsInstantiated()) { |
| 352 __ pushq(RDX); // Instantiator type arguments. | 346 __ pushq(RDX); // Instantiator type arguments. |
| 353 } else { | 347 } else { |
| 354 __ pushq(raw_null); // Null instantiator. | 348 __ pushq(raw_null); // Null instantiator. |
| 355 } | 349 } |
| 356 __ PushObject(dst_name); // Push the name of the destination. | 350 __ PushObject(dst_name); // Push the name of the destination. |
| 357 GenerateCallRuntime(cid, | 351 GenerateCallRuntime(cid, |
| 358 token_index, | 352 token_index, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 void FlowGraphCompiler::VisitAssertBoolean(AssertBooleanComp* comp) { | 408 void FlowGraphCompiler::VisitAssertBoolean(AssertBooleanComp* comp) { |
| 415 LoadValue(RAX, comp->value()); | 409 LoadValue(RAX, comp->value()); |
| 416 // Check that the type of the value is allowed in conditional context. | 410 // Check that the type of the value is allowed in conditional context. |
| 417 // Call the runtime if the object is not bool::true or bool::false. | 411 // Call the runtime if the object is not bool::true or bool::false. |
| 418 Label done; | 412 Label done; |
| 419 __ CompareObject(RAX, Bool::ZoneHandle(Bool::True())); | 413 __ CompareObject(RAX, Bool::ZoneHandle(Bool::True())); |
| 420 __ j(EQUAL, &done, Assembler::kNearJump); | 414 __ j(EQUAL, &done, Assembler::kNearJump); |
| 421 __ CompareObject(RAX, Bool::ZoneHandle(Bool::False())); | 415 __ CompareObject(RAX, Bool::ZoneHandle(Bool::False())); |
| 422 __ j(EQUAL, &done, Assembler::kNearJump); | 416 __ j(EQUAL, &done, Assembler::kNearJump); |
| 423 | 417 |
| 424 const Immediate location = | 418 __ pushq(Immediate(Smi::RawValue(comp->token_index()))); // Source location. |
| 425 Immediate(reinterpret_cast<int64_t>(Smi::New(comp->token_index()))); | |
| 426 __ pushq(location); // Push the source location. | |
| 427 __ pushq(RAX); // Push the source object. | 419 __ pushq(RAX); // Push the source object. |
| 428 GenerateCallRuntime(comp->cid(), | 420 GenerateCallRuntime(comp->cid(), |
| 429 comp->token_index(), | 421 comp->token_index(), |
| 430 comp->try_index(), | 422 comp->try_index(), |
| 431 kConditionTypeErrorRuntimeEntry); | 423 kConditionTypeErrorRuntimeEntry); |
| 432 // We should never return here. | 424 // We should never return here. |
| 433 __ int3(); | 425 __ int3(); |
| 434 | 426 |
| 435 __ Bind(&done); | 427 __ Bind(&done); |
| 436 } | 428 } |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 // Dynamic at run time. | 827 // Dynamic at run time. |
| 836 __ cmpq(RAX, raw_null); | 828 __ cmpq(RAX, raw_null); |
| 837 __ j(EQUAL, &is_not_instance); | 829 __ j(EQUAL, &is_not_instance); |
| 838 } | 830 } |
| 839 | 831 |
| 840 // Generate inline instanceof test. | 832 // Generate inline instanceof test. |
| 841 GenerateInlineInstanceof(type, &is_instance, &is_not_instance); | 833 GenerateInlineInstanceof(type, &is_instance, &is_not_instance); |
| 842 | 834 |
| 843 // Generate runtime call. | 835 // Generate runtime call. |
| 844 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 836 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 845 const Immediate location = | 837 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location. |
| 846 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index))); | 838 __ pushq(Immediate(Smi::RawValue(cid))); // Computation id. |
| 847 const Immediate cid_as_smi = | |
| 848 Immediate(reinterpret_cast<int64_t>(Smi::New(cid))); | |
| 849 __ pushq(location); // Push the source location. | |
| 850 __ pushq(cid_as_smi); | |
| 851 __ pushq(RAX); // Push the instance. | 839 __ pushq(RAX); // Push the instance. |
| 852 __ PushObject(type); // Push the type. | 840 __ PushObject(type); // Push the type. |
| 853 if (!type.IsInstantiated()) { | 841 if (!type.IsInstantiated()) { |
| 854 __ pushq(RDX); // Instantiator type arguments. | 842 __ pushq(RDX); // Instantiator type arguments. |
| 855 } else { | 843 } else { |
| 856 __ pushq(raw_null); // Null instantiator. | 844 __ pushq(raw_null); // Null instantiator. |
| 857 } | 845 } |
| 858 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry); | 846 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry); |
| 859 // Pop the two parameters supplied to the runtime entry. The result of the | 847 // Pop the two parameters supplied to the runtime entry. The result of the |
| 860 // instanceof runtime call will be left as the result of the operation. | 848 // instanceof runtime call will be left as the result of the operation. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 887 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 900 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 888 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 901 GenerateCall(comp->token_index(), comp->try_index(), &label, | 889 GenerateCall(comp->token_index(), comp->try_index(), &label, |
| 902 PcDescriptors::kOther); | 890 PcDescriptors::kOther); |
| 903 for (intptr_t i = 0; i < comp->arguments().length(); i++) { | 891 for (intptr_t i = 0; i < comp->arguments().length(); i++) { |
| 904 __ popq(RCX); // Discard allocation argument | 892 __ popq(RCX); // Discard allocation argument |
| 905 } | 893 } |
| 906 } | 894 } |
| 907 | 895 |
| 908 | 896 |
| 897 void FlowGraphCompiler::VisitAllocateObjectWithBoundsCheck( |
| 898 AllocateObjectWithBoundsCheckComp* comp) { |
| 899 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); |
| 900 __ popq(RCX); // Pop instantiator type arguments. |
| 901 __ popq(RAX); // Pop type arguments. |
| 902 |
| 903 // Push the result place holder initialized to NULL. |
| 904 __ PushObject(Object::ZoneHandle()); |
| 905 __ pushq(Immediate(Smi::RawValue(comp->token_index()))); |
| 906 __ PushObject(cls); |
| 907 __ pushq(RAX); // Push type arguments. |
| 908 __ pushq(RCX); // Push instantiator type arguments. |
| 909 GenerateCallRuntime(comp->cid(), |
| 910 comp->token_index(), |
| 911 comp->try_index(), |
| 912 kAllocateObjectWithBoundsCheckRuntimeEntry); |
| 913 __ popq(RCX); // Pop instantiator type arguments. |
| 914 __ popq(RCX); // Pop type arguments. |
| 915 __ popq(RCX); // Pop class. |
| 916 __ popq(RCX); // Pop source location. |
| 917 __ popq(RAX); // Pop new instance. |
| 918 } |
| 919 |
| 920 |
| 909 void FlowGraphCompiler::VisitCreateArray(CreateArrayComp* comp) { | 921 void FlowGraphCompiler::VisitCreateArray(CreateArrayComp* comp) { |
| 910 // 1. Allocate the array. R10 = length, RBX = element type. | 922 // 1. Allocate the array. R10 = length, RBX = element type. |
| 911 __ movq(R10, Immediate(Smi::RawValue(comp->ElementCount()))); | 923 __ movq(R10, Immediate(Smi::RawValue(comp->ElementCount()))); |
| 912 const AbstractTypeArguments& element_type = comp->type_arguments(); | 924 const AbstractTypeArguments& element_type = comp->type_arguments(); |
| 913 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | 925 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); |
| 914 __ LoadObject(RBX, element_type); | 926 __ LoadObject(RBX, element_type); |
| 915 GenerateCall(comp->token_index(), | 927 GenerateCall(comp->token_index(), |
| 916 comp->try_index(), | 928 comp->try_index(), |
| 917 &StubCode::AllocateArrayLabel(), | 929 &StubCode::AllocateArrayLabel(), |
| 918 PcDescriptors::kOther); | 930 PcDescriptors::kOther); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 // Instantiate non-null type arguments. | 985 // Instantiate non-null type arguments. |
| 974 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 986 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 975 Label type_arguments_uninstantiated; | 987 Label type_arguments_uninstantiated; |
| 976 // Check if the instantiator type argument vector is a TypeArguments of a | 988 // Check if the instantiator type argument vector is a TypeArguments of a |
| 977 // matching length and, if so, use it as the instantiated type_arguments. | 989 // matching length and, if so, use it as the instantiated type_arguments. |
| 978 // No need to check the instantiator (RAX) for null here, because a null | 990 // No need to check the instantiator (RAX) for null here, because a null |
| 979 // instantiator will have the wrong class (Null instead of TypeArguments). | 991 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 980 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 992 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 981 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 993 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 982 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 994 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 983 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 995 Immediate arguments_length = |
| 984 Smi::New(comp->type_arguments().Length()))); | 996 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 985 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 997 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 986 arguments_length); | 998 arguments_length); |
| 987 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 999 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 988 __ Bind(&type_arguments_uninstantiated); | 1000 __ Bind(&type_arguments_uninstantiated); |
| 989 } | 1001 } |
| 990 // A runtime call to instantiate the type arguments is required before | 1002 // A runtime call to instantiate the type arguments is required before |
| 991 // calling the factory. | 1003 // calling the factory. |
| 992 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1004 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 993 __ PushObject(comp->type_arguments()); | 1005 __ PushObject(comp->type_arguments()); |
| 994 __ pushq(RAX); // Push instantiator type arguments. | 1006 __ pushq(RAX); // Push instantiator type arguments. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1023 // Instantiate non-null type arguments. | 1035 // Instantiate non-null type arguments. |
| 1024 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 1036 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 1025 // Check if the instantiator type argument vector is a TypeArguments of a | 1037 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1026 // matching length and, if so, use it as the instantiated type_arguments. | 1038 // matching length and, if so, use it as the instantiated type_arguments. |
| 1027 // No need to check the instantiator (RAX) for null here, because a null | 1039 // No need to check the instantiator (RAX) for null here, because a null |
| 1028 // instantiator will have the wrong class (Null instead of TypeArguments). | 1040 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1029 Label type_arguments_uninstantiated; | 1041 Label type_arguments_uninstantiated; |
| 1030 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 1042 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 1031 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 1043 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1032 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1044 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1033 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 1045 Immediate arguments_length = |
| 1034 Smi::New(comp->type_arguments().Length()))); | 1046 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 1035 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 1047 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 1036 arguments_length); | 1048 arguments_length); |
| 1037 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1049 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1038 __ Bind(&type_arguments_uninstantiated); | 1050 __ Bind(&type_arguments_uninstantiated); |
| 1039 } | 1051 } |
| 1040 // In the non-factory case, we rely on the allocation stub to | 1052 // In the non-factory case, we rely on the allocation stub to |
| 1041 // instantiate the type arguments. | 1053 // instantiate the type arguments. |
| 1042 __ LoadObject(RAX, comp->type_arguments()); | 1054 __ LoadObject(RAX, comp->type_arguments()); |
| 1043 // RAX: uninstantiated type arguments. | 1055 // RAX: uninstantiated type arguments. |
| 1044 __ Bind(&type_arguments_instantiated); | 1056 __ Bind(&type_arguments_instantiated); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 // TODO(regis): This code will still change, because bounds checking is not | 1091 // TODO(regis): This code will still change, because bounds checking is not |
| 1080 // implemented yet. | 1092 // implemented yet. |
| 1081 | 1093 |
| 1082 // Check if the instantiator type argument vector is a TypeArguments of a | 1094 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1083 // matching length and, if so, use it as the instantiated type_arguments. | 1095 // matching length and, if so, use it as the instantiated type_arguments. |
| 1084 // No need to check the instantiator (RAX) for null here, because a null | 1096 // No need to check the instantiator (RAX) for null here, because a null |
| 1085 // instantiator will have the wrong class (Null instead of TypeArguments). | 1097 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1086 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 1098 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); |
| 1087 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 1099 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 1088 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1100 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1089 Immediate arguments_length = Immediate(reinterpret_cast<int64_t>( | 1101 Immediate arguments_length = |
| 1090 Smi::New(comp->type_arguments().Length()))); | 1102 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 1091 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 1103 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 1092 arguments_length); | 1104 arguments_length); |
| 1093 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1105 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1094 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 1106 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 1095 // instantiated type arguments, no proper instantiator needed. | 1107 // instantiated type arguments, no proper instantiator needed. |
| 1096 __ movq(RAX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1108 __ movq(RAX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 1097 } | 1109 } |
| 1098 __ Bind(&done); | 1110 __ Bind(&done); |
| 1099 // RAX: instantiator or kNoInstantiator. | 1111 // RAX: instantiator or kNoInstantiator. |
| 1100 } | 1112 } |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1714 ASSERT(exception_handlers_list_ != NULL); | 1726 ASSERT(exception_handlers_list_ != NULL); |
| 1715 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1727 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 1716 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1728 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 1717 code.set_exception_handlers(handlers); | 1729 code.set_exception_handlers(handlers); |
| 1718 } | 1730 } |
| 1719 | 1731 |
| 1720 | 1732 |
| 1721 } // namespace dart | 1733 } // namespace dart |
| 1722 | 1734 |
| 1723 #endif // defined TARGET_ARCH_X64 | 1735 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |