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
This commit is contained in:
kmillikin@chromium.org 2009-10-27 08:48:01 +00:00
parent c84af6828b
commit 76e1e22f15
6 changed files with 198 additions and 248 deletions

View File

@ -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.
}
}
__ 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);
if (right->AsLiteral() != NULL) {
if (destination.is_temporary()) {
__ mov(ip, Operand(right->AsLiteral()->handle()));
__ push(ip);
} else if (destination.is_nowhere() && right_source.is_temporary()) {
} 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);

View File

@ -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.
}

View File

@ -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();
}

View File

@ -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.
}
}
__ 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);
if (right->AsLiteral() != NULL) {
if (destination.is_temporary()) {
__ push(Immediate(right->AsLiteral()->handle()));
} else if (destination.is_nowhere() && right_source.is_temporary()) {
} 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);

View File

@ -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) {}

View File

@ -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.
}
}
__ 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);
if (right->AsLiteral() != NULL) {
if (destination.is_temporary()) {
__ Push(right->AsLiteral()->handle());
} else if (destination.is_nowhere() && right_source.is_temporary()) {
} 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);