| Index: src/x64/fast-codegen-x64.cc | 
| =================================================================== | 
| --- src/x64/fast-codegen-x64.cc	(revision 3079) | 
| +++ src/x64/fast-codegen-x64.cc	(working copy) | 
| @@ -112,8 +112,19 @@ | 
| void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 
| Comment cmnt(masm_, "[ ReturnStatement"); | 
| SetStatementPosition(stmt); | 
| -  Visit(stmt->expression()); | 
| -  __ pop(rax); | 
| +  Expression* expr = stmt->expression(); | 
| +  Visit(expr); | 
| + | 
| +  // Complete the statement based on the location of the subexpression. | 
| +  Location source = expr->location(); | 
| +  ASSERT(!source.is_nowhere()); | 
| +  if (source.is_temporary()) { | 
| +    __ pop(rax); | 
| +  } else { | 
| +    ASSERT(source.is_constant()); | 
| +    ASSERT(expr->AsLiteral() != NULL); | 
| +    __ Move(rax, expr->AsLiteral()->handle()); | 
| +  } | 
| __ RecordJSReturn(); | 
| // Do not use the leave instruction here because it is too short to | 
| // patch with the code required by the debugger. | 
| @@ -149,31 +160,45 @@ | 
| } | 
|  | 
|  | 
| -void FastCodeGenerator::VisitLiteral(Literal* expr) { | 
| -  Comment cmnt(masm_, "[ Literal"); | 
| -  if (expr->location().is_temporary()) { | 
| -    __ Push(expr->handle()); | 
| -  } else { | 
| -    ASSERT(expr->location().is_nowhere()); | 
| -  } | 
| -} | 
| - | 
| - | 
| void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 
| Comment cmnt(masm_, "[ Assignment"); | 
| ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 
| +  Expression* rhs = expr->value(); | 
| +  Visit(rhs); | 
|  | 
| -  Visit(expr->value()); | 
| - | 
| +  // Left-hand side is always a (parameter or local) slot. | 
| Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 
| ASSERT(var != NULL && var->slot() != NULL); | 
|  | 
| -  if (expr->location().is_temporary()) { | 
| -    __ movq(rax, Operand(rsp, 0)); | 
| -    __ movq(Operand(rbp, SlotOffset(var->slot())), rax); | 
| +  // Complete the assignment based on the location of the right-hand-side | 
| +  // value and the desired location of the assignment value. | 
| +  Location destination = expr->location(); | 
| +  Location source = rhs->location(); | 
| +  ASSERT(!destination.is_constant()); | 
| +  ASSERT(!source.is_nowhere()); | 
| + | 
| +  if (source.is_temporary()) { | 
| +    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()))); | 
| +    } | 
| } else { | 
| -    ASSERT(expr->location().is_nowhere()); | 
| -    __ pop(Operand(rbp, SlotOffset(var->slot()))); | 
| +    ASSERT(source.is_constant()); | 
| +    ASSERT(rhs->AsLiteral() != NULL); | 
| +    // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 
| +    // 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); | 
| +    } | 
| } | 
| } | 
|  | 
|  |