| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 } | 803 } |
| 804 | 804 |
| 805 | 805 |
| 806 void CodeGenerator::VisitPrimaryNode(PrimaryNode* node) { | 806 void CodeGenerator::VisitPrimaryNode(PrimaryNode* node) { |
| 807 // PrimaryNodes are temporary during parsing. | 807 // PrimaryNodes are temporary during parsing. |
| 808 UNREACHABLE(); | 808 UNREACHABLE(); |
| 809 } | 809 } |
| 810 | 810 |
| 811 | 811 |
| 812 void CodeGenerator::VisitCloneContextNode(CloneContextNode *node) { | 812 void CodeGenerator::VisitCloneContextNode(CloneContextNode *node) { |
| 813 const Context& result = Context::ZoneHandle(); | 813 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 814 __ PushObject(result); | |
| 815 __ pushl(CTX); | 814 __ pushl(CTX); |
| 816 GenerateCallRuntime(node->id(), | 815 GenerateCallRuntime(node->id(), |
| 817 node->token_index(), kCloneContextRuntimeEntry); | 816 node->token_index(), kCloneContextRuntimeEntry); |
| 818 __ popl(EAX); | 817 __ popl(EAX); |
| 819 __ popl(CTX); // result: cloned context. Set as current context. | 818 __ popl(CTX); // result: cloned context. Set as current context. |
| 820 } | 819 } |
| 821 | 820 |
| 822 | 821 |
| 823 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { | 822 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { |
| 824 CodeGeneratorState codegen_state(this); | 823 CodeGeneratorState codegen_state(this); |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1304 // - Class equality (only if class is not parameterized). | 1303 // - Class equality (only if class is not parameterized). |
| 1305 // Inputs: | 1304 // Inputs: |
| 1306 // - EAX: object. | 1305 // - EAX: object. |
| 1307 // Destroys ECX. | 1306 // Destroys ECX. |
| 1308 // Returns: | 1307 // Returns: |
| 1309 // - true or false on stack. | 1308 // - true or false on stack. |
| 1310 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, | 1309 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, |
| 1311 intptr_t token_index, | 1310 intptr_t token_index, |
| 1312 const AbstractType& type, | 1311 const AbstractType& type, |
| 1313 bool negate_result) { | 1312 bool negate_result) { |
| 1314 ASSERT(type.IsFinalized()); | 1313 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 1315 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1314 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 1316 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1315 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 1317 | 1316 |
| 1318 // All instances are of a subtype of the Object type. | 1317 // All instances are of a subtype of the Object type. |
| 1319 const Type& object_type = | 1318 const Type& object_type = |
| 1320 Type::Handle(Isolate::Current()->object_store()->object_type()); | 1319 Type::Handle(Isolate::Current()->object_store()->object_type()); |
| 1321 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { | 1320 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { |
| 1322 __ PushObject(negate_result ? bool_false : bool_true); | 1321 __ PushObject(negate_result ? bool_false : bool_true); |
| 1323 return; | 1322 return; |
| 1324 } | 1323 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1412 Label runtime_call; | 1411 Label runtime_call; |
| 1413 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1412 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1414 __ CompareObject(ECX, *compare_class); | 1413 __ CompareObject(ECX, *compare_class); |
| 1415 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); | 1414 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); |
| 1416 __ PushObject(negate_result ? bool_false : bool_true); | 1415 __ PushObject(negate_result ? bool_false : bool_true); |
| 1417 __ jmp(&done, Assembler::kNearJump); | 1416 __ jmp(&done, Assembler::kNearJump); |
| 1418 __ Bind(&runtime_call); | 1417 __ Bind(&runtime_call); |
| 1419 } | 1418 } |
| 1420 } | 1419 } |
| 1421 } | 1420 } |
| 1422 const Object& result = Object::ZoneHandle(); | 1421 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1423 __ PushObject(result); // Make room for the result of the runtime call. | |
| 1424 __ pushl(EAX); // Push the instance. | 1422 __ pushl(EAX); // Push the instance. |
| 1425 __ PushObject(type); // Push the type. | 1423 __ PushObject(type); // Push the type. |
| 1426 if (!type.IsInstantiated()) { | 1424 if (!type.IsInstantiated()) { |
| 1427 GenerateInstantiatorTypeArguments(token_index); | 1425 GenerateInstantiatorTypeArguments(token_index); |
| 1428 } else { | 1426 } else { |
| 1429 __ pushl(raw_null); // Null instantiator. | 1427 __ pushl(raw_null); // Null instantiator. |
| 1430 } | 1428 } |
| 1431 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); | 1429 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); |
| 1432 // Pop the two parameters supplied to the runtime entry. The result of the | 1430 // Pop the two parameters supplied to the runtime entry. The result of the |
| 1433 // instanceof runtime call will be left as the result of the operation. | 1431 // instanceof runtime call will be left as the result of the operation. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1466 // - object in EAX for successful assignable check (or throws TypeError). | 1464 // - object in EAX for successful assignable check (or throws TypeError). |
| 1467 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, | 1465 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, |
| 1468 intptr_t token_index, | 1466 intptr_t token_index, |
| 1469 const AbstractType& dst_type, | 1467 const AbstractType& dst_type, |
| 1470 const String& dst_name) { | 1468 const String& dst_name) { |
| 1471 ASSERT(FLAG_enable_type_checks); | 1469 ASSERT(FLAG_enable_type_checks); |
| 1472 ASSERT(token_index >= 0); | 1470 ASSERT(token_index >= 0); |
| 1473 ASSERT(!dst_type.IsNull()); | 1471 ASSERT(!dst_type.IsNull()); |
| 1474 ASSERT(dst_type.IsFinalized()); | 1472 ASSERT(dst_type.IsFinalized()); |
| 1475 | 1473 |
| 1474 // Generate throw new TypeError() if the type is malformed. |
| 1475 if (dst_type.IsMalformed()) { |
| 1476 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 1477 const String& error_message = String::ZoneHandle( |
| 1478 String::NewSymbol(error.ToErrorCString())); |
| 1479 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1480 const Immediate location = |
| 1481 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
| 1482 __ pushl(location); // Push the source location. |
| 1483 __ pushl(EAX); // Push the source object. |
| 1484 __ PushObject(error_message); |
| 1485 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry); |
| 1486 // We should never return here. |
| 1487 __ int3(); |
| 1488 return; |
| 1489 } |
| 1490 |
| 1476 // Any expression is assignable to the Dynamic type and to the Object type. | 1491 // Any expression is assignable to the Dynamic type and to the Object type. |
| 1477 // Skip the test. | 1492 // Skip the test. |
| 1478 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { | 1493 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { |
| 1479 return; | 1494 return; |
| 1480 } | 1495 } |
| 1481 | 1496 |
| 1482 // It is a compile-time error to explicitly return a value (including null) | 1497 // It is a compile-time error to explicitly return a value (including null) |
| 1483 // from a void function. However, functions that do not explicitly return a | 1498 // from a void function. However, functions that do not explicitly return a |
| 1484 // value, implicitly return null. This includes void functions. Therefore, we | 1499 // value, implicitly return null. This includes void functions. Therefore, we |
| 1485 // skip the type test here and trust the parser to only return null in void | 1500 // skip the type test here and trust the parser to only return null in void |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1587 } else if (dst_type.IsFunctionInterface()) { | 1602 } else if (dst_type.IsFunctionInterface()) { |
| 1588 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1603 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1589 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); | 1604 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); |
| 1590 __ cmpl(ECX, raw_null); | 1605 __ cmpl(ECX, raw_null); |
| 1591 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1606 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1592 } | 1607 } |
| 1593 } | 1608 } |
| 1594 } | 1609 } |
| 1595 } | 1610 } |
| 1596 __ Bind(&runtime_call); | 1611 __ Bind(&runtime_call); |
| 1597 const Object& result = Object::ZoneHandle(); | 1612 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1598 __ PushObject(result); // Make room for the result of the runtime call. | |
| 1599 const Immediate location = | 1613 const Immediate location = |
| 1600 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1614 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
| 1601 __ pushl(location); // Push the source location. | 1615 __ pushl(location); // Push the source location. |
| 1602 __ pushl(EAX); // Push the source object. | 1616 __ pushl(EAX); // Push the source object. |
| 1603 __ PushObject(dst_type); // Push the type of the destination. | 1617 __ PushObject(dst_type); // Push the type of the destination. |
| 1604 if (!dst_type.IsInstantiated()) { | 1618 if (!dst_type.IsInstantiated()) { |
| 1605 GenerateInstantiatorTypeArguments(token_index); | 1619 GenerateInstantiatorTypeArguments(token_index); |
| 1606 } else { | 1620 } else { |
| 1607 __ pushl(raw_null); // Null instantiator. | 1621 __ pushl(raw_null); // Null instantiator. |
| 1608 } | 1622 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1654 // This check should pass if the receiver's class implements the interface | 1668 // This check should pass if the receiver's class implements the interface |
| 1655 // 'bool'. Check only class 'Bool' since it is the only legal implementation | 1669 // 'bool'. Check only class 'Bool' since it is the only legal implementation |
| 1656 // of the interface 'bool'. | 1670 // of the interface 'bool'. |
| 1657 const Class& bool_class = | 1671 const Class& bool_class = |
| 1658 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); | 1672 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); |
| 1659 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1673 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1660 __ CompareObject(ECX, bool_class); | 1674 __ CompareObject(ECX, bool_class); |
| 1661 __ j(EQUAL, &done, Assembler::kNearJump); | 1675 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1662 | 1676 |
| 1663 __ Bind(&runtime_call); | 1677 __ Bind(&runtime_call); |
| 1664 const Object& result = Object::ZoneHandle(); | |
| 1665 __ PushObject(result); // Make room for the result of the runtime call. | |
| 1666 const Immediate location = | 1678 const Immediate location = |
| 1667 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1679 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
| 1668 __ pushl(location); // Push the source location. | 1680 __ pushl(location); // Push the source location. |
| 1669 __ pushl(EAX); // Push the source object. | 1681 __ pushl(EAX); // Push the source object. |
| 1670 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); | 1682 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); |
| 1671 // Pop the parameters supplied to the runtime entry. The result of the | 1683 // We should never return here. |
| 1672 // type check runtime call is the checked value. | 1684 __ int3(); |
| 1673 __ addl(ESP, Immediate(3 * kWordSize)); | |
| 1674 | 1685 |
| 1675 __ Bind(&done); | 1686 __ Bind(&done); |
| 1676 } | 1687 } |
| 1677 | 1688 |
| 1678 | 1689 |
| 1679 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { | 1690 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { |
| 1680 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1691 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 1681 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1692 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 1682 node->left()->Visit(this); | 1693 node->left()->Visit(this); |
| 1683 | 1694 |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2189 // Pushes the type arguments of the instantiator on the stack. | 2200 // Pushes the type arguments of the instantiator on the stack. |
| 2190 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { | 2201 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { |
| 2191 const Class& instantiator_class = Class::Handle( | 2202 const Class& instantiator_class = Class::Handle( |
| 2192 parsed_function().function().owner()); | 2203 parsed_function().function().owner()); |
| 2193 if (instantiator_class.NumTypeParameters() == 0) { | 2204 if (instantiator_class.NumTypeParameters() == 0) { |
| 2194 // The type arguments are compile time constants. | 2205 // The type arguments are compile time constants. |
| 2195 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); | 2206 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); |
| 2196 // TODO(regis): Temporary type should be allocated in new gen heap. | 2207 // TODO(regis): Temporary type should be allocated in new gen heap. |
| 2197 Type& type = Type::Handle( | 2208 Type& type = Type::Handle( |
| 2198 Type::New(instantiator_class, type_arguments, token_index)); | 2209 Type::New(instantiator_class, type_arguments, token_index)); |
| 2199 type ^= ClassFinalizer::FinalizeType(instantiator_class, type); | 2210 type ^= ClassFinalizer::FinalizeType( |
| 2211 instantiator_class, type, ClassFinalizer::kFinalizeWellFormed); |
| 2200 type_arguments = type.arguments(); | 2212 type_arguments = type.arguments(); |
| 2201 __ PushObject(type_arguments); | 2213 __ PushObject(type_arguments); |
| 2202 } else { | 2214 } else { |
| 2203 ASSERT(parsed_function().instantiator() != NULL); | 2215 ASSERT(parsed_function().instantiator() != NULL); |
| 2204 parsed_function().instantiator()->Visit(this); | 2216 parsed_function().instantiator()->Visit(this); |
| 2205 Function& outer_function = | 2217 Function& outer_function = |
| 2206 Function::Handle(parsed_function().function().raw()); | 2218 Function::Handle(parsed_function().function().raw()); |
| 2207 while (outer_function.IsLocalFunction()) { | 2219 while (outer_function.IsLocalFunction()) { |
| 2208 outer_function = outer_function.parent_function(); | 2220 outer_function = outer_function.parent_function(); |
| 2209 } | 2221 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2272 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( | 2284 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( |
| 2273 Smi::New(node->type_arguments().Length()))); | 2285 Smi::New(node->type_arguments().Length()))); |
| 2274 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), | 2286 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), |
| 2275 arguments_length); | 2287 arguments_length); |
| 2276 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2288 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2277 } | 2289 } |
| 2278 __ Bind(&type_arguments_uninstantiated); | 2290 __ Bind(&type_arguments_uninstantiated); |
| 2279 if (node->constructor().IsFactory()) { | 2291 if (node->constructor().IsFactory()) { |
| 2280 // A runtime call to instantiate the type arguments is required before | 2292 // A runtime call to instantiate the type arguments is required before |
| 2281 // calling the factory. | 2293 // calling the factory. |
| 2282 const Object& result = Object::ZoneHandle(); | 2294 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2283 __ PushObject(result); // Make room for the result of the runtime call. | |
| 2284 __ PushObject(node->type_arguments()); | 2295 __ PushObject(node->type_arguments()); |
| 2285 __ pushl(EAX); // Push instantiator type arguments. | 2296 __ pushl(EAX); // Push instantiator type arguments. |
| 2286 GenerateCallRuntime(node->id(), | 2297 GenerateCallRuntime(node->id(), |
| 2287 node->token_index(), | 2298 node->token_index(), |
| 2288 kInstantiateTypeArgumentsRuntimeEntry); | 2299 kInstantiateTypeArgumentsRuntimeEntry); |
| 2289 __ popl(EAX); // Pop instantiator type arguments. | 2300 __ popl(EAX); // Pop instantiator type arguments. |
| 2290 __ popl(EAX); // Pop uninstantiated type arguments. | 2301 __ popl(EAX); // Pop uninstantiated type arguments. |
| 2291 __ popl(EAX); // Pop instantiated type arguments. | 2302 __ popl(EAX); // Pop instantiated type arguments. |
| 2292 __ Bind(&type_arguments_instantiated); | 2303 __ Bind(&type_arguments_instantiated); |
| 2293 __ pushl(EAX); // Instantiated type arguments. | 2304 __ pushl(EAX); // Instantiated type arguments. |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2607 } | 2618 } |
| 2608 | 2619 |
| 2609 // Generate code for the finally block if one exists. | 2620 // Generate code for the finally block if one exists. |
| 2610 if (node->finally_block() != NULL) { | 2621 if (node->finally_block() != NULL) { |
| 2611 node->finally_block()->Visit(this); | 2622 node->finally_block()->Visit(this); |
| 2612 } | 2623 } |
| 2613 } | 2624 } |
| 2614 | 2625 |
| 2615 | 2626 |
| 2616 void CodeGenerator::VisitThrowNode(ThrowNode* node) { | 2627 void CodeGenerator::VisitThrowNode(ThrowNode* node) { |
| 2617 const Object& result = Object::ZoneHandle(); | |
| 2618 node->exception()->Visit(this); | 2628 node->exception()->Visit(this); |
| 2619 __ popl(EAX); // Exception object is now in EAX. | 2629 // Exception object is on TOS. |
| 2620 if (node->stacktrace() != NULL) { | 2630 if (node->stacktrace() != NULL) { |
| 2621 __ PushObject(result); // Make room for the result of the runtime call. | |
| 2622 __ pushl(EAX); // Push the exception object. | |
| 2623 node->stacktrace()->Visit(this); | 2631 node->stacktrace()->Visit(this); |
| 2624 GenerateCallRuntime(node->id(), node->token_index(), kReThrowRuntimeEntry); | 2632 GenerateCallRuntime(node->id(), node->token_index(), kReThrowRuntimeEntry); |
| 2625 } else { | 2633 } else { |
| 2626 __ PushObject(result); // Make room for the result of the runtime call. | |
| 2627 __ pushl(EAX); // Push the exception object. | |
| 2628 GenerateCallRuntime(node->id(), node->token_index(), kThrowRuntimeEntry); | 2634 GenerateCallRuntime(node->id(), node->token_index(), kThrowRuntimeEntry); |
| 2629 } | 2635 } |
| 2630 // We should never return here. | 2636 // We should never return here. |
| 2631 __ int3(); | 2637 __ int3(); |
| 2632 } | 2638 } |
| 2633 | 2639 |
| 2634 | 2640 |
| 2635 void CodeGenerator::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 2641 void CodeGenerator::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
| 2636 int try_index = state()->try_index(); | 2642 int try_index = state()->try_index(); |
| 2637 if (try_index >= 0) { | 2643 if (try_index >= 0) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2695 const Error& error = Error::Handle( | 2701 const Error& error = Error::Handle( |
| 2696 Parser::FormatError(script, token_index, "Error", format, args)); | 2702 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2697 va_end(args); | 2703 va_end(args); |
| 2698 Isolate::Current()->long_jump_base()->Jump(1, error); | 2704 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2699 UNREACHABLE(); | 2705 UNREACHABLE(); |
| 2700 } | 2706 } |
| 2701 | 2707 |
| 2702 } // namespace dart | 2708 } // namespace dart |
| 2703 | 2709 |
| 2704 #endif // defined TARGET_ARCH_IA32 | 2710 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |