| 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 1214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1225 intptr_t node_id, | 1225 intptr_t node_id, |
| 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 Label loop, found_in_cache, runtime_call; | |
| 1236 // Check immediate equality. | 1235 // Check immediate equality. |
| 1237 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1236 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1238 // ECX: instance class. | 1237 // ECX: instance class. |
| 1239 __ CompareObject(ECX, type_class); | 1238 __ CompareObject(ECX, type_class); |
| 1240 __ j(EQUAL, is_instance_lbl); | 1239 __ j(EQUAL, is_instance_lbl); |
| 1241 | 1240 |
| 1242 // Check immediate superclass equality. | 1241 // Check immediate superclass equality. |
| 1243 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset())); | 1242 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset())); |
| 1244 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset())); | 1243 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset())); |
| 1245 __ CompareObject(EDI, type_class); | 1244 __ CompareObject(EDI, type_class); |
| 1246 __ j(EQUAL, is_instance_lbl); | 1245 __ j(EQUAL, is_instance_lbl); |
| 1247 | 1246 |
| 1248 __ LoadObject(EDX, type_test_cache); | 1247 __ LoadObject(EDX, type_test_cache); |
| 1249 __ pushl(EDX); // Cache array. | 1248 __ pushl(EDX); // Cache array. |
| 1250 __ pushl(EAX); // Instance. | 1249 __ pushl(EAX); // Instance. |
| 1251 __ pushl(raw_null); // Unused | 1250 __ pushl(raw_null); // Unused |
| 1252 __ call(&StubCode::Subtype1TestCacheLabel()); | 1251 __ call(&StubCode::Subtype1TestCacheLabel()); |
| 1253 __ popl(EAX); // Discard. | 1252 __ popl(EAX); // Discard. |
| 1254 __ popl(EAX); // Restore receiver. | 1253 __ popl(EAX); // Restore receiver. |
| 1255 __ popl(EDX); // Discard. | 1254 __ popl(EDX); // Discard. |
| 1256 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. | 1255 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. |
| 1257 | 1256 |
| 1257 Label runtime_call; |
| 1258 __ cmpl(ECX, raw_null); | 1258 __ cmpl(ECX, raw_null); |
| 1259 __ j(EQUAL, &runtime_call, Assembler::kNearJump); | 1259 __ j(EQUAL, &runtime_call, Assembler::kNearJump); |
| 1260 __ CompareObject(ECX, bool_true); | 1260 __ CompareObject(ECX, bool_true); |
| 1261 __ j(EQUAL, is_instance_lbl); | 1261 __ j(EQUAL, is_instance_lbl); |
| 1262 __ jmp(is_not_instance_lbl); | 1262 __ jmp(is_not_instance_lbl); |
| 1263 __ Bind(&runtime_call); | 1263 __ Bind(&runtime_call); |
| 1264 return type_test_cache.raw(); | 1264 return type_test_cache.raw(); |
| 1265 } | 1265 } |
| 1266 | 1266 |
| 1267 | 1267 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1458 if (!type_class.is_interface()) { |
| 1459 __ CompareObject(ECX, type_class); |
| 1460 __ j(EQUAL, is_instance_lbl); |
| 1461 } |
| 1458 if (type.IsListInterface()) { | 1462 if (type.IsListInterface()) { |
| 1459 // TODO(srdjan) also accept List<Object>. | 1463 // TODO(srdjan) also accept List<Object>. |
| 1460 __ CompareObject(ECX, *CoreClass("ObjectArray")); | 1464 __ CompareObject(ECX, *CoreClass("ObjectArray")); |
| 1461 __ j(EQUAL, is_instance_lbl); | 1465 __ j(EQUAL, is_instance_lbl); |
| 1462 __ CompareObject(ECX, *CoreClass("GrowableObjectArray")); | 1466 __ CompareObject(ECX, *CoreClass("GrowableObjectArray")); |
| 1463 __ j(EQUAL, is_instance_lbl); | 1467 __ j(EQUAL, is_instance_lbl); |
| 1464 } | 1468 } |
| 1465 return | 1469 return |
| 1466 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class, | 1470 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class, |
| 1467 is_instance_lbl, is_not_instance_lbl); | 1471 is_instance_lbl, is_not_instance_lbl); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 | 1550 |
| 1547 // Checking against interface. | 1551 // Checking against interface. |
| 1548 // However, for specific core library interfaces, we can check for | 1552 // However, for specific core library interfaces, we can check for |
| 1549 // specific core library classes. | 1553 // specific core library classes. |
| 1550 if (type.IsBoolInterface()) { | 1554 if (type.IsBoolInterface()) { |
| 1551 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1555 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1552 const Class& bool_class = Class::ZoneHandle( | 1556 const Class& bool_class = Class::ZoneHandle( |
| 1553 Isolate::Current()->object_store()->bool_class()); | 1557 Isolate::Current()->object_store()->bool_class()); |
| 1554 __ CompareObject(ECX, bool_class); | 1558 __ CompareObject(ECX, bool_class); |
| 1555 __ j(EQUAL, is_instance_lbl); | 1559 __ j(EQUAL, is_instance_lbl); |
| 1560 __ jmp(is_not_instance_lbl); |
| 1556 return; | 1561 return; |
| 1557 } | 1562 } |
| 1558 // If type is an interface, we can skip the class equality check, | 1563 // If type is an interface, we can skip the class equality check, |
| 1559 // because instances cannot be of an interface type. | 1564 // because instances cannot be of an interface type. |
| 1560 if (!type_class.is_interface()) { | 1565 if (!type_class.is_interface()) { |
| 1561 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1566 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1562 __ CompareObject(ECX, type_class); | 1567 __ CompareObject(ECX, type_class); |
| 1563 __ j(EQUAL, is_instance_lbl); | 1568 __ j(EQUAL, is_instance_lbl); |
| 1564 } | 1569 } |
| 1565 if (type.IsSubtypeOf( | 1570 if (type.IsSubtypeOf( |
| 1566 Type::Handle(Type::NumberInterface()), &malformed_error)) { | 1571 Type::Handle(Type::NumberInterface()), &malformed_error)) { |
| 1567 // Custom checking for numbers (Smi, Mint, Bigint and Double) | 1572 // Custom checking for numbers (Smi, Mint, Bigint and Double) |
| 1568 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1573 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1569 if (type.IsIntInterface() || type.IsNumberInterface()) { | 1574 if (type.IsIntInterface() || type.IsNumberInterface()) { |
| 1570 // We already checked for Smi above. | 1575 // We already checked for Smi above. |
| 1571 const Class& mint_class = Class::ZoneHandle( | 1576 const Class& mint_class = Class::ZoneHandle( |
| 1572 Isolate::Current()->object_store()->mint_class()); | 1577 Isolate::Current()->object_store()->mint_class()); |
| 1573 const Class& bigint_class = Class::ZoneHandle( | 1578 const Class& bigint_class = Class::ZoneHandle( |
| 1574 Isolate::Current()->object_store()->bigint_class()); | 1579 Isolate::Current()->object_store()->bigint_class()); |
| 1575 __ CompareObject(ECX, mint_class); | 1580 __ CompareObject(ECX, mint_class); |
| 1576 __ j(EQUAL, is_instance_lbl); | 1581 __ j(EQUAL, is_instance_lbl); |
| 1577 __ CompareObject(ECX, bigint_class); | 1582 __ CompareObject(ECX, bigint_class); |
| 1578 __ j(EQUAL, is_instance_lbl); | 1583 __ j(EQUAL, is_instance_lbl); |
| 1584 if (type.IsIntInterface()) { |
| 1585 __ jmp(is_not_instance_lbl); |
| 1586 } |
| 1579 } | 1587 } |
| 1580 if (type.IsDoubleInterface() || type.IsNumberInterface()) { | 1588 if (type.IsDoubleInterface() || type.IsNumberInterface()) { |
| 1581 const Class& double_class = Class::ZoneHandle( | 1589 const Class& double_class = Class::ZoneHandle( |
| 1582 Isolate::Current()->object_store()->double_class()); | 1590 Isolate::Current()->object_store()->double_class()); |
| 1583 __ CompareObject(ECX, double_class); | 1591 __ CompareObject(ECX, double_class); |
| 1584 __ j(EQUAL, is_instance_lbl); | 1592 __ j(EQUAL, is_instance_lbl); |
| 1593 __ jmp(is_not_instance_lbl); |
| 1585 } | 1594 } |
| 1586 } else if (type.IsStringInterface()) { | 1595 } else if (type.IsStringInterface()) { |
| 1587 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1596 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1588 const Class& one_byte_string_class = Class::ZoneHandle( | 1597 const Class& one_byte_string_class = Class::ZoneHandle( |
| 1589 Isolate::Current()->object_store()->one_byte_string_class()); | 1598 Isolate::Current()->object_store()->one_byte_string_class()); |
| 1590 const Class& two_byte_string_class = Class::ZoneHandle( | 1599 const Class& two_byte_string_class = Class::ZoneHandle( |
| 1591 Isolate::Current()->object_store()->two_byte_string_class()); | 1600 Isolate::Current()->object_store()->two_byte_string_class()); |
| 1592 const Class& four_byte_string_class = Class::ZoneHandle( | 1601 const Class& four_byte_string_class = Class::ZoneHandle( |
| 1593 Isolate::Current()->object_store()->four_byte_string_class()); | 1602 Isolate::Current()->object_store()->four_byte_string_class()); |
| 1594 __ CompareObject(ECX, one_byte_string_class); | 1603 __ CompareObject(ECX, one_byte_string_class); |
| (...skipping 1379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2974 const Error& error = Error::Handle( | 2983 const Error& error = Error::Handle( |
| 2975 Parser::FormatError(script, token_index, "Error", format, args)); | 2984 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2976 va_end(args); | 2985 va_end(args); |
| 2977 Isolate::Current()->long_jump_base()->Jump(1, error); | 2986 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2978 UNREACHABLE(); | 2987 UNREACHABLE(); |
| 2979 } | 2988 } |
| 2980 | 2989 |
| 2981 } // namespace dart | 2990 } // namespace dart |
| 2982 | 2991 |
| 2983 #endif // defined TARGET_ARCH_IA32 | 2992 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |