Some cleanup of the toplevel code generator:
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 Jan 2010 08:48:26 +0000 (08:48 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 Jan 2010 08:48:26 +0000 (08:48 +0000)
* Rename the operation of filling a context with a value.  Formerly it
  was 'Move', now it's 'Apply' so as to avoid confusion with various
  other Moves (eg, in the toplevel codegen, in the macro assemblers).

* Use the abstraction Drop rather than math on the stack pointer.

* Add a predicate on AST expression nodes to abstract a repeated test
  whether we should us a regular (named) IC or a keyed IC.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3580 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

14 files changed:
src/arm/codegen-arm.cc
src/arm/fast-codegen-arm.cc
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/ast.h
src/compiler.cc
src/fast-codegen.cc
src/fast-codegen.h
src/ia32/codegen-ia32.cc
src/ia32/fast-codegen-ia32.cc
src/ia32/macro-assembler-ia32.h
src/x64/codegen-x64.cc
src/x64/fast-codegen-x64.cc
src/x64/macro-assembler-x64.h

index f773664..5cda172 100644 (file)
@@ -614,15 +614,7 @@ void CodeGenerator::LoadReference(Reference* ref) {
     // The expression is either a property or a variable proxy that rewrites
     // to a property.
     LoadAndSpill(property->obj());
-    // We use a named reference if the key is a literal symbol, unless it is
-    // a string that can be legally parsed as an integer.  This is because
-    // otherwise we will not get into the slow case code that handles [] on
-    // String objects.
-    Literal* literal = property->key()->AsLiteral();
-    uint32_t dummy;
-    if (literal != NULL &&
-        literal->handle()->IsSymbol() &&
-        !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
+    if (property->key()->IsPropertyName()) {
       ref->set_type(Reference::NAMED);
     } else {
       LoadAndSpill(property->key());
index bc406fd..27bdd0f 100644 (file)
@@ -214,56 +214,100 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
 }
 
 
-void FastCodeGenerator::Move(Expression::Context context, Register source) {
+void FastCodeGenerator::Apply(Expression::Context context,
+                              Slot* slot,
+                              Register scratch) {
   switch (context) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
       break;
     case Expression::kValue:
-      __ push(source);
+    case Expression::kTest:
+    case Expression::kValueTest:
+    case Expression::kTestValue:
+      Move(scratch, slot);
+      Apply(context, scratch);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
+  switch (context) {
+    case Expression::kUninitialized:
+      UNREACHABLE();
+    case Expression::kEffect:
       break;
+    case Expression::kValue:
     case Expression::kTest:
-      TestAndBranch(source, true_label_, false_label_);
+    case Expression::kValueTest:
+    case Expression::kTestValue:
+      __ mov(ip, Operand(lit->handle()));
+      Apply(context, ip);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::ApplyTOS(Expression::Context context) {
+  switch (context) {
+    case Expression::kUninitialized:
+      UNREACHABLE();
+    case Expression::kEffect:
+      __ Drop(1);
+      break;
+    case Expression::kValue:
+      break;
+    case Expression::kTest:
+      __ pop(r0);
+      TestAndBranch(r0, true_label_, false_label_);
       break;
     case Expression::kValueTest: {
       Label discard;
-      __ push(source);
-      TestAndBranch(source, true_label_, &discard);
+      __ ldr(r0, MemOperand(sp, 0));
+      TestAndBranch(r0, true_label_, &discard);
       __ bind(&discard);
-      __ pop();
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
     case Expression::kTestValue: {
       Label discard;
-      __ push(source);
-      TestAndBranch(source, &discard, false_label_);
+      __ ldr(r0, MemOperand(sp, 0));
+      TestAndBranch(r0, &discard, false_label_);
       __ bind(&discard);
-      __ pop();
+      __ Drop(1);
       __ jmp(true_label_);
     }
   }
 }
 
 
-void FastCodeGenerator::MoveTOS(Expression::Context context) {
+void FastCodeGenerator::DropAndApply(int count,
+                                     Expression::Context context,
+                                     Register reg) {
+  ASSERT(count > 0);
+  ASSERT(!reg.is(sp));
   switch (context) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      __ Drop(1);
+      __ Drop(count);
       break;
     case Expression::kValue:
+      if (count > 1) __ Drop(count - 1);
+      __ str(reg, MemOperand(sp));
       break;
     case Expression::kTest:
-      __ pop(r0);
-      TestAndBranch(r0, true_label_, false_label_);
+      __ Drop(count);
+      TestAndBranch(reg, true_label_, false_label_);
       break;
     case Expression::kValueTest: {
       Label discard;
-      __ ldr(r0, MemOperand(sp, 0));
-      TestAndBranch(r0, true_label_, &discard);
+      if (count > 1) __ Drop(count - 1);
+      __ str(reg, MemOperand(sp));
+      TestAndBranch(reg, true_label_, &discard);
       __ bind(&discard);
       __ Drop(1);
       __ jmp(false_label_);
@@ -271,11 +315,13 @@ void FastCodeGenerator::MoveTOS(Expression::Context context) {
     }
     case Expression::kTestValue: {
       Label discard;
-      __ ldr(r0, MemOperand(sp, 0));
-      TestAndBranch(r0, &discard, false_label_);
+      if (count > 1) __ Drop(count - 1);
+      __ str(reg, MemOperand(sp));
+      TestAndBranch(reg, &discard, false_label_);
       __ bind(&discard);
       __ Drop(1);
       __ jmp(true_label_);
+      break;
     }
   }
 }
@@ -308,42 +354,6 @@ void FastCodeGenerator::Move(Register destination, Slot* source) {
 
 
 
-void FastCodeGenerator::Move(Expression::Context context,
-                             Slot* source,
-                             Register scratch) {
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      break;
-    case Expression::kValue:
-    case Expression::kTest:
-    case Expression::kValueTest:
-    case Expression::kTestValue:
-      Move(scratch, source);
-      Move(context, scratch);
-      break;
-  }
-}
-
-
-void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      break;
-    case Expression::kValue:
-    case Expression::kTest:
-    case Expression::kValueTest:
-    case Expression::kTestValue:
-      __ mov(ip, Operand(expr->handle()));
-      Move(context, ip);
-      break;
-  }
-}
-
-
 void FastCodeGenerator::Move(Slot* dst,
                              Register src,
                              Register scratch1,
@@ -361,55 +371,6 @@ void FastCodeGenerator::Move(Slot* dst,
 
 
 
-void FastCodeGenerator::DropAndMove(Expression::Context context,
-                                    Register source,
-                                    int drop_count) {
-  ASSERT(drop_count > 0);
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      __ add(sp, sp, Operand(drop_count * kPointerSize));
-      break;
-    case Expression::kValue:
-      if (drop_count > 1) {
-        __ add(sp, sp, Operand((drop_count - 1) * kPointerSize));
-      }
-      __ str(source, MemOperand(sp));
-      break;
-    case Expression::kTest:
-      ASSERT(!source.is(sp));
-      __ add(sp, sp, Operand(drop_count * kPointerSize));
-      TestAndBranch(source, true_label_, false_label_);
-      break;
-    case Expression::kValueTest: {
-      Label discard;
-      if (drop_count > 1) {
-        __ add(sp, sp, Operand((drop_count - 1) * kPointerSize));
-      }
-      __ str(source, MemOperand(sp));
-      TestAndBranch(source, true_label_, &discard);
-      __ bind(&discard);
-      __ pop();
-      __ jmp(false_label_);
-      break;
-    }
-    case Expression::kTestValue: {
-      Label discard;
-      if (drop_count > 1) {
-        __ add(sp, sp, Operand((drop_count - 1) * kPointerSize));
-      }
-      __ str(source, MemOperand(sp));
-      TestAndBranch(source, &discard, false_label_);
-      __ bind(&discard);
-      __ pop();
-      __ jmp(true_label_);
-      break;
-    }
-  }
-}
-
-
 void FastCodeGenerator::TestAndBranch(Register source,
                                       Label* true_label,
                                       Label* false_label) {
@@ -524,7 +485,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
 
       // Value in r0 is ignored (declarations are statements).  Receiver
       // and key on stack are discarded.
-      __ add(sp, sp, Operand(2 * kPointerSize));
+      __ Drop(2);
     }
   }
 }
@@ -555,7 +516,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   __ mov(r0, Operand(boilerplate));
   __ stm(db_w, sp, cp.bit() | r0.bit());
   __ CallRuntime(Runtime::kNewClosure, 2);
-  Move(expr->context(), r0);
+  Apply(expr->context(), r0);
 }
 
 
@@ -578,7 +539,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
     __ mov(r2, Operand(var->name()));
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
-    DropAndMove(context, r0);
+    DropAndApply(1, context, r0);
   } else if (rewrite->AsSlot() != NULL) {
     Slot* slot = rewrite->AsSlot();
     if (FLAG_debug_code) {
@@ -597,17 +558,18 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
           break;
       }
     }
-    Move(context, slot, r0);
+    Apply(context, slot, r0);
   } else {
-    // A variable has been rewritten into an explicit access to
-    // an object property.
+    Comment cmnt(masm_, "Variable rewritten to property");
+    // A variable has been rewritten into an explicit access to an object
+    // property.
     Property* property = rewrite->AsProperty();
     ASSERT_NOT_NULL(property);
 
-    // Currently the only parameter expressions that can occur are
-    // on the form "slot[literal]".
+    // The only property expressions that can occur are of the form
+    // "slot[literal]".
 
-    // Check that the object is in a slot.
+    // Assert that the object is in a slot.
     Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
     ASSERT_NOT_NULL(object_var);
     Slot* object_slot = object_var->slot();
@@ -616,7 +578,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
     // Load the object.
     Move(r2, object_slot);
 
-    // Check that the key is a smi.
+    // Assert that the key is a smi.
     Literal* key_literal = property->key()->AsLiteral();
     ASSERT_NOT_NULL(key_literal);
     ASSERT(key_literal->handle()->IsSmi());
@@ -627,12 +589,12 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
     // Push both as arguments to ic.
     __ stm(db_w, sp, r2.bit() | r1.bit());
 
-    // Do a KEYED property load.
+    // Do a keyed property load.
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
 
     // Drop key and object left on the stack by IC, and push the result.
-    DropAndMove(context, r0, 2);
+    DropAndApply(2, context, r0);
   }
 }
 
@@ -660,7 +622,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   __ bind(&done);
-  Move(expr->context(), r0);
+  Apply(expr->context(), r0);
 }
 
 
@@ -742,7 +704,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      if (result_saved) __ pop();
+      if (result_saved) __ Drop(1);
       break;
     case Expression::kValue:
       if (!result_saved) __ push(r0);
@@ -756,7 +718,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       if (!result_saved) __ push(r0);
       TestAndBranch(r0, true_label_, &discard);
       __ bind(&discard);
-      __ pop();
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
@@ -765,7 +727,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       if (!result_saved) __ push(r0);
       TestAndBranch(r0, &discard, false_label_);
       __ bind(&discard);
-      __ pop();
+      __ Drop(1);
       __ jmp(true_label_);
       break;
     }
@@ -824,7 +786,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      if (result_saved) __ pop();
+      if (result_saved) __ Drop(1);
       break;
     case Expression::kValue:
       if (!result_saved) __ push(r0);
@@ -838,7 +800,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
       if (!result_saved) __ push(r0);
       TestAndBranch(r0, true_label_, &discard);
       __ bind(&discard);
-      __ pop();
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
@@ -847,7 +809,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
       if (!result_saved) __ push(r0);
       TestAndBranch(r0, &discard, false_label_);
       __ bind(&discard);
-      __ pop();
+      __ Drop(1);
       __ jmp(true_label_);
       break;
     }
@@ -862,7 +824,7 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
   __ mov(r2, Operand(key->handle()));
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
-  Move(context, r0);
+  Apply(context, r0);
 }
 
 
@@ -871,7 +833,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop,
   SetSourcePosition(prop->position());
   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
-  Move(context, r0);
+  Apply(context, r0);
 }
 
 
@@ -882,7 +844,7 @@ void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
   GenericBinaryOpStub stub(op,
                            NO_OVERWRITE);
   __ CallStub(&stub);
-  Move(context, r0);
+  Apply(context, r0);
 }
 
 
@@ -901,7 +863,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
     Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // Overwrite the global object on the stack with the result if needed.
-    DropAndMove(context, r0);
+    DropAndApply(1, context, r0);
 
   } else if (var->slot() != NULL) {
     Slot* slot = var->slot();
@@ -934,7 +896,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
             __ str(r0, target);
             TestAndBranch(r0, true_label_, &discard);
             __ bind(&discard);
-            __ pop();
+            __ Drop(1);
             __ jmp(false_label_);
             break;
           }
@@ -944,7 +906,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
             __ str(r0, target);
             TestAndBranch(r0, &discard, false_label_);
             __ bind(&discard);
-            __ pop();
+            __ Drop(1);
             __ jmp(true_label_);
             break;
           }
@@ -976,7 +938,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
         __ RecordWrite(r1, r2, r0);
         __ bind(&exit);
         if (context != Expression::kEffect && context != Expression::kValue) {
-          Move(context, r3);
+          Apply(context, r3);
         }
         break;
       }
@@ -1022,7 +984,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
     __ pop(r0);
   }
 
-  DropAndMove(expr->context(), r0);
+  DropAndApply(1, expr->context(), r0);
 }
 
 
@@ -1054,15 +1016,13 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   }
 
   // Receiver and key are still on stack.
-  __ add(sp, sp, Operand(2 * kPointerSize));
-  Move(expr->context(), r0);
+  DropAndApply(2, expr->context(), r0);
 }
 
 
 void FastCodeGenerator::VisitProperty(Property* expr) {
   Comment cmnt(masm_, "[ Property");
   Expression* key = expr->key();
-  uint32_t dummy;
 
   // Record the source position for the property load.
   SetSourcePosition(expr->position());
@@ -1070,22 +1030,21 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
   // Evaluate receiver.
   Visit(expr->obj());
 
-  if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
-      !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
-    // Do a NAMED property load.
-    // The IC expects the property name in r2 and the receiver on the stack.
+  if (key->IsPropertyName()) {
+    // Do a named property load.  The IC expects the property name in r2 and
+    // the receiver on the stack.
     __ mov(r2, Operand(key->AsLiteral()->handle()));
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
+    DropAndApply(1, expr->context(), r0);
   } else {
-    // Do a KEYED property load.
+    // Do a keyed property load.
     Visit(expr->key());
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // Drop key and receiver left on the stack by IC.
-    __ pop();
+    DropAndApply(2, expr->context(), r0);
   }
-  DropAndMove(expr->context(), r0);
 }
 
 void FastCodeGenerator::EmitCallWithIC(Call* expr,
@@ -1107,7 +1066,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
   // Restore context register.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndMove(expr->context(), r0);
+  DropAndApply(1, expr->context(), r0);
 }
 
 
@@ -1125,7 +1084,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
   // Restore context register.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndMove(expr->context(), r0);
+  DropAndApply(1, expr->context(), r0);
 }
 
 
@@ -1234,7 +1193,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
   __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
 
   // Replace function on TOS with result in r0, or pop it.
-  DropAndMove(expr->context(), r0);
+  DropAndApply(1, expr->context(), r0);
 }
 
 
@@ -1265,11 +1224,11 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
     // Restore context register.
     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
     // Discard the function left on TOS.
-    DropAndMove(expr->context(), r0);
+    DropAndApply(1, expr->context(), r0);
   } else {
     // Call the C runtime function.
     __ CallRuntime(expr->function(), arg_count);
-    Move(expr->context(), r0);
+    Apply(expr->context(), r0);
   }
 }
 
@@ -1398,7 +1357,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       }
 
       __ CallRuntime(Runtime::kTypeof, 1);
-      Move(expr->context(), r0);
+      Apply(expr->context(), r0);
       break;
     }
 
@@ -1499,7 +1458,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
         // For all contexts except kEffect: We have the result on
         // top of the stack.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
@@ -1513,10 +1472,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
       if (expr->is_postfix()) {
         __ Drop(1);  // Result is on the stack under the receiver.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
-        DropAndMove(expr->context(), r0);
+        DropAndApply(1, expr->context(), r0);
       }
       break;
     }
@@ -1526,10 +1485,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
       if (expr->is_postfix()) {
         __ Drop(2);  // Result is on the stack under the key and the receiver.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
-        DropAndMove(expr->context(), r0, 2);
+        DropAndApply(2, expr->context(), r0);
       }
       break;
     }
@@ -1573,7 +1532,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
       GenericBinaryOpStub stub(expr->op(),
                                NO_OVERWRITE);
       __ CallStub(&stub);
-      Move(expr->context(), r0);
+      Apply(expr->context(), r0);
 
       break;
     }
@@ -1748,7 +1707,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
 
 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  Move(expr->context(), r0);
+  Apply(expr->context(), r0);
 }
 
 
index 876eec1..18cadac 100644 (file)
@@ -162,9 +162,9 @@ void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
 }
 
 
-void MacroAssembler::Drop(int stack_elements, Condition cond) {
-  if (stack_elements > 0) {
-    add(sp, sp, Operand(stack_elements * kPointerSize), LeaveCC, cond);
+void MacroAssembler::Drop(int count, Condition cond) {
+  if (count > 0) {
+    add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond);
   }
 }
 
index 88bfa9c..8f2064a 100644 (file)
@@ -64,7 +64,11 @@ class MacroAssembler: public Assembler {
   void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
   void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
   void Ret(Condition cond = al);
-  void Drop(int stack_elements, Condition cond = al);
+
+  // Emit code to discard a non-negative number of pointer-sized elements
+  // from the stack, clobbering only the sp register.
+  void Drop(int count, Condition cond = al);
+
   void Call(Label* target);
   void Move(Register dst, Handle<Object> value);
   // Jumps to the label at the index given by the Smi in "index".
index 5d2a8b6..ec32318 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -187,6 +187,11 @@ class Expression: public AstNode {
   virtual bool IsValidJSON() { return false; }
   virtual bool IsValidLeftHandSide() { return false; }
 
+  // Symbols that cannot be parsed as array indices are considered property
+  // names.  We do not treat symbols that can be array indexes as property
+  // names because [] for string objects is handled only by keyed ICs.
+  virtual bool IsPropertyName() { return false; }
+
   // Mark the expression as being compiled as an expression
   // statement. This is used to transform postfix increments to
   // (faster) prefix increments.
@@ -707,6 +712,14 @@ class Literal: public Expression {
 
   virtual bool IsValidJSON() { return true; }
 
+  virtual bool IsPropertyName() {
+    if (handle_->IsSymbol()) {
+      uint32_t ignored;
+      return !String::cast(*handle_)->AsArrayIndex(&ignored);
+    }
+    return false;
+  }
+
   // Identity testers.
   bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
   bool IsTrue() const { return handle_.is_identical_to(Factory::true_value()); }
index 87cbefa..519362c 100644 (file)
@@ -902,11 +902,7 @@ void CodeGenSelector::VisitAssignment(Assignment* expr) {
     // We will only visit the key during code generation for keyed property
     // stores.  Leave its expression context uninitialized for named
     // property stores.
-    Literal* lit = prop->key()->AsLiteral();
-    uint32_t ignored;
-    if (lit == NULL ||
-        !lit->handle()->IsSymbol() ||
-        String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
+    if (!prop->key()->IsPropertyName()) {
       ProcessExpression(prop->key(), Expression::kValue);
       CHECK_BAILOUT;
     }
@@ -1030,11 +1026,7 @@ void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
     // We will only visit the key during code generation for keyed property
     // stores.  Leave its expression context uninitialized for named
     // property stores.
-    Literal* lit = prop->key()->AsLiteral();
-    uint32_t ignored;
-    if (lit == NULL ||
-        !lit->handle()->IsSymbol() ||
-        String::cast(*(lit->handle()))->AsArrayIndex(&ignored)) {
+    if (!prop->key()->IsPropertyName()) {
       ProcessExpression(prop->key(), Expression::kValue);
       CHECK_BAILOUT;
     }
index 83714f0..a76ae9c 100644 (file)
@@ -75,6 +75,39 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
 }
 
 
+void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
+  switch (context) {
+    case Expression::kUninitialized:
+      UNREACHABLE();
+    case Expression::kEffect:
+      break;
+    case Expression::kValue:
+      __ push(reg);
+      break;
+    case Expression::kTest:
+      TestAndBranch(reg, true_label_, false_label_);
+      break;
+    case Expression::kValueTest: {
+      Label discard;
+      __ push(reg);
+      TestAndBranch(reg, true_label_, &discard);
+      __ bind(&discard);
+      __ Drop(1);
+      __ jmp(false_label_);
+      break;
+    }
+    case Expression::kTestValue: {
+      Label discard;
+      __ push(reg);
+      TestAndBranch(reg, &discard, false_label_);
+      __ bind(&discard);
+      __ Drop(1);
+      __ jmp(true_label_);
+    }
+  }
+}
+
+
 void FastCodeGenerator::VisitDeclarations(
     ZoneList<Declaration*>* declarations) {
   int length = declarations->length();
@@ -624,7 +657,7 @@ void FastCodeGenerator::VisitSlot(Slot* expr) {
 
 void FastCodeGenerator::VisitLiteral(Literal* expr) {
   Comment cmnt(masm_, "[ Literal");
-  Move(expr->context(), expr);
+  Apply(expr->context(), expr);
 }
 
 
index 6fbce65..74c9b4d 100644 (file)
@@ -212,10 +212,23 @@ class FastCodeGenerator: public AstVisitor {
 
 
   int SlotOffset(Slot* slot);
-  void Move(Expression::Context destination, Register source);
-  void MoveTOS(Expression::Context destination);
-  void Move(Expression::Context destination, Slot* source, Register scratch);
-  void Move(Expression::Context destination, Literal* source);
+
+  // Emit code to complete the evaluation of an expression based on its
+  // expression context and given its value is in a register, non-lookup
+  // slot, or a literal.
+  void Apply(Expression::Context context, Register reg);
+  void Apply(Expression::Context context, Slot* slot, Register scratch);
+  void Apply(Expression::Context context, Literal* lit);
+
+  // Emit code to complete the evaluation of an expression based on its
+  // expression context and given its value is on top of the stack.
+  void ApplyTOS(Expression::Context context);
+
+  // Emit code to discard count elements from the top of stack, then
+  // complete the evaluation of an expression based on its expression
+  // context and given its value is in a register.
+  void DropAndApply(int count, Expression::Context context, Register reg);
+
   void Move(Slot* dst, Register source, Register scratch1, Register scratch2);
   void Move(Register dst, Slot* source);
 
@@ -224,12 +237,6 @@ class FastCodeGenerator: public AstVisitor {
   // register.
   MemOperand EmitSlotSearch(Slot* slot, Register scratch);
 
-  // Drop the TOS, and store source to destination.
-  // If destination is TOS, just overwrite TOS with source.
-  void DropAndMove(Expression::Context destination,
-                   Register source,
-                   int drop_count = 1);
-
   // Test the JavaScript value in source as if in a test context, compile
   // control flow to a pair of labels.
   void TestAndBranch(Register source, Label* true_label, Label* false_label);
index ff26956..819231a 100644 (file)
@@ -664,15 +664,7 @@ void CodeGenerator::LoadReference(Reference* ref) {
     // The expression is either a property or a variable proxy that rewrites
     // to a property.
     Load(property->obj());
-    // We use a named reference if the key is a literal symbol, unless it is
-    // a string that can be legally parsed as an integer.  This is because
-    // otherwise we will not get into the slow case code that handles [] on
-    // String objects.
-    Literal* literal = property->key()->AsLiteral();
-    uint32_t dummy;
-    if (literal != NULL &&
-        literal->handle()->IsSymbol() &&
-        !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
+    if (property->key()->IsPropertyName()) {
       ref->set_type(Reference::NAMED);
     } else {
       Load(property->key());
index ea91d52..ddb6d0b 100644 (file)
@@ -194,56 +194,106 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
 }
 
 
-void FastCodeGenerator::Move(Expression::Context context, Register source) {
+void FastCodeGenerator::Apply(Expression::Context context,
+                              Slot* slot,
+                              Register scratch) {
   switch (context) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
       break;
+    case Expression::kValue: {
+      MemOperand location = EmitSlotSearch(slot, scratch);
+      __ push(location);
+      break;
+    }
+    case Expression::kTest:
+    case Expression::kValueTest:
+    case Expression::kTestValue:
+      Move(scratch, slot);
+      Apply(context, scratch);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
+  switch (context) {
+    case Expression::kUninitialized:
+      UNREACHABLE();
+    case Expression::kEffect:
+      break;
+    case Expression::kValue:
+      __ push(Immediate(lit->handle()));
+      break;
+    case Expression::kTest:
+    case Expression::kValueTest:
+    case Expression::kTestValue:
+      __ mov(eax, lit->handle());
+      Apply(context, eax);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::ApplyTOS(Expression::Context context) {
+  switch (context) {
+    case Expression::kUninitialized:
+      UNREACHABLE();
+    case Expression::kEffect:
+      __ Drop(1);
+      break;
     case Expression::kValue:
-      __ push(source);
       break;
     case Expression::kTest:
-      TestAndBranch(source, true_label_, false_label_);
+      __ pop(eax);
+      TestAndBranch(eax, true_label_, false_label_);
       break;
     case Expression::kValueTest: {
       Label discard;
-      __ push(source);
-      TestAndBranch(source, true_label_, &discard);
+      __ mov(eax, Operand(esp, 0));
+      TestAndBranch(eax, true_label_, &discard);
       __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
     case Expression::kTestValue: {
       Label discard;
-      __ push(source);
-      TestAndBranch(source, &discard, false_label_);
+      __ mov(eax, Operand(esp, 0));
+      TestAndBranch(eax, &discard, false_label_);
       __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(true_label_);
     }
   }
 }
 
 
-void FastCodeGenerator::MoveTOS(Expression::Context context) {
+void FastCodeGenerator::DropAndApply(int count,
+                                     Expression::Context context,
+                                     Register reg) {
+  ASSERT(count > 0);
+  ASSERT(!reg.is(esp));
   switch (context) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      __ Drop(1);
+      __ Drop(count);
       break;
     case Expression::kValue:
+      if (count > 1) __ Drop(count - 1);
+      __ mov(Operand(esp, 0), reg);
       break;
     case Expression::kTest:
-      __ pop(eax);
-      TestAndBranch(eax, true_label_, false_label_);
+      __ Drop(count);
+      TestAndBranch(reg, true_label_, false_label_);
       break;
     case Expression::kValueTest: {
       Label discard;
-      __ mov(eax, Operand(esp, 0));
-      TestAndBranch(eax, true_label_, &discard);
+      if (count > 1) __ Drop(count - 1);
+      __ mov(Operand(esp, 0), reg);
+      TestAndBranch(reg, true_label_, &discard);
       __ bind(&discard);
       __ Drop(1);
       __ jmp(false_label_);
@@ -251,11 +301,13 @@ void FastCodeGenerator::MoveTOS(Expression::Context context) {
     }
     case Expression::kTestValue: {
       Label discard;
-      __ mov(eax, Operand(esp, 0));
-      TestAndBranch(eax, &discard, false_label_);
+      if (count > 1) __ Drop(count - 1);
+      __ mov(Operand(esp, 0), reg);
+      TestAndBranch(reg, &discard, false_label_);
       __ bind(&discard);
       __ Drop(1);
       __ jmp(true_label_);
+      break;
     }
   }
 }
@@ -286,48 +338,6 @@ void FastCodeGenerator::Move(Register destination, Slot* source) {
 }
 
 
-void FastCodeGenerator::Move(Expression::Context context,
-                             Slot* source,
-                             Register scratch) {
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      break;
-    case Expression::kValue: {
-      MemOperand location = EmitSlotSearch(source, scratch);
-      __ push(location);
-      break;
-    }
-    case Expression::kTest:
-    case Expression::kValueTest:
-    case Expression::kTestValue:
-      Move(scratch, source);
-      Move(context, scratch);
-      break;
-  }
-}
-
-
-void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      break;
-    case Expression::kValue:
-      __ push(Immediate(expr->handle()));
-      break;
-    case Expression::kTest:
-    case Expression::kValueTest:
-    case Expression::kTestValue:
-      __ mov(eax, expr->handle());
-      Move(context, eax);
-      break;
-  }
-}
-
-
 void FastCodeGenerator::Move(Slot* dst,
                              Register src,
                              Register scratch1,
@@ -344,55 +354,6 @@ void FastCodeGenerator::Move(Slot* dst,
 }
 
 
-void FastCodeGenerator::DropAndMove(Expression::Context context,
-                                    Register source,
-                                    int count) {
-  ASSERT(count > 0);
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      __ add(Operand(esp), Immediate(count * kPointerSize));
-      break;
-    case Expression::kValue:
-      if (count > 1) {
-        __ add(Operand(esp), Immediate((count - 1) * kPointerSize));
-      }
-      __ mov(Operand(esp, 0), source);
-      break;
-    case Expression::kTest:
-      ASSERT(!source.is(esp));
-      __ add(Operand(esp), Immediate(count * kPointerSize));
-      TestAndBranch(source, true_label_, false_label_);
-      break;
-    case Expression::kValueTest: {
-      Label discard;
-      if (count > 1) {
-        __ add(Operand(esp), Immediate((count - 1) * kPointerSize));
-      }
-      __ mov(Operand(esp, 0), source);
-      TestAndBranch(source, true_label_, &discard);
-      __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
-      __ jmp(false_label_);
-      break;
-    }
-    case Expression::kTestValue: {
-      Label discard;
-      if (count > 1) {
-        __ add(Operand(esp), Immediate((count - 1) * kPointerSize));
-      }
-      __ mov(Operand(esp, 0), source);
-      TestAndBranch(source, &discard, false_label_);
-      __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
-      __ jmp(true_label_);
-      break;
-    }
-  }
-}
-
-
 void FastCodeGenerator::TestAndBranch(Register source,
                                       Label* true_label,
                                       Label* false_label) {
@@ -518,7 +479,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
 
       // Value in eax is ignored (declarations are statements).  Receiver
       // and key on stack are discarded.
-      __ add(Operand(esp), Immediate(2 * kPointerSize));
+      __ Drop(2);
     }
   }
 }
@@ -548,7 +509,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   __ push(esi);
   __ push(Immediate(boilerplate));
   __ CallRuntime(Runtime::kNewClosure, 2);
-  Move(expr->context(), eax);
+  Apply(expr->context(), eax);
 }
 
 
@@ -575,7 +536,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
     // Remember that the assembler may choose to do peephole optimization
     // (eg, push/pop elimination).
     __ nop();
-    DropAndMove(context, eax);
+    DropAndApply(1, context, eax);
   } else if (rewrite->AsSlot() != NULL) {
     Slot* slot = rewrite->AsSlot();
     if (FLAG_debug_code) {
@@ -594,42 +555,43 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
           break;
       }
     }
-    Move(context, slot, eax);
+    Apply(context, slot, eax);
   } else {
-    Comment cmnt(masm_, "Variable rewritten to Property");
-    // A variable has been rewritten into an explicit access to
-    // an object property.
+    Comment cmnt(masm_, "Variable rewritten to property");
+    // A variable has been rewritten into an explicit access to an object
+    // property.
     Property* property = rewrite->AsProperty();
     ASSERT_NOT_NULL(property);
 
-    // Currently the only parameter expressions that can occur are
-    // on the form "slot[literal]".
+    // The only property expressions that can occur are of the form
+    // "slot[literal]".
 
-    // Check that the object is in a slot.
+    // Assert that the object is in a slot.
     Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
     ASSERT_NOT_NULL(object_var);
     Slot* object_slot = object_var->slot();
     ASSERT_NOT_NULL(object_slot);
 
     // Load the object.
-    Move(Expression::kValue, object_slot, eax);
+    MemOperand object_loc = EmitSlotSearch(object_slot, eax);
+    __ push(object_loc);
 
-    // Check that the key is a smi.
+    // Assert that the key is a smi.
     Literal* key_literal = property->key()->AsLiteral();
     ASSERT_NOT_NULL(key_literal);
     ASSERT(key_literal->handle()->IsSmi());
 
     // Load the key.
-    Move(Expression::kValue, key_literal);
+    __ push(Immediate(key_literal->handle()));
 
-    // Do a KEYED property load.
+    // Do a keyed property load.
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
-    // Notice: We must not have a "test eax, ..." instruction after
-    // the call. It is treated specially by the LoadIC code.
+    // Notice: We must not have a "test eax, ..." instruction after the
+    // call. It is treated specially by the LoadIC code.
     __ nop();
     // Drop key and object left on the stack by IC.
-    DropAndMove(context, eax, 2);
+    DropAndApply(2, context, eax);
   }
 }
 
@@ -657,7 +619,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   // Label done:
   __ bind(&done);
-  Move(expr->context(), eax);
+  Apply(expr->context(), eax);
 }
 
 
@@ -733,7 +695,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
+      if (result_saved) __ Drop(1);
       break;
     case Expression::kValue:
       if (!result_saved) __ push(eax);
@@ -747,7 +709,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       if (!result_saved) __ push(eax);
       TestAndBranch(eax, true_label_, &discard);
       __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
@@ -756,7 +718,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       if (!result_saved) __ push(eax);
       TestAndBranch(eax, &discard, false_label_);
       __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
+      __ Drop (1);
       __ jmp(true_label_);
       break;
     }
@@ -812,7 +774,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
+      if (result_saved) __ Drop(1);
       break;
     case Expression::kValue:
       if (!result_saved) __ push(eax);
@@ -826,7 +788,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
       if (!result_saved) __ push(eax);
       TestAndBranch(eax, true_label_, &discard);
       __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
@@ -835,7 +797,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
       if (!result_saved) __ push(eax);
       TestAndBranch(eax, &discard, false_label_);
       __ bind(&discard);
-      __ add(Operand(esp), Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(true_label_);
       break;
     }
@@ -850,7 +812,7 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
   __ mov(ecx, Immediate(key->handle()));
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
-  Move(context, eax);
+  Apply(context, eax);
 }
 
 
@@ -859,7 +821,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop,
   SetSourcePosition(prop->position());
   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
-  Move(context, eax);
+  Apply(context, eax);
 }
 
 
@@ -869,7 +831,7 @@ void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
                            NO_OVERWRITE,
                            NO_GENERIC_BINARY_FLAGS);
   __ CallStub(&stub);
-  Move(context, eax);
+  Apply(context, eax);
 }
 
 
@@ -887,7 +849,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
     Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
     // Overwrite the receiver on the stack with the result if needed.
-    DropAndMove(context, eax);
+    DropAndApply(1, context, eax);
 
   } else if (var->slot() != NULL) {
     Slot* slot = var->slot();
@@ -919,7 +881,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
             __ mov(target, eax);
             TestAndBranch(eax, true_label_, &discard);
             __ bind(&discard);
-            __ add(Operand(esp), Immediate(kPointerSize));
+            __ Drop(1);
             __ jmp(false_label_);
             break;
           }
@@ -929,7 +891,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
             __ mov(target, eax);
             TestAndBranch(eax, &discard, false_label_);
             __ bind(&discard);
-            __ add(Operand(esp), Immediate(kPointerSize));
+            __ Drop(1);
             __ jmp(true_label_);
             break;
           }
@@ -950,9 +912,8 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
         }
         int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
         __ RecordWrite(ecx, offset, eax, ebx);
-        if (context != Expression::kEffect &&
-            context != Expression::kValue) {
-          Move(context, edx);
+        if (context != Expression::kEffect && context != Expression::kValue) {
+          Apply(context, edx);
         }
         break;
       }
@@ -996,7 +957,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
     __ pop(eax);
   }
 
-  DropAndMove(expr->context(), eax);
+  DropAndApply(1, expr->context(), eax);
 }
 
 
@@ -1029,34 +990,32 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   }
 
   // Receiver and key are still on stack.
-  __ add(Operand(esp), Immediate(2 * kPointerSize));
-  Move(expr->context(), eax);
+  DropAndApply(2, expr->context(), eax);
 }
 
 
 void FastCodeGenerator::VisitProperty(Property* expr) {
   Comment cmnt(masm_, "[ Property");
   Expression* key = expr->key();
-  uint32_t dummy;
 
   // Record the source position for the property load.
   SetSourcePosition(expr->position());
 
-  // Evaluate receiver.
+  // Evaluate the receiver.
   Visit(expr->obj());
 
-  if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
-      !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
-    // Do a NAMED property load.
-    // The IC expects the property name in ecx and the receiver on the stack.
+  if (key->IsPropertyName()) {
+    // Do a named property load.  The IC expects the property name in ecx
+    // and the receiver on the stack.
     __ mov(ecx, Immediate(key->AsLiteral()->handle()));
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
     // By emitting a nop we make sure that we do not have a test eax
     // instruction after the call it is treated specially by the LoadIC code.
     __ nop();
+    DropAndApply(1, expr->context(), eax);
   } else {
-    // Do a KEYED property load.
+    // Do a keyed property load.
     Visit(expr->key());
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
@@ -1064,9 +1023,8 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
     // instruction after the call it is treated specially by the LoadIC code.
     __ nop();
     // Drop key left on the stack by IC.
-    __ add(Operand(esp), Immediate(kPointerSize));
+    DropAndApply(2, expr->context(), eax);
   }
-  DropAndMove(expr->context(), eax);
 }
 
 
@@ -1088,7 +1046,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
   __ call(ic, mode);
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  Move(expr->context(), eax);
+  Apply(expr->context(), eax);
 }
 
 
@@ -1105,7 +1063,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
   __ CallStub(&stub);
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  DropAndMove(expr->context(), eax);
+  DropAndApply(1, expr->context(), eax);
 }
 
 
@@ -1146,7 +1104,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
       // instruction after the call it is treated specially by the LoadIC code.
       __ nop();
       // Drop key left on the stack by IC.
-      __ add(Operand(esp), Immediate(kPointerSize));
+      __ Drop(1);
       // Pop receiver.
       __ pop(ebx);
       // Push result (function).
@@ -1214,7 +1172,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
   __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
 
   // Replace function on TOS with result in eax, or pop it.
-  DropAndMove(expr->context(), eax);
+  DropAndApply(1, expr->context(), eax);
 }
 
 
@@ -1247,7 +1205,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
     // Call the C runtime function.
     __ CallRuntime(expr->function(), arg_count);
   }
-  Move(expr->context(), eax);
+  Apply(expr->context(), eax);
 }
 
 
@@ -1369,7 +1327,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       }
 
       __ CallRuntime(Runtime::kTypeof, 1);
-      Move(expr->context(), eax);
+      Apply(expr->context(), eax);
       break;
     }
 
@@ -1469,7 +1427,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
         // For all contexts except kEffect: We have the result on
         // top of the stack.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
@@ -1486,10 +1444,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
       if (expr->is_postfix()) {
         __ Drop(1);  // Result is on the stack under the receiver.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
-        DropAndMove(expr->context(), eax);
+        DropAndApply(1, expr->context(), eax);
       }
       break;
     }
@@ -1502,10 +1460,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
       if (expr->is_postfix()) {
         __ Drop(2);  // Result is on the stack under the key and the receiver.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
-        DropAndMove(expr->context(), eax, 2);
+        DropAndApply(2, expr->context(), eax);
       }
       break;
     }
@@ -1548,7 +1506,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
                                NO_OVERWRITE,
                                NO_GENERIC_BINARY_FLAGS);
       __ CallStub(&stub);
-      Move(expr->context(), eax);
+      Apply(expr->context(), eax);
 
       break;
     }
@@ -1719,7 +1677,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
 
 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  Move(expr->context(), eax);
+  Apply(expr->context(), eax);
 }
 
 
index c78c769..ceecebf 100644 (file)
@@ -368,6 +368,8 @@ class MacroAssembler: public Assembler {
 
   void Ret();
 
+  // Emit code to discard a non-negative number of pointer-sized elements
+  // from the stack, clobbering only the esp register.
   void Drop(int element_count);
 
   void Call(Label* target) { call(target); }
index 73ebc30..904d02d 100644 (file)
@@ -4256,15 +4256,7 @@ void CodeGenerator::LoadReference(Reference* ref) {
     // The expression is either a property or a variable proxy that rewrites
     // to a property.
     Load(property->obj());
-    // We use a named reference if the key is a literal symbol, unless it is
-    // a string that can be legally parsed as an integer.  This is because
-    // otherwise we will not get into the slow case code that handles [] on
-    // String objects.
-    Literal* literal = property->key()->AsLiteral();
-    uint32_t dummy;
-    if (literal != NULL &&
-        literal->handle()->IsSymbol() &&
-        !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
+    if (property->key()->IsPropertyName()) {
       ref->set_type(Reference::NAMED);
     } else {
       Load(property->key());
index a9940bb..fea0cdb 100644 (file)
@@ -202,57 +202,106 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
 }
 
 
-void FastCodeGenerator::Move(Expression::Context context, Register source) {
+void FastCodeGenerator::Apply(Expression::Context context,
+                              Slot* slot,
+                              Register scratch) {
+  switch (context) {
+    case Expression::kUninitialized:
+      UNREACHABLE();
+    case Expression::kEffect:
+      break;
+    case Expression::kValue: {
+      MemOperand location = EmitSlotSearch(slot, scratch);
+      __ push(location);
+      break;
+    }
+    case Expression::kTest:
+    case Expression::kValueTest:
+    case Expression::kTestValue:
+      Move(scratch, slot);
+      Apply(context, scratch);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
   switch (context) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
       break;
     case Expression::kValue:
-      __ push(source);
+      __ Push(lit->handle());
       break;
     case Expression::kTest:
-      TestAndBranch(source, true_label_, false_label_);
+    case Expression::kValueTest:
+    case Expression::kTestValue:
+      __ Move(rax, lit->handle());
+      Apply(context, rax);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::ApplyTOS(Expression::Context context) {
+  switch (context) {
+    case Expression::kUninitialized:
+      UNREACHABLE();
+    case Expression::kEffect:
+      __ Drop(1);
+      break;
+    case Expression::kValue:
+      break;
+    case Expression::kTest:
+      __ pop(rax);
+      TestAndBranch(rax, true_label_, false_label_);
       break;
     case Expression::kValueTest: {
       Label discard;
-      __ push(source);
-      TestAndBranch(source, true_label_, &discard);
+      __ movq(rax, Operand(rsp, 0));
+      TestAndBranch(rax, true_label_, &discard);
       __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
     case Expression::kTestValue: {
       Label discard;
-      __ push(source);
-      TestAndBranch(source, &discard, false_label_);
+      __ movq(rax, Operand(rsp, 0));
+      TestAndBranch(rax, &discard, false_label_);
       __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(true_label_);
-      break;
     }
   }
 }
 
 
-void FastCodeGenerator::MoveTOS(Expression::Context context) {
+void FastCodeGenerator::DropAndApply(int count,
+                                     Expression::Context context,
+                                     Register reg) {
+  ASSERT(count > 0);
+  ASSERT(!reg.is(rsp));
   switch (context) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      __ Drop(1);
+      __ Drop(count);
       break;
     case Expression::kValue:
+      if (count > 1) __ Drop(count - 1);
+      __ movq(Operand(rsp, 0), reg);
       break;
     case Expression::kTest:
-      __ pop(rax);
-      TestAndBranch(rax, true_label_, false_label_);
+      __ Drop(count);
+      TestAndBranch(reg, true_label_, false_label_);
       break;
     case Expression::kValueTest: {
       Label discard;
-      __ movq(rax, Operand(rsp, 0));
-      TestAndBranch(rax, true_label_, &discard);
+      if (count > 1) __ Drop(count - 1);
+      __ movq(Operand(rsp, 0), reg);
+      TestAndBranch(reg, true_label_, &discard);
       __ bind(&discard);
       __ Drop(1);
       __ jmp(false_label_);
@@ -260,11 +309,13 @@ void FastCodeGenerator::MoveTOS(Expression::Context context) {
     }
     case Expression::kTestValue: {
       Label discard;
-      __ movq(rax, Operand(rsp, 0));
-      TestAndBranch(rax, &discard, false_label_);
+      if (count > 1) __ Drop(count - 1);
+      __ movq(Operand(rsp, 0), reg);
+      TestAndBranch(reg, &discard, false_label_);
       __ bind(&discard);
       __ Drop(1);
       __ jmp(true_label_);
+      break;
     }
   }
 }
@@ -295,48 +346,6 @@ void FastCodeGenerator::Move(Register destination, Slot* source) {
 }
 
 
-void FastCodeGenerator::Move(Expression::Context context,
-                             Slot* source,
-                             Register scratch) {
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      break;
-    case Expression::kValue: {
-      MemOperand location = EmitSlotSearch(source, scratch);
-      __ push(location);
-      break;
-    }
-    case Expression::kTest:
-    case Expression::kValueTest:
-    case Expression::kTestValue:
-      Move(scratch, source);
-      Move(context, scratch);
-      break;
-  }
-}
-
-
-void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      break;
-    case Expression::kValue:
-      __ Push(expr->handle());
-      break;
-    case Expression::kTest:
-    case Expression::kValueTest:
-    case Expression::kTestValue:
-      __ Move(rax, expr->handle());
-      Move(context, rax);
-      break;
-  }
-}
-
-
 void FastCodeGenerator::Move(Slot* dst,
                              Register src,
                              Register scratch1,
@@ -353,52 +362,6 @@ void FastCodeGenerator::Move(Slot* dst,
 }
 
 
-void FastCodeGenerator::DropAndMove(Expression::Context context,
-                                    Register source,
-                                    int drop_count) {
-  ASSERT(drop_count > 0);
-  switch (context) {
-    case Expression::kUninitialized:
-      UNREACHABLE();
-    case Expression::kEffect:
-      __ addq(rsp, Immediate(drop_count * kPointerSize));
-      break;
-    case Expression::kValue:
-      if (drop_count > 1) {
-        __ addq(rsp, Immediate((drop_count - 1) * kPointerSize));
-      }
-      __ movq(Operand(rsp, 0), source);
-      break;
-    case Expression::kTest:
-      ASSERT(!source.is(rsp));
-      __ addq(rsp, Immediate(drop_count * kPointerSize));
-      TestAndBranch(source, true_label_, false_label_);
-      break;
-    case Expression::kValueTest: {
-      Label discard;
-      if (drop_count > 1) {
-        __ addq(rsp, Immediate((drop_count - 1) * kPointerSize));
-      }
-      __ movq(Operand(rsp, 0), source);
-      TestAndBranch(source, true_label_, &discard);
-      __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
-      __ jmp(false_label_);
-      break;
-    }
-    case Expression::kTestValue: {
-      Label discard;
-      __ movq(Operand(rsp, 0), source);
-      TestAndBranch(source, &discard, false_label_);
-      __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
-      __ jmp(true_label_);
-      break;
-    }
-  }
-}
-
-
 void FastCodeGenerator::TestAndBranch(Register source,
                                       Label* true_label,
                                       Label* false_label) {
@@ -528,7 +491,7 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
 
       // Value in rax is ignored (declarations are statements).  Receiver
       // and key on stack are discarded.
-      __ addq(rsp, Immediate(2 * kPointerSize));
+      __ Drop(2);
     }
   }
 }
@@ -558,7 +521,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   __ push(rsi);
   __ Push(boilerplate);
   __ CallRuntime(Runtime::kNewClosure, 2);
-  Move(expr->context(), rax);
+  Apply(expr->context(), rax);
 }
 
 
@@ -585,7 +548,7 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
     // is no test rax instruction here.
     __ nop();
 
-    DropAndMove(context, rax);
+    DropAndApply(1, context, rax);
   } else if (rewrite->AsSlot() != NULL) {
     Slot* slot = rewrite->AsSlot();
     if (FLAG_debug_code) {
@@ -604,41 +567,43 @@ void FastCodeGenerator::EmitVariableLoad(Variable* var,
           break;
       }
     }
-    Move(context, slot, rax);
+    Apply(context, slot, rax);
   } else {
-    // A variable has been rewritten into an explicit access to
-    // an object property.
+    Comment cmnt(masm_, "Variable rewritten to property");
+    // A variable has been rewritten into an explicit access to an object
+    // property.
     Property* property = rewrite->AsProperty();
     ASSERT_NOT_NULL(property);
 
-    // Currently the only parameter expressions that can occur are
-    // on the form "slot[literal]".
+    // The only property expressions that can occur are of the form
+    // "slot[literal]".
 
-    // Check that the object is in a slot.
+    // Assert that the object is in a slot.
     Variable* object = property->obj()->AsVariableProxy()->AsVariable();
     ASSERT_NOT_NULL(object);
     Slot* object_slot = object->slot();
     ASSERT_NOT_NULL(object_slot);
 
     // Load the object.
-    Move(Expression::kValue, object_slot, rax);
+    MemOperand object_loc = EmitSlotSearch(object_slot, rax);
+    __ push(object_loc);
 
-    // Check that the key is a smi.
+    // Assert that the key is a smi.
     Literal* key_literal = property->key()->AsLiteral();
     ASSERT_NOT_NULL(key_literal);
     ASSERT(key_literal->handle()->IsSmi());
 
     // Load the key.
-    Move(Expression::kValue, key_literal);
+    __ Push(key_literal->handle());
 
-    // Do a KEYED property load.
+    // Do a keyed property load.
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
-    // Notice: We must not have a "test rax, ..." instruction after
-    // the call. It is treated specially by the LoadIC code.
+    // Notice: We must not have a "test rax, ..." instruction after the
+    // call. It is treated specially by the LoadIC code.
 
     // Drop key and object left on the stack by IC, and push the result.
-    DropAndMove(context, rax, 2);
+    DropAndApply(2, context, rax);
   }
 }
 
@@ -666,7 +631,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   // Label done:
   __ bind(&done);
-  Move(expr->context(), rax);
+  Apply(expr->context(), rax);
 }
 
 
@@ -742,7 +707,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      if (result_saved) __ addq(rsp, Immediate(kPointerSize));
+      if (result_saved) __ Drop(1);
       break;
     case Expression::kValue:
       if (!result_saved) __ push(rax);
@@ -756,7 +721,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       if (!result_saved) __ push(rax);
       TestAndBranch(rax, true_label_, &discard);
       __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
@@ -765,7 +730,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       if (!result_saved) __ push(rax);
       TestAndBranch(rax, &discard, false_label_);
       __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(true_label_);
       break;
     }
@@ -821,7 +786,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     case Expression::kUninitialized:
       UNREACHABLE();
     case Expression::kEffect:
-      if (result_saved) __ addq(rsp, Immediate(kPointerSize));
+      if (result_saved) __ Drop(1);
       break;
     case Expression::kValue:
       if (!result_saved) __ push(rax);
@@ -835,7 +800,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
       if (!result_saved) __ push(rax);
       TestAndBranch(rax, true_label_, &discard);
       __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(false_label_);
       break;
     }
@@ -844,7 +809,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
       if (!result_saved) __ push(rax);
       TestAndBranch(rax, &discard, false_label_);
       __ bind(&discard);
-      __ addq(rsp, Immediate(kPointerSize));
+      __ Drop(1);
       __ jmp(true_label_);
       break;
     }
@@ -859,7 +824,7 @@ void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
   __ Move(rcx, key->handle());
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
-  Move(context, rax);
+  Apply(context, rax);
 }
 
 
@@ -868,7 +833,7 @@ void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop,
   SetSourcePosition(prop->position());
   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
-  Move(context, rax);
+  Apply(context, rax);
 }
 
 
@@ -878,7 +843,7 @@ void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
                            NO_OVERWRITE,
                            NO_GENERIC_BINARY_FLAGS);
   __ CallStub(&stub);
-  Move(context, rax);
+  Apply(context, rax);
 }
 
 
@@ -896,7 +861,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
     Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // Overwrite the global object on the stack with the result if needed.
-    DropAndMove(context, rax);
+    DropAndApply(1, context, rax);
 
   } else if (var->slot() != NULL) {
     Slot* slot = var->slot();
@@ -928,7 +893,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
             __ movq(target, rax);
             TestAndBranch(rax, true_label_, &discard);
             __ bind(&discard);
-            __ addq(rsp, Immediate(kPointerSize));
+            __ Drop(1);
             __ jmp(false_label_);
             break;
           }
@@ -938,7 +903,7 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
             __ movq(target, rax);
             TestAndBranch(rax, &discard, false_label_);
             __ bind(&discard);
-            __ addq(rsp, Immediate(kPointerSize));
+            __ Drop(1);
             __ jmp(true_label_);
             break;
           }
@@ -959,9 +924,8 @@ void FastCodeGenerator::EmitVariableAssignment(Variable* var,
         }
         int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
         __ RecordWrite(rcx, offset, rax, rbx);
-        if (context != Expression::kEffect &&
-            context != Expression::kValue) {
-          Move(context, rdx);
+        if (context != Expression::kEffect && context != Expression::kValue) {
+          Apply(context, rdx);
         }
         break;
       }
@@ -1005,7 +969,7 @@ void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
     __ pop(rax);
   }
 
-  DropAndMove(expr->context(), rax);
+  DropAndApply(1, expr->context(), rax);
 }
 
 
@@ -1038,15 +1002,13 @@ void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   }
 
   // Receiver and key are still on stack.
-  __ addq(rsp, Immediate(2 * kPointerSize));
-  Move(expr->context(), rax);
+  DropAndApply(2, expr->context(), rax);
 }
 
 
 void FastCodeGenerator::VisitProperty(Property* expr) {
   Comment cmnt(masm_, "[ Property");
   Expression* key = expr->key();
-  uint32_t dummy;
 
   // Record the source position for the property load.
   SetSourcePosition(expr->position());
@@ -1054,29 +1016,27 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
   // Evaluate receiver.
   Visit(expr->obj());
 
-
-  if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() &&
-      !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) {
-    // Do a NAMED property load.
-    // The IC expects the property name in rcx and the receiver on the stack.
+  if (key->IsPropertyName()) {
+    // Do a named property load.  The IC expects the property name in rcx
+    // and the receiver on the stack.
     __ Move(rcx, key->AsLiteral()->handle());
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
     // By emitting a nop we make sure that we do not have a "test rax,..."
     // instruction after the call it is treated specially by the LoadIC code.
     __ nop();
+    DropAndApply(1, expr->context(), rax);
   } else {
-    // Do a KEYED property load.
+    // Do a keyed property load.
     Visit(expr->key());
     Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
     __ call(ic, RelocInfo::CODE_TARGET);
-    // Notice: We must not have a "test rax, ..." instruction after
-    // the call. It is treated specially by the LoadIC code.
-
-    // Drop key left on the stack by IC.
-    __ addq(rsp, Immediate(kPointerSize));
+    // Notice: We must not have a "test rax, ..." instruction after the
+    // call. It is treated specially by the LoadIC code.
+    __ nop();
+    // Drop key and receiver left on the stack by IC.
+    DropAndApply(2, expr->context(), rax);
   }
-  DropAndMove(expr->context(), rax);
 }
 
 
@@ -1099,7 +1059,7 @@ void FastCodeGenerator::EmitCallWithIC(Call* expr,
   // Restore context register.
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndMove(expr->context(), rax);
+  DropAndApply(1, expr->context(), rax);
 }
 
 
@@ -1117,7 +1077,7 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
   // Restore context register.
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  DropAndMove(expr->context(), rax);
+  DropAndApply(1, expr->context(), rax);
 }
 
 
@@ -1161,7 +1121,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
       // instruction after the call it is treated specially by the LoadIC code.
       __ nop();
       // Drop key left on the stack by IC.
-      __ addq(rsp, Immediate(kPointerSize));
+      __ Drop(1);
       // Pop receiver.
       __ pop(rbx);
       // Push result (function).
@@ -1230,7 +1190,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* expr) {
   __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
 
   // Replace function on TOS with result in rax, or pop it.
-  DropAndMove(expr->context(), rax);
+  DropAndApply(1, expr->context(), rax);
 }
 
 
@@ -1260,10 +1220,10 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
     // Restore context register.
     __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
     // Discard the function left on TOS.
-    DropAndMove(expr->context(), rax);
+    DropAndApply(1, expr->context(), rax);
   } else {
     __ CallRuntime(expr->function(), arg_count);
-    Move(expr->context(), rax);
+    Apply(expr->context(), rax);
   }
 }
 
@@ -1386,7 +1346,7 @@ void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
       }
 
       __ CallRuntime(Runtime::kTypeof, 1);
-      Move(expr->context(), rax);
+      Apply(expr->context(), rax);
       break;
     }
 
@@ -1486,7 +1446,7 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
         // For all contexts except kEffect: We have the result on
         // top of the stack.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
@@ -1503,10 +1463,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
       if (expr->is_postfix()) {
         __ Drop(1);  // Result is on the stack under the receiver.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
-        DropAndMove(expr->context(), rax);
+        DropAndApply(1, expr->context(), rax);
       }
       break;
     }
@@ -1519,10 +1479,10 @@ void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
       if (expr->is_postfix()) {
         __ Drop(2);  // Result is on the stack under the key and the receiver.
         if (expr->context() != Expression::kEffect) {
-          MoveTOS(expr->context());
+          ApplyTOS(expr->context());
         }
       } else {
-        DropAndMove(expr->context(), rax, 2);
+        DropAndApply(2, expr->context(), rax);
       }
       break;
     }
@@ -1564,7 +1524,7 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
                                NO_OVERWRITE,
                                NO_GENERIC_BINARY_FLAGS);
       __ CallStub(&stub);
-      Move(expr->context(), rax);
+      Apply(expr->context(), rax);
 
       break;
     }
@@ -1732,7 +1692,7 @@ void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
 
 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  Move(expr->context(), rax);
+  Apply(expr->context(), rax);
 }
 
 
index 24b3037..37f96a6 100644 (file)
@@ -415,7 +415,11 @@ class MacroAssembler: public Assembler {
   void Cmp(Register dst, Handle<Object> source);
   void Cmp(const Operand& dst, Handle<Object> source);
   void Push(Handle<Object> source);
+
+  // Emit code to discard a non-negative number of pointer-sized elements
+  // from the stack, clobbering only the rsp register.
   void Drop(int stack_elements);
+
   void Call(Label* target) { call(target); }
 
   // Control Flow