Chromium Code Reviews| Index: runtime/vm/code_generator_ia32.cc |
| =================================================================== |
| --- runtime/vm/code_generator_ia32.cc (revision 6977) |
| +++ runtime/vm/code_generator_ia32.cc (working copy) |
| @@ -1511,7 +1511,7 @@ |
| __ testl(EAX, Immediate(kSmiTagMask)); |
| __ j(ZERO, is_not_instance_lbl); |
| const AbstractTypeArguments& type_arguments = |
| - AbstractTypeArguments::Handle(type.arguments()); |
| + AbstractTypeArguments::ZoneHandle(type.arguments()); |
| const bool is_raw_type = type_arguments.IsNull() || |
| type_arguments.IsRaw(type_arguments.Length()); |
| if (is_raw_type) { |
| @@ -1526,9 +1526,84 @@ |
| } |
| GenerateClassTestCache(node_id, token_index, type_class, |
| is_instance_lbl, is_not_instance_lbl); |
| + return; |
| } |
| - // TODO(srdjan): do type test on type arguments. |
| + // 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.
|
| + if (type_arguments.Length() != 1) { |
| + return; |
| + } |
| + 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
|
| + AbstractType::ZoneHandle(type_arguments.TypeAt(0)); |
| + 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.
|
| + return; |
| + } |
| + // Check if type argument is dynamic or Object. |
| + const Type& object_type = |
| + Type::Handle(Isolate::Current()->object_store()->object_type()); |
| + Error& malformed_error = Error::Handle(); |
| + if (object_type.IsSubtypeOf(type_at_0, &malformed_error)) { |
| + // Instance class test only necessary. |
| + 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
|
| + is_instance_lbl, is_not_instance_lbl); |
| + return; |
| + } |
| + |
| + // First step is to check instance class. |
| + Label check_type_argument, fall_through; |
| + 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.
|
| + &check_type_argument, is_not_instance_lbl); |
| + // Class test not conclusive (fall-through). |
| + __ jmp(&fall_through); |
| + __ Bind(&check_type_argument); |
| + // Get type argument of instance. |
| + const Class& type_at_0_class = Class::ZoneHandle(type_at_0.type_class()); |
| + __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| + __ movl(EDI, FieldAddress(ECX, |
| + type_at_0_class.type_arguments_instance_field_offset_offset())); |
| + // EDI: intptr_t offset of type arguments in instance. |
| + __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); |
| + __ 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
|
| + __ movl(EDI, FieldAddress(EAX, EDI, TIMES_1, 0)); |
| + // EDI: type arguments of the instance. |
| + // Is type argument dynamic? |
| + const Immediate raw_null = |
| + Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| + __ cmpl(EDI, raw_null); |
| + __ j(EQUAL, is_instance_lbl); |
| + // Type arguments may be canonicalized: are they equal? |
| + __ CompareObject(EDI, type_arguments); |
| + __ j(EQUAL, is_instance_lbl); |
|
regis
2012/04/26 00:36:17
Consider
class A<T> implements I<bool>
new A() is
|
| + |
| + // We can handle only type of class TypeArguments. |
| + __ movl(EDX, FieldAddress(EDI, Object::class_offset())); |
| + __ CompareObject(EDX, |
| + Object::ZoneHandle(Object::type_arguments_class())); |
| + __ j(NOT_EQUAL, &fall_through); |
| + // EDI: instance of class 'TypeArguments'. |
| + __ movl(EDX, FieldAddress(EDI, TypeArguments::length_offset())); |
| + // Handling only tests with one type argument. |
| + Immediate smi_one_imm = |
| + Immediate(reinterpret_cast<int32_t>(Smi::New(1))); |
| + __ cmpl(EDX, smi_one_imm); |
| + __ j(NOT_EQUAL, &fall_through); |
| + __ movl(ECX, FieldAddress(EDI, TypeArguments::type_at_offset(0))); |
| + __ CompareObject(ECX, type_at_0); |
| + __ j(EQUAL, is_instance_lbl); |
| + // If the type is not parameterized do the subclass check. |
| + if (!type_at_0_class.HasTypeArguments()) { |
| + __ LoadObject(EDX, type_at_0_class); |
| + __ movl(ECX, FieldAddress(ECX, Type::type_class_offset())); |
| + __ cmpl(ECX, EDX); |
| + __ j(EQUAL, is_instance_lbl); |
| + // A non-parameterized class is in EDX, compare with class in ECX |
| + // EAX, EDX are preserved in stub. |
| + __ call(&StubCode::IsRawSubTypeLabel()); |
| + // Result in EBX: 1 is raw subtype. |
| + __ cmpl(EBX, Immediate(1)); |
| + __ j(EQUAL, is_instance_lbl); |
| + } |
| // Fall through if type test is not conclusive |
| + __ Bind(&fall_through); |
| } |