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 10243013: Simpler and better inlined type checks as discussed. Changed inline type test cache arrays to conta… (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
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 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1306 __ CompareObject(ECX, type_class); 1306 __ CompareObject(ECX, type_class);
1307 __ j(EQUAL, is_instance_lbl); 1307 __ j(EQUAL, is_instance_lbl);
1308 1308
1309 // Check immediate superclass equality. 1309 // Check immediate superclass equality.
1310 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset())); 1310 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset()));
1311 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset())); 1311 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset()));
1312 __ CompareObject(EDI, type_class); 1312 __ CompareObject(EDI, type_class);
1313 __ j(EQUAL, is_instance_lbl); 1313 __ j(EQUAL, is_instance_lbl);
1314 1314
1315 // ECX: instance class. 1315 // ECX: instance class.
1316 // Insert subtype test cache into the code stream.
1316 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index); 1317 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index);
1317 __ LoadObject(EDX, Array::ZoneHandle(Array::New(2))); 1318 __ LoadObject(EDX, Array::ZoneHandle(
1319 Array::New(SubTypeTestCache::kNumEntries)));
1320 // EDX: cache array.
1318 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag)); 1321 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag));
1319 __ Bind(&loop); 1322 __ Bind(&loop);
1320 __ movl(EBX, Address(EDX, 0)); 1323 __ movl(EBX, Address(EDX, kWordSize * SubTypeTestCache::kInstanceClass));
1321 __ cmpl(ECX, EBX); 1324 __ cmpl(ECX, EBX);
1322 __ j(EQUAL, &found_in_cache, Assembler::kNearJump); 1325 __ j(EQUAL, &found_in_cache, Assembler::kNearJump);
1323 __ addl(EDX, Immediate(kWordSize * 2)); 1326 __ addl(EDX, Immediate(kWordSize * SubTypeTestCache::kNumEntries));
1324 __ cmpl(EBX, raw_null); 1327 __ cmpl(EBX, raw_null);
1325 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1328 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1326 __ jmp(&runtime_call, Assembler::kNearJump); 1329 __ jmp(&runtime_call, Assembler::kNearJump);
1327 1330
1328 __ Bind(&found_in_cache); 1331 __ Bind(&found_in_cache);
1329 __ movl(EDX, Address(EDX, kWordSize)); 1332 __ movl(EDX, Address(EDX, kWordSize * SubTypeTestCache::kTestResult));
1330 __ CompareObject(EDX, bool_true); 1333 __ CompareObject(EDX, bool_true);
1331 __ j(EQUAL, is_instance_lbl); 1334 __ j(EQUAL, is_instance_lbl);
1332 __ jmp(is_not_instance_lbl); 1335 __ jmp(is_not_instance_lbl);
1333 __ Bind(&runtime_call); 1336 __ Bind(&runtime_call);
1334 } 1337 }
1335 1338
1336 1339
1337 // Inline tests according to the 'type' being tested. Jump to labels 1340 // Inline tests according to the 'type' being tested. Jump to labels
1338 // if we can compute the type-test, otherwise fallthrough. 1341 // if we can compute the type-test, otherwise fallthrough.
1339 // EAX: instance to be tested. 1342 // EAX: instance to be tested, must be preserved.
1340 // Clobbers many registers. 1343 // Clobbers many registers.
1341 void CodeGenerator::GenerateInlineInstanceof(intptr_t node_id, 1344 void CodeGenerator::GenerateInlineInstanceof(intptr_t node_id,
1342 intptr_t token_index, 1345 intptr_t token_index,
1343 const AbstractType& type, 1346 const AbstractType& type,
1344 Label* is_instance_lbl, 1347 Label* is_instance_lbl,
1345 Label* is_not_instance_lbl) { 1348 Label* is_not_instance_lbl) {
1346 if (type.IsInstantiated()) { 1349 if (type.IsInstantiated()) {
1347 const Class& type_class = Class::ZoneHandle(type.type_class()); 1350 const Class& type_class = Class::ZoneHandle(type.type_class());
1348 // A Smi object cannot be the instance of a parameterized class. 1351 // A Smi object cannot be the instance of a parameterized class.
1349 // A class equality check is only applicable with a dst type of a 1352 // A class equality check is only applicable with a dst type of a
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1545 // Check if type argument is dynamic or Object. 1548 // Check if type argument is dynamic or Object.
1546 const Type& object_type = 1549 const Type& object_type =
1547 Type::Handle(Isolate::Current()->object_store()->object_type()); 1550 Type::Handle(Isolate::Current()->object_store()->object_type());
1548 Error& malformed_error = Error::Handle(); 1551 Error& malformed_error = Error::Handle();
1549 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) { 1552 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) {
1550 // Instance class test only necessary. 1553 // Instance class test only necessary.
1551 GenerateSubtypeTestCacheLookup(node_id, token_index, type_class, 1554 GenerateSubtypeTestCacheLookup(node_id, token_index, type_class,
1552 is_instance_lbl, is_not_instance_lbl); 1555 is_instance_lbl, is_not_instance_lbl);
1553 return; 1556 return;
1554 } 1557 }
1555 // Efficient type argument check can be done only on known classes.
1556 const Type& list_type =
1557 Type::Handle(Isolate::Current()->object_store()->list_interface());
1558 Label inlined_check, fall_through; 1558 Label inlined_check, fall_through;
1559 if (!list_type.IsSubtypeOf(type, &malformed_error)) {
1560 // Since we support only known subtypes of List, no need to emit code
1561 // otherwise.
1562 return;
1563 }
1564 // TODO(srdjan): Recognize somehow classes that are 'regular' i.e., which
1565 // type-parameters are simple structure.
1566 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1567 __ CompareObject(ECX, *CoreClass("ObjectArray"));
1568 __ j(EQUAL, &inlined_check);
1569 __ CompareObject(ECX, *CoreClass("GrowableObjectArray"));
1570 __ j(NOT_EQUAL, &fall_through);
1571 __ Bind(&inlined_check);
1572
1573 // First step is to check instance class.
1574 Label check_type_argument;
1575 GenerateSubtypeTestCacheLookup(node_id, token_index, type_class,
1576 &check_type_argument, is_not_instance_lbl);
1577 // Class test not conclusive (fall-through).
1578 __ jmp(&fall_through);
1579 __ Bind(&check_type_argument);
1580 // Get type argument of instance.
1581 const Class& tp_argument_class = Class::ZoneHandle(tp_argument.type_class());
1582 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1583 __ movl(EDI, FieldAddress(ECX,
1584 tp_argument_class.type_arguments_instance_field_offset_offset()));
1585 // EDI: intptr_t offset of type arguments in instance.
1586 __ cmpl(EDI, Immediate(Class::kNoTypeArguments));
1587 __ j(EQUAL, is_instance_lbl);
1588 __ movl(EDI, FieldAddress(EAX, EDI, TIMES_1, 0));
1589 // EDI: type arguments of the instance.
1590 // Is type argument dynamic?
1591 const Immediate raw_null = 1559 const Immediate raw_null =
1592 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1560 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1593 __ cmpl(EDI, raw_null); 1561 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index);
1562 __ LoadObject(EDX, Array::ZoneHandle(
1563 Array::New(SubTypeTestCache::kNumEntries)));
1564 __ pushl(EDX); // Cache array.
1565 __ pushl(EAX); // Instance.
1566 __ pushl(raw_null); // Instantiator type arguments, no instantiator -> null.
1567 __ call(&StubCode::SubtypeTestCacheLabel());
1568 __ popl(EDX); // Discard.
1569 __ popl(EAX); // Restore receiver.
1570 __ popl(EDX); // Discard.
1571 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False.
1572
1573 __ cmpl(ECX, raw_null);
1574 __ j(EQUAL, &fall_through, Assembler::kNearJump);
1575 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1576 __ CompareObject(ECX, bool_true);
1594 __ j(EQUAL, is_instance_lbl); 1577 __ j(EQUAL, is_instance_lbl);
1595 // Type arguments may be canonicalized: are they equal? 1578 __ jmp(is_not_instance_lbl);
1596 __ CompareObject(EDI, type_arguments);
1597 __ j(EQUAL, is_instance_lbl);
1598
1599 // We can handle only type of class TypeArguments.
1600 __ movl(EDX, FieldAddress(EDI, Object::class_offset()));
1601 __ CompareObject(EDX,
1602 Object::ZoneHandle(Object::type_arguments_class()));
1603 __ j(NOT_EQUAL, &fall_through);
1604 // EDI: instance of class 'TypeArguments'.
1605 __ movl(EDX, FieldAddress(EDI, TypeArguments::length_offset()));
1606 // Handling only tests with one type argument.
1607 Immediate smi_one_imm =
1608 Immediate(reinterpret_cast<int32_t>(Smi::New(1)));
1609 __ cmpl(EDX, smi_one_imm);
1610 __ j(NOT_EQUAL, &fall_through);
1611 __ movl(ECX, FieldAddress(EDI, TypeArguments::type_at_offset(0)));
1612 __ CompareObject(ECX, tp_argument);
1613 __ j(EQUAL, is_instance_lbl);
1614 // If the type is not parameterized do the subclass check.
1615 if (!tp_argument_class.HasTypeArguments()) {
1616 __ LoadObject(EDX, tp_argument_class);
1617 __ movl(ECX, FieldAddress(ECX, Type::type_class_offset()));
1618 __ cmpl(ECX, EDX);
1619 __ j(EQUAL, is_instance_lbl);
1620 // A non-parameterized class is in EDX, compare with class in ECX
1621 // EAX, EDX are preserved in stub.
1622 __ call(&StubCode::IsRawSubTypeLabel());
1623 // Result in EBX: 1 is raw subtype.
1624 __ cmpl(EBX, Immediate(1));
1625 __ j(EQUAL, is_instance_lbl);
1626 }
1627 // Fall through if type test is not conclusive.
1628 __ Bind(&fall_through); 1579 __ Bind(&fall_through);
1629 } 1580 }
1630 1581
1631 1582
1632 // EAX: instance to test. 1583 // EAX: instance to test.
1633 // Clobbers: EBX, ECX, EDX. 1584 // Clobbers: EBX, ECX, EDX.
1634 void CodeGenerator::GenerateInstantiatedTypeNoArgumentsTest( 1585 void CodeGenerator::GenerateInstantiatedTypeNoArgumentsTest(
1635 intptr_t node_id, 1586 intptr_t node_id,
1636 intptr_t token_index, 1587 intptr_t token_index,
1637 const AbstractType& type, 1588 const AbstractType& type,
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after
3016 const Error& error = Error::Handle( 2967 const Error& error = Error::Handle(
3017 Parser::FormatError(script, token_index, "Error", format, args)); 2968 Parser::FormatError(script, token_index, "Error", format, args));
3018 va_end(args); 2969 va_end(args);
3019 Isolate::Current()->long_jump_base()->Jump(1, error); 2970 Isolate::Current()->long_jump_base()->Jump(1, error);
3020 UNREACHABLE(); 2971 UNREACHABLE();
3021 } 2972 }
3022 2973
3023 } // namespace dart 2974 } // namespace dart
3024 2975
3025 #endif // defined TARGET_ARCH_IA32 2976 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698