Chromium Code Reviews| Index: runtime/vm/flow_graph_builder.cc |
| =================================================================== |
| --- runtime/vm/flow_graph_builder.cc (revision 25661) |
| +++ runtime/vm/flow_graph_builder.cc (working copy) |
| @@ -1840,8 +1840,9 @@ |
| char name[64]; |
| OS::SNPrint(name, 64, ":tmp_local%"Pd, index); |
| LocalVariable* var = |
| - new LocalVariable(0, String::ZoneHandle(Symbols::New(name)), |
| - Type::ZoneHandle(Type::DynamicType())); |
| + new LocalVariable(0, |
| + String::ZoneHandle(Symbols::New(name)), |
| + *value->Type()->ToAbstractType()); |
| var->set_index(index); |
| return var; |
| } |
| @@ -1978,7 +1979,6 @@ |
| ReturnDefinition(new ConstantInstr(closure)); |
| return; |
| } |
| - Value* receiver = NULL; |
| if (function.IsNonImplicitClosureFunction()) { |
| // The context scope may have already been set by the non-optimizing |
| // compiler. If it was not, set it here. |
| @@ -1990,40 +1990,109 @@ |
| ASSERT(function.context_scope() == ContextScope::null()); |
| function.set_context_scope(context_scope); |
| } |
| - receiver = BuildNullValue(); |
| + ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| + new ZoneGrowableArray<PushArgumentInstr*>(2); |
| + ASSERT(function.context_scope() != ContextScope::null()); |
| + |
| + // The function type of a closure may have type arguments. In that case, |
| + // pass the type arguments of the instantiator. |
| + const Class& cls = Class::ZoneHandle(function.signature_class()); |
| + ASSERT(!cls.IsNull()); |
| + const bool requires_type_arguments = cls.HasTypeArguments(); |
| + Value* type_arguments = NULL; |
| + if (requires_type_arguments) { |
| + ASSERT(cls.type_arguments_field_offset() == |
| + Closure::type_arguments_offset()); |
| + const Class& instantiator_class = Class::Handle( |
| + owner()->parsed_function()->function().Owner()); |
| + type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), |
| + instantiator_class, |
| + NULL); |
| + arguments->Add(PushArgument(type_arguments)); |
| + |
| + Value* instantiator_val = Bind(new ConstantInstr( |
| + Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator)))); |
| + arguments->Add(PushArgument(instantiator_val)); |
| + } |
| + AllocateObjectInstr* alloc = new AllocateObjectInstr(node->token_pos(), |
| + cls, |
| + arguments); |
| + alloc->set_closure_function(function); |
| + |
| + // Create fake fields for function and context. Only the context field is |
| + // stored at the allocation to be used later when inlining a closure call. |
| + const Field& function_field = |
| + Field::ZoneHandle(Field::New( |
| + String::Handle(Symbols::New(":function")), |
|
srdjan
2013/08/01 00:54:47
Add ":function" and ":context" to the symbols.
Florian Schneider
2013/08/05 14:41:55
Done.
|
| + false, // !static |
| + false, // !final |
| + false, // !const |
| + alloc->cls(), |
| + 0)); // No token position. |
| + function_field.SetOffset(Closure::function_offset()); |
| + const Field& context_field = |
| + Field::ZoneHandle(Field::New( |
| + String::Handle(Symbols::New(":context")), |
| + false, // !static |
| + false, // !final |
| + false, // !const |
| + alloc->cls(), |
| + 0)); // No token position. |
| + context_field.SetOffset(Closure::context_offset()); |
| + alloc->set_context_field(context_field); |
| + |
| + Value* closure_val = Bind(alloc); |
| + { LocalVariable* tmp_var = EnterTempLocalScope(closure_val); |
| + // Store function. |
| + Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); |
| + Value* func_val = |
| + Bind(new ConstantInstr(Function::ZoneHandle(function.raw()))); |
| + Do(new StoreInstanceFieldInstr(function_field, |
| + tmp_val, |
| + func_val, |
| + kEmitStoreBarrier)); |
| + // Store current context. |
| + tmp_val = Bind(new LoadLocalInstr(*tmp_var)); |
| + Value* context = Bind(new CurrentContextInstr()); |
| + Do(new StoreInstanceFieldInstr(context_field, |
| + tmp_val, |
| + context, |
| + kEmitStoreBarrier)); |
| + ReturnDefinition(ExitTempLocalScope(tmp_var)); |
| + } |
| } else { |
| ASSERT(function.IsImplicitInstanceClosureFunction()); |
| ValueGraphVisitor for_receiver(owner(), temp_index()); |
| node->receiver()->Visit(&for_receiver); |
| Append(for_receiver); |
| - receiver = for_receiver.value(); |
| - } |
| - PushArgumentInstr* push_receiver = PushArgument(receiver); |
| - ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| - new ZoneGrowableArray<PushArgumentInstr*>(2); |
| - arguments->Add(push_receiver); |
| - ASSERT(function.context_scope() != ContextScope::null()); |
| + Value* receiver = for_receiver.value(); |
| - // The function type of a closure may have type arguments. In that case, pass |
| - // the type arguments of the instantiator. Otherwise, pass null object. |
| - const Class& cls = Class::Handle(function.signature_class()); |
| - ASSERT(!cls.IsNull()); |
| - const bool requires_type_arguments = cls.HasTypeArguments(); |
| - Value* type_arguments = NULL; |
| - if (requires_type_arguments) { |
| - ASSERT(!function.IsImplicitStaticClosureFunction()); |
| - const Class& instantiator_class = Class::Handle( |
| - owner()->parsed_function()->function().Owner()); |
| - type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), |
| - instantiator_class, |
| - NULL); |
| - } else { |
| - type_arguments = BuildNullValue(); |
| + PushArgumentInstr* push_receiver = PushArgument(receiver); |
| + ZoneGrowableArray<PushArgumentInstr*>* arguments = |
| + new ZoneGrowableArray<PushArgumentInstr*>(2); |
| + arguments->Add(push_receiver); |
| + ASSERT(function.context_scope() != ContextScope::null()); |
| + |
| + // The function type of a closure may have type arguments. In that case, |
| + // pass the type arguments of the instantiator. Otherwise, pass null object. |
| + const Class& cls = Class::Handle(function.signature_class()); |
| + ASSERT(!cls.IsNull()); |
| + const bool requires_type_arguments = cls.HasTypeArguments(); |
| + Value* type_arguments = NULL; |
| + if (requires_type_arguments) { |
| + const Class& instantiator_class = Class::Handle( |
| + owner()->parsed_function()->function().Owner()); |
| + type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), |
| + instantiator_class, |
| + NULL); |
| + } else { |
| + type_arguments = BuildNullValue(); |
| + } |
| + PushArgumentInstr* push_type_arguments = PushArgument(type_arguments); |
| + arguments->Add(push_type_arguments); |
| + ReturnDefinition( |
| + new CreateClosureInstr(node->function(), arguments, node->token_pos())); |
| } |
| - PushArgumentInstr* push_type_arguments = PushArgument(type_arguments); |
| - arguments->Add(push_type_arguments); |
| - ReturnDefinition( |
| - new CreateClosureInstr(node->function(), arguments, node->token_pos())); |
| } |
| @@ -2200,7 +2269,10 @@ |
| BuildConstructorTypeArguments(node, allocate_arguments); |
| } |
| - allocation = new AllocateObjectInstr(node, allocate_arguments); |
| + allocation = new AllocateObjectInstr( |
| + node->token_pos(), |
| + Class::ZoneHandle(node->constructor().Owner()), |
| + allocate_arguments); |
| } |
| return Bind(allocation); |
| } |