Make it more pleasant to work with expression locations in the
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 Oct 2009 13:38:57 +0000 (13:38 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 Oct 2009 13:38:57 +0000 (13:38 +0000)
top-level code generator backend.  Introduce function to move one
location to another (source cannot be nowhere); to move registers,
slots, and literals into a location; and to move a location to a
register or slot.

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

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

src/arm/fast-codegen-arm.cc
src/fast-codegen.cc
src/fast-codegen.h
src/ia32/fast-codegen-ia32.cc
src/location.h
src/x64/fast-codegen-x64.cc

index e5d9bd18fce4042cf83d4bb70165cd30e295846f..02557d37ee5c5a1042dc596a3fcfb83f8f1cbc20 100644 (file)
@@ -120,6 +120,42 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
 }
 
 
+void FastCodeGenerator::Move(Location destination, Slot* source) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+    case Location::TEMP:
+      __ ldr(ip, MemOperand(fp, SlotOffset(source)));
+      __ push(ip);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Move(Location destination, Literal* expr) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+    case Location::TEMP:
+      __ mov(ip, Operand(expr->handle()));
+      __ push(ip);
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Move(Slot* destination, Location source) {
+  switch (source.type()) {
+    case Location::NOWHERE:
+      UNREACHABLE();
+    case Location::TEMP:
+      __ pop(ip);
+      __ str(ip, MemOperand(fp, SlotOffset(destination)));
+      break;
+  }
+}
+
+
 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   // Call the runtime to declare the globals.
   // The context is the first argument.
@@ -131,20 +167,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
 }
 
 
-void FastCodeGenerator::VisitBlock(Block* stmt) {
-  Comment cmnt(masm_, "[ Block");
-  SetStatementPosition(stmt);
-  VisitStatements(stmt->statements());
-}
-
-
-void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
-  Comment cmnt(masm_, "[ ExpressionStatement");
-  SetStatementPosition(stmt);
-  Visit(stmt->expression());
-}
-
-
 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
   Comment cmnt(masm_, "[ ReturnStatement");
   SetStatementPosition(stmt);
@@ -154,8 +176,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
     __ mov(r0, Operand(expr->AsLiteral()->handle()));
   } else {
     Visit(expr);
-    ASSERT(expr->location().is_temporary());
-    __ pop(r0);
+    Move(r0, expr->location());
   }
 
   if (FLAG_trace) {
@@ -185,12 +206,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   __ mov(r0, Operand(boilerplate));
   __ stm(db_w, sp, cp.bit() | r0.bit());
   __ CallRuntime(Runtime::kNewClosure, 2);
-
-  if (expr->location().is_temporary()) {
-    __ push(r0);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), r0);
 }
 
 
@@ -206,34 +222,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
     __ mov(r2, Operand(expr->name()));
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
-    if (expr->location().is_temporary()) {
-      // Replace the global object with the result.
-      __ str(r0, MemOperand(sp));
-    } else {
-      ASSERT(expr->location().is_nowhere());
-      __ pop();
+    switch (expr->location().type()) {
+      case Location::NOWHERE:
+        __ pop();
+        break;
+      case Location::TEMP:
+        // Replace the global object with the result.
+        __ str(r0, MemOperand(sp));
+        break;
     }
 
   } else {
     Comment cmnt(masm_, "Stack slot");
-    Slot* slot = rewrite->AsSlot();
-    ASSERT(slot != NULL);
-    if (expr->location().is_temporary()) {
-      __ ldr(ip, MemOperand(fp, SlotOffset(slot)));
-      __ push(ip);
-    } else {
-      ASSERT(expr->location().is_nowhere());
-    }
-  }
-}
-
-
-void FastCodeGenerator::VisitLiteral(Literal* expr) {
-  if (expr->location().is_temporary()) {
-    __ mov(ip, Operand(expr->AsLiteral()->handle()));
-    __ push(ip);
-  } else {
-    ASSERT(expr->location().is_nowhere());
+    Move(expr->location(), rewrite->AsSlot());
   }
 }
 
@@ -315,11 +316,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       default: UNREACHABLE();
     }
   }
-  if (expr->location().is_nowhere() && result_saved) {
-    __ pop();
-  } else if (expr->location().is_temporary() && !result_saved) {
-    ASSERT(expr->location().is_temporary());
-    __ push(r0);
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      if (result_saved) __ pop();
+      break;
+    case Location::TEMP:
+      if (!result_saved) __ push(r0);
+      break;
   }
 }
 
@@ -347,11 +350,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   __ bind(&done);
-  if (expr->location().is_temporary()) {
-    __ push(r0);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), r0);
 }
 
 
@@ -419,11 +418,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     __ RecordWrite(r1, r2, r0);
   }
 
-  Location destination = expr->location();
-  if (destination.is_nowhere() && result_saved) {
-    __ pop();
-  } else if (destination.is_temporary() && !result_saved) {
-    __ push(r0);
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      if (result_saved) __ pop();
+      break;
+    case Location::TEMP:
+      if (!result_saved) __ push(r0);
+      break;
   }
 }
 
@@ -458,11 +459,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
     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.
-    if (destination.is_temporary()) {
-      __ str(r0, MemOperand(sp));
-    } else {
-      ASSERT(destination.is_nowhere());
-      __ pop();
+    switch (expr->location().type()) {
+      case Location::NOWHERE:
+        __ pop();
+        break;
+      case Location::TEMP:
+        __ str(r0, MemOperand(sp));
+        break;
     }
 
   } else {
@@ -474,22 +477,23 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
       // discarded result.  Always perform the assignment.
       __ mov(ip, Operand(rhs->AsLiteral()->handle()));
       __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
-      if (destination.is_temporary()) {
-        // Case 'temp <- (var = constant)'.  Save result.
-        __ push(ip);
-      }
+      Move(expr->location(), ip);
     } else {
       ASSERT(rhs->location().is_temporary());
       Visit(rhs);
-      if (destination.is_temporary()) {
-        // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
-        // temporary on the stack.
-        __ ldr(ip, MemOperand(sp));
-      } else {
-        ASSERT(destination.is_nowhere());
-        // Case 'var = temp'.  Discard right-hand-side temporary.
-        __ pop(ip);
+      // Load right-hand side into ip.
+      switch (expr->location().type()) {
+        case Location::NOWHERE:
+          // Case 'var = temp'.  Discard right-hand-side temporary.
+          __ pop(ip);
+          break;
+        case Location::TEMP:
+          // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
+          // temporary on the stack.
+          __ ldr(ip, MemOperand(sp));
+          break;
       }
+      // Do the slot assignment.
       __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
     }
   }
@@ -521,11 +525,13 @@ void FastCodeGenerator::VisitCall(Call* expr) {
   __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
   // Restore context register.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-  if (expr->location().is_temporary()) {
-    __ str(r0, MemOperand(sp));
-  } else {
-    ASSERT(expr->location().is_nowhere());
-    __ pop();
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      __ pop();
+      break;
+    case Location::TEMP:
+      __ str(r0, MemOperand(sp));
+      break;
   }
 }
 
@@ -545,11 +551,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   }
 
   __ CallRuntime(function, arg_count);
-  if (expr->location().is_temporary()) {
-    __ push(r0);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), r0);
 }
 
 
@@ -591,20 +593,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
   if (destination.is_temporary()) __ pop();
   // Save or discard the right-hand value as needed.
   if (right->AsLiteral() != NULL) {
-    if (destination.is_temporary()) {
-      __ mov(ip, Operand(right->AsLiteral()->handle()));
-      __ push(ip);
-    } else {
-      ASSERT(destination.is_nowhere());
-    }
+    Move(destination, right->AsLiteral());
   } else {
     Visit(right);
-    ASSERT(right->location().is_temporary());
-    if (destination.is_nowhere()) {
-      __ pop();
-    } else {
-      ASSERT(destination.is_temporary());
-    }
+    Move(destination, right->location());
   }
 
   __ bind(&done);
index d5952e5b3d457bea3ed6e1de38781e98ee50542d..a93e91140779d014ecbe57216b07bb5bcf19365d 100644 (file)
@@ -53,6 +53,7 @@ Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
 
 
 int FastCodeGenerator::SlotOffset(Slot* slot) {
+  ASSERT(slot != NULL);
   // Offset is negative because higher indexes are at lower addresses.
   int offset = -slot->index() * kPointerSize;
   // Adjust by a (parameter or local) base offset.
@@ -70,6 +71,48 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
 }
 
 
+void FastCodeGenerator::Move(Location destination, Location source) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+
+    case Location::TEMP:
+      switch (source.type()) {
+        case Location::NOWHERE:
+          UNREACHABLE();
+        case Location::TEMP:
+          break;
+      }
+      break;
+  }
+}
+
+
+// All platform macro assemblers in {ia32,x64,arm} have a push(Register)
+// function.
+void FastCodeGenerator::Move(Location destination, Register source) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+    case Location::TEMP:
+      masm_->push(source);
+      break;
+  }
+}
+
+
+// All platform macro assemblers in {ia32,x64,arm} have a pop(Register)
+// function.
+void FastCodeGenerator::Move(Register destination, Location source) {
+  switch (source.type()) {
+    case Location::NOWHERE:
+      UNREACHABLE();
+    case Location::TEMP:
+      masm_->pop(destination);
+  }
+}
+
+
 void FastCodeGenerator::VisitDeclarations(
     ZoneList<Declaration*>* declarations) {
   int length = declarations->length();
@@ -191,6 +234,20 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
 }
 
 
+void FastCodeGenerator::VisitBlock(Block* stmt) {
+  Comment cmnt(masm_, "[ Block");
+  SetStatementPosition(stmt);
+  VisitStatements(stmt->statements());
+}
+
+
+void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
+  Comment cmnt(masm_, "[ ExpressionStatement");
+  SetStatementPosition(stmt);
+  Visit(stmt->expression());
+}
+
+
 void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
   Comment cmnt(masm_, "[ EmptyStatement");
   SetStatementPosition(stmt);
@@ -279,6 +336,11 @@ void FastCodeGenerator::VisitSlot(Slot* expr) {
 }
 
 
+void FastCodeGenerator::VisitLiteral(Literal* expr) {
+  Move(expr->location(), expr);
+}
+
+
 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
   UNREACHABLE();
 }
index 42d6cde90110cba5d5d746c08206c82f58d2d4cc..c50239294fa115fd5cb8b0fe3d27bcae91c16347 100644 (file)
@@ -51,6 +51,15 @@ class FastCodeGenerator: public AstVisitor {
  private:
   int SlotOffset(Slot* slot);
 
+  void Move(Location destination, Location source);
+
+  void Move(Location destination, Register source);
+  void Move(Location destination, Slot* source);
+  void Move(Location destination, Literal* source);
+
+  void Move(Register destination, Location source);
+  void Move(Slot* destination, Location source);
+
   void VisitDeclarations(ZoneList<Declaration*>* declarations);
   Handle<JSFunction> BuildBoilerplate(FunctionLiteral* fun);
   void DeclareGlobals(Handle<FixedArray> pairs);
index ee940b3c5ddaf2e754f5b427ebb633f7b5475bab..9b53223d445b76a7e04999878eeb89db09f94d89 100644 (file)
@@ -108,6 +108,39 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
 }
 
 
+void FastCodeGenerator::Move(Location destination, Slot* source) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+    case Location::TEMP:
+      __ push(Operand(ebp, SlotOffset(source)));
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Move(Location destination, Literal* expr) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+    case Location::TEMP:
+      __ push(Immediate(expr->handle()));
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Move(Slot* destination, Location source) {
+  switch (source.type()) {
+    case Location::NOWHERE:
+      UNREACHABLE();
+    case Location::TEMP:
+      __ pop(Operand(ebp, SlotOffset(destination)));
+      break;
+  }
+}
+
+
 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   // Call the runtime to declare the globals.
   __ push(esi);  // The context is the first argument.
@@ -118,20 +151,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
 }
 
 
-void FastCodeGenerator::VisitBlock(Block* stmt) {
-  Comment cmnt(masm_, "[ Block");
-  SetStatementPosition(stmt);
-  VisitStatements(stmt->statements());
-}
-
-
-void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
-  Comment cmnt(masm_, "[ ExpressionStatement");
-  SetStatementPosition(stmt);
-  Visit(stmt->expression());
-}
-
-
 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
   Comment cmnt(masm_, "[ ReturnStatement");
   SetStatementPosition(stmt);
@@ -141,8 +160,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
     __ mov(eax, expr->AsLiteral()->handle());
   } else {
     Visit(expr);
-    ASSERT(expr->location().is_temporary());
-    __ pop(eax);
+    Move(eax, expr->location());
   }
 
   if (FLAG_trace) {
@@ -172,12 +190,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   __ push(esi);
   __ push(Immediate(boilerplate));
   __ CallRuntime(Runtime::kNewClosure, 2);
-
-  if (expr->location().is_temporary()) {
-    __ push(eax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), eax);
 }
 
 
@@ -197,32 +210,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
     // indicate that the inobject property case was inlined.  Ensure there
     // is no test eax instruction here.  Remember that the assembler may
     // choose to do peephole optimization (eg, push/pop elimination).
-    if (expr->location().is_temporary()) {
-      // Replace the global object with the result.
-      __ mov(Operand(esp, 0), eax);
-    } else {
-      ASSERT(expr->location().is_nowhere());
-      __ add(Operand(esp), Immediate(kPointerSize));
+    switch (expr->location().type()) {
+      case Location::NOWHERE:
+        __ add(Operand(esp), Immediate(kPointerSize));
+        break;
+      case Location::TEMP:
+        // Replace the global object with the result.
+        __ mov(Operand(esp, 0), eax);
+        break;
     }
 
   } else {
     Comment cmnt(masm_, "Stack slot");
-    Slot* slot = rewrite->AsSlot();
-    ASSERT(slot != NULL);
-    if (expr->location().is_temporary()) {
-      __ push(Operand(ebp, SlotOffset(slot)));
-    } else {
-      ASSERT(expr->location().is_nowhere());
-    }
-  }
-}
-
-
-void FastCodeGenerator::VisitLiteral(Literal* expr) {
-  if (expr->location().is_temporary()) {
-    __ push(Immediate(expr->handle()));
-  } else {
-    ASSERT(expr->location().is_nowhere());
+    Move(expr->location(), rewrite->AsSlot());
   }
 }
 
@@ -283,8 +283,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       case ObjectLiteral::Property::COMPUTED:
         if (key->handle()->IsSymbol()) {
           Visit(value);
-          ASSERT(value->location().is_temporary());
-          __ pop(eax);
+          Move(eax, value->location());
           __ mov(ecx, Immediate(key->handle()));
           Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
           __ call(ic, RelocInfo::CODE_TARGET);
@@ -317,10 +316,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       default: UNREACHABLE();
     }
   }
-  if (expr->location().is_nowhere() && result_saved) {
-    __ add(Operand(esp), Immediate(kPointerSize));
-  } else if (expr->location().is_temporary() && !result_saved) {
-    __ push(eax);
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
+      break;
+    case Location::TEMP:
+      if (!result_saved) __ push(eax);
+      break;
   }
 }
 
@@ -348,11 +350,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   // Label done:
   __ bind(&done);
-  if (expr->location().is_temporary()) {
-    __ push(eax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), eax);
 }
 
 
@@ -417,11 +415,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     __ RecordWrite(ebx, offset, eax, ecx);
   }
 
-  Location destination = expr->location();
-  if (destination.is_nowhere() && result_saved) {
-    __ add(Operand(esp), Immediate(kPointerSize));
-  } else if (destination.is_temporary() && !result_saved) {
-    __ push(eax);
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
+      break;
+    case Location::TEMP:
+      if (!result_saved) __ push(eax);
+      break;
   }
 }
 
@@ -436,7 +436,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
   ASSERT(var->is_global() || var->slot() != NULL);
 
   Expression* rhs = expr->value();
-  Location destination = expr->location();
   if (var->is_global()) {
     // Assignment to a global variable, use inline caching.  Right-hand-side
     // value is passed in eax, variable name in ecx, and the global object
@@ -455,11 +454,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
     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.
-    if (destination.is_temporary()) {
-      __ mov(Operand(esp, 0), eax);
-    } else {
-      ASSERT(destination.is_nowhere());
-      __ add(Operand(esp), Immediate(kPointerSize));
+    switch (expr->location().type()) {
+      case Location::NOWHERE:
+        __ add(Operand(esp), Immediate(kPointerSize));
+        break;
+      case Location::TEMP:
+        __ mov(Operand(esp, 0), eax);
+        break;
     }
   } else {
     // Local or parameter assignment.
@@ -470,22 +471,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
       // discarded result.  Always perform the assignment.
       __ mov(eax, rhs->AsLiteral()->handle());
       __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
-      if (destination.is_temporary()) {
-        // Case 'temp <- (var = constant)'.  Save result.
-        __ push(eax);
-      }
+      Move(expr->location(), eax);
     } else {
       ASSERT(rhs->location().is_temporary());
       Visit(rhs);
-      if (destination.is_temporary()) {
-        // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
-        // temporary on the stack.
-        __ mov(eax, Operand(esp, 0));
-        __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
-      } else {
-        ASSERT(destination.is_nowhere());
-        // Case 'var = temp'.  Discard right-hand-side temporary.
-        __ pop(Operand(ebp, SlotOffset(var->slot())));
+      switch (expr->location().type()) {
+        case Location::NOWHERE:
+          // Case 'var = temp'.  Discard right-hand-side temporary.
+          Move(var->slot(), rhs->location());
+          break;
+        case Location::TEMP:
+          // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
+          // temporary on the stack.
+          __ mov(eax, Operand(esp, 0));
+          __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
+          break;
       }
     }
   }
@@ -516,11 +516,13 @@ void FastCodeGenerator::VisitCall(Call* expr) {
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  if (expr->location().is_temporary()) {
-    __ mov(Operand(esp, 0), eax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-    __ add(Operand(esp), Immediate(kPointerSize));
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      __ add(Operand(esp), Immediate(kPointerSize));
+      break;
+    case Location::TEMP:
+      __ mov(Operand(esp, 0), eax);
+      break;
   }
 }
 
@@ -540,11 +542,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   }
 
   __ CallRuntime(function, arg_count);
-  if (expr->location().is_temporary()) {
-    __ push(eax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), eax);
 }
 
 
@@ -572,14 +570,17 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
   } else {
     Visit(left);
     ASSERT(left->location().is_temporary());
-    if (destination.is_temporary()) {
-      // Copy the left-hand value into eax because we may need it as the
-      // final result.
-      __ mov(eax, Operand(esp, 0));
-    } else {
-      // Pop the left-hand value into eax because we will not need it as the
-      // final result.
-      __ pop(eax);
+    switch (destination.type()) {
+      case Location::NOWHERE:
+        // Pop the left-hand value into eax because we will not need it as the
+        // final result.
+        __ pop(eax);
+        break;
+      case Location::TEMP:
+        // Copy the left-hand value into eax because we may need it as the
+        // final result.
+        __ mov(eax, Operand(esp, 0));
+        break;
     }
   }
   // The left-hand value is in eax.  It is also on the stack iff the
@@ -612,19 +613,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
   }
   // Save or discard the right-hand value as needed.
   if (right->AsLiteral() != NULL) {
-    if (destination.is_temporary()) {
-      __ push(Immediate(right->AsLiteral()->handle()));
-    } else {
-      ASSERT(destination.is_nowhere());
-    }
+    Move(destination, right->AsLiteral());
   } else {
     Visit(right);
-    ASSERT(right->location().is_temporary());
-    if (destination.is_nowhere()) {
-      __ add(Operand(esp), Immediate(kPointerSize));
-    } else {
-      ASSERT(destination.is_temporary());
-    }
+    Move(destination, right->location());
   }
 
   __ bind(&done);
index 1a7b5c7544cb70d66b1073fc02953603ea5e65c5..c4a77cb5d13fc2f59ef3b606606fd8cf27346608 100644 (file)
@@ -35,15 +35,17 @@ namespace internal {
 
 class Location BASE_EMBEDDED {
  public:
+  enum Type { NOWHERE, TEMP };
+
   static Location Temporary() { return Location(TEMP); }
   static Location Nowhere() { return Location(NOWHERE); }
 
   bool is_temporary() { return type_ == TEMP; }
   bool is_nowhere() { return type_ == NOWHERE; }
 
- private:
-  enum Type { TEMP, NOWHERE };
+  Type type() { return type_; }
 
+ private:
   explicit Location(Type type) : type_(type) {}
 
   Type type_;
index d64fb9238ef37b790a4307317c4fae60d3561323..802635feea2e132e3722aade01632429130dad88 100644 (file)
@@ -116,6 +116,39 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
 }
 
 
+void FastCodeGenerator::Move(Location destination, Slot* source) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+    case Location::TEMP:
+      __ push(Operand(rbp, SlotOffset(source)));
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Move(Location destination, Literal* expr) {
+  switch (destination.type()) {
+    case Location::NOWHERE:
+      break;
+    case Location::TEMP:
+      __ Push(expr->handle());
+      break;
+  }
+}
+
+
+void FastCodeGenerator::Move(Slot* destination, Location source) {
+  switch (source.type()) {
+    case Location::NOWHERE:
+      UNREACHABLE();
+    case Location::TEMP:
+      __ pop(Operand(rbp, SlotOffset(destination)));
+      break;
+  }
+}
+
+
 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   // Call the runtime to declare the globals.
   __ push(rsi);  // The context is the first argument.
@@ -126,20 +159,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
 }
 
 
-void FastCodeGenerator::VisitBlock(Block* stmt) {
-  Comment cmnt(masm_, "[ Block");
-  SetStatementPosition(stmt);
-  VisitStatements(stmt->statements());
-}
-
-
-void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
-  Comment cmnt(masm_, "[ ExpressionStatement");
-  SetStatementPosition(stmt);
-  Visit(stmt->expression());
-}
-
-
 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
   Comment cmnt(masm_, "[ ReturnStatement");
   SetStatementPosition(stmt);
@@ -149,8 +168,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
     __ Move(rax, expr->AsLiteral()->handle());
   } else {
     Visit(expr);
-    ASSERT(expr->location().is_temporary());
-    __ pop(rax);
+    Move(rax, expr->location());
   }
 
   if (FLAG_trace) {
@@ -189,12 +207,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   __ push(rsi);
   __ Push(boilerplate);
   __ CallRuntime(Runtime::kNewClosure, 2);
-
-  if (expr->location().is_temporary()) {
-    __ push(rax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), rax);
 }
 
 
@@ -213,32 +226,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
     // A test rax instruction following the call is used by the IC to
     // indicate that the inobject property case was inlined.  Ensure there
     // is no test rax instruction here.
-    if (expr->location().is_temporary()) {
-      // Replace the global object with the result.
-      __ movq(Operand(rsp, 0), rax);
-    } else {
-      ASSERT(expr->location().is_nowhere());
-      __ addq(rsp, Immediate(kPointerSize));
+    switch (expr->location().type()) {
+      case Location::NOWHERE:
+        __ addq(rsp, Immediate(kPointerSize));
+        break;
+      case Location::TEMP:
+        // Replace the global object with the result.
+        __ movq(Operand(rsp, 0), rax);
+        break;
     }
 
   } else {
     Comment cmnt(masm_, "Stack slot");
-    Slot* slot = rewrite->AsSlot();
-    ASSERT(slot != NULL);
-    if (expr->location().is_temporary()) {
-      __ push(Operand(rbp, SlotOffset(slot)));
-    } else {
-      ASSERT(expr->location().is_nowhere());
-    }
-  }
-}
-
-
-void FastCodeGenerator::VisitLiteral(Literal* expr) {
-  if (expr->location().is_temporary()) {
-    __ Push(expr->handle());
-  } else {
-    ASSERT(expr->location().is_nowhere());
+    Move(expr->location(), rewrite->AsSlot());
   }
 }
 
@@ -329,10 +329,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
       default: UNREACHABLE();
     }
   }
-  if (expr->location().is_nowhere() && result_saved) {
-    __ addq(rsp, Immediate(kPointerSize));
-  } else if (expr->location().is_temporary() && !result_saved) {
-    __ push(rax);
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      if (result_saved) __ addq(rsp, Immediate(kPointerSize));
+      break;
+    case Location::TEMP:
+      if (!result_saved) __ push(rax);
+      break;
   }
 }
 
@@ -360,11 +363,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
   // Label done:
   __ bind(&done);
-  if (expr->location().is_temporary()) {
-    __ push(rax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), rax);
 }
 
 
@@ -429,11 +428,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     __ RecordWrite(rbx, offset, rax, rcx);
   }
 
-  Location destination = expr->location();
-  if (destination.is_nowhere() && result_saved) {
-    __ addq(rsp, Immediate(kPointerSize));
-  } else if (destination.is_temporary() && !result_saved) {
-    __ push(rax);
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      if (result_saved) __ addq(rsp, Immediate(kPointerSize));
+      break;
+    case Location::TEMP:
+      if (!result_saved) __ push(rax);
+      break;
   }
 }
 
@@ -467,10 +468,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
     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.
-    if (destination.is_temporary()) {
-      __ movq(Operand(rsp, 0), rax);
-    } else {
-      __ addq(rsp, Immediate(kPointerSize));
+    switch (expr->location().type()) {
+      case Location::NOWHERE:
+        __ addq(rsp, Immediate(kPointerSize));
+        break;
+      case Location::TEMP:
+        __ movq(Operand(rsp, 0), rax);
+        break;
     }
   } else {
     // Local or parameter assignment.
@@ -481,22 +485,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
       // discarded result.  Always perform the assignment.
       __ Move(kScratchRegister, rhs->AsLiteral()->handle());
       __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
-      if (destination.is_temporary()) {
-        // Case 'temp <- (var = constant)'.  Save result.
-        __ push(kScratchRegister);
-      }
+      Move(expr->location(), kScratchRegister);
     } else {
       ASSERT(rhs->location().is_temporary());
       Visit(rhs);
-      if (destination.is_temporary()) {
-        // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side temporary
-        // on the stack.
-        __ movq(kScratchRegister, Operand(rsp, 0));
-        __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
-      } else {
-        ASSERT(destination.is_nowhere());
-        // Case 'var = temp'.  Discard right-hand-side temporary.
-        __ pop(Operand(rbp, SlotOffset(var->slot())));
+      switch (expr->location().type()) {
+        case Location::NOWHERE:
+          // Case 'var = temp'.  Discard right-hand-side temporary.
+          Move(var->slot(), rhs->location());
+          break;
+        case Location::TEMP:
+          // Case 'temp1 <- (var = temp0)'.  Preserve right-hand-side
+          // temporary on the stack.
+          __ movq(kScratchRegister, Operand(rsp, 0));
+          __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
+          break;
       }
     }
   }
@@ -527,11 +530,13 @@ void FastCodeGenerator::VisitCall(Call* expr) {
   // Restore context register.
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
   // Discard the function left on TOS.
-  if (expr->location().is_temporary()) {
-    __ movq(Operand(rsp, 0), rax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-    __ addq(rsp, Immediate(kPointerSize));
+  switch (expr->location().type()) {
+    case Location::NOWHERE:
+      __ addq(rsp, Immediate(kPointerSize));
+      break;
+    case Location::TEMP:
+      __ movq(Operand(rsp, 0), rax);
+      break;
   }
 }
 
@@ -551,11 +556,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   }
 
   __ CallRuntime(function, arg_count);
-  if (expr->location().is_temporary()) {
-    __ push(rax);
-  } else {
-    ASSERT(expr->location().is_nowhere());
-  }
+  Move(expr->location(), rax);
 }
 
 
@@ -583,14 +584,17 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
   } else {
     Visit(left);
     ASSERT(left->location().is_temporary());
-    if (destination.is_temporary()) {
-      // Copy the left-hand value into rax because we may need it as the
-      // final result.
-      __ movq(rax, Operand(rsp, 0));
-    } else {
-      // Pop the left-hand value into rax because we will not need it as the
-      // final result.
-      __ pop(rax);
+    switch (destination.type()) {
+      case Location::NOWHERE:
+        // Pop the left-hand value into rax because we will not need it as the
+        // final result.
+        __ pop(rax);
+        break;
+      case Location::TEMP:
+        // Copy the left-hand value into rax because we may need it as the
+        // final result.
+        __ movq(rax, Operand(rsp, 0));
+        break;
     }
   }
   // The left-hand value is in rax.  It is also on the stack iff the
@@ -624,19 +628,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
   }
   // Save or discard the right-hand value as needed.
   if (right->AsLiteral() != NULL) {
-    if (destination.is_temporary()) {
-      __ Push(right->AsLiteral()->handle());
-    } else {
-      ASSERT(destination.is_nowhere());
-    }
+    Move(destination, right->AsLiteral());
   } else {
     Visit(right);
-    ASSERT(right->location().is_temporary());
-    if (destination.is_nowhere()) {
-      __ addq(rsp, Immediate(kPointerSize));
-    } else {
-      ASSERT(destination.is_temporary());
-    }
+    Move(destination, right->location());
   }
 
   __ bind(&done);