Chromium Code Reviews| Index: runtime/vm/code_generator_ia32.cc |
| =================================================================== |
| --- runtime/vm/code_generator_ia32.cc (revision 7346) |
| +++ runtime/vm/code_generator_ia32.cc (working copy) |
| @@ -794,7 +794,7 @@ |
| const bool requires_type_arguments = cls.HasTypeArguments(); |
| if (requires_type_arguments) { |
| ASSERT(!function.IsImplicitStaticClosureFunction()); |
| - GenerateInstantiatorTypeArguments(node->token_index()); |
| + GenerateInstantiatorTypeArguments(node->token_index(), false); |
|
regis
2012/05/04 21:53:39
Document what false means.
srdjan
2012/05/04 23:01:58
Done.
|
| } |
| const Code& stub = Code::Handle( |
| StubCode::GetAllocationStubForClosure(function)); |
| @@ -1278,9 +1278,11 @@ |
| is_instance_lbl, is_not_instance_lbl); |
| } |
| } else { |
| - GenerateUninstantiatedTypeTest(type, |
| - token_index, |
| - is_instance_lbl); |
| + return GenerateUninstantiatedTypeTest(type, |
| + node_id, |
| + token_index, |
| + is_instance_lbl, |
| + is_not_instance_lbl); |
| } |
| return SubtypeTestCache::null(); |
| } |
| @@ -1374,17 +1376,18 @@ |
| __ pushl(node_id_as_smi); // node-id. |
| __ pushl(EAX); // Push the instance. |
| __ PushObject(type); // Push the type. |
| - if (!type.IsInstantiated()) { |
| - GenerateInstantiatorTypeArguments(token_index); |
| + if (type.IsInstantiated()) { |
| + __ pushl(raw_null); // Null instantiator. |
| + __ pushl(raw_null); // Null instantiator. |
| } else { |
| - __ pushl(raw_null); // Null instantiator. |
| + GenerateInstantiatorTypeArguments(token_index, true); |
|
regis
2012/05/04 21:53:39
Document what true means.
srdjan
2012/05/04 23:01:58
Done.
|
| } |
| __ LoadObject(EAX, test_cache); |
| __ pushl(EAX); |
| GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); |
| // Pop the two parameters supplied to the runtime entry. The result of the |
| // instanceof runtime call will be left as the result of the operation. |
| - __ addl(ESP, Immediate(6 * kWordSize)); |
| + __ addl(ESP, Immediate(7 * kWordSize)); |
| if (negate_result) { |
| __ popl(EDX); |
| __ CompareObject(EDX, bool_false); |
| @@ -1469,7 +1472,7 @@ |
| const Immediate raw_null = |
| Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| __ LoadObject(EDX, type_test_cache); |
| - __ pushl(EDX); // Cache array. |
| + __ pushl(EDX); // Subtype test cache. |
| __ pushl(EAX); // Instance. |
| __ pushl(raw_null); // Unused. |
| __ call(&StubCode::Subtype2TestCacheLabel()); |
| @@ -1587,18 +1590,20 @@ |
| // EAX: instance to test. |
| // Clobbers: EBX, EDX, ECX. |
| -void CodeGenerator::GenerateUninstantiatedTypeTest( |
| +RawSubtypeTestCache* CodeGenerator::GenerateUninstantiatedTypeTest( |
| const AbstractType& type, |
| + intptr_t node_id, |
| intptr_t token_index, |
| - Label* is_instance_lbl) { |
| + Label* is_instance_lbl, |
| + Label* is_not_instance_lbl) { |
| ASSERT(!type.IsInstantiated()); |
| // Skip check if destination is a dynamic type. |
| + const Immediate raw_null = |
| + Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| if (type.IsTypeParameter()) { |
| - const Immediate raw_null = |
| - Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| // EAX must be preserved! |
| Label fall_through; |
| - GenerateInstantiatorTypeArguments(token_index); |
| + GenerateInstantiatorTypeArguments(token_index, false); |
|
regis
2012/05/04 21:53:39
ditto
srdjan
2012/05/04 23:01:58
Done.
|
| // Type arguments are on stack. |
| __ popl(EBX); |
| // Check if type argument is dynamic. |
| @@ -1658,7 +1663,35 @@ |
| // Test not conclusive. |
| __ Bind(&fall_through); |
| + return SubtypeTestCache::null(); |
| } |
| + if (type.IsType()) { |
| + Label fall_through; |
| + __ testl(EAX, Immediate(kSmiTagMask)); // Is instance Smi? |
| + __ j(ZERO, is_not_instance_lbl, Assembler::kNearJump); |
| + // Uninstantiated type class is known at compile time, but the type |
| + // arguments are determined at runtime by the instantiator. |
| + const SubtypeTestCache& type_test_cache = |
| + SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| + __ LoadObject(EDX, type_test_cache); |
| + __ pushl(EDX); // Subtype test cache. |
| + __ pushl(EAX); // Instance. |
| + GenerateInstantiatorTypeArguments(token_index, false); // type arguments. |
|
regis
2012/05/04 21:53:39
ditto
srdjan
2012/05/04 23:01:58
Done.
|
| + __ call(&StubCode::Subtype3TestCacheLabel()); |
| + __ popl(EDX); // Discard type arguments. |
| + __ popl(EAX); // Restore receiver. |
| + __ popl(EDX); // Discard subtype test cache. |
| + // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False. |
| + __ cmpl(ECX, raw_null); |
| + __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| + const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| + __ CompareObject(ECX, bool_true); |
| + __ j(EQUAL, is_instance_lbl); |
| + __ jmp(is_not_instance_lbl); |
| + __ Bind(&fall_through); |
| + return type_test_cache.raw(); |
| + } |
| + return SubtypeTestCache::null(); |
| } |
| @@ -1757,8 +1790,9 @@ |
| __ PushObject(dst_type); // Push the type of the destination. |
| if (dst_type.IsInstantiated()) { |
| __ pushl(raw_null); // Null instantiator. |
| + __ pushl(raw_null); // Null instantiator type argument. |
| } else { |
| - GenerateInstantiatorTypeArguments(token_index); |
| + GenerateInstantiatorTypeArguments(token_index, true); |
|
regis
2012/05/04 21:53:39
ditto
srdjan
2012/05/04 23:01:58
Done.
|
| } |
| __ PushObject(dst_name); // Push the name of the destination. |
| __ LoadObject(EAX, test_cache); |
| @@ -1766,7 +1800,7 @@ |
| GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry); |
| // Pop the parameters supplied to the runtime entry. The result of the |
| // type check runtime call is the checked value. |
| - __ addl(ESP, Immediate(7 * kWordSize)); |
| + __ addl(ESP, Immediate(8 * kWordSize)); |
| __ popl(EAX); |
| // EAX: value. |
| @@ -2363,7 +2397,13 @@ |
| // Pushes the type arguments of the instantiator on the stack. |
| // Destroys EBX. |
| -void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { |
| +void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index, |
| + bool push_instantiator) { |
| + if (push_instantiator) { |
| + const Immediate raw_null = |
| + Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| + __ pushl(raw_null); // Initial instantiator. |
| + } |
| const Class& instantiator_class = Class::Handle( |
| parsed_function().function().owner()); |
| if (instantiator_class.NumTypeParameters() == 0) { |
| @@ -2385,7 +2425,14 @@ |
| outer_function = outer_function.parent_function(); |
| } |
| if (!outer_function.IsFactory()) { |
| - __ popl(EBX); // Pop instantiator. |
| + if (push_instantiator) { |
| + __ popl(EBX); // Pop instantiator. |
| + __ popl(ECX); // Discard null instantiator. |
| + __ pushl(EBX); // Replace it with the real one. |
| + } else { |
| + __ popl(EBX); // Pop instantiator. |
| + } |
| + // EBX: instantiator. |
| // The instantiator is the receiver of the caller, which is not a factory. |
| // The receiver cannot be null; extract its AbstractTypeArguments object. |
| // Note that in the factory case, the instantiator is the first parameter |
| @@ -2424,7 +2471,7 @@ |
| } |
| } else { |
| // The type arguments are uninstantiated. |
| - GenerateInstantiatorTypeArguments(token_index); |
| + GenerateInstantiatorTypeArguments(token_index, false); |
|
regis
2012/05/04 21:53:39
Document false
srdjan
2012/05/04 23:01:58
Done.
|
| __ popl(EAX); // Pop instantiator. |
| // EAX is the instantiator AbstractTypeArguments object (or null). |
| // If the instantiator is null and if the type argument vector |