diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc index 0565862f09..e5d9bd18fc 100644 --- a/src/arm/fast-codegen-arm.cc +++ b/src/arm/fast-codegen-arm.cc @@ -149,22 +149,16 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { Comment cmnt(masm_, "[ ReturnStatement"); SetStatementPosition(stmt); 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(r0); - } else { - ASSERT(source.is_constant()); - ASSERT(expr->AsLiteral() != NULL); + // Complete the statement based on the type of the subexpression. + if (expr->AsLiteral() != NULL) { __ mov(r0, Operand(expr->AsLiteral()->handle())); + } else { + Visit(expr); + ASSERT(expr->location().is_temporary()); + __ pop(r0); } if (FLAG_trace) { - // Push the return value on the stack as the parameter. - // Runtime::TraceExit returns its parameter in r0. __ push(r0); __ CallRuntime(Runtime::kTraceExit, 1); } @@ -234,6 +228,16 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } +void FastCodeGenerator::VisitLiteral(Literal* expr) { + if (expr->location().is_temporary()) { + __ mov(ip, Operand(expr->AsLiteral()->handle())); + __ push(ip); + } else { + ASSERT(expr->location().is_nowhere()); + } +} + + void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { Comment cmnt(masm_, "[ ObjectLiteral"); Label boilerplate_exists; @@ -288,10 +292,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case ObjectLiteral::Property::PROTOTYPE: __ push(r0); Visit(key); - if (key->location().is_constant()) { - __ mov(r1, Operand(key->handle())); - __ push(r1); - } + ASSERT(key->location().is_temporary()); Visit(value); ASSERT(value->location().is_temporary()); __ CallRuntime(Runtime::kSetProperty, 3); @@ -301,10 +302,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case ObjectLiteral::Property::GETTER: __ push(r0); Visit(key); - if (key->location().is_constant()) { - __ mov(r1, Operand(key->handle())); - __ push(r1); - } + ASSERT(key->location().is_temporary()); __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? Smi::FromInt(1) : Smi::FromInt(0))); @@ -433,31 +431,26 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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); // Left-hand side can only be a global or a (parameter or local) slot. Variable* var = expr->target()->AsVariableProxy()->AsVariable(); ASSERT(var != NULL); ASSERT(var->is_global() || var->slot() != NULL); - // Complete the assignment based on the location of the right-hand-side - // value and the desired location of the assignment value. + Expression* rhs = expr->value(); Location destination = expr->location(); - Location source = rhs->location(); - ASSERT(!destination.is_constant()); - ASSERT(!source.is_nowhere()); - if (var->is_global()) { // Assignment to a global variable, use inline caching. Right-hand-side // value is passed in r0, variable name in r2, and the global object on // the stack. - if (source.is_temporary()) { - __ pop(r0); - } else { - ASSERT(source.is_constant()); - ASSERT(rhs->AsLiteral() != NULL); + + // Code for the right-hand-side expression depends on its type. + if (rhs->AsLiteral() != NULL) { __ mov(r0, Operand(rhs->AsLiteral()->handle())); + } else { + ASSERT(rhs->location().is_temporary()); + Visit(rhs); + __ pop(r0); } __ mov(r2, Operand(var->name())); __ ldr(ip, CodeGenerator::GlobalObject()); @@ -473,7 +466,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { } } else { - if (source.is_temporary()) { + // Local or parameter assignment. + + // Code for the right-hand side expression depends on its type. + if (rhs->AsLiteral() != NULL) { + // Two cases: 'temp <- (var = constant)', or 'var = constant' with a + // 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); + } + } else { + ASSERT(rhs->location().is_temporary()); + Visit(rhs); if (destination.is_temporary()) { // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side // temporary on the stack. @@ -484,17 +491,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { __ pop(ip); } __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); - } else { - ASSERT(source.is_constant()); - ASSERT(rhs->AsLiteral() != NULL); - // Two cases: 'temp <- (var = constant)', or 'var = constant' with a - // 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); - } } } } @@ -515,12 +511,7 @@ void FastCodeGenerator::VisitCall(Call* expr) { int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { Visit(args->at(i)); - ASSERT(!args->at(i)->location().is_nowhere()); - if (args->at(i)->location().is_constant()) { - ASSERT(args->at(i)->AsLiteral() != NULL); - __ mov(r0, Operand(args->at(i)->AsLiteral()->handle())); - __ push(r0); - } + ASSERT(args->at(i)->location().is_temporary()); } // Record source position for debugger SetSourcePosition(expr->position()); @@ -550,16 +541,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { Visit(args->at(i)); - ASSERT(!args->at(i)->location().is_nowhere()); - if (args->at(i)->location().is_constant()) { - ASSERT(args->at(i)->AsLiteral() != NULL); - __ mov(r0, Operand(args->at(i)->AsLiteral()->handle())); - __ push(r0); - } else { - ASSERT(args->at(i)->location().is_temporary()); - // If location is temporary, it is already on the stack, - // so nothing to do here. - } + ASSERT(args->at(i)->location().is_temporary()); } __ CallRuntime(function, arg_count); @@ -580,30 +562,23 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { Label done; Location destination = expr->location(); - ASSERT(!destination.is_constant()); - Expression* left = expr->left(); - Location left_source = left->location(); - ASSERT(!left_source.is_nowhere()); - Expression* right = expr->right(); - Location right_source = right->location(); - ASSERT(!right_source.is_nowhere()); - Visit(left); // Call the runtime to find the boolean value of the left-hand // subexpression. Duplicate the value if it may be needed as the final // result. - if (left_source.is_temporary()) { + if (left->AsLiteral() != NULL) { + __ mov(r0, Operand(left->AsLiteral()->handle())); + __ push(r0); + if (destination.is_temporary()) __ push(r0); + } else { + Visit(left); + ASSERT(left->location().is_temporary()); if (destination.is_temporary()) { __ ldr(r0, MemOperand(sp)); __ push(r0); } - } else { - ASSERT(left->AsLiteral() != NULL); - __ mov(r0, Operand(left->AsLiteral()->handle())); - __ push(r0); - if (destination.is_temporary()) __ push(r0); } // The left-hand value is in on top of the stack. It is duplicated on the // stack iff the destination location is temporary. @@ -614,15 +589,22 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { // Discard the left-hand value if present on the stack. if (destination.is_temporary()) __ pop(); - Visit(right); - // Save or discard the right-hand value as needed. - if (destination.is_temporary() && right_source.is_constant()) { - ASSERT(right->AsLiteral() != NULL); - __ mov(ip, Operand(right->AsLiteral()->handle())); - __ push(ip); - } else if (destination.is_nowhere() && right_source.is_temporary()) { - __ pop(); + if (right->AsLiteral() != NULL) { + if (destination.is_temporary()) { + __ mov(ip, Operand(right->AsLiteral()->handle())); + __ push(ip); + } else { + ASSERT(destination.is_nowhere()); + } + } else { + Visit(right); + ASSERT(right->location().is_temporary()); + if (destination.is_nowhere()) { + __ pop(); + } else { + ASSERT(destination.is_temporary()); + } } __ bind(&done); diff --git a/src/compiler.cc b/src/compiler.cc index fb32c3989a..436e429bc7 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -628,8 +628,7 @@ void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) { void CodeGenSelector::VisitLiteral(Literal* expr) { - // All literals are supported. - expr->set_location(Location::Constant()); + // Literals are supported. } diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc index 3657a6b6eb..d5952e5b3d 100644 --- a/src/fast-codegen.cc +++ b/src/fast-codegen.cc @@ -279,11 +279,6 @@ void FastCodeGenerator::VisitSlot(Slot* expr) { } -void FastCodeGenerator::VisitLiteral(Literal* expr) { - // No code is emitted (here) for simple literals. -} - - void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { UNREACHABLE(); } diff --git a/src/ia32/fast-codegen-ia32.cc b/src/ia32/fast-codegen-ia32.cc index ceeaff2eaa..ee940b3c5d 100644 --- a/src/ia32/fast-codegen-ia32.cc +++ b/src/ia32/fast-codegen-ia32.cc @@ -136,18 +136,15 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { Comment cmnt(masm_, "[ ReturnStatement"); SetStatementPosition(stmt); 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(eax); - } else { - ASSERT(source.is_constant()); - ASSERT(expr->AsLiteral() != NULL); + // Complete the statement based on the type of the subexpression. + if (expr->AsLiteral() != NULL) { __ mov(eax, expr->AsLiteral()->handle()); + } else { + Visit(expr); + ASSERT(expr->location().is_temporary()); + __ pop(eax); } + if (FLAG_trace) { __ push(eax); __ CallRuntime(Runtime::kTraceExit, 1); @@ -221,6 +218,15 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } +void FastCodeGenerator::VisitLiteral(Literal* expr) { + if (expr->location().is_temporary()) { + __ push(Immediate(expr->handle())); + } else { + ASSERT(expr->location().is_nowhere()); + } +} + + void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { Comment cmnt(masm_, "[ ObjectLiteral"); Label exists; @@ -289,9 +295,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case ObjectLiteral::Property::PROTOTYPE: __ push(eax); Visit(key); - if (key->location().is_constant()) { - __ push(Immediate(key->handle())); - } + ASSERT(key->location().is_temporary()); Visit(value); ASSERT(value->location().is_temporary()); __ CallRuntime(Runtime::kSetProperty, 3); @@ -301,9 +305,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case ObjectLiteral::Property::GETTER: __ push(eax); Visit(key); - if (key->location().is_constant()) { - __ push(Immediate(key->handle())); - } + ASSERT(key->location().is_temporary()); __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? Smi::FromInt(1) : Smi::FromInt(0))); @@ -427,31 +429,26 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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); // Left-hand side can only be a global or a (parameter or local) slot. Variable* var = expr->target()->AsVariableProxy()->AsVariable(); ASSERT(var != NULL); ASSERT(var->is_global() || var->slot() != NULL); - // Complete the assignment based on the location of the right-hand-side - // value and the desired location of the assignment value. + Expression* rhs = expr->value(); Location destination = expr->location(); - Location source = rhs->location(); - ASSERT(!destination.is_constant()); - ASSERT(!source.is_nowhere()); - 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 // on the stack. - if (source.is_temporary()) { - __ pop(eax); - } else { - ASSERT(source.is_constant()); - ASSERT(rhs->AsLiteral() != NULL); + + // Code for the right-hand-side expression depends on its type. + if (rhs->AsLiteral() != NULL) { __ mov(eax, rhs->AsLiteral()->handle()); + } else { + ASSERT(rhs->location().is_temporary()); + Visit(rhs); + __ pop(eax); } __ mov(ecx, var->name()); __ push(CodeGenerator::GlobalObject()); @@ -464,10 +461,22 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ASSERT(destination.is_nowhere()); __ add(Operand(esp), Immediate(kPointerSize)); } - } else { // Local or parameter assignment. - if (source.is_temporary()) { + + // Code for the right-hand side expression depends on its type. + if (rhs->AsLiteral() != NULL) { + // Two cases: 'temp <- (var = constant)', or 'var = constant' with a + // 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); + } + } else { + ASSERT(rhs->location().is_temporary()); + Visit(rhs); if (destination.is_temporary()) { // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side // temporary on the stack. @@ -478,17 +487,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { // Case 'var = temp'. Discard right-hand-side temporary. __ pop(Operand(ebp, SlotOffset(var->slot()))); } - } else { - ASSERT(source.is_constant()); - ASSERT(rhs->AsLiteral() != NULL); - // Two cases: 'temp <- (var = constant)', or 'var = constant' with a - // 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); - } } } } @@ -507,11 +505,7 @@ void FastCodeGenerator::VisitCall(Call* expr) { int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { Visit(args->at(i)); - ASSERT(!args->at(i)->location().is_nowhere()); - if (args->at(i)->location().is_constant()) { - ASSERT(args->at(i)->AsLiteral() != NULL); - __ push(Immediate(args->at(i)->AsLiteral()->handle())); - } + ASSERT(args->at(i)->location().is_temporary()); } // Record source position for debugger SetSourcePosition(expr->position()); @@ -542,15 +536,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { Visit(args->at(i)); - ASSERT(!args->at(i)->location().is_nowhere()); - if (args->at(i)->location().is_constant()) { - ASSERT(args->at(i)->AsLiteral() != NULL); - __ push(Immediate(args->at(i)->AsLiteral()->handle())); - } else { - ASSERT(args->at(i)->location().is_temporary()); - // If location is temporary, it is already on the stack, - // so nothing to do here. - } + ASSERT(args->at(i)->location().is_temporary()); } __ CallRuntime(function, arg_count); @@ -571,21 +557,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { Label eval_right, done; Location destination = expr->location(); - ASSERT(!destination.is_constant()); - Expression* left = expr->left(); - Location left_source = left->location(); - ASSERT(!left_source.is_nowhere()); - Expression* right = expr->right(); - Location right_source = right->location(); - ASSERT(!right_source.is_nowhere()); - Visit(left); // Use the shared ToBoolean stub to find the boolean value of the // left-hand subexpression. Load the value into eax to perform some // inlined checks assumed by the stub. - if (left_source.is_temporary()) { + + // Compile the left-hand value into eax. Put it on the stack if we may + // need it as the value of the whole expression. + if (left->AsLiteral() != NULL) { + __ mov(eax, left->AsLiteral()->handle()); + if (destination.is_temporary()) __ push(eax); + } 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. @@ -595,12 +581,6 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { // final result. __ pop(eax); } - } else { - // Load the left-hand value into eax. Put it on the stack if we may - // need it. - ASSERT(left->AsLiteral() != NULL); - __ mov(eax, left->AsLiteral()->handle()); - if (destination.is_temporary()) __ push(eax); } // The left-hand value is in eax. It is also on the stack iff the // destination location is temporary. @@ -630,14 +610,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { if (destination.is_temporary()) { __ add(Operand(esp), Immediate(kPointerSize)); } - Visit(right); - // Save or discard the right-hand value as needed. - if (destination.is_temporary() && right_source.is_constant()) { - ASSERT(right->AsLiteral() != NULL); - __ push(Immediate(right->AsLiteral()->handle())); - } else if (destination.is_nowhere() && right_source.is_temporary()) { - __ add(Operand(esp), Immediate(kPointerSize)); + if (right->AsLiteral() != NULL) { + if (destination.is_temporary()) { + __ push(Immediate(right->AsLiteral()->handle())); + } else { + ASSERT(destination.is_nowhere()); + } + } else { + Visit(right); + ASSERT(right->location().is_temporary()); + if (destination.is_nowhere()) { + __ add(Operand(esp), Immediate(kPointerSize)); + } else { + ASSERT(destination.is_temporary()); + } } __ bind(&done); diff --git a/src/location.h b/src/location.h index 9702ce4e3f..1a7b5c7544 100644 --- a/src/location.h +++ b/src/location.h @@ -37,14 +37,12 @@ class Location BASE_EMBEDDED { public: static Location Temporary() { return Location(TEMP); } static Location Nowhere() { return Location(NOWHERE); } - static Location Constant() { return Location(CONSTANT); } bool is_temporary() { return type_ == TEMP; } bool is_nowhere() { return type_ == NOWHERE; } - bool is_constant() { return type_ == CONSTANT; } private: - enum Type { TEMP, NOWHERE, CONSTANT }; + enum Type { TEMP, NOWHERE }; explicit Location(Type type) : type_(type) {} diff --git a/src/x64/fast-codegen-x64.cc b/src/x64/fast-codegen-x64.cc index 7aa03e7040..98e04832f2 100644 --- a/src/x64/fast-codegen-x64.cc +++ b/src/x64/fast-codegen-x64.cc @@ -144,18 +144,15 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { Comment cmnt(masm_, "[ ReturnStatement"); SetStatementPosition(stmt); 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); + // Complete the statement based on the type of the subexpression. + if (expr->AsLiteral() != NULL) { __ Move(rax, expr->AsLiteral()->handle()); + } else { + Visit(expr); + ASSERT(expr->location().is_temporary()); + __ pop(rax); } + if (FLAG_trace) { __ push(rax); __ CallRuntime(Runtime::kTraceExit, 1); @@ -237,6 +234,15 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { } +void FastCodeGenerator::VisitLiteral(Literal* expr) { + if (expr->location().is_temporary()) { + __ Push(expr->handle()); + } else { + ASSERT(expr->location().is_nowhere()); + } +} + + void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { Comment cmnt(masm_, "[ ObjectLiteral"); Label boilerplate_exists; @@ -301,9 +307,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case ObjectLiteral::Property::PROTOTYPE: __ push(rax); Visit(key); - if (key->location().is_constant()) { - __ Push(key->handle()); - } + ASSERT(key->location().is_temporary()); Visit(value); ASSERT(value->location().is_temporary()); __ CallRuntime(Runtime::kSetProperty, 3); @@ -313,9 +317,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { case ObjectLiteral::Property::GETTER: __ push(rax); Visit(key); - if (key->location().is_constant()) { - __ Push(key->handle()); - } + ASSERT(key->location.is_temporary()); __ Push(property->kind() == ObjectLiteral::Property::SETTER ? Smi::FromInt(1) : Smi::FromInt(0)); @@ -439,31 +441,26 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 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); // Left-hand side can only be a global or a (parameter or local) slot. Variable* var = expr->target()->AsVariableProxy()->AsVariable(); ASSERT(var != NULL); ASSERT(var->is_global() || var->slot() != NULL); - // Complete the assignment based on the location of the right-hand-side - // value and the desired location of the assignment value. + Expression* rhs = expr->value(); Location destination = expr->location(); - Location source = rhs->location(); - ASSERT(!destination.is_constant()); - ASSERT(!source.is_nowhere()); - if (var->is_global()) { // Assignment to a global variable, use inline caching. Right-hand-side // value is passed in rax, variable name in rcx, and the global object // on the stack. - if (source.is_temporary()) { - __ pop(rax); - } else { - ASSERT(source.is_constant()); - ASSERT(rhs->AsLiteral() != NULL); + + // Code for the right-hand-side expression depends on its type. + if (rhs->AsLiteral() != NULL) { __ Move(rax, rhs->AsLiteral()->handle()); + } else { + ASSERT(rhs->location().is_temporary()); + Visit(rhs); + __ pop(rax); } __ Move(rcx, var->name()); __ push(CodeGenerator::GlobalObject()); @@ -476,7 +473,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { __ addq(rsp, Immediate(kPointerSize)); } } else { - if (source.is_temporary()) { + // Local or parameter assignment. + + // Code for the right-hand-side expression depends on its type. + if (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); + } + } else { + ASSERT(rhs->location().is_temporary()); + Visit(rhs); if (destination.is_temporary()) { // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary // on the stack. @@ -487,17 +498,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { // Case 'var = temp'. Discard right-hand-side temporary. __ pop(Operand(rbp, SlotOffset(var->slot()))); } - } else { - 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); - } } } } @@ -516,11 +516,7 @@ void FastCodeGenerator::VisitCall(Call* expr) { int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { Visit(args->at(i)); - ASSERT(!args->at(i)->location().is_nowhere()); - if (args->at(i)->location().is_constant()) { - ASSERT(args->at(i)->AsLiteral() != NULL); - __ Push(args->at(i)->AsLiteral()->handle()); - } + ASSERT(args->at(i)->location().is_temporary()); } // Record source position for debugger SetSourcePosition(expr->position()); @@ -551,15 +547,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { int arg_count = args->length(); for (int i = 0; i < arg_count; i++) { Visit(args->at(i)); - ASSERT(!args->at(i)->location().is_nowhere()); - if (args->at(i)->location().is_constant()) { - ASSERT(args->at(i)->AsLiteral() != NULL); - __ Push(args->at(i)->AsLiteral()->handle()); - } else { - ASSERT(args->at(i)->location().is_temporary()); - // If location is temporary, it is already on the stack, - // so nothing to do here. - } + ASSERT(args->at(i)->location().is_temporary()); } __ CallRuntime(function, arg_count); @@ -580,21 +568,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { Label eval_right, done; Location destination = expr->location(); - ASSERT(!destination.is_constant()); - Expression* left = expr->left(); - Location left_source = left->location(); - ASSERT(!left_source.is_nowhere()); - Expression* right = expr->right(); - Location right_source = right->location(); - ASSERT(!right_source.is_nowhere()); - Visit(left); // Use the shared ToBoolean stub to find the boolean value of the // left-hand subexpression. Load the value into rax to perform some // inlined checks assumed by the stub. - if (left_source.is_temporary()) { + + // Compile the left-hand value into rax. Put it on the stack if we may + // need it as the value of the whole expression. + if (left->AsLiteral() != NULL) { + __ Move(rax, left->AsLiteral()->handle()); + if (destination.is_temporary()) __ push(rax); + } 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. @@ -604,12 +592,6 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { // final result. __ pop(rax); } - } else { - // Load the left-hand value into rax. Put it on the stack if we may - // need it. - ASSERT(left->AsLiteral() != NULL); - __ Move(rax, left->AsLiteral()->handle()); - if (destination.is_temporary()) __ push(rax); } // The left-hand value is in rax. It is also on the stack iff the // destination location is temporary. @@ -640,14 +622,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { if (destination.is_temporary()) { __ addq(rsp, Immediate(kPointerSize)); } - Visit(right); - // Save or discard the right-hand value as needed. - if (destination.is_temporary() && right_source.is_constant()) { - ASSERT(right->AsLiteral() != NULL); - __ Push(right->AsLiteral()->handle()); - } else if (destination.is_nowhere() && right_source.is_temporary()) { - __ addq(rsp, Immediate(kPointerSize)); + if (right->AsLiteral() != NULL) { + if (destination.is_temporary()) { + __ Push(right->AsLiteral()->handle()); + } else { + ASSERT(destination.is_nowhere()); + } + } else { + Visit(right); + ASSERT(right->location().is_temporary()); + if (destination.is_nowhere()) { + __ addq(rsp, Immediate(kPointerSize)); + } else { + ASSERT(destination.is_temporary()); + } } __ bind(&done);