Allow inlining of functions containing %_Arguments.

R=svenpanne@chromium.org
TEST=mjsunit/compiler/inline-arguments

Review URL: https://codereview.chromium.org/356773002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22060 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0be40ff5
......@@ -1114,11 +1114,6 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
// Don't try to inline JS runtime calls because we don't (currently) even
// optimize them.
add_flag(kDontInline);
} else if (node->function()->intrinsic_type == Runtime::INLINE &&
node->raw_name()->IsOneByteEqualTo("_Arguments")) {
// Don't inline the %_Arguments because it's implementation will not work.
// There is no stack frame to get them from.
add_flag(kDontInline);
}
}
......
......@@ -7738,19 +7738,19 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
inner_env->BindContext(context);
HArgumentsObject* arguments_object = NULL;
// If the function uses arguments object create and bind one, also copy
// Create a dematerialized arguments object for the function, also copy the
// current arguments values to use them for materialization.
HEnvironment* arguments_env = inner_env->arguments_environment();
int parameter_count = arguments_env->parameter_count();
HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
for (int i = 0; i < parameter_count; i++) {
arguments_object->AddArgument(arguments_env->Lookup(i), zone());
}
// If the function uses arguments object then bind bind one.
if (function->scope()->arguments() != NULL) {
ASSERT(function->scope()->arguments()->IsStackAllocated());
HEnvironment* arguments_env = inner_env->arguments_environment();
int arguments_count = arguments_env->parameter_count();
arguments_object = Add<HArgumentsObject>(arguments_count);
inner_env->Bind(function->scope()->arguments(), arguments_object);
for (int i = 0; i < arguments_count; i++) {
arguments_object->AddArgument(arguments_env->Lookup(i), zone());
}
}
// Capture the state before invoking the inlined function for deopt in the
......@@ -11326,18 +11326,26 @@ void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
// Our implementation of arguments (based on this stack frame or an
// adapter below it) does not work for inlined functions. This runtime
// function is blacklisted by AstNode::IsInlineable.
ASSERT(function_state()->outer() == NULL);
ASSERT(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* index = Pop();
HInstruction* elements = Add<HArgumentsElements>(false);
HInstruction* length = Add<HArgumentsLength>(elements);
HInstruction* checked_index = Add<HBoundsCheck>(index, length);
HAccessArgumentsAt* result = New<HAccessArgumentsAt>(
elements, length, checked_index);
HInstruction* result = NULL;
if (function_state()->outer() == NULL) {
HInstruction* elements = Add<HArgumentsElements>(false);
HInstruction* length = Add<HArgumentsLength>(elements);
HInstruction* checked_index = Add<HBoundsCheck>(index, length);
result = New<HAccessArgumentsAt>(elements, length, checked_index);
} else {
EnsureArgumentsArePushedForAccess();
// Number of arguments without receiver.
HInstruction* elements = function_state()->arguments_elements();
int argument_count = environment()->
arguments_environment()->parameter_count() - 1;
HInstruction* length = Add<HConstant>(argument_count);
HInstruction* checked_key = Add<HBoundsCheck>(index, length);
result = New<HAccessArgumentsAt>(elements, length, checked_key);
}
return ast_context()->ReturnInstruction(result, call->id());
}
......
......@@ -309,3 +309,29 @@ test_toarr(toarr2);
delete forceDeopt.deopt;
outer();
})();
// Test inlining of functions with %_Arguments and %_ArgumentsLength intrinsic.
(function () {
function inner(len,a,b,c) {
assertSame(len, %_ArgumentsLength());
for (var i = 1; i < len; ++i) {
var c = String.fromCharCode(96 + i);
assertSame(c, %_Arguments(i));
}
}
function outer() {
inner(1);
inner(2, 'a');
inner(3, 'a', 'b');
inner(4, 'a', 'b', 'c');
inner(5, 'a', 'b', 'c', 'd');
inner(6, 'a', 'b', 'c', 'd', 'e');
}
outer();
outer();
%OptimizeFunctionOnNextCall(outer);
outer();
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment