Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(786)

Side by Side Diff: runtime/vm/code_generator_ia32.cc

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

Powered by Google App Engine
This is Rietveld 408576698