Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 18a62c689bd3c5bea3ee9733923bbf4e46367205..b70a7fab698ebe19eac1b6aae49b54e09c652783 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -2639,10 +2639,14 @@ void HGraphBuilder::SetUpScope(Scope* scope) { |
| if (!scope->arguments()->IsStackAllocated()) { |
| return Bailout("context-allocated arguments"); |
| } |
| - HArgumentsObject* object = new(zone()) HArgumentsObject; |
| - AddInstruction(object); |
| - graph()->SetArgumentsObject(object); |
| - environment()->Bind(scope->arguments(), object); |
| + |
| + if (!graph()->HasArgumentsObject()) { |
| + HArgumentsObject* object = new(zone()) HArgumentsObject; |
| + AddInstruction(object); |
| + graph()->SetArgumentsObject(object); |
| + } |
| + environment()->Bind(scope->arguments(), |
| + graph()->GetArgumentsObject()); |
| } |
| } |
| @@ -5226,10 +5230,20 @@ bool HGraphBuilder::TryInline(CallKind call_kind, |
| return false; |
| } |
| - // Don't inline functions that uses the arguments object. |
| + // If the function uses arguments object check that inlining of functions |
|
fschneider
2012/03/12 10:13:32
[...] uses _the_ arguments object [...]
|
| + // with arguments object is enabled and variable arguments is stack allocated. |
|
fschneider
2012/03/12 10:13:32
[...] and the arguments-variable [...]
|
| if (function->scope()->arguments() != NULL) { |
| - TraceInline(target, caller, "target requires special argument handling"); |
| - return false; |
| + if (!FLAG_inline_arguments) { |
| + TraceInline(target, caller, "target uses arguments object"); |
| + return false; |
| + } |
| + |
| + if (!function->scope()->arguments()->IsStackAllocated()) { |
| + TraceInline(target, |
| + caller, |
| + "target uses non-stackallocated arguments object"); |
| + return false; |
| + } |
| } |
| // All declarations must be inlineable. |
| @@ -5307,6 +5321,17 @@ bool HGraphBuilder::TryInline(CallKind call_kind, |
| function, |
| call_kind, |
| function_state()->is_construct())); |
| + // If the function uses arguments object create and bind one. |
| + if (function->scope()->arguments() != NULL) { |
| + ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| + if (!graph()->HasArgumentsObject()) { |
| + HArgumentsObject* object = new(zone()) HArgumentsObject; |
| + AddInstruction(object); |
| + graph()->SetArgumentsObject(object); |
| + } |
| + environment()->Bind(function->scope()->arguments(), |
| + graph()->GetArgumentsObject()); |
| + } |
| VisitDeclarations(target_info.scope()->declarations()); |
| VisitStatements(function->body()); |
| if (HasStackOverflow()) { |
| @@ -5645,13 +5670,6 @@ bool HGraphBuilder::TryCallApply(Call* expr) { |
| HValue* arg_two_value = environment()->Lookup(arg_two->var()); |
| if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| - // Our implementation of arguments (based on this stack frame or an |
| - // adapter below it) does not work for inlined functions. |
| - if (function_state()->outer() != NULL) { |
| - Bailout("Function.prototype.apply optimization in inlined function"); |
| - return true; |
| - } |
| - |
| // Found pattern f.apply(receiver, arguments). |
| VisitForValue(prop->obj()); |
| if (HasStackOverflow() || current_block() == NULL) return true; |
| @@ -5662,13 +5680,61 @@ bool HGraphBuilder::TryCallApply(Call* expr) { |
| VisitForValue(args->at(0)); |
| if (HasStackOverflow() || current_block() == NULL) return true; |
| HValue* receiver = Pop(); |
| - HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| - HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| - HInstruction* result = |
| - new(zone()) HApplyArguments(function, receiver, length, elements); |
| - result->set_position(expr->position()); |
| - ast_context()->ReturnInstruction(result, expr->id()); |
| - return true; |
| + |
| + if (function_state()->outer() == NULL) { |
| + HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| + HInstruction* length = |
| + AddInstruction(new(zone()) HArgumentsLength(elements)); |
| + HValue* wrapped_receiver = receiver; |
| + if (!receiver->IsAllocateObject()) { |
| + wrapped_receiver = |
| + AddInstruction(new(zone()) HWrapReceiver(receiver, function)); |
| + } |
| + HInstruction* result = |
| + new(zone()) HApplyArguments(function, |
| + wrapped_receiver, |
| + length, |
| + elements); |
| + result->set_position(expr->position()); |
| + ast_context()->ReturnInstruction(result, expr->id()); |
| + return true; |
| + } else { |
| + // We are inside inlined function and we know exactly what is inside |
| + // arguments object. |
| + HValue* context = environment()->LookupContext(); |
| + |
| + HValue* wrapped_receiver = receiver; |
| + if (!receiver->IsAllocateObject()) { |
|
fschneider
2012/03/12 10:13:32
You can use receiver->type().IsJSObject() instead.
|
| + wrapped_receiver = |
| + AddInstruction(new(zone()) HWrapReceiver(receiver, function)); |
| + } |
| + PushAndAdd(new(zone()) HPushArgument(wrapped_receiver)); |
| + |
| + int parameter_count = environment()->parameter_count(); |
| + for (int i = 1; i < environment()->parameter_count(); i++) { |
| + PushAndAdd(new(zone()) HPushArgument(environment()->Lookup(i))); |
| + } |
| + |
| + if (environment()->outer()->frame_type() == ARGUMENTS_ADAPTOR) { |
| + HEnvironment* adaptor = environment()->outer(); |
| + parameter_count = adaptor->parameter_count(); |
| + |
| + for (int i = environment()->parameter_count(); |
| + i < adaptor->parameter_count(); |
| + i++) { |
| + PushAndAdd(new(zone()) HPushArgument(adaptor->Lookup(i))); |
| + } |
| + } |
| + |
| + HInvokeFunction* call = new(zone()) HInvokeFunction( |
| + context, |
| + function, |
| + parameter_count); |
| + Drop(parameter_count); |
| + call->set_position(expr->position()); |
| + ast_context()->ReturnInstruction(call, expr->id()); |
| + return true; |
| + } |
| } |