| 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 122 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 123 __ CompareObject(RCX, *CoreClass("ObjectArray")); | 123 __ CompareObject(RCX, *CoreClass("ObjectArray")); |
| 124 __ j(EQUAL, is_instance); | 124 __ j(EQUAL, is_instance); |
| 125 __ CompareObject(RCX, *CoreClass("GrowableObjectArray")); | 125 __ CompareObject(RCX, *CoreClass("GrowableObjectArray")); |
| 126 __ j(EQUAL, is_instance); | 126 __ j(EQUAL, is_instance); |
| 127 } else if (!type_class.is_interface()) { | 127 } else if (!type_class.is_interface()) { |
| 128 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 128 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 129 __ CompareObject(RCX, type_class); | 129 __ CompareObject(RCX, type_class); |
| 130 __ j(EQUAL, is_instance); | 130 __ j(EQUAL, is_instance); |
| 131 } | 131 } |
| 132 // Fall through to runtime class. | 132 // Fall through to runtime call. |
| 133 } | 133 } |
| 134 } else { // type has NO type arguments. | 134 } else { // type has NO type arguments. |
| 135 Label compare_classes; | 135 Label compare_classes; |
| 136 __ testq(RAX, Immediate(kSmiTagMask)); | 136 __ testq(RAX, Immediate(kSmiTagMask)); |
| 137 __ j(NOT_ZERO, &compare_classes); | 137 __ j(NOT_ZERO, &compare_classes); |
| 138 // Object is Smi. | 138 // Object is Smi. |
| 139 const Class& smi_class = Class::Handle(Smi::Class()); | 139 const Class& smi_class = Class::Handle(Smi::Class()); |
| 140 // TODO(regis): We should introduce a SmiType. | 140 // TODO(regis): We should introduce a SmiType. |
| 141 Error& malformed_error = Error::Handle(); | 141 Error& malformed_error = Error::Handle(); |
| 142 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), | 142 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // - RAX: object. | 288 // - RAX: object. |
| 289 // - RDX: optional instantiator type arguments. | 289 // - RDX: optional instantiator type arguments. |
| 290 // Destroys RCX and RDX. | 290 // Destroys RCX and RDX. |
| 291 // Returns: | 291 // Returns: |
| 292 // - object in RAX for successful assignable check (or throws TypeError). | 292 // - object in RAX for successful assignable check (or throws TypeError). |
| 293 // Performance notes: positive checks must be quick, negative checks can be slow | 293 // Performance notes: positive checks must be quick, negative checks can be slow |
| 294 // as they throw an exception. | 294 // as they throw an exception. |
| 295 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t node_id, | 295 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t node_id, |
| 296 intptr_t token_index, | 296 intptr_t token_index, |
| 297 intptr_t try_index, | 297 intptr_t try_index, |
| 298 Value* value, | |
| 299 const AbstractType& dst_type, | 298 const AbstractType& dst_type, |
| 300 const String& dst_name) { | 299 const String& dst_name) { |
| 301 ASSERT(FLAG_enable_type_checks); | 300 ASSERT(FLAG_enable_type_checks); |
| 302 ASSERT(token_index >= 0); | 301 ASSERT(token_index >= 0); |
| 303 ASSERT(!dst_type.IsNull()); | 302 ASSERT(!dst_type.IsNull()); |
| 304 ASSERT(dst_type.IsFinalized()); | 303 ASSERT(dst_type.IsFinalized()); |
| 305 | 304 ASSERT(dst_type.IsMalformed() || |
| 306 // Any expression is assignable to the Dynamic type and to the Object type. | 305 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| 307 // Skip the test. | 306 ASSERT(!dst_type.IsVoidType()); |
| 308 if (!dst_type.IsMalformed() && | |
| 309 (dst_type.IsDynamicType() || dst_type.IsObjectType())) { | |
| 310 return; | |
| 311 } | |
| 312 | |
| 313 // It is a compile-time error to explicitly return a value (including null) | |
| 314 // from a void function. However, functions that do not explicitly return a | |
| 315 // value, implicitly return null. This includes void functions. Therefore, we | |
| 316 // skip the type test here and trust the parser to only return null in void | |
| 317 // function. | |
| 318 if (dst_type.IsVoidType()) { | |
| 319 return; | |
| 320 } | |
| 321 | |
| 322 // TODO(regis): Move this compile time check to the graph builder. | |
| 323 // Eliminate the test if it can be performed successfully at compile time. | |
| 324 if ((value != NULL) && value->IsConstant()) { | |
| 325 Instance& literal_value = Instance::Handle(); | |
| 326 literal_value ^= value->AsConstant()->value().raw(); | |
| 327 const Class& cls = Class::Handle(literal_value.clazz()); | |
| 328 if (cls.IsNullClass()) { | |
| 329 ASSERT(literal_value.IsNull() || | |
| 330 (literal_value.raw() == Object::sentinel()) || | |
| 331 (literal_value.raw() == Object::transition_sentinel())); | |
| 332 return; | |
| 333 } | |
| 334 Error& malformed_error = Error::Handle(); | |
| 335 if (!dst_type.IsMalformed() && | |
| 336 dst_type.IsInstantiated() && | |
| 337 literal_value.IsInstanceOf(dst_type, | |
| 338 TypeArguments::Handle(), | |
| 339 &malformed_error)) { | |
| 340 return; | |
| 341 } | |
| 342 } | |
| 343 | 307 |
| 344 // A null object is always assignable and is returned as result. | 308 // A null object is always assignable and is returned as result. |
| 345 const Immediate raw_null = | 309 const Immediate raw_null = |
| 346 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 310 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 347 Label is_assignable, runtime_call; | 311 Label is_assignable, runtime_call; |
| 348 __ cmpq(RAX, raw_null); | 312 __ cmpq(RAX, raw_null); |
| 349 __ j(EQUAL, &is_assignable); | 313 __ j(EQUAL, &is_assignable); |
| 350 | 314 |
| 351 // Generate throw new TypeError() if the type is malformed. | 315 // Generate throw new TypeError() if the type is malformed. |
| 352 if (dst_type.IsMalformed()) { | 316 if (dst_type.IsMalformed()) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 LoadValue(RAX, val); | 384 LoadValue(RAX, val); |
| 421 } | 385 } |
| 422 | 386 |
| 423 | 387 |
| 424 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { | 388 void FlowGraphCompiler::VisitConstant(ConstantVal* val) { |
| 425 LoadValue(RAX, val); | 389 LoadValue(RAX, val); |
| 426 } | 390 } |
| 427 | 391 |
| 428 | 392 |
| 429 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { | 393 void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { |
| 430 if (comp->type_arguments() != NULL) { | 394 if (comp->instantiator_type_arguments() != NULL) { |
| 431 __ popq(RDX); | 395 __ popq(RDX); |
| 432 } | 396 } |
| 433 LoadValue(RAX, comp->value()); | 397 LoadValue(RAX, comp->value()); |
| 434 GenerateAssertAssignable(comp->node_id(), | 398 GenerateAssertAssignable(comp->node_id(), |
| 435 comp->token_index(), | 399 comp->token_index(), |
| 436 comp->try_index(), | 400 comp->try_index(), |
| 437 comp->value(), | |
| 438 comp->dst_type(), | 401 comp->dst_type(), |
| 439 comp->dst_name()); | 402 comp->dst_name()); |
| 440 } | 403 } |
| 441 | 404 |
| 442 | 405 |
| 443 void FlowGraphCompiler::VisitAssertBoolean(AssertBooleanComp* comp) { | 406 void FlowGraphCompiler::VisitAssertBoolean(AssertBooleanComp* comp) { |
| 444 LoadValue(RAX, comp->value()); | 407 LoadValue(RAX, comp->value()); |
| 445 // Check that the type of the value is allowed in conditional context. | 408 // Check that the type of the value is allowed in conditional context. |
| 446 // Call the runtime if the object is not bool::true or bool::false. | 409 // Call the runtime if the object is not bool::true or bool::false. |
| 447 Label done; | 410 Label done; |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 // - Class equality (only if class is not parameterized). | 796 // - Class equality (only if class is not parameterized). |
| 834 // Inputs: | 797 // Inputs: |
| 835 // - RAX: object. | 798 // - RAX: object. |
| 836 // - RDX: optional instantiator type arguments. | 799 // - RDX: optional instantiator type arguments. |
| 837 // Destroys RCX and RDX. | 800 // Destroys RCX and RDX. |
| 838 // Returns: | 801 // Returns: |
| 839 // - true or false in RAX. | 802 // - true or false in RAX. |
| 840 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id, | 803 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id, |
| 841 intptr_t token_index, | 804 intptr_t token_index, |
| 842 intptr_t try_index, | 805 intptr_t try_index, |
| 843 Value* value, | |
| 844 const AbstractType& type, | 806 const AbstractType& type, |
| 845 bool negate_result) { | 807 bool negate_result) { |
| 846 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 808 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 847 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 809 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 848 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 810 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 849 | 811 |
| 850 const Immediate raw_null = | 812 const Immediate raw_null = |
| 851 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 813 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 852 Label is_instance, is_not_instance; | 814 Label is_instance, is_not_instance; |
| 853 // If type is instantiated and non-parameterized, we can inline code | 815 // If type is instantiated and non-parameterized, we can inline code |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 | 871 |
| 910 | 872 |
| 911 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { | 873 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { |
| 912 if (comp->type_arguments() != NULL) { | 874 if (comp->type_arguments() != NULL) { |
| 913 __ popq(RDX); | 875 __ popq(RDX); |
| 914 } | 876 } |
| 915 LoadValue(RAX, comp->value()); | 877 LoadValue(RAX, comp->value()); |
| 916 GenerateInstanceOf(comp->node_id(), | 878 GenerateInstanceOf(comp->node_id(), |
| 917 comp->token_index(), | 879 comp->token_index(), |
| 918 comp->try_index(), | 880 comp->try_index(), |
| 919 comp->value(), | |
| 920 comp->type(), | 881 comp->type(), |
| 921 comp->negate_result()); | 882 comp->negate_result()); |
| 922 } | 883 } |
| 923 | 884 |
| 924 | 885 |
| 925 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { | 886 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { |
| 926 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); | 887 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); |
| 927 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 888 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 928 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 889 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 929 GenerateCall(comp->token_index(), comp->try_index(), &label, | 890 GenerateCall(comp->token_index(), comp->try_index(), &label, |
| (...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 ASSERT(exception_handlers_list_ != NULL); | 1711 ASSERT(exception_handlers_list_ != NULL); |
| 1751 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1712 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 1752 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1713 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 1753 code.set_exception_handlers(handlers); | 1714 code.set_exception_handlers(handlers); |
| 1754 } | 1715 } |
| 1755 | 1716 |
| 1756 | 1717 |
| 1757 } // namespace dart | 1718 } // namespace dart |
| 1758 | 1719 |
| 1759 #endif // defined TARGET_ARCH_X64 | 1720 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |