Chromium Code Reviews| 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 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 } | 787 } |
| 788 ASSERT(function.context_scope() != ContextScope::null()); | 788 ASSERT(function.context_scope() != ContextScope::null()); |
| 789 | 789 |
| 790 // The function type of a closure may have type arguments. In that case, pass | 790 // The function type of a closure may have type arguments. In that case, pass |
| 791 // the type arguments of the instantiator. | 791 // the type arguments of the instantiator. |
| 792 const Class& cls = Class::Handle(function.signature_class()); | 792 const Class& cls = Class::Handle(function.signature_class()); |
| 793 ASSERT(!cls.IsNull()); | 793 ASSERT(!cls.IsNull()); |
| 794 const bool requires_type_arguments = cls.HasTypeArguments(); | 794 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 795 if (requires_type_arguments) { | 795 if (requires_type_arguments) { |
| 796 ASSERT(!function.IsImplicitStaticClosureFunction()); | 796 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 797 GenerateInstantiatorTypeArguments(node->token_index()); | 797 GenerateInstantiatorTypeArguments(node->token_index(), false); |
|
regis
2012/05/04 21:53:39
Document what false means.
srdjan
2012/05/04 23:01:58
Done.
| |
| 798 } | 798 } |
| 799 const Code& stub = Code::Handle( | 799 const Code& stub = Code::Handle( |
| 800 StubCode::GetAllocationStubForClosure(function)); | 800 StubCode::GetAllocationStubForClosure(function)); |
| 801 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 801 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 802 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); | 802 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); |
| 803 if (requires_type_arguments) { | 803 if (requires_type_arguments) { |
| 804 __ popl(ECX); // Pop type arguments. | 804 __ popl(ECX); // Pop type arguments. |
| 805 } | 805 } |
| 806 if (function.IsImplicitInstanceClosureFunction()) { | 806 if (function.IsImplicitInstanceClosureFunction()) { |
| 807 __ popl(ECX); // Pop receiver. | 807 __ popl(ECX); // Pop receiver. |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1271 type, | 1271 type, |
| 1272 is_instance_lbl, | 1272 is_instance_lbl, |
| 1273 is_not_instance_lbl); | 1273 is_not_instance_lbl); |
| 1274 // If test non-conclusive so far, try the inlined type-test cache. | 1274 // If test non-conclusive so far, try the inlined type-test cache. |
| 1275 // 'type' is known at compile time. | 1275 // 'type' is known at compile time. |
| 1276 return GenerateSubtype1TestCacheLookup( | 1276 return GenerateSubtype1TestCacheLookup( |
| 1277 node_id, token_index, type_class, | 1277 node_id, token_index, type_class, |
| 1278 is_instance_lbl, is_not_instance_lbl); | 1278 is_instance_lbl, is_not_instance_lbl); |
| 1279 } | 1279 } |
| 1280 } else { | 1280 } else { |
| 1281 GenerateUninstantiatedTypeTest(type, | 1281 return GenerateUninstantiatedTypeTest(type, |
| 1282 token_index, | 1282 node_id, |
| 1283 is_instance_lbl); | 1283 token_index, |
| 1284 is_instance_lbl, | |
| 1285 is_not_instance_lbl); | |
| 1284 } | 1286 } |
| 1285 return SubtypeTestCache::null(); | 1287 return SubtypeTestCache::null(); |
| 1286 } | 1288 } |
| 1287 | 1289 |
| 1288 | 1290 |
| 1289 // If instanceof type test cannot be performed successfully at compile time and | 1291 // If instanceof type test cannot be performed successfully at compile time and |
| 1290 // therefore eliminated, optimize it by adding inlined tests for: | 1292 // therefore eliminated, optimize it by adding inlined tests for: |
| 1291 // - NULL -> return false. | 1293 // - NULL -> return false. |
| 1292 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 1294 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 1293 // - Class equality (only if class is not parameterized). | 1295 // - Class equality (only if class is not parameterized). |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1367 test_cache = GenerateInlineInstanceof(node_id, token_index, type, | 1369 test_cache = GenerateInlineInstanceof(node_id, token_index, type, |
| 1368 &is_instance_of, &is_not_instance_of); | 1370 &is_instance_of, &is_not_instance_of); |
| 1369 | 1371 |
| 1370 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1372 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1371 const Immediate location = Immediate(Smi::RawValue(token_index)); | 1373 const Immediate location = Immediate(Smi::RawValue(token_index)); |
| 1372 const Immediate node_id_as_smi = Immediate(Smi::RawValue(node_id)); | 1374 const Immediate node_id_as_smi = Immediate(Smi::RawValue(node_id)); |
| 1373 __ pushl(location); // Push the source location. | 1375 __ pushl(location); // Push the source location. |
| 1374 __ pushl(node_id_as_smi); // node-id. | 1376 __ pushl(node_id_as_smi); // node-id. |
| 1375 __ pushl(EAX); // Push the instance. | 1377 __ pushl(EAX); // Push the instance. |
| 1376 __ PushObject(type); // Push the type. | 1378 __ PushObject(type); // Push the type. |
| 1377 if (!type.IsInstantiated()) { | 1379 if (type.IsInstantiated()) { |
| 1378 GenerateInstantiatorTypeArguments(token_index); | 1380 __ pushl(raw_null); // Null instantiator. |
| 1381 __ pushl(raw_null); // Null instantiator. | |
| 1379 } else { | 1382 } else { |
| 1380 __ pushl(raw_null); // Null instantiator. | 1383 GenerateInstantiatorTypeArguments(token_index, true); |
|
regis
2012/05/04 21:53:39
Document what true means.
srdjan
2012/05/04 23:01:58
Done.
| |
| 1381 } | 1384 } |
| 1382 __ LoadObject(EAX, test_cache); | 1385 __ LoadObject(EAX, test_cache); |
| 1383 __ pushl(EAX); | 1386 __ pushl(EAX); |
| 1384 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); | 1387 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); |
| 1385 // Pop the two parameters supplied to the runtime entry. The result of the | 1388 // Pop the two parameters supplied to the runtime entry. The result of the |
| 1386 // instanceof runtime call will be left as the result of the operation. | 1389 // instanceof runtime call will be left as the result of the operation. |
| 1387 __ addl(ESP, Immediate(6 * kWordSize)); | 1390 __ addl(ESP, Immediate(7 * kWordSize)); |
| 1388 if (negate_result) { | 1391 if (negate_result) { |
| 1389 __ popl(EDX); | 1392 __ popl(EDX); |
| 1390 __ CompareObject(EDX, bool_false); | 1393 __ CompareObject(EDX, bool_false); |
| 1391 __ j(EQUAL, &is_not_instance_of, Assembler::kNearJump); | 1394 __ j(EQUAL, &is_not_instance_of, Assembler::kNearJump); |
| 1392 // Fall through to is_instance_of. | 1395 // Fall through to is_instance_of. |
| 1393 } else { | 1396 } else { |
| 1394 __ jmp(&done); | 1397 __ jmp(&done); |
| 1395 } | 1398 } |
| 1396 | 1399 |
| 1397 __ Bind(&is_instance_of); | 1400 __ Bind(&is_instance_of); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1462 // Instance class test only necessary. | 1465 // Instance class test only necessary. |
| 1463 return GenerateSubtype1TestCacheLookup( | 1466 return GenerateSubtype1TestCacheLookup( |
| 1464 node_id, token_index, type_class, is_instance_lbl, is_not_instance_lbl); | 1467 node_id, token_index, type_class, is_instance_lbl, is_not_instance_lbl); |
| 1465 } | 1468 } |
| 1466 const SubtypeTestCache& type_test_cache = | 1469 const SubtypeTestCache& type_test_cache = |
| 1467 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 1470 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| 1468 Label inlined_check, fall_through; | 1471 Label inlined_check, fall_through; |
| 1469 const Immediate raw_null = | 1472 const Immediate raw_null = |
| 1470 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1473 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1471 __ LoadObject(EDX, type_test_cache); | 1474 __ LoadObject(EDX, type_test_cache); |
| 1472 __ pushl(EDX); // Cache array. | 1475 __ pushl(EDX); // Subtype test cache. |
| 1473 __ pushl(EAX); // Instance. | 1476 __ pushl(EAX); // Instance. |
| 1474 __ pushl(raw_null); // Unused. | 1477 __ pushl(raw_null); // Unused. |
| 1475 __ call(&StubCode::Subtype2TestCacheLabel()); | 1478 __ call(&StubCode::Subtype2TestCacheLabel()); |
| 1476 __ popl(EAX); // Discard. | 1479 __ popl(EAX); // Discard. |
| 1477 __ popl(EAX); // Restore receiver. | 1480 __ popl(EAX); // Restore receiver. |
| 1478 __ popl(EDX); // Discard. | 1481 __ popl(EDX); // Discard. |
| 1479 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. | 1482 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. |
| 1480 | 1483 |
| 1481 __ cmpl(ECX, raw_null); | 1484 __ cmpl(ECX, raw_null); |
| 1482 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1485 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1580 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); | 1583 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); |
| 1581 __ cmpl(ECX, raw_null); | 1584 __ cmpl(ECX, raw_null); |
| 1582 __ j(NOT_EQUAL, is_instance_lbl); | 1585 __ j(NOT_EQUAL, is_instance_lbl); |
| 1583 } | 1586 } |
| 1584 // Otherwise fallthrough. | 1587 // Otherwise fallthrough. |
| 1585 } | 1588 } |
| 1586 | 1589 |
| 1587 | 1590 |
| 1588 // EAX: instance to test. | 1591 // EAX: instance to test. |
| 1589 // Clobbers: EBX, EDX, ECX. | 1592 // Clobbers: EBX, EDX, ECX. |
| 1590 void CodeGenerator::GenerateUninstantiatedTypeTest( | 1593 RawSubtypeTestCache* CodeGenerator::GenerateUninstantiatedTypeTest( |
| 1591 const AbstractType& type, | 1594 const AbstractType& type, |
| 1595 intptr_t node_id, | |
| 1592 intptr_t token_index, | 1596 intptr_t token_index, |
| 1593 Label* is_instance_lbl) { | 1597 Label* is_instance_lbl, |
| 1598 Label* is_not_instance_lbl) { | |
| 1594 ASSERT(!type.IsInstantiated()); | 1599 ASSERT(!type.IsInstantiated()); |
| 1595 // Skip check if destination is a dynamic type. | 1600 // Skip check if destination is a dynamic type. |
| 1601 const Immediate raw_null = | |
| 1602 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 1596 if (type.IsTypeParameter()) { | 1603 if (type.IsTypeParameter()) { |
| 1597 const Immediate raw_null = | |
| 1598 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 1599 // EAX must be preserved! | 1604 // EAX must be preserved! |
| 1600 Label fall_through; | 1605 Label fall_through; |
| 1601 GenerateInstantiatorTypeArguments(token_index); | 1606 GenerateInstantiatorTypeArguments(token_index, false); |
|
regis
2012/05/04 21:53:39
ditto
srdjan
2012/05/04 23:01:58
Done.
| |
| 1602 // Type arguments are on stack. | 1607 // Type arguments are on stack. |
| 1603 __ popl(EBX); | 1608 __ popl(EBX); |
| 1604 // Check if type argument is dynamic. | 1609 // Check if type argument is dynamic. |
| 1605 __ cmpl(EBX, raw_null); | 1610 __ cmpl(EBX, raw_null); |
| 1606 __ j(EQUAL, is_instance_lbl); | 1611 __ j(EQUAL, is_instance_lbl); |
| 1607 | 1612 |
| 1608 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. | 1613 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. |
| 1609 __ movl(EDX, FieldAddress(EBX, Object::class_offset())); | 1614 __ movl(EDX, FieldAddress(EBX, Object::class_offset())); |
| 1610 __ CompareObject(EDX, Object::ZoneHandle(Object::type_arguments_class())); | 1615 __ CompareObject(EDX, Object::ZoneHandle(Object::type_arguments_class())); |
| 1611 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1616 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1651 // We have a non-parameterized class in EDX, compare with class of | 1656 // We have a non-parameterized class in EDX, compare with class of |
| 1652 // value in EAX. EAX, EDX are preserved in stub. | 1657 // value in EAX. EAX, EDX are preserved in stub. |
| 1653 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1658 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1654 __ call(&StubCode::IsRawSubTypeLabel()); | 1659 __ call(&StubCode::IsRawSubTypeLabel()); |
| 1655 // Result in EBX: 1 is raw subtype. | 1660 // Result in EBX: 1 is raw subtype. |
| 1656 __ cmpl(EBX, Immediate(1)); | 1661 __ cmpl(EBX, Immediate(1)); |
| 1657 __ j(EQUAL, is_instance_lbl); | 1662 __ j(EQUAL, is_instance_lbl); |
| 1658 | 1663 |
| 1659 // Test not conclusive. | 1664 // Test not conclusive. |
| 1660 __ Bind(&fall_through); | 1665 __ Bind(&fall_through); |
| 1666 return SubtypeTestCache::null(); | |
| 1661 } | 1667 } |
| 1668 if (type.IsType()) { | |
| 1669 Label fall_through; | |
| 1670 __ testl(EAX, Immediate(kSmiTagMask)); // Is instance Smi? | |
| 1671 __ j(ZERO, is_not_instance_lbl, Assembler::kNearJump); | |
| 1672 // Uninstantiated type class is known at compile time, but the type | |
| 1673 // arguments are determined at runtime by the instantiator. | |
| 1674 const SubtypeTestCache& type_test_cache = | |
| 1675 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | |
| 1676 __ LoadObject(EDX, type_test_cache); | |
| 1677 __ pushl(EDX); // Subtype test cache. | |
| 1678 __ pushl(EAX); // Instance. | |
| 1679 GenerateInstantiatorTypeArguments(token_index, false); // type arguments. | |
|
regis
2012/05/04 21:53:39
ditto
srdjan
2012/05/04 23:01:58
Done.
| |
| 1680 __ call(&StubCode::Subtype3TestCacheLabel()); | |
| 1681 __ popl(EDX); // Discard type arguments. | |
| 1682 __ popl(EAX); // Restore receiver. | |
| 1683 __ popl(EDX); // Discard subtype test cache. | |
| 1684 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. | |
| 1685 __ cmpl(ECX, raw_null); | |
| 1686 __ j(EQUAL, &fall_through, Assembler::kNearJump); | |
| 1687 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 1688 __ CompareObject(ECX, bool_true); | |
| 1689 __ j(EQUAL, is_instance_lbl); | |
| 1690 __ jmp(is_not_instance_lbl); | |
| 1691 __ Bind(&fall_through); | |
| 1692 return type_test_cache.raw(); | |
| 1693 } | |
| 1694 return SubtypeTestCache::null(); | |
| 1662 } | 1695 } |
| 1663 | 1696 |
| 1664 | 1697 |
| 1665 // If type check cannot be performed successfully at compile time and therefore | 1698 // If type check cannot be performed successfully at compile time and therefore |
| 1666 // eliminated, optimize it by adding inlined tests for: | 1699 // eliminated, optimize it by adding inlined tests for: |
| 1667 // - NULL -> return NULL. | 1700 // - NULL -> return NULL. |
| 1668 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 1701 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 1669 // - Class equality (only if class is not parameterized). | 1702 // - Class equality (only if class is not parameterized). |
| 1670 // Inputs: | 1703 // Inputs: |
| 1671 // - EAX: object. | 1704 // - EAX: object. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1750 &done, &runtime_call); | 1783 &done, &runtime_call); |
| 1751 | 1784 |
| 1752 __ Bind(&runtime_call); | 1785 __ Bind(&runtime_call); |
| 1753 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1786 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1754 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. | 1787 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. |
| 1755 __ pushl(Immediate(Smi::RawValue(node_id))); // node-id. | 1788 __ pushl(Immediate(Smi::RawValue(node_id))); // node-id. |
| 1756 __ pushl(EAX); // Push the source object. | 1789 __ pushl(EAX); // Push the source object. |
| 1757 __ PushObject(dst_type); // Push the type of the destination. | 1790 __ PushObject(dst_type); // Push the type of the destination. |
| 1758 if (dst_type.IsInstantiated()) { | 1791 if (dst_type.IsInstantiated()) { |
| 1759 __ pushl(raw_null); // Null instantiator. | 1792 __ pushl(raw_null); // Null instantiator. |
| 1793 __ pushl(raw_null); // Null instantiator type argument. | |
| 1760 } else { | 1794 } else { |
| 1761 GenerateInstantiatorTypeArguments(token_index); | 1795 GenerateInstantiatorTypeArguments(token_index, true); |
|
regis
2012/05/04 21:53:39
ditto
srdjan
2012/05/04 23:01:58
Done.
| |
| 1762 } | 1796 } |
| 1763 __ PushObject(dst_name); // Push the name of the destination. | 1797 __ PushObject(dst_name); // Push the name of the destination. |
| 1764 __ LoadObject(EAX, test_cache); | 1798 __ LoadObject(EAX, test_cache); |
| 1765 __ pushl(EAX); | 1799 __ pushl(EAX); |
| 1766 GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry); | 1800 GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry); |
| 1767 // Pop the parameters supplied to the runtime entry. The result of the | 1801 // Pop the parameters supplied to the runtime entry. The result of the |
| 1768 // type check runtime call is the checked value. | 1802 // type check runtime call is the checked value. |
| 1769 __ addl(ESP, Immediate(7 * kWordSize)); | 1803 __ addl(ESP, Immediate(8 * kWordSize)); |
| 1770 __ popl(EAX); | 1804 __ popl(EAX); |
| 1771 | 1805 |
| 1772 // EAX: value. | 1806 // EAX: value. |
| 1773 __ Bind(&done); | 1807 __ Bind(&done); |
| 1774 } | 1808 } |
| 1775 | 1809 |
| 1776 | 1810 |
| 1777 void CodeGenerator::GenerateArgumentTypeChecks() { | 1811 void CodeGenerator::GenerateArgumentTypeChecks() { |
| 1778 const Function& function = parsed_function_.function(); | 1812 const Function& function = parsed_function_.function(); |
| 1779 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | 1813 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2356 __ popl(CTX); | 2390 __ popl(CTX); |
| 2357 // Result is in EAX. | 2391 // Result is in EAX. |
| 2358 if (IsResultNeeded(node)) { | 2392 if (IsResultNeeded(node)) { |
| 2359 __ pushl(EAX); | 2393 __ pushl(EAX); |
| 2360 } | 2394 } |
| 2361 } | 2395 } |
| 2362 | 2396 |
| 2363 | 2397 |
| 2364 // Pushes the type arguments of the instantiator on the stack. | 2398 // Pushes the type arguments of the instantiator on the stack. |
| 2365 // Destroys EBX. | 2399 // Destroys EBX. |
| 2366 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { | 2400 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index, |
| 2401 bool push_instantiator) { | |
| 2402 if (push_instantiator) { | |
| 2403 const Immediate raw_null = | |
| 2404 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 2405 __ pushl(raw_null); // Initial instantiator. | |
| 2406 } | |
| 2367 const Class& instantiator_class = Class::Handle( | 2407 const Class& instantiator_class = Class::Handle( |
| 2368 parsed_function().function().owner()); | 2408 parsed_function().function().owner()); |
| 2369 if (instantiator_class.NumTypeParameters() == 0) { | 2409 if (instantiator_class.NumTypeParameters() == 0) { |
| 2370 // The type arguments are compile time constants. | 2410 // The type arguments are compile time constants. |
| 2371 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); | 2411 AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(); |
| 2372 // TODO(regis): Temporary type should be allocated in new gen heap. | 2412 // TODO(regis): Temporary type should be allocated in new gen heap. |
| 2373 Type& type = Type::Handle( | 2413 Type& type = Type::Handle( |
| 2374 Type::New(instantiator_class, type_arguments, token_index)); | 2414 Type::New(instantiator_class, type_arguments, token_index)); |
| 2375 type ^= ClassFinalizer::FinalizeType( | 2415 type ^= ClassFinalizer::FinalizeType( |
| 2376 instantiator_class, type, ClassFinalizer::kFinalizeWellFormed); | 2416 instantiator_class, type, ClassFinalizer::kFinalizeWellFormed); |
| 2377 type_arguments = type.arguments(); | 2417 type_arguments = type.arguments(); |
| 2378 __ PushObject(type_arguments); | 2418 __ PushObject(type_arguments); |
| 2379 } else { | 2419 } else { |
| 2380 ASSERT(parsed_function().instantiator() != NULL); | 2420 ASSERT(parsed_function().instantiator() != NULL); |
| 2381 parsed_function().instantiator()->Visit(this); | 2421 parsed_function().instantiator()->Visit(this); |
| 2382 Function& outer_function = | 2422 Function& outer_function = |
| 2383 Function::Handle(parsed_function().function().raw()); | 2423 Function::Handle(parsed_function().function().raw()); |
| 2384 while (outer_function.IsLocalFunction()) { | 2424 while (outer_function.IsLocalFunction()) { |
| 2385 outer_function = outer_function.parent_function(); | 2425 outer_function = outer_function.parent_function(); |
| 2386 } | 2426 } |
| 2387 if (!outer_function.IsFactory()) { | 2427 if (!outer_function.IsFactory()) { |
| 2388 __ popl(EBX); // Pop instantiator. | 2428 if (push_instantiator) { |
| 2429 __ popl(EBX); // Pop instantiator. | |
| 2430 __ popl(ECX); // Discard null instantiator. | |
| 2431 __ pushl(EBX); // Replace it with the real one. | |
| 2432 } else { | |
| 2433 __ popl(EBX); // Pop instantiator. | |
| 2434 } | |
| 2435 // EBX: instantiator. | |
| 2389 // The instantiator is the receiver of the caller, which is not a factory. | 2436 // The instantiator is the receiver of the caller, which is not a factory. |
| 2390 // The receiver cannot be null; extract its AbstractTypeArguments object. | 2437 // The receiver cannot be null; extract its AbstractTypeArguments object. |
| 2391 // Note that in the factory case, the instantiator is the first parameter | 2438 // Note that in the factory case, the instantiator is the first parameter |
| 2392 // of the factory, i.e. already an AbstractTypeArguments object. | 2439 // of the factory, i.e. already an AbstractTypeArguments object. |
| 2393 intptr_t type_arguments_instance_field_offset = | 2440 intptr_t type_arguments_instance_field_offset = |
| 2394 instantiator_class.type_arguments_instance_field_offset(); | 2441 instantiator_class.type_arguments_instance_field_offset(); |
| 2395 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | 2442 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| 2396 __ movl(EBX, FieldAddress(EBX, type_arguments_instance_field_offset)); | 2443 __ movl(EBX, FieldAddress(EBX, type_arguments_instance_field_offset)); |
| 2397 __ pushl(EBX); | 2444 __ pushl(EBX); |
| 2398 } | 2445 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 2417 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { | 2464 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
| 2418 // The type arguments are instantiated. | 2465 // The type arguments are instantiated. |
| 2419 __ PushObject(type_arguments); | 2466 __ PushObject(type_arguments); |
| 2420 if (!instantiate_type_arguments) { | 2467 if (!instantiate_type_arguments) { |
| 2421 // The type arguments of the instantiator are not needed, since the | 2468 // The type arguments of the instantiator are not needed, since the |
| 2422 // type arguments are instantiated. | 2469 // type arguments are instantiated. |
| 2423 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 2470 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2424 } | 2471 } |
| 2425 } else { | 2472 } else { |
| 2426 // The type arguments are uninstantiated. | 2473 // The type arguments are uninstantiated. |
| 2427 GenerateInstantiatorTypeArguments(token_index); | 2474 GenerateInstantiatorTypeArguments(token_index, false); |
|
regis
2012/05/04 21:53:39
Document false
srdjan
2012/05/04 23:01:58
Done.
| |
| 2428 __ popl(EAX); // Pop instantiator. | 2475 __ popl(EAX); // Pop instantiator. |
| 2429 // EAX is the instantiator AbstractTypeArguments object (or null). | 2476 // EAX is the instantiator AbstractTypeArguments object (or null). |
| 2430 // If the instantiator is null and if the type argument vector | 2477 // If the instantiator is null and if the type argument vector |
| 2431 // instantiated from null becomes a vector of Dynamic, then use null as | 2478 // instantiated from null becomes a vector of Dynamic, then use null as |
| 2432 // the type arguments. | 2479 // the type arguments. |
| 2433 Label type_arguments_instantiated; | 2480 Label type_arguments_instantiated; |
| 2434 const intptr_t len = type_arguments.Length(); | 2481 const intptr_t len = type_arguments.Length(); |
| 2435 if (type_arguments.IsRawInstantiatedRaw(len)) { | 2482 if (type_arguments.IsRawInstantiatedRaw(len)) { |
| 2436 __ cmpl(EAX, raw_null); | 2483 __ cmpl(EAX, raw_null); |
| 2437 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2484 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2905 const Error& error = Error::Handle( | 2952 const Error& error = Error::Handle( |
| 2906 Parser::FormatError(script, token_index, "Error", format, args)); | 2953 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2907 va_end(args); | 2954 va_end(args); |
| 2908 Isolate::Current()->long_jump_base()->Jump(1, error); | 2955 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2909 UNREACHABLE(); | 2956 UNREACHABLE(); |
| 2910 } | 2957 } |
| 2911 | 2958 |
| 2912 } // namespace dart | 2959 } // namespace dart |
| 2913 | 2960 |
| 2914 #endif // defined TARGET_ARCH_IA32 | 2961 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |