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

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

Issue 10134069: Inline type check where type argument that we check against is instantiated. (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
« runtime/vm/code_generator.cc ('K') | « runtime/vm/code_generator.cc ('k') | no next file » | 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 1493 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 Label* is_not_instance_lbl) { 1504 Label* is_not_instance_lbl) {
1505 ASSERT(type.IsInstantiated()); 1505 ASSERT(type.IsInstantiated());
1506 const Class& type_class = Class::ZoneHandle(type.type_class()); 1506 const Class& type_class = Class::ZoneHandle(type.type_class());
1507 ASSERT(type_class.HasTypeArguments()); 1507 ASSERT(type_class.HasTypeArguments());
1508 // A Smi object cannot be the instance of a parameterized class. 1508 // A Smi object cannot be the instance of a parameterized class.
1509 // 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
1510 // 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.
1511 __ testl(EAX, Immediate(kSmiTagMask)); 1511 __ testl(EAX, Immediate(kSmiTagMask));
1512 __ j(ZERO, is_not_instance_lbl); 1512 __ j(ZERO, is_not_instance_lbl);
1513 const AbstractTypeArguments& type_arguments = 1513 const AbstractTypeArguments& type_arguments =
1514 AbstractTypeArguments::Handle(type.arguments()); 1514 AbstractTypeArguments::ZoneHandle(type.arguments());
1515 const bool is_raw_type = type_arguments.IsNull() || 1515 const bool is_raw_type = type_arguments.IsNull() ||
1516 type_arguments.IsRaw(type_arguments.Length()); 1516 type_arguments.IsRaw(type_arguments.Length());
1517 if (is_raw_type) { 1517 if (is_raw_type) {
1518 // Dynamic type argument, check only classes. 1518 // Dynamic type argument, check only classes.
1519 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1519 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1520 if (type.IsListInterface()) { 1520 if (type.IsListInterface()) {
1521 // TODO(srdjan) also accept List<Object>. 1521 // TODO(srdjan) also accept List<Object>.
1522 __ CompareObject(ECX, *CoreClass("ObjectArray")); 1522 __ CompareObject(ECX, *CoreClass("ObjectArray"));
1523 __ j(EQUAL, is_instance_lbl); 1523 __ j(EQUAL, is_instance_lbl);
1524 __ CompareObject(ECX, *CoreClass("GrowableObjectArray")); 1524 __ CompareObject(ECX, *CoreClass("GrowableObjectArray"));
1525 __ j(EQUAL, is_instance_lbl); 1525 __ j(EQUAL, is_instance_lbl);
1526 } 1526 }
1527 GenerateClassTestCache(node_id, token_index, type_class, 1527 GenerateClassTestCache(node_id, token_index, type_class,
1528 is_instance_lbl, is_not_instance_lbl); 1528 is_instance_lbl, is_not_instance_lbl);
1529 return;
1529 } 1530 }
1530 // TODO(srdjan): do type test on type arguments. 1531 // Inline checks for one type-argument only.
regis 2012/04/26 00:36:17 one type argument
srdjan 2012/04/26 18:08:37 Done.
1532 if (type_arguments.Length() != 1) {
1533 return;
1534 }
1535 const AbstractType& type_at_0 =
regis 2012/04/26 00:36:17 type_argument instead of type_at_0?
srdjan 2012/04/26 18:08:37 As discussed: type_argument sounds too close to ty
1536 AbstractType::ZoneHandle(type_arguments.TypeAt(0));
1537 if (!type_at_0.IsType() || !type_at_0.HasResolvedTypeClass()) {
regis 2012/04/26 00:36:17 We already checked for type.IsMalformed() in the c
srdjan 2012/04/26 18:08:37 Changing to assert.
1538 return;
1539 }
1540 // Check if type argument is dynamic or Object.
1541 const Type& object_type =
1542 Type::Handle(Isolate::Current()->object_store()->object_type());
1543 Error& malformed_error = Error::Handle();
1544 if (object_type.IsSubtypeOf(type_at_0, &malformed_error)) {
1545 // Instance class test only necessary.
1546 GenerateClassTestCache(node_id, token_index, type_class,
regis 2012/04/26 00:36:17 I do not understand this shortcut. Wouldn't this i
srdjan 2012/04/26 18:08:37 Made simpler comment to GenerateClassTestCache. Th
1547 is_instance_lbl, is_not_instance_lbl);
1548 return;
1549 }
1550
1551 // First step is to check instance class.
1552 Label check_type_argument, fall_through;
1553 GenerateClassTestCache(node_id, token_index, type_class,
regis 2012/04/26 00:36:17 The same argument applies here. Consider class A<T
srdjan 2012/04/26 18:08:37 Discussed and answered offline, I guess.
1554 &check_type_argument, is_not_instance_lbl);
1555 // Class test not conclusive (fall-through).
1556 __ jmp(&fall_through);
1557 __ Bind(&check_type_argument);
1558 // Get type argument of instance.
1559 const Class& type_at_0_class = Class::ZoneHandle(type_at_0.type_class());
1560 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1561 __ movl(EDI, FieldAddress(ECX,
1562 type_at_0_class.type_arguments_instance_field_offset_offset()));
1563 // EDI: intptr_t offset of type arguments in instance.
1564 __ cmpl(EDI, Immediate(Class::kNoTypeArguments));
1565 __ j(EQUAL, is_instance_lbl);
regis 2012/04/26 00:36:17 I do not understand this either. Consider class A
srdjan 2012/04/26 18:08:37 You are right. Nifty example, and there is no test
1566 __ movl(EDI, FieldAddress(EAX, EDI, TIMES_1, 0));
1567 // EDI: type arguments of the instance.
1568 // Is type argument dynamic?
1569 const Immediate raw_null =
1570 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1571 __ cmpl(EDI, raw_null);
1572 __ j(EQUAL, is_instance_lbl);
1573 // Type arguments may be canonicalized: are they equal?
1574 __ CompareObject(EDI, type_arguments);
1575 __ j(EQUAL, is_instance_lbl);
regis 2012/04/26 00:36:17 Consider class A<T> implements I<bool> new A() is
1576
1577 // We can handle only type of class TypeArguments.
1578 __ movl(EDX, FieldAddress(EDI, Object::class_offset()));
1579 __ CompareObject(EDX,
1580 Object::ZoneHandle(Object::type_arguments_class()));
1581 __ j(NOT_EQUAL, &fall_through);
1582 // EDI: instance of class 'TypeArguments'.
1583 __ movl(EDX, FieldAddress(EDI, TypeArguments::length_offset()));
1584 // Handling only tests with one type argument.
1585 Immediate smi_one_imm =
1586 Immediate(reinterpret_cast<int32_t>(Smi::New(1)));
1587 __ cmpl(EDX, smi_one_imm);
1588 __ j(NOT_EQUAL, &fall_through);
1589 __ movl(ECX, FieldAddress(EDI, TypeArguments::type_at_offset(0)));
1590 __ CompareObject(ECX, type_at_0);
1591 __ j(EQUAL, is_instance_lbl);
1592 // If the type is not parameterized do the subclass check.
1593 if (!type_at_0_class.HasTypeArguments()) {
1594 __ LoadObject(EDX, type_at_0_class);
1595 __ movl(ECX, FieldAddress(ECX, Type::type_class_offset()));
1596 __ cmpl(ECX, EDX);
1597 __ j(EQUAL, is_instance_lbl);
1598 // A non-parameterized class is in EDX, compare with class in ECX
1599 // EAX, EDX are preserved in stub.
1600 __ call(&StubCode::IsRawSubTypeLabel());
1601 // Result in EBX: 1 is raw subtype.
1602 __ cmpl(EBX, Immediate(1));
1603 __ j(EQUAL, is_instance_lbl);
1604 }
1531 // Fall through if type test is not conclusive 1605 // Fall through if type test is not conclusive
1606 __ Bind(&fall_through);
1532 } 1607 }
1533 1608
1534 1609
1535 // EAX: instance to test. 1610 // EAX: instance to test.
1536 // Clobbers: EBX, ECX, EDX. 1611 // Clobbers: EBX, ECX, EDX.
1537 void CodeGenerator::GenerateInstantiatedTypeNoArgumentsTest( 1612 void CodeGenerator::GenerateInstantiatedTypeNoArgumentsTest(
1538 intptr_t node_id, 1613 intptr_t node_id,
1539 intptr_t token_index, 1614 intptr_t token_index,
1540 const AbstractType& type, 1615 const AbstractType& type,
1541 Label* is_instance_lbl, 1616 Label* is_instance_lbl,
(...skipping 1377 matching lines...) Expand 10 before | Expand all | Expand 10 after
2919 const Error& error = Error::Handle( 2994 const Error& error = Error::Handle(
2920 Parser::FormatError(script, token_index, "Error", format, args)); 2995 Parser::FormatError(script, token_index, "Error", format, args));
2921 va_end(args); 2996 va_end(args);
2922 Isolate::Current()->long_jump_base()->Jump(1, error); 2997 Isolate::Current()->long_jump_base()->Jump(1, error);
2923 UNREACHABLE(); 2998 UNREACHABLE();
2924 } 2999 }
2925 3000
2926 } // namespace dart 3001 } // namespace dart
2927 3002
2928 #endif // defined TARGET_ARCH_IA32 3003 #endif // defined TARGET_ARCH_IA32
OLDNEW
« runtime/vm/code_generator.cc ('K') | « runtime/vm/code_generator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698