Chromium Code Reviews| 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 1493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |