Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(400)

Unified Diff: src/hydrogen.cc

Issue 9643001: Inline functions that use arguments object in f.apply(o, arguments) pattern. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: regression test Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
+ // with arguments object is enabled and variable arguments is stack allocated.
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()) {
+ 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;
+ }
}

Powered by Google App Engine
This is Rietveld 408576698