Revision: 8445
Author:   [email protected]
Date:     Tue Jun 28 05:51:21 2011
Log: 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.

[email protected]
BUG=
TEST=

Review URL: http://codereview.chromium.org/7274020
http://code.google.com/p/v8/source/detail?r=8445

Modified:
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h

=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Jun 28 01:54:09 2011
+++ /branches/bleeding_edge/src/hydrogen.cc     Tue Jun 28 05:51:21 2011
@@ -2179,9 +2179,12 @@
 }


-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 @@
   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 @@
       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 @@
     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 @@
argument_count));
       } else {
         HValue* context = environment()->LookupContext();
-        PushAndAdd(new(zone()) HGlobalObject(context));
-        CHECK_ALIVE(VisitExpressions(expr->arguments()));
-
-        call = PreProcessCall(new(zone()) HCallGlobal(context,
-                                                      var->name(),
-                                                      argument_count));
+        HGlobalObject* receiver = new(zone()) HGlobalObject(context);
+        AddInstruction(receiver);
+        PushAndAdd(new(zone()) HPushArgument(receiver));
+        CHECK_ALIVE(VisitArgumentList(expr->arguments()));
+
+ 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()));
-
- call = PreProcessCall(new(zone()) HCallFunction(context, argument_count));
+      AddInstruction(receiver);
+      PushAndAdd(new(zone()) HPushArgument(receiver));
+      CHECK_ALIVE(VisitArgumentList(expr->arguments()));
+
+ // 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 @@
   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());
 }

=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Tue Jun 28 01:54:09 2011
+++ /branches/bleeding_edge/src/hydrogen.h      Tue Jun 28 05:51:21 2011
@@ -816,8 +816,9 @@
                        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.

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to