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

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

Issue 10458031: In generated code for x64 don't load object's class directly from class_ field. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Eliminate CoreClass helpers on ia32/x64 and use class ids for array classes. Created 8 years, 6 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/assembler_x64.cc ('k') | runtime/vm/flow_graph_compiler_x64.h » ('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 1188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 operator_name, 1199 operator_name,
1200 kNumberOfArguments, 1200 kNumberOfArguments,
1201 kNoArgumentNames, 1201 kNoArgumentNames,
1202 kNumArgumentsChecked); 1202 kNumArgumentsChecked);
1203 if (IsResultNeeded(node)) { 1203 if (IsResultNeeded(node)) {
1204 __ pushl(EAX); 1204 __ pushl(EAX);
1205 } 1205 }
1206 } 1206 }
1207 1207
1208 1208
1209 static const Class* CoreClass(const char* c_name) {
1210 const String& class_name = String::Handle(String::NewSymbol(c_name));
1211 const Class& cls = Class::ZoneHandle(Library::Handle(
1212 Library::CoreImplLibrary()).LookupClass(class_name));
1213 ASSERT(!cls.IsNull());
1214 return &cls;
1215 }
1216
1217
1218 // Instance to test is in EAX. Test if its class is in subtype test cache array 1209 // Instance to test is in EAX. Test if its class is in subtype test cache array
1219 // and use the result in the array to jump to one of the labels. Fall through 1210 // and use the result in the array to jump to one of the labels. Fall through
1220 // if the instance is not in the cache array. 1211 // if the instance is not in the cache array.
1221 // TODO(srdjan): Implement a quicker subtype check, as type test 1212 // TODO(srdjan): Implement a quicker subtype check, as type test
1222 // arrays can grow too high, but they may be useful when optimizing 1213 // arrays can grow too high, but they may be useful when optimizing
1223 // code (type-feedback). 1214 // code (type-feedback).
1224 RawSubtypeTestCache* CodeGenerator::GenerateSubtype1TestCacheLookup( 1215 RawSubtypeTestCache* CodeGenerator::GenerateSubtype1TestCacheLookup(
1225 intptr_t node_id, 1216 intptr_t node_id,
1226 intptr_t token_index, 1217 intptr_t token_index,
1227 const Class& type_class, 1218 const Class& type_class,
1228 Label* is_instance_lbl, 1219 Label* is_instance_lbl,
1229 Label* is_not_instance_lbl) { 1220 Label* is_not_instance_lbl) {
1230 const SubtypeTestCache& type_test_cache = 1221 const SubtypeTestCache& type_test_cache =
1231 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 1222 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
1232 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1223 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1233 const Immediate raw_null = 1224 const Immediate raw_null =
1234 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1225 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1235 // Check immediate equality. 1226 // Check immediate equality.
1236 __ LoadClassOfObject(ECX, EAX, EDI); 1227 __ LoadClass(ECX, EAX, EDI);
1237 // ECX: instance class. 1228 // ECX: instance class.
1238 __ CompareObject(ECX, type_class); 1229 __ CompareObject(ECX, type_class);
1239 __ j(EQUAL, is_instance_lbl); 1230 __ j(EQUAL, is_instance_lbl);
1240 1231
1241 // Check immediate superclass equality. 1232 // Check immediate superclass equality.
1242 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset())); 1233 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset()));
1243 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset())); 1234 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset()));
1244 __ CompareObject(EDI, type_class); 1235 __ CompareObject(EDI, type_class);
1245 __ j(EQUAL, is_instance_lbl); 1236 __ j(EQUAL, is_instance_lbl);
1246 1237
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 // A class equality check is only applicable with a dst type of a 1438 // A class equality check is only applicable with a dst type of a
1448 // non-parameterized class or with a raw dst type of a parameterized class. 1439 // non-parameterized class or with a raw dst type of a parameterized class.
1449 __ testl(EAX, Immediate(kSmiTagMask)); 1440 __ testl(EAX, Immediate(kSmiTagMask));
1450 __ j(ZERO, is_not_instance_lbl); 1441 __ j(ZERO, is_not_instance_lbl);
1451 const AbstractTypeArguments& type_arguments = 1442 const AbstractTypeArguments& type_arguments =
1452 AbstractTypeArguments::ZoneHandle(type.arguments()); 1443 AbstractTypeArguments::ZoneHandle(type.arguments());
1453 const bool is_raw_type = type_arguments.IsNull() || 1444 const bool is_raw_type = type_arguments.IsNull() ||
1454 type_arguments.IsRaw(type_arguments.Length()); 1445 type_arguments.IsRaw(type_arguments.Length());
1455 if (is_raw_type) { 1446 if (is_raw_type) {
1456 // Dynamic type argument, check only classes. 1447 // Dynamic type argument, check only classes.
1457 __ LoadClassIndexOfObject(ECX, EAX); 1448 __ LoadClassId(ECX, EAX);
1458 if (!type_class.is_interface()) { 1449 if (!type_class.is_interface()) {
1459 __ cmpl(ECX, Immediate(type_class.index())); 1450 __ cmpl(ECX, Immediate(type_class.index()));
1460 __ j(EQUAL, is_instance_lbl); 1451 __ j(EQUAL, is_instance_lbl);
1461 } 1452 }
1462 if (type.IsListInterface()) { 1453 if (type.IsListInterface()) {
1463 // TODO(srdjan) also accept List<Object>. 1454 // TODO(srdjan) also accept List<Object>.
1464 __ cmpl(ECX, Immediate(CoreClass("ObjectArray")->index())); 1455 __ cmpl(ECX, Immediate(kArray));
1465 __ j(EQUAL, is_instance_lbl); 1456 __ j(EQUAL, is_instance_lbl);
1466 __ cmpl(ECX, Immediate(CoreClass("GrowableObjectArray")->index())); 1457 __ cmpl(ECX, Immediate(kGrowableObjectArray));
1467 __ j(EQUAL, is_instance_lbl); 1458 __ j(EQUAL, is_instance_lbl);
1468 } 1459 }
1469 return 1460 return
1470 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class, 1461 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class,
1471 is_instance_lbl, is_not_instance_lbl); 1462 is_instance_lbl, is_not_instance_lbl);
1472 } 1463 }
1473 // If one type argument only, quick check. 1464 // If one type argument only, quick check.
1474 if (type_arguments.Length() == 1) { 1465 if (type_arguments.Length() == 1) {
1475 const AbstractType& tp_argument = AbstractType::ZoneHandle( 1466 const AbstractType& tp_argument = AbstractType::ZoneHandle(
1476 type_arguments.TypeAt(0)); 1467 type_arguments.TypeAt(0));
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1545 } else { 1536 } else {
1546 __ jmp(is_not_instance_lbl); 1537 __ jmp(is_not_instance_lbl);
1547 } 1538 }
1548 // Compare if the classes are equal. 1539 // Compare if the classes are equal.
1549 __ Bind(&compare_classes); 1540 __ Bind(&compare_classes);
1550 1541
1551 // Checking against interface. 1542 // Checking against interface.
1552 // However, for specific core library interfaces, we can check for 1543 // However, for specific core library interfaces, we can check for
1553 // specific core library classes. 1544 // specific core library classes.
1554 if (type.IsBoolInterface()) { 1545 if (type.IsBoolInterface()) {
1555 const Class& bool_class = Class::Handle( 1546 __ CompareClassId(EAX, kBool, ECX);
1556 Isolate::Current()->object_store()->bool_class());
1557 __ CompareClassOfObject(EAX, bool_class, ECX);
1558 __ j(EQUAL, is_instance_lbl); 1547 __ j(EQUAL, is_instance_lbl);
1559 __ jmp(is_not_instance_lbl); 1548 __ jmp(is_not_instance_lbl);
1560 return; 1549 return;
1561 } 1550 }
1562 // If type is an interface, we can skip the class equality check, 1551 // If type is an interface, we can skip the class equality check,
1563 // because instances cannot be of an interface type. 1552 // because instances cannot be of an interface type.
1564 if (!type_class.is_interface()) { 1553 if (!type_class.is_interface()) {
1565 __ CompareClassOfObject(EAX, type_class, ECX); 1554 __ CompareClassId(EAX, type_class.index(), ECX);
1566 __ j(EQUAL, is_instance_lbl); 1555 __ j(EQUAL, is_instance_lbl);
1567 } 1556 }
1568 if (type.IsSubtypeOf( 1557 if (type.IsSubtypeOf(
1569 Type::Handle(Type::NumberInterface()), &malformed_error)) { 1558 Type::Handle(Type::NumberInterface()), &malformed_error)) {
1570 // Custom checking for numbers (Smi, Mint, Bigint and Double) 1559 // Custom checking for numbers (Smi, Mint, Bigint and Double)
1571 __ LoadClassIndexOfObject(ECX, EAX); 1560 __ LoadClassId(ECX, EAX);
1572 1561
1573 if (type.IsIntInterface() || type.IsNumberInterface()) { 1562 if (type.IsIntInterface() || type.IsNumberInterface()) {
1574 // We already checked for Smi above. 1563 // We already checked for Smi above.
1575 __ cmpl(ECX, Immediate(kMint)); 1564 __ cmpl(ECX, Immediate(kMint));
1576 __ j(EQUAL, is_instance_lbl); 1565 __ j(EQUAL, is_instance_lbl);
1577 __ cmpl(ECX, Immediate(kBigint)); 1566 __ cmpl(ECX, Immediate(kBigint));
1578 __ j(EQUAL, is_instance_lbl); 1567 __ j(EQUAL, is_instance_lbl);
1579 if (type.IsIntInterface()) { 1568 if (type.IsIntInterface()) {
1580 __ jmp(is_not_instance_lbl); 1569 __ jmp(is_not_instance_lbl);
1581 } 1570 }
1582 } 1571 }
1583 if (type.IsDoubleInterface() || type.IsNumberInterface()) { 1572 if (type.IsDoubleInterface() || type.IsNumberInterface()) {
1584 __ cmpl(ECX, Immediate(kDouble)); 1573 __ cmpl(ECX, Immediate(kDouble));
1585 __ j(EQUAL, is_instance_lbl); 1574 __ j(EQUAL, is_instance_lbl);
1586 __ jmp(is_not_instance_lbl); 1575 __ jmp(is_not_instance_lbl);
1587 } 1576 }
1588 } else if (type.IsStringInterface()) { 1577 } else if (type.IsStringInterface()) {
1589 __ LoadClassIndexOfObject(ECX, EAX); 1578 __ LoadClassId(ECX, EAX);
1590 __ cmpl(ECX, Immediate(kOneByteString)); 1579 __ cmpl(ECX, Immediate(kOneByteString));
1591 __ j(EQUAL, is_instance_lbl); 1580 __ j(EQUAL, is_instance_lbl);
1592 __ cmpl(ECX, Immediate(kTwoByteString)); 1581 __ cmpl(ECX, Immediate(kTwoByteString));
1593 __ j(EQUAL, is_instance_lbl); 1582 __ j(EQUAL, is_instance_lbl);
1594 __ cmpl(ECX, Immediate(kFourByteString)); 1583 __ cmpl(ECX, Immediate(kFourByteString));
1595 __ j(EQUAL, is_instance_lbl); 1584 __ j(EQUAL, is_instance_lbl);
1596 } else if (type.IsFunctionInterface()) { 1585 } else if (type.IsFunctionInterface()) {
1597 // Check if instance is a closure. 1586 // Check if instance is a closure.
1598 const Immediate raw_null = 1587 const Immediate raw_null =
1599 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1588 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1600 __ LoadClassOfObject(ECX, EAX, EBX); 1589 __ LoadClass(ECX, EAX, EBX);
1601 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); 1590 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset()));
1602 __ cmpl(ECX, raw_null); 1591 __ cmpl(ECX, raw_null);
1603 __ j(NOT_EQUAL, is_instance_lbl); 1592 __ j(NOT_EQUAL, is_instance_lbl);
1604 } 1593 }
1605 // Otherwise fallthrough. 1594 // Otherwise fallthrough.
1606 } 1595 }
1607 1596
1608 1597
1609 // EAX: instance to test. 1598 // EAX: instance to test.
1610 // Clobbers: EBX, EDX, ECX. 1599 // Clobbers: EBX, EDX, ECX.
(...skipping 15 matching lines...) Expand all
1626 // Type arguments are on stack. 1615 // Type arguments are on stack.
1627 __ popl(EBX); 1616 __ popl(EBX);
1628 // Check if type argument is dynamic. 1617 // Check if type argument is dynamic.
1629 __ cmpl(EBX, raw_null); 1618 __ cmpl(EBX, raw_null);
1630 __ j(EQUAL, is_instance_lbl); 1619 __ j(EQUAL, is_instance_lbl);
1631 1620
1632 // EBX: instantiator type arguments. 1621 // EBX: instantiator type arguments.
1633 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. 1622 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
1634 // We expect that frequently checked objects wull have their type arguments 1623 // We expect that frequently checked objects wull have their type arguments
1635 // converted into instance of TypeArguments. 1624 // converted into instance of TypeArguments.
1636 __ CompareClassOfObject(EBX, 1625 __ CompareClassId(EBX, kTypeArguments, EDX);
1637 Class::Handle(Object::type_arguments_class()),
1638 EDX);
1639 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1626 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1640 1627
1641 __ movl(EDX, 1628 __ movl(EDX,
1642 FieldAddress(EBX, TypeArguments::type_at_offset(type.Index()))); 1629 FieldAddress(EBX, TypeArguments::type_at_offset(type.Index())));
1643 // EDX: concrete type of type. 1630 // EDX: concrete type of type.
1644 // Check if type argument is dynamic. 1631 // Check if type argument is dynamic.
1645 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType())); 1632 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType()));
1646 __ j(EQUAL, is_instance_lbl); 1633 __ j(EQUAL, is_instance_lbl);
1647 __ cmpl(EDX, raw_null); 1634 __ cmpl(EDX, raw_null);
1648 __ j(EQUAL, is_instance_lbl); 1635 __ j(EQUAL, is_instance_lbl);
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1859 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1846 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1860 Label runtime_call, done; 1847 Label runtime_call, done;
1861 __ movl(EAX, Address(ESP, 0)); 1848 __ movl(EAX, Address(ESP, 0));
1862 __ cmpl(EAX, raw_null); 1849 __ cmpl(EAX, raw_null);
1863 __ j(EQUAL, &runtime_call, Assembler::kNearJump); 1850 __ j(EQUAL, &runtime_call, Assembler::kNearJump);
1864 __ testl(EAX, Immediate(kSmiTagMask)); 1851 __ testl(EAX, Immediate(kSmiTagMask));
1865 __ j(ZERO, &runtime_call, Assembler::kNearJump); // Call runtime for Smi. 1852 __ j(ZERO, &runtime_call, Assembler::kNearJump); // Call runtime for Smi.
1866 // This check should pass if the receiver's class implements the interface 1853 // This check should pass if the receiver's class implements the interface
1867 // 'bool'. Check only class 'Bool' since it is the only legal implementation 1854 // 'bool'. Check only class 'Bool' since it is the only legal implementation
1868 // of the interface 'bool'. 1855 // of the interface 'bool'.
1869 const Class& bool_class = 1856 __ CompareClassId(EAX, kBool, ECX);
1870 Class::Handle(Isolate::Current()->object_store()->bool_class());
1871 __ CompareClassOfObject(EAX, bool_class, ECX);
1872 __ j(EQUAL, &done, Assembler::kNearJump); 1857 __ j(EQUAL, &done, Assembler::kNearJump);
1873 1858
1874 __ Bind(&runtime_call); 1859 __ Bind(&runtime_call);
1875 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. 1860 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
1876 __ pushl(EAX); // Push the source object. 1861 __ pushl(EAX); // Push the source object.
1877 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); 1862 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry);
1878 // We should never return here. 1863 // We should never return here.
1879 __ int3(); 1864 __ int3();
1880 1865
1881 __ Bind(&done); 1866 __ Bind(&done);
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
2503 __ cmpl(EAX, raw_null); 2488 __ cmpl(EAX, raw_null);
2504 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2489 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2505 } 2490 }
2506 // Instantiate non-null type arguments. 2491 // Instantiate non-null type arguments.
2507 if (type_arguments.IsUninstantiatedIdentity()) { 2492 if (type_arguments.IsUninstantiatedIdentity()) {
2508 // Check if the instantiator type argument vector is a TypeArguments of a 2493 // Check if the instantiator type argument vector is a TypeArguments of a
2509 // matching length and, if so, use it as the instantiated type_arguments. 2494 // matching length and, if so, use it as the instantiated type_arguments.
2510 // No need to check RAX for null (again), because a null instance will 2495 // No need to check RAX for null (again), because a null instance will
2511 // have the wrong class (Null instead of TypeArguments). 2496 // have the wrong class (Null instead of TypeArguments).
2512 Label type_arguments_uninstantiated; 2497 Label type_arguments_uninstantiated;
2513 __ CompareClassOfObject(EAX, 2498 __ CompareClassId(EAX, kTypeArguments, ECX);
2514 Class::Handle(Object::type_arguments_class()),
2515 ECX);
2516 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 2499 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
2517 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), 2500 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()),
2518 Immediate(Smi::RawValue(len))); 2501 Immediate(Smi::RawValue(len)));
2519 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2502 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2520 __ Bind(&type_arguments_uninstantiated); 2503 __ Bind(&type_arguments_uninstantiated);
2521 } 2504 }
2522 if (instantiate_type_arguments) { 2505 if (instantiate_type_arguments) {
2523 // A runtime call to instantiate the type arguments is required. 2506 // A runtime call to instantiate the type arguments is required.
2524 __ PushObject(Object::ZoneHandle()); // Make room for the result. 2507 __ PushObject(Object::ZoneHandle()); // Make room for the result.
2525 __ PushObject(type_arguments); 2508 __ PushObject(type_arguments);
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2971 const Error& error = Error::Handle( 2954 const Error& error = Error::Handle(
2972 Parser::FormatError(script, token_index, "Error", format, args)); 2955 Parser::FormatError(script, token_index, "Error", format, args));
2973 va_end(args); 2956 va_end(args);
2974 Isolate::Current()->long_jump_base()->Jump(1, error); 2957 Isolate::Current()->long_jump_base()->Jump(1, error);
2975 UNREACHABLE(); 2958 UNREACHABLE();
2976 } 2959 }
2977 2960
2978 } // namespace dart 2961 } // namespace dart
2979 2962
2980 #endif // defined TARGET_ARCH_IA32 2963 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/assembler_x64.cc ('k') | runtime/vm/flow_graph_compiler_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698