Better placement of argument pushing for a few hydrogen call instructions.

Where it's simple to do so (keyed calls, calls to unknown global variables,
calls to local variables and non-property/non-variable expressions), end the
live range of argument subexpressions immediately after the last use of the
expression rather than at the call.

R=fschneider@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/7274020

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8445 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3f70c456
......@@ -2179,9 +2179,12 @@ void HGraphBuilder::VisitForControl(Expression* expr,
}
void HGraphBuilder::VisitArgument(Expression* expr) {
CHECK_ALIVE(VisitForValue(expr));
Push(AddInstruction(new(zone()) HPushArgument(Pop())));
HValue* HGraphBuilder::VisitArgument(Expression* expr) {
VisitForValue(expr);
if (HasStackOverflow() || current_block() == NULL) return NULL;
HValue* value = Pop();
Push(AddInstruction(new(zone()) HPushArgument(value)));
return value;
}
......@@ -4691,7 +4694,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
if (prop != NULL) {
if (!prop->key()->IsPropertyName()) {
// Keyed function call.
CHECK_ALIVE(VisitForValue(prop->obj()));
CHECK_ALIVE(VisitArgument(prop->obj()));
CHECK_ALIVE(VisitForValue(prop->key()));
// Push receiver and key like the non-optimized code generator expects it.
......@@ -4700,13 +4703,12 @@ void HGraphBuilder::VisitCall(Call* expr) {
Push(key);
Push(receiver);
CHECK_ALIVE(VisitExpressions(expr->arguments()));
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
HValue* context = environment()->LookupContext();
call = PreProcessCall(
new(zone()) HCallKeyed(context, key, argument_count));
call = new(zone()) HCallKeyed(context, key, argument_count);
call->set_position(expr->position());
Drop(1); // Key.
Drop(argument_count + 1); // 1 is the key.
ast_context()->ReturnInstruction(call, expr->id());
return;
}
......@@ -4766,11 +4768,6 @@ void HGraphBuilder::VisitCall(Call* expr) {
Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
bool global_call = (var != NULL) && var->is_global() && !var->is_this();
if (!global_call) {
++argument_count;
CHECK_ALIVE(VisitForValue(expr->expression()));
}
if (global_call) {
bool known_global_function = false;
// If there is a global property cell for the name at compile time and
......@@ -4810,22 +4807,29 @@ void HGraphBuilder::VisitCall(Call* expr) {
argument_count));
} else {
HValue* context = environment()->LookupContext();
PushAndAdd(new(zone()) HGlobalObject(context));
CHECK_ALIVE(VisitExpressions(expr->arguments()));
HGlobalObject* receiver = new(zone()) HGlobalObject(context);
AddInstruction(receiver);
PushAndAdd(new(zone()) HPushArgument(receiver));
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
call = PreProcessCall(new(zone()) HCallGlobal(context,
var->name(),
argument_count));
call = new(zone()) HCallGlobal(context, var->name(), argument_count);
Drop(argument_count);
}
} else {
CHECK_ALIVE(VisitArgument(expr->expression()));
HValue* context = environment()->LookupContext();
HGlobalObject* global_object = new(zone()) HGlobalObject(context);
HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
AddInstruction(global_object);
PushAndAdd(new(zone()) HGlobalReceiver(global_object));
CHECK_ALIVE(VisitExpressions(expr->arguments()));
AddInstruction(receiver);
PushAndAdd(new(zone()) HPushArgument(receiver));
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
call = PreProcessCall(new(zone()) HCallFunction(context, argument_count));
// The function to call is treated as an argument to the call function
// stub.
call = new(zone()) HCallFunction(context, argument_count + 1);
Drop(argument_count + 1);
}
}
......@@ -4840,18 +4844,18 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) {
ASSERT(current_block()->HasPredecessor());
// The constructor function is also used as the receiver argument to the
// JS construct call builtin.
CHECK_ALIVE(VisitForValue(expr->expression()));
CHECK_ALIVE(VisitExpressions(expr->arguments()));
HValue* constructor = NULL;
CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
HValue* context = environment()->LookupContext();
// The constructor is both an operand to the instruction and an argument
// to the construct call.
int arg_count = expr->arguments()->length() + 1; // Plus constructor.
HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count);
call->set_position(expr->position());
PreProcessCall(call);
Drop(arg_count);
ast_context()->ReturnInstruction(call, expr->id());
}
......
......@@ -816,8 +816,9 @@ class HGraphBuilder: public AstVisitor {
HBasicBlock* false_block);
// Visit an argument subexpression and emit a push to the outgoing
// arguments.
void VisitArgument(Expression* expr);
// arguments. Returns the hydrogen value that was pushed.
HValue* VisitArgument(Expression* expr);
void VisitArgumentList(ZoneList<Expression*>* arguments);
// Visit a list of expressions from left to right, each in a value context.
......
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