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

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

Issue 10345003: Temporary fix for GrowableArray type arguments: use the type arguments stores in GrowableArray inst… (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/object.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 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 return &cls; 1285 return &cls;
1286 } 1286 }
1287 1287
1288 1288
1289 // Instance to test is in EAX. Test if its class is in subtype test cache array 1289 // Instance to test is in EAX. Test if its class is in subtype test cache array
1290 // and use the result in the array to jump to one of the labels. Fall through 1290 // and use the result in the array to jump to one of the labels. Fall through
1291 // if the instance is not in the cache array. 1291 // if the instance is not in the cache array.
1292 // TODO(srdjan): Implement a quicker subtype check, as type test 1292 // TODO(srdjan): Implement a quicker subtype check, as type test
1293 // arrays can grow too high, but they may be useful when optimizing 1293 // arrays can grow too high, but they may be useful when optimizing
1294 // code (type-feedback). 1294 // code (type-feedback).
1295 void CodeGenerator::GenerateSubtypeTestCacheLookup(intptr_t node_id, 1295 void CodeGenerator::GenerateSubtype1TestCacheLookup(
1296 intptr_t token_index, 1296 intptr_t node_id,
1297 const Class& type_class, 1297 intptr_t token_index,
1298 Label* is_instance_lbl, 1298 const Class& type_class,
1299 Label* is_not_instance_lbl) { 1299 Label* is_instance_lbl,
1300 Label* is_not_instance_lbl) {
1300 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1301 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1301 const Immediate raw_null = 1302 const Immediate raw_null =
1302 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1303 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1303 Label loop, found_in_cache, runtime_call; 1304 Label loop, found_in_cache, runtime_call;
1304 // Check immediate equality. 1305 // Check immediate equality.
1305 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1306 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1306 // ECX: instance class. 1307 // ECX: instance class.
1307 __ CompareObject(ECX, type_class); 1308 __ CompareObject(ECX, type_class);
1308 __ j(EQUAL, is_instance_lbl); 1309 __ j(EQUAL, is_instance_lbl);
1309 1310
1310 // Check immediate superclass equality. 1311 // Check immediate superclass equality.
1311 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset())); 1312 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset()));
1312 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset())); 1313 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset()));
1313 __ CompareObject(EDI, type_class); 1314 __ CompareObject(EDI, type_class);
1314 __ j(EQUAL, is_instance_lbl); 1315 __ j(EQUAL, is_instance_lbl);
1315 1316
1316 // ECX: instance class.
1317 // Insert subtype test cache into the code stream.
1318 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index); 1317 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index);
1319 __ LoadObject(EDX, Array::ZoneHandle( 1318 __ LoadObject(EDX, Array::ZoneHandle(
1320 Array::New(SubTypeTestCache::kNumEntries))); 1319 Array::New(SubTypeTestCache::kNumEntries)));
1321 // EDX: cache array. 1320 __ pushl(EDX); // Cache array.
1322 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag)); 1321 __ pushl(EAX); // Instance.
1323 __ Bind(&loop); 1322 __ pushl(raw_null); // Unused
1324 __ movl(EBX, Address(EDX, kWordSize * SubTypeTestCache::kInstanceClass)); 1323 __ call(&StubCode::Subtype1TestCacheLabel());
1325 __ cmpl(ECX, EBX); 1324 __ popl(EAX); // Discard.
1326 __ j(EQUAL, &found_in_cache, Assembler::kNearJump); 1325 __ popl(EAX); // Restore receiver.
1327 __ addl(EDX, Immediate(kWordSize * SubTypeTestCache::kNumEntries)); 1326 __ popl(EDX); // Discard.
1328 __ cmpl(EBX, raw_null); 1327 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False.
1329 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1330 __ jmp(&runtime_call, Assembler::kNearJump);
1331 1328
1332 __ Bind(&found_in_cache); 1329 __ cmpl(ECX, raw_null);
1333 __ movl(EDX, Address(EDX, kWordSize * SubTypeTestCache::kTestResult)); 1330 __ j(EQUAL, &runtime_call, Assembler::kNearJump);
1334 __ CompareObject(EDX, bool_true); 1331 __ CompareObject(ECX, bool_true);
1335 __ j(EQUAL, is_instance_lbl); 1332 __ j(EQUAL, is_instance_lbl);
1336 __ jmp(is_not_instance_lbl); 1333 __ jmp(is_not_instance_lbl);
1337 __ Bind(&runtime_call); 1334 __ Bind(&runtime_call);
1338 } 1335 }
1339 1336
1340 1337
1341 // Inline tests according to the 'type' being tested. Jump to labels 1338 // Inline tests according to the 'type' being tested. Jump to labels
1342 // if we can compute the type-test, otherwise fallthrough. 1339 // if we can compute the type-test, otherwise fallthrough.
1343 // EAX: instance to be tested, must be preserved. 1340 // EAX: instance to be tested, must be preserved.
1344 // Clobbers many registers. 1341 // Clobbers many registers.
(...skipping 15 matching lines...) Expand all
1360 is_not_instance_lbl); 1357 is_not_instance_lbl);
1361 // Fall through to runtime call. 1358 // Fall through to runtime call.
1362 } else { 1359 } else {
1363 GenerateInstantiatedTypeNoArgumentsTest(node_id, 1360 GenerateInstantiatedTypeNoArgumentsTest(node_id,
1364 token_index, 1361 token_index,
1365 type, 1362 type,
1366 is_instance_lbl, 1363 is_instance_lbl,
1367 is_not_instance_lbl); 1364 is_not_instance_lbl);
1368 // If test non-conclusive so far, try the inlined type-test cache. 1365 // If test non-conclusive so far, try the inlined type-test cache.
1369 // 'type' is known at compile time. 1366 // 'type' is known at compile time.
1370 GenerateSubtypeTestCacheLookup(node_id, token_index, type_class, 1367 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class,
1371 is_instance_lbl, is_not_instance_lbl); 1368 is_instance_lbl, is_not_instance_lbl);
1372 } 1369 }
1373 } else { 1370 } else {
1374 GenerateUninstantiatedTypeTest(type, 1371 GenerateUninstantiatedTypeTest(type,
1375 token_index, 1372 token_index,
1376 is_instance_lbl); 1373 is_instance_lbl);
1377 } 1374 }
1378 } 1375 }
1379 1376
1380 1377
1381 // If instanceof type test cannot be performed successfully at compile time and 1378 // If instanceof type test cannot be performed successfully at compile time and
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 if (is_raw_type) { 1516 if (is_raw_type) {
1520 // Dynamic type argument, check only classes. 1517 // Dynamic type argument, check only classes.
1521 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1518 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1522 if (type.IsListInterface()) { 1519 if (type.IsListInterface()) {
1523 // TODO(srdjan) also accept List<Object>. 1520 // TODO(srdjan) also accept List<Object>.
1524 __ CompareObject(ECX, *CoreClass("ObjectArray")); 1521 __ CompareObject(ECX, *CoreClass("ObjectArray"));
1525 __ j(EQUAL, is_instance_lbl); 1522 __ j(EQUAL, is_instance_lbl);
1526 __ CompareObject(ECX, *CoreClass("GrowableObjectArray")); 1523 __ CompareObject(ECX, *CoreClass("GrowableObjectArray"));
1527 __ j(EQUAL, is_instance_lbl); 1524 __ j(EQUAL, is_instance_lbl);
1528 } 1525 }
1529 GenerateSubtypeTestCacheLookup(node_id, token_index, type_class, 1526 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class,
1530 is_instance_lbl, is_not_instance_lbl); 1527 is_instance_lbl, is_not_instance_lbl);
1531 return; 1528 return;
1532 } 1529 }
1533 // Note that the test below must be synced with the tests in 1530 // Note that the test below must be synced with the tests in
1534 // CodeGenerator::UpdateTestCache. 1531 // CodeGenerator::UpdateTestCache.
1535 // Inline checks for one type argument only. 1532 // Inline checks for one type argument only.
1536 if (type_arguments.Length() != 1) { 1533 if (type_arguments.Length() != 1) {
1537 return; 1534 return;
1538 } 1535 }
1539 const AbstractType& tp_argument = 1536 const AbstractType& tp_argument =
1540 AbstractType::ZoneHandle(type_arguments.TypeAt(0)); 1537 AbstractType::ZoneHandle(type_arguments.TypeAt(0));
1541 if (!tp_argument.IsType()) { 1538 if (!tp_argument.IsType()) {
1542 // E.g., it is a TypeParameter. 1539 // E.g., it is a TypeParameter.
1543 return; 1540 return;
1544 } 1541 }
1545 // Malformed type has been caught in the caller chain of this function. 1542 // Malformed type has been caught in the caller chain of this function.
1546 ASSERT(tp_argument.HasResolvedTypeClass()); 1543 ASSERT(tp_argument.HasResolvedTypeClass());
1547 // Check if type argument is dynamic or Object. 1544 // Check if type argument is dynamic or Object.
1548 const Type& object_type = 1545 const Type& object_type =
1549 Type::Handle(Isolate::Current()->object_store()->object_type()); 1546 Type::Handle(Isolate::Current()->object_store()->object_type());
1550 Error& malformed_error = Error::Handle(); 1547 Error& malformed_error = Error::Handle();
1551 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) { 1548 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) {
1552 // Instance class test only necessary. 1549 // Instance class test only necessary.
1553 GenerateSubtypeTestCacheLookup(node_id, token_index, type_class, 1550 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class,
1554 is_instance_lbl, is_not_instance_lbl); 1551 is_instance_lbl, is_not_instance_lbl);
1555 return; 1552 return;
1556 } 1553 }
1557 Label inlined_check, fall_through; 1554 Label inlined_check, fall_through;
1558 const Immediate raw_null = 1555 const Immediate raw_null =
1559 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1556 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1560 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index); 1557 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index);
1561 __ LoadObject(EDX, Array::ZoneHandle( 1558 __ LoadObject(EDX, Array::ZoneHandle(
1562 Array::New(SubTypeTestCache::kNumEntries))); 1559 Array::New(SubTypeTestCache::kNumEntries)));
1563 __ pushl(EDX); // Cache array. 1560 __ pushl(EDX); // Cache array.
1564 __ pushl(EAX); // Instance. 1561 __ pushl(EAX); // Instance.
1565 __ pushl(raw_null); // Instantiator type arguments, no instantiator -> null. 1562 __ pushl(raw_null); // Unused.
1566 __ call(&StubCode::SubtypeTestCacheLabel()); 1563 __ call(&StubCode::Subtype2TestCacheLabel());
1567 __ popl(EDX); // Discard. 1564 __ popl(EAX); // Discard.
1568 __ popl(EAX); // Restore receiver. 1565 __ popl(EAX); // Restore receiver.
1569 __ popl(EDX); // Discard. 1566 __ popl(EDX); // Discard.
1570 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. 1567 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False.
1571 1568
1572 __ cmpl(ECX, raw_null); 1569 __ cmpl(ECX, raw_null);
1573 __ j(EQUAL, &fall_through, Assembler::kNearJump); 1570 __ j(EQUAL, &fall_through, Assembler::kNearJump);
1574 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1571 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1575 __ CompareObject(ECX, bool_true); 1572 __ CompareObject(ECX, bool_true);
1576 __ j(EQUAL, is_instance_lbl); 1573 __ j(EQUAL, is_instance_lbl);
1577 __ jmp(is_not_instance_lbl); 1574 __ jmp(is_not_instance_lbl);
(...skipping 1417 matching lines...) Expand 10 before | Expand all | Expand 10 after
2995 const Error& error = Error::Handle( 2992 const Error& error = Error::Handle(
2996 Parser::FormatError(script, token_index, "Error", format, args)); 2993 Parser::FormatError(script, token_index, "Error", format, args));
2997 va_end(args); 2994 va_end(args);
2998 Isolate::Current()->long_jump_base()->Jump(1, error); 2995 Isolate::Current()->long_jump_base()->Jump(1, error);
2999 UNREACHABLE(); 2996 UNREACHABLE();
3000 } 2997 }
3001 2998
3002 } // namespace dart 2999 } // namespace dart
3003 3000
3004 #endif // defined TARGET_ARCH_IA32 3001 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698