From 76e1e22f152c0d5c2a10185222fa63d8ef6921a8 Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Tue, 27 Oct 2009 08:48:01 +0000 Subject: [PATCH] Eliminate the constant location used for literals in the AST. Literals now have a location of temporary by default and are responsible for moving themselves into their location like all other expressions. The constant location turned out not to allow us to avoid checking subexpressions in AST interior nodes, and it turned out to require checking after some normal calls to Visit (like for the arguments to a call). With this change do not have to check after a call to Visit that we got our result in the expected location. Review URL: http://codereview.chromium.org/339004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3137 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/fast-codegen-arm.cc | 148 +++++++++++++++------------------- src/compiler.cc | 3 +- src/fast-codegen.cc | 5 -- src/ia32/fast-codegen-ia32.cc | 143 +++++++++++++++----------------- src/location.h | 4 +- src/x64/fast-codegen-x64.cc | 143 +++++++++++++++----------------- 6 files changed, 198 insertions(+), 248 deletions(-) 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);