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

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

Issue 10447064: In generated code for ia32 don't load object's class directly from class_ field. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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
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 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 intptr_t token_index, 1226 intptr_t token_index,
1227 const Class& type_class, 1227 const Class& type_class,
1228 Label* is_instance_lbl, 1228 Label* is_instance_lbl,
1229 Label* is_not_instance_lbl) { 1229 Label* is_not_instance_lbl) {
1230 const SubtypeTestCache& type_test_cache = 1230 const SubtypeTestCache& type_test_cache =
1231 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 1231 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
1232 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1232 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1233 const Immediate raw_null = 1233 const Immediate raw_null =
1234 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1234 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1235 // Check immediate equality. 1235 // Check immediate equality.
1236 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1236 __ LoadClassOfObject(ECX, EAX, EDI);
1237 // ECX: instance class. 1237 // ECX: instance class.
1238 __ CompareObject(ECX, type_class); 1238 __ CompareObject(ECX, type_class);
1239 __ j(EQUAL, is_instance_lbl); 1239 __ j(EQUAL, is_instance_lbl);
1240 1240
1241 // Check immediate superclass equality. 1241 // Check immediate superclass equality.
1242 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset())); 1242 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset()));
1243 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset())); 1243 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset()));
1244 __ CompareObject(EDI, type_class); 1244 __ CompareObject(EDI, type_class);
1245 __ j(EQUAL, is_instance_lbl); 1245 __ j(EQUAL, is_instance_lbl);
1246 1246
(...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 1447 // 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. 1448 // non-parameterized class or with a raw dst type of a parameterized class.
1449 __ testl(EAX, Immediate(kSmiTagMask)); 1449 __ testl(EAX, Immediate(kSmiTagMask));
1450 __ j(ZERO, is_not_instance_lbl); 1450 __ j(ZERO, is_not_instance_lbl);
1451 const AbstractTypeArguments& type_arguments = 1451 const AbstractTypeArguments& type_arguments =
1452 AbstractTypeArguments::ZoneHandle(type.arguments()); 1452 AbstractTypeArguments::ZoneHandle(type.arguments());
1453 const bool is_raw_type = type_arguments.IsNull() || 1453 const bool is_raw_type = type_arguments.IsNull() ||
1454 type_arguments.IsRaw(type_arguments.Length()); 1454 type_arguments.IsRaw(type_arguments.Length());
1455 if (is_raw_type) { 1455 if (is_raw_type) {
1456 // Dynamic type argument, check only classes. 1456 // Dynamic type argument, check only classes.
1457 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1457 __ LoadClassIndexOfObject(ECX, EAX);
1458 if (!type_class.is_interface()) { 1458 if (!type_class.is_interface()) {
1459 __ CompareObject(ECX, type_class); 1459 __ cmpl(ECX, Immediate(type_class.index()));
1460 __ j(EQUAL, is_instance_lbl); 1460 __ j(EQUAL, is_instance_lbl);
1461 } 1461 }
1462 if (type.IsListInterface()) { 1462 if (type.IsListInterface()) {
1463 // TODO(srdjan) also accept List<Object>. 1463 // TODO(srdjan) also accept List<Object>.
1464 __ CompareObject(ECX, *CoreClass("ObjectArray")); 1464 __ cmpl(ECX, Immediate(CoreClass("ObjectArray")->index()));
1465 __ j(EQUAL, is_instance_lbl); 1465 __ j(EQUAL, is_instance_lbl);
1466 __ CompareObject(ECX, *CoreClass("GrowableObjectArray")); 1466 __ cmpl(ECX, Immediate(CoreClass("GrowableObjectArray")->index()));
1467 __ j(EQUAL, is_instance_lbl); 1467 __ j(EQUAL, is_instance_lbl);
1468 } 1468 }
1469 return 1469 return
1470 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class, 1470 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class,
1471 is_instance_lbl, is_not_instance_lbl); 1471 is_instance_lbl, is_not_instance_lbl);
1472 } 1472 }
1473 // If one type argument only, quick check. 1473 // If one type argument only, quick check.
1474 if (type_arguments.Length() == 1) { 1474 if (type_arguments.Length() == 1) {
1475 const AbstractType& tp_argument = AbstractType::ZoneHandle( 1475 const AbstractType& tp_argument = AbstractType::ZoneHandle(
1476 type_arguments.TypeAt(0)); 1476 type_arguments.TypeAt(0));
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1545 } else { 1545 } else {
1546 __ jmp(is_not_instance_lbl); 1546 __ jmp(is_not_instance_lbl);
1547 } 1547 }
1548 // Compare if the classes are equal. 1548 // Compare if the classes are equal.
1549 __ Bind(&compare_classes); 1549 __ Bind(&compare_classes);
1550 1550
1551 // Checking against interface. 1551 // Checking against interface.
1552 // However, for specific core library interfaces, we can check for 1552 // However, for specific core library interfaces, we can check for
1553 // specific core library classes. 1553 // specific core library classes.
1554 if (type.IsBoolInterface()) { 1554 if (type.IsBoolInterface()) {
1555 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1555 const Class& bool_class = Class::Handle(
1556 const Class& bool_class = Class::ZoneHandle(
1557 Isolate::Current()->object_store()->bool_class()); 1556 Isolate::Current()->object_store()->bool_class());
1558 __ CompareObject(ECX, bool_class); 1557 __ CompareClassOfObject(EAX, bool_class, ECX);
1559 __ j(EQUAL, is_instance_lbl); 1558 __ j(EQUAL, is_instance_lbl);
1560 __ jmp(is_not_instance_lbl); 1559 __ jmp(is_not_instance_lbl);
1561 return; 1560 return;
1562 } 1561 }
1563 // If type is an interface, we can skip the class equality check, 1562 // If type is an interface, we can skip the class equality check,
1564 // because instances cannot be of an interface type. 1563 // because instances cannot be of an interface type.
1565 if (!type_class.is_interface()) { 1564 if (!type_class.is_interface()) {
1566 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1565 __ CompareClassOfObject(EAX, type_class, ECX);
1567 __ CompareObject(ECX, type_class);
1568 __ j(EQUAL, is_instance_lbl); 1566 __ j(EQUAL, is_instance_lbl);
1569 } 1567 }
1570 if (type.IsSubtypeOf( 1568 if (type.IsSubtypeOf(
1571 Type::Handle(Type::NumberInterface()), &malformed_error)) { 1569 Type::Handle(Type::NumberInterface()), &malformed_error)) {
1572 // Custom checking for numbers (Smi, Mint, Bigint and Double) 1570 // Custom checking for numbers (Smi, Mint, Bigint and Double)
1573 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1571 __ LoadClassIndexOfObject(ECX, EAX);
1572
1574 if (type.IsIntInterface() || type.IsNumberInterface()) { 1573 if (type.IsIntInterface() || type.IsNumberInterface()) {
1575 // We already checked for Smi above. 1574 // We already checked for Smi above.
1576 const Class& mint_class = Class::ZoneHandle( 1575 const Class& mint_class = Class::ZoneHandle(
Ivan Posva 2012/05/30 05:48:09 ZoneHandle no longer needed, a Handle should be en
1577 Isolate::Current()->object_store()->mint_class()); 1576 Isolate::Current()->object_store()->mint_class());
1578 const Class& bigint_class = Class::ZoneHandle( 1577 const Class& bigint_class = Class::ZoneHandle(
1579 Isolate::Current()->object_store()->bigint_class()); 1578 Isolate::Current()->object_store()->bigint_class());
1580 __ CompareObject(ECX, mint_class); 1579 __ cmpl(ECX, Immediate(mint_class.index()));
1581 __ j(EQUAL, is_instance_lbl); 1580 __ j(EQUAL, is_instance_lbl);
1582 __ CompareObject(ECX, bigint_class); 1581 __ cmpl(ECX, Immediate(bigint_class.index()));
1583 __ j(EQUAL, is_instance_lbl); 1582 __ j(EQUAL, is_instance_lbl);
1584 if (type.IsIntInterface()) { 1583 if (type.IsIntInterface()) {
1585 __ jmp(is_not_instance_lbl); 1584 __ jmp(is_not_instance_lbl);
1586 } 1585 }
1587 } 1586 }
1588 if (type.IsDoubleInterface() || type.IsNumberInterface()) { 1587 if (type.IsDoubleInterface() || type.IsNumberInterface()) {
1589 const Class& double_class = Class::ZoneHandle( 1588 const Class& double_class = Class::ZoneHandle(
1590 Isolate::Current()->object_store()->double_class()); 1589 Isolate::Current()->object_store()->double_class());
1591 __ CompareObject(ECX, double_class); 1590 __ cmpl(ECX, Immediate(double_class.index()));
1592 __ j(EQUAL, is_instance_lbl); 1591 __ j(EQUAL, is_instance_lbl);
1593 __ jmp(is_not_instance_lbl); 1592 __ jmp(is_not_instance_lbl);
1594 } 1593 }
1595 } else if (type.IsStringInterface()) { 1594 } else if (type.IsStringInterface()) {
1596 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1595 __ LoadClassIndexOfObject(ECX, EAX);
1597 const Class& one_byte_string_class = Class::ZoneHandle( 1596 const Class& one_byte_string_class = Class::ZoneHandle(
1598 Isolate::Current()->object_store()->one_byte_string_class()); 1597 Isolate::Current()->object_store()->one_byte_string_class());
1599 const Class& two_byte_string_class = Class::ZoneHandle( 1598 const Class& two_byte_string_class = Class::ZoneHandle(
1600 Isolate::Current()->object_store()->two_byte_string_class()); 1599 Isolate::Current()->object_store()->two_byte_string_class());
1601 const Class& four_byte_string_class = Class::ZoneHandle( 1600 const Class& four_byte_string_class = Class::ZoneHandle(
1602 Isolate::Current()->object_store()->four_byte_string_class()); 1601 Isolate::Current()->object_store()->four_byte_string_class());
1603 __ CompareObject(ECX, one_byte_string_class); 1602 __ cmpl(ECX, Immediate(one_byte_string_class.index()));
1604 __ j(EQUAL, is_instance_lbl); 1603 __ j(EQUAL, is_instance_lbl);
1605 __ CompareObject(ECX, two_byte_string_class); 1604 __ cmpl(ECX, Immediate(two_byte_string_class.index()));
1606 __ j(EQUAL, is_instance_lbl); 1605 __ j(EQUAL, is_instance_lbl);
1607 __ CompareObject(ECX, four_byte_string_class); 1606 __ cmpl(ECX, Immediate(four_byte_string_class.index()));
1608 __ j(EQUAL, is_instance_lbl); 1607 __ j(EQUAL, is_instance_lbl);
1609 } else if (type.IsFunctionInterface()) { 1608 } else if (type.IsFunctionInterface()) {
1610 // Check if instance is a closure. 1609 // Check if instance is a closure.
1611 const Immediate raw_null = 1610 const Immediate raw_null =
1612 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1611 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1613 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1612 __ LoadClassOfObject(ECX, EAX, EBX);
1614 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); 1613 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset()));
1615 __ cmpl(ECX, raw_null); 1614 __ cmpl(ECX, raw_null);
1616 __ j(NOT_EQUAL, is_instance_lbl); 1615 __ j(NOT_EQUAL, is_instance_lbl);
1617 } 1616 }
1618 // Otherwise fallthrough. 1617 // Otherwise fallthrough.
1619 } 1618 }
1620 1619
1621 1620
1622 // EAX: instance to test. 1621 // EAX: instance to test.
1623 // Clobbers: EBX, EDX, ECX. 1622 // Clobbers: EBX, EDX, ECX.
(...skipping 15 matching lines...) Expand all
1639 // Type arguments are on stack. 1638 // Type arguments are on stack.
1640 __ popl(EBX); 1639 __ popl(EBX);
1641 // Check if type argument is dynamic. 1640 // Check if type argument is dynamic.
1642 __ cmpl(EBX, raw_null); 1641 __ cmpl(EBX, raw_null);
1643 __ j(EQUAL, is_instance_lbl); 1642 __ j(EQUAL, is_instance_lbl);
1644 1643
1645 // EBX: instantiator type arguments. 1644 // EBX: instantiator type arguments.
1646 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. 1645 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
1647 // We expect that frequently checked objects wull have their type arguments 1646 // We expect that frequently checked objects wull have their type arguments
1648 // converted into instance of TypeArguments. 1647 // converted into instance of TypeArguments.
1649 __ movl(EDX, FieldAddress(EBX, Object::class_offset())); 1648 __ CompareClassOfObject(EBX,
1650 __ CompareObject(EDX, Object::ZoneHandle(Object::type_arguments_class())); 1649 Class::Handle(Object::type_arguments_class()),
1650 EDX);
1651 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1651 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1652 1652
1653 __ movl(EDX, 1653 __ movl(EDX,
1654 FieldAddress(EBX, TypeArguments::type_at_offset(type.Index()))); 1654 FieldAddress(EBX, TypeArguments::type_at_offset(type.Index())));
1655 // EDX: concrete type of type. 1655 // EDX: concrete type of type.
1656 // Check if type argument is dynamic. 1656 // Check if type argument is dynamic.
1657 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType())); 1657 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType()));
1658 __ j(EQUAL, is_instance_lbl); 1658 __ j(EQUAL, is_instance_lbl);
1659 __ cmpl(EDX, raw_null); 1659 __ cmpl(EDX, raw_null);
1660 __ j(EQUAL, is_instance_lbl); 1660 __ j(EQUAL, is_instance_lbl);
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1872 Label runtime_call, done; 1872 Label runtime_call, done;
1873 __ movl(EAX, Address(ESP, 0)); 1873 __ movl(EAX, Address(ESP, 0));
1874 __ cmpl(EAX, raw_null); 1874 __ cmpl(EAX, raw_null);
1875 __ j(EQUAL, &runtime_call, Assembler::kNearJump); 1875 __ j(EQUAL, &runtime_call, Assembler::kNearJump);
1876 __ testl(EAX, Immediate(kSmiTagMask)); 1876 __ testl(EAX, Immediate(kSmiTagMask));
1877 __ j(ZERO, &runtime_call, Assembler::kNearJump); // Call runtime for Smi. 1877 __ j(ZERO, &runtime_call, Assembler::kNearJump); // Call runtime for Smi.
1878 // This check should pass if the receiver's class implements the interface 1878 // This check should pass if the receiver's class implements the interface
1879 // 'bool'. Check only class 'Bool' since it is the only legal implementation 1879 // 'bool'. Check only class 'Bool' since it is the only legal implementation
1880 // of the interface 'bool'. 1880 // of the interface 'bool'.
1881 const Class& bool_class = 1881 const Class& bool_class =
1882 Class::ZoneHandle(Isolate::Current()->object_store()->bool_class()); 1882 Class::Handle(Isolate::Current()->object_store()->bool_class());
1883 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1883 __ CompareClassOfObject(EAX, bool_class, ECX);
1884 __ CompareObject(ECX, bool_class);
1885 __ j(EQUAL, &done, Assembler::kNearJump); 1884 __ j(EQUAL, &done, Assembler::kNearJump);
1886 1885
1887 __ Bind(&runtime_call); 1886 __ Bind(&runtime_call);
1888 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. 1887 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
1889 __ pushl(EAX); // Push the source object. 1888 __ pushl(EAX); // Push the source object.
1890 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); 1889 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry);
1891 // We should never return here. 1890 // We should never return here.
1892 __ int3(); 1891 __ int3();
1893 1892
1894 __ Bind(&done); 1893 __ Bind(&done);
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
2516 __ cmpl(EAX, raw_null); 2515 __ cmpl(EAX, raw_null);
2517 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2516 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2518 } 2517 }
2519 // Instantiate non-null type arguments. 2518 // Instantiate non-null type arguments.
2520 if (type_arguments.IsUninstantiatedIdentity()) { 2519 if (type_arguments.IsUninstantiatedIdentity()) {
2521 // Check if the instantiator type argument vector is a TypeArguments of a 2520 // Check if the instantiator type argument vector is a TypeArguments of a
2522 // matching length and, if so, use it as the instantiated type_arguments. 2521 // matching length and, if so, use it as the instantiated type_arguments.
2523 // No need to check RAX for null (again), because a null instance will 2522 // No need to check RAX for null (again), because a null instance will
2524 // have the wrong class (Null instead of TypeArguments). 2523 // have the wrong class (Null instead of TypeArguments).
2525 Label type_arguments_uninstantiated; 2524 Label type_arguments_uninstantiated;
2526 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); 2525 __ CompareClassOfObject(EAX,
2527 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); 2526 Class::Handle(Object::type_arguments_class()),
2527 ECX);
2528 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 2528 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
2529 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), 2529 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()),
2530 Immediate(Smi::RawValue(len))); 2530 Immediate(Smi::RawValue(len)));
2531 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2531 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2532 __ Bind(&type_arguments_uninstantiated); 2532 __ Bind(&type_arguments_uninstantiated);
2533 } 2533 }
2534 if (instantiate_type_arguments) { 2534 if (instantiate_type_arguments) {
2535 // A runtime call to instantiate the type arguments is required. 2535 // A runtime call to instantiate the type arguments is required.
2536 __ PushObject(Object::ZoneHandle()); // Make room for the result. 2536 __ PushObject(Object::ZoneHandle()); // Make room for the result.
2537 __ PushObject(type_arguments); 2537 __ PushObject(type_arguments);
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2983 const Error& error = Error::Handle( 2983 const Error& error = Error::Handle(
2984 Parser::FormatError(script, token_index, "Error", format, args)); 2984 Parser::FormatError(script, token_index, "Error", format, args));
2985 va_end(args); 2985 va_end(args);
2986 Isolate::Current()->long_jump_base()->Jump(1, error); 2986 Isolate::Current()->long_jump_base()->Jump(1, error);
2987 UNREACHABLE(); 2987 UNREACHABLE();
2988 } 2988 }
2989 2989
2990 } // namespace dart 2990 } // namespace dart
2991 2991
2992 #endif // defined TARGET_ARCH_IA32 2992 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698