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

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

Issue 10209002: Progress toward inlined type checks for classes with type arguments: factor out code, optimize typ… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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 1267 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 1278
1279 static const Class* CoreClass(const char* c_name) { 1279 static const Class* CoreClass(const char* c_name) {
1280 const String& class_name = String::Handle(String::NewSymbol(c_name)); 1280 const String& class_name = String::Handle(String::NewSymbol(c_name));
1281 const Class& cls = Class::ZoneHandle(Library::Handle( 1281 const Class& cls = Class::ZoneHandle(Library::Handle(
1282 Library::CoreImplLibrary()).LookupClass(class_name)); 1282 Library::CoreImplLibrary()).LookupClass(class_name));
1283 ASSERT(!cls.IsNull()); 1283 ASSERT(!cls.IsNull());
1284 return &cls; 1284 return &cls;
1285 } 1285 }
1286 1286
1287 1287
1288 // Instance to test is in EAX, test if it is a subtype of type_class.
1289 // The instance may not be a Smi (test before calling this).
1290 // The instance may not be NULL (test before calling this).
1291 // TODO(srdjan): Implement a quicker subtype check, as type test
1292 // arrays can grow too high, but they may be useful when optimizing
1293 // code (type-feedback).
1294 void CodeGenerator::GenerateClassTestCache(intptr_t node_id,
1295 intptr_t token_index,
1296 const Class& type_class,
1297 Label* is_instance_lbl,
1298 Label* is_not_instance_lbl) {
1299 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1300 const Immediate raw_null =
1301 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1302 Label loop, found_in_cache, runtime_call;
1303 // Check immediate equality.
1304 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1305 // ECX: instance class.
1306 __ CompareObject(ECX, type_class);
1307 __ j(EQUAL, is_instance_lbl);
1308
1309 // Check immediate superclass equality.
1310 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset()));
1311 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset()));
1312 __ CompareObject(EDI, type_class);
1313 __ j(EQUAL, is_instance_lbl);
1314
1315 // ECX: instance class.
1316 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index);
1317 __ LoadObject(EDX, Array::ZoneHandle(Array::New(2)));
1318 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag));
1319 __ Bind(&loop);
1320 __ movl(EBX, Address(EDX, 0));
1321 __ cmpl(ECX, EBX);
1322 __ j(EQUAL, &found_in_cache, Assembler::kNearJump);
1323 __ addl(EDX, Immediate(kWordSize * 2));
1324 __ cmpl(EBX, raw_null);
1325 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1326 __ jmp(&runtime_call, Assembler::kNearJump);
1327
1328 __ Bind(&found_in_cache);
1329 __ movl(EDX, Address(EDX, kWordSize));
1330 __ CompareObject(EDX, bool_true);
1331 __ j(EQUAL, is_instance_lbl);
1332 __ jmp(is_not_instance_lbl);
1333 __ Bind(&runtime_call);
1334 }
1335
1336
1288 // Inline tests according to the 'type' being tested. Jump to labels 1337 // Inline tests according to the 'type' being tested. Jump to labels
1289 // if we can compute the type-test, otherwise fallthrough. 1338 // if we can compute the type-test, otherwise fallthrough.
1290 // EAX: instance to be tested. 1339 // EAX: instance to be tested.
1291 // Clobbers many registers. 1340 // Clobbers many registers.
1292 void CodeGenerator::GenerateInlineInstanceof(intptr_t node_id, 1341 void CodeGenerator::GenerateInlineInstanceof(intptr_t node_id,
1293 intptr_t token_index, 1342 intptr_t token_index,
1294 const AbstractType& type, 1343 const AbstractType& type,
1295 Label* is_instance_lbl, 1344 Label* is_instance_lbl,
1296 Label* is_not_instance_lbl) { 1345 Label* is_not_instance_lbl) {
1297 if (type.IsInstantiated()) { 1346 if (type.IsInstantiated()) {
1298 const Class& type_class = Class::ZoneHandle(type.type_class()); 1347 const Class& type_class = Class::ZoneHandle(type.type_class());
1299 // A Smi object cannot be the instance of a parameterized class. 1348 // A Smi object cannot be the instance of a parameterized class.
1300 // A class equality check is only applicable with a dst type of a 1349 // A class equality check is only applicable with a dst type of a
1301 // non-parameterized class or with a raw dst type of a parameterized class. 1350 // non-parameterized class or with a raw dst type of a parameterized class.
1302 if (type_class.HasTypeArguments()) { 1351 if (type_class.HasTypeArguments()) {
1303 GenerateInstantiatedTypeWithArgumentsTest(type, 1352 GenerateInstantiatedTypeWithArgumentsTest(node_id,
1353 token_index,
1354 type,
1304 is_instance_lbl, 1355 is_instance_lbl,
1305 is_not_instance_lbl); 1356 is_not_instance_lbl);
1306 // Fall through to runtime call. 1357 // Fall through to runtime call.
1307 } else { 1358 } else {
1308 GenerateInstantiatedTypeNoArgumentsTest(node_id, 1359 GenerateInstantiatedTypeNoArgumentsTest(node_id,
1309 token_index, 1360 token_index,
1310 type, 1361 type,
1311 is_instance_lbl, 1362 is_instance_lbl,
1312 is_not_instance_lbl); 1363 is_not_instance_lbl);
1313 // If test non-conclusive so far, try the inlined type-test cache. 1364 // If test non-conclusive so far, try the inlined type-test cache.
1314 // 'type' is known at compile time. 1365 // 'type' is known at compile time.
1315 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1366 GenerateClassTestCache(node_id, token_index, type_class,
1316 const Immediate raw_null = 1367 is_instance_lbl, is_not_instance_lbl);
1317 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1318 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1319 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index);
1320 __ LoadObject(EDX, Array::ZoneHandle(Array::New(2)));
1321 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag));
1322 Label loop, found_in_cache, runtime_call;
1323 __ Bind(&loop);
1324 __ movl(EBX, Address(EDX, 0));
1325 __ cmpl(ECX, EBX);
1326 __ j(EQUAL, &found_in_cache, Assembler::kNearJump);
1327 __ addl(EDX, Immediate(kWordSize * 2));
1328 __ cmpl(EBX, raw_null);
1329 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1330 __ jmp(&runtime_call, Assembler::kNearJump);
1331
1332 __ Bind(&found_in_cache);
1333 __ movl(EDX, Address(EDX, kWordSize));
1334 __ CompareObject(EDX, bool_true);
1335 __ j(EQUAL, is_instance_lbl);
1336 __ jmp(is_not_instance_lbl);
1337 __ Bind(&runtime_call);
1338 } 1368 }
1339 } else { 1369 } else {
1340 GenerateUninstantiatedTypeTest(type, 1370 GenerateUninstantiatedTypeTest(type,
1341 token_index, 1371 token_index,
1342 is_instance_lbl); 1372 is_instance_lbl);
1343 } 1373 }
1344 } 1374 }
1345 1375
1346 1376
1347 // If instanceof type test cannot be performed successfully at compile time and 1377 // If instanceof type test cannot be performed successfully at compile time and
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1460 __ Bind(&done); 1490 __ Bind(&done);
1461 } 1491 }
1462 1492
1463 1493
1464 // EAX: instance to test. 1494 // EAX: instance to test.
1465 // Clobbers: ECX. 1495 // Clobbers: ECX.
1466 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if 1496 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if
1467 // type test is conclusive, otherwise fallthrough if a type test could not 1497 // type test is conclusive, otherwise fallthrough if a type test could not
1468 // be completed. 1498 // be completed.
1469 void CodeGenerator::GenerateInstantiatedTypeWithArgumentsTest( 1499 void CodeGenerator::GenerateInstantiatedTypeWithArgumentsTest(
1500 intptr_t node_id,
1501 intptr_t token_index,
1470 const AbstractType& type, 1502 const AbstractType& type,
1471 Label* is_instance_lbl, 1503 Label* is_instance_lbl,
1472 Label* is_not_instance_lbl) { 1504 Label* is_not_instance_lbl) {
1473 ASSERT(type.IsInstantiated()); 1505 ASSERT(type.IsInstantiated());
1474 const Class& type_class = Class::ZoneHandle(type.type_class()); 1506 const Class& type_class = Class::ZoneHandle(type.type_class());
1475 ASSERT(type_class.HasTypeArguments()); 1507 ASSERT(type_class.HasTypeArguments());
1476 // A Smi object cannot be the instance of a parameterized class. 1508 // A Smi object cannot be the instance of a parameterized class.
1477 // A class equality check is only applicable with a dst type of a 1509 // A class equality check is only applicable with a dst type of a
1478 // non-parameterized class or with a raw dst type of a parameterized class. 1510 // non-parameterized class or with a raw dst type of a parameterized class.
1479 __ testl(EAX, Immediate(kSmiTagMask)); 1511 __ testl(EAX, Immediate(kSmiTagMask));
1480 __ j(ZERO, is_not_instance_lbl); 1512 __ j(ZERO, is_not_instance_lbl);
1481 const AbstractTypeArguments& type_arguments = 1513 const AbstractTypeArguments& type_arguments =
1482 AbstractTypeArguments::Handle(type.arguments()); 1514 AbstractTypeArguments::Handle(type.arguments());
1483 const bool is_raw_type = type_arguments.IsNull() || 1515 const bool is_raw_type = type_arguments.IsNull() ||
1484 type_arguments.IsRaw(type_arguments.Length()); 1516 type_arguments.IsRaw(type_arguments.Length());
1485 if (is_raw_type) { 1517 if (is_raw_type) {
1486 // Dynamic type argument, check only classes. 1518 // Dynamic type argument, check only classes.
1487 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1519 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1488 if (type.IsListInterface()) { 1520 if (type.IsListInterface()) {
1489 // TODO(srdjan) also accept List<Object>. 1521 // TODO(srdjan) also accept List<Object>.
1490 __ CompareObject(ECX, *CoreClass("ObjectArray")); 1522 __ CompareObject(ECX, *CoreClass("ObjectArray"));
1491 __ j(EQUAL, is_instance_lbl); 1523 __ j(EQUAL, is_instance_lbl);
1492 __ CompareObject(ECX, *CoreClass("GrowableObjectArray")); 1524 __ CompareObject(ECX, *CoreClass("GrowableObjectArray"));
1493 __ j(EQUAL, is_instance_lbl); 1525 __ j(EQUAL, is_instance_lbl);
1494 } else if (!type_class.is_interface()) {
1495 __ CompareObject(ECX, type_class);
1496 __ j(EQUAL, is_instance_lbl);
1497 } 1526 }
1498 } else { 1527 GenerateClassTestCache(node_id, token_index, type_class,
1499 // TODO(srdjan): do type test on type arguments. 1528 is_instance_lbl, is_not_instance_lbl);
1500 } 1529 }
1530 // TODO(srdjan): do type test on type arguments.
1501 // Fall through if type test is not conclusive 1531 // Fall through if type test is not conclusive
1502 } 1532 }
1503 1533
1504 1534
1505 // EAX: instance to test. 1535 // EAX: instance to test.
1506 // Clobbers: EBX, ECX, EDX. 1536 // Clobbers: EBX, ECX, EDX.
1507 void CodeGenerator::GenerateInstantiatedTypeNoArgumentsTest( 1537 void CodeGenerator::GenerateInstantiatedTypeNoArgumentsTest(
1508 intptr_t node_id, 1538 intptr_t node_id,
1509 intptr_t token_index, 1539 intptr_t token_index,
1510 const AbstractType& type, 1540 const AbstractType& type,
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1647 // InstantiatedType. It is therefore necessary to check its class. 1677 // InstantiatedType. It is therefore necessary to check its class.
1648 __ movl(ECX, FieldAddress(EDX, Object::class_offset())); 1678 __ movl(ECX, FieldAddress(EDX, Object::class_offset()));
1649 __ CompareObject(ECX, Object::ZoneHandle(Object::type_class())); 1679 __ CompareObject(ECX, Object::ZoneHandle(Object::type_class()));
1650 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1680 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1651 1681
1652 __ movl(EDX, FieldAddress(EDX, Type::type_class_offset())); 1682 __ movl(EDX, FieldAddress(EDX, Type::type_class_offset()));
1653 __ movl(ECX, FieldAddress(EDX, Class::type_parameters_offset())); 1683 __ movl(ECX, FieldAddress(EDX, Class::type_parameters_offset()));
1654 // Check that class of type has no type parameters. 1684 // Check that class of type has no type parameters.
1655 __ cmpl(ECX, raw_null); 1685 __ cmpl(ECX, raw_null);
1656 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1686 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1687 // EAX has non-parameterized class.
1688 // Check class equality
1689 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1690 __ movl(ECX, FieldAddress(ECX, Type::Type::type_class_offset()));
1691 __ cmpl(ECX, EDX);
1692 __ j(EQUAL, is_instance_lbl);
1693
1657 // We have a non-parameterized class in EDX, compare with class of 1694 // We have a non-parameterized class in EDX, compare with class of
1658 // value in EAX. EAX, EDX are preserved in stub. 1695 // value in EAX. EAX, EDX are preserved in stub.
1696 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1659 __ call(&StubCode::IsRawSubTypeLabel()); 1697 __ call(&StubCode::IsRawSubTypeLabel());
1660 // Result in EBX: 1 is raw subtype. 1698 // Result in EBX: 1 is raw subtype.
1661 __ cmpl(EBX, Immediate(1)); 1699 __ cmpl(EBX, Immediate(1));
1662 __ j(EQUAL, is_instance_lbl); 1700 __ j(EQUAL, is_instance_lbl);
1663 1701
1664 // Test not conclusive. 1702 // Test not conclusive.
1665 __ Bind(&fall_through); 1703 __ Bind(&fall_through);
1666 } 1704 }
1667 } 1705 }
1668 1706
(...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after
2881 const Error& error = Error::Handle( 2919 const Error& error = Error::Handle(
2882 Parser::FormatError(script, token_index, "Error", format, args)); 2920 Parser::FormatError(script, token_index, "Error", format, args));
2883 va_end(args); 2921 va_end(args);
2884 Isolate::Current()->long_jump_base()->Jump(1, error); 2922 Isolate::Current()->long_jump_base()->Jump(1, error);
2885 UNREACHABLE(); 2923 UNREACHABLE();
2886 } 2924 }
2887 2925
2888 } // namespace dart 2926 } // namespace dart
2889 2927
2890 #endif // defined TARGET_ARCH_IA32 2928 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698