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"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
Expression* expr = stmt->expression(); Expression* expr = stmt->expression();
Visit(expr); // Complete the statement based on the type of the subexpression.
if (expr->AsLiteral() != NULL) {
// 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);
__ mov(r0, Operand(expr->AsLiteral()->handle())); __ mov(r0, Operand(expr->AsLiteral()->handle()));
} else {
Visit(expr);
ASSERT(expr->location().is_temporary());
__ pop(r0);
} }
if (FLAG_trace) { if (FLAG_trace) {
// Push the return value on the stack as the parameter.
// Runtime::TraceExit returns its parameter in r0.
__ push(r0); __ push(r0);
__ CallRuntime(Runtime::kTraceExit, 1); __ 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) { void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
Label boilerplate_exists; Label boilerplate_exists;
@ -288,10 +292,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE: case ObjectLiteral::Property::PROTOTYPE:
__ push(r0); __ push(r0);
Visit(key); Visit(key);
if (key->location().is_constant()) { ASSERT(key->location().is_temporary());
__ mov(r1, Operand(key->handle()));
__ push(r1);
}
Visit(value); Visit(value);
ASSERT(value->location().is_temporary()); ASSERT(value->location().is_temporary());
__ CallRuntime(Runtime::kSetProperty, 3); __ CallRuntime(Runtime::kSetProperty, 3);
@ -301,10 +302,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
__ push(r0); __ push(r0);
Visit(key); Visit(key);
if (key->location().is_constant()) { ASSERT(key->location().is_temporary());
__ mov(r1, Operand(key->handle()));
__ push(r1);
}
__ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) : Smi::FromInt(1) :
Smi::FromInt(0))); Smi::FromInt(0)));
@ -433,31 +431,26 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FastCodeGenerator::VisitAssignment(Assignment* expr) { void FastCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment"); Comment cmnt(masm_, "[ Assignment");
ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 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. // Left-hand side can only be a global or a (parameter or local) slot.
Variable* var = expr->target()->AsVariableProxy()->AsVariable(); Variable* var = expr->target()->AsVariableProxy()->AsVariable();
ASSERT(var != NULL); ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL); ASSERT(var->is_global() || var->slot() != NULL);
// Complete the assignment based on the location of the right-hand-side Expression* rhs = expr->value();
// value and the desired location of the assignment value.
Location destination = expr->location(); Location destination = expr->location();
Location source = rhs->location();
ASSERT(!destination.is_constant());
ASSERT(!source.is_nowhere());
if (var->is_global()) { if (var->is_global()) {
// Assignment to a global variable, use inline caching. Right-hand-side // 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 // value is passed in r0, variable name in r2, and the global object on
// the stack. // the stack.
if (source.is_temporary()) {
__ pop(r0); // Code for the right-hand-side expression depends on its type.
} else { if (rhs->AsLiteral() != NULL) {
ASSERT(source.is_constant());
ASSERT(rhs->AsLiteral() != NULL);
__ mov(r0, Operand(rhs->AsLiteral()->handle())); __ mov(r0, Operand(rhs->AsLiteral()->handle()));
} else {
ASSERT(rhs->location().is_temporary());
Visit(rhs);
__ pop(r0);
} }
__ mov(r2, Operand(var->name())); __ mov(r2, Operand(var->name()));
__ ldr(ip, CodeGenerator::GlobalObject()); __ ldr(ip, CodeGenerator::GlobalObject());
@ -473,7 +466,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
} }
} else { } 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()) { if (destination.is_temporary()) {
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack. // temporary on the stack.
@ -484,17 +491,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
__ pop(ip); __ pop(ip);
} }
__ str(ip, MemOperand(fp, SlotOffset(var->slot()))); __ 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(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
Visit(args->at(i)); Visit(args->at(i));
ASSERT(!args->at(i)->location().is_nowhere()); ASSERT(args->at(i)->location().is_temporary());
if (args->at(i)->location().is_constant()) {
ASSERT(args->at(i)->AsLiteral() != NULL);
__ mov(r0, Operand(args->at(i)->AsLiteral()->handle()));
__ push(r0);
}
} }
// Record source position for debugger // Record source position for debugger
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
@ -550,16 +541,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
Visit(args->at(i)); Visit(args->at(i));
ASSERT(!args->at(i)->location().is_nowhere()); ASSERT(args->at(i)->location().is_temporary());
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); __ CallRuntime(function, arg_count);
@ -580,30 +562,23 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Label done; Label done;
Location destination = expr->location(); Location destination = expr->location();
ASSERT(!destination.is_constant());
Expression* left = expr->left(); Expression* left = expr->left();
Location left_source = left->location();
ASSERT(!left_source.is_nowhere());
Expression* right = expr->right(); 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 // Call the runtime to find the boolean value of the left-hand
// subexpression. Duplicate the value if it may be needed as the final // subexpression. Duplicate the value if it may be needed as the final
// result. // 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()) { if (destination.is_temporary()) {
__ ldr(r0, MemOperand(sp)); __ ldr(r0, MemOperand(sp));
__ push(r0); __ 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 // The left-hand value is in on top of the stack. It is duplicated on the
// stack iff the destination location is temporary. // 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. // Discard the left-hand value if present on the stack.
if (destination.is_temporary()) __ pop(); if (destination.is_temporary()) __ pop();
Visit(right);
// Save or discard the right-hand value as needed. // Save or discard the right-hand value as needed.
if (destination.is_temporary() && right_source.is_constant()) { if (right->AsLiteral() != NULL) {
ASSERT(right->AsLiteral() != NULL); if (destination.is_temporary()) {
__ mov(ip, Operand(right->AsLiteral()->handle())); __ mov(ip, Operand(right->AsLiteral()->handle()));
__ push(ip); __ push(ip);
} else if (destination.is_nowhere() && right_source.is_temporary()) { } else {
__ pop(); ASSERT(destination.is_nowhere());
}
} else {
Visit(right);
ASSERT(right->location().is_temporary());
if (destination.is_nowhere()) {
__ pop();
} else {
ASSERT(destination.is_temporary());
}
} }
__ bind(&done); __ bind(&done);

View File

@ -628,8 +628,7 @@ void CodeGenSelector::VisitVariableProxy(VariableProxy* expr) {
void CodeGenSelector::VisitLiteral(Literal* expr) { void CodeGenSelector::VisitLiteral(Literal* expr) {
// All literals are supported. // Literals are supported.
expr->set_location(Location::Constant());
} }

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) { void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -136,18 +136,15 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
Expression* expr = stmt->expression(); Expression* expr = stmt->expression();
Visit(expr); // Complete the statement based on the type of the subexpression.
if (expr->AsLiteral() != NULL) {
// 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);
__ mov(eax, expr->AsLiteral()->handle()); __ mov(eax, expr->AsLiteral()->handle());
} else {
Visit(expr);
ASSERT(expr->location().is_temporary());
__ pop(eax);
} }
if (FLAG_trace) { if (FLAG_trace) {
__ push(eax); __ push(eax);
__ CallRuntime(Runtime::kTraceExit, 1); __ 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) { void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
Label exists; Label exists;
@ -289,9 +295,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE: case ObjectLiteral::Property::PROTOTYPE:
__ push(eax); __ push(eax);
Visit(key); Visit(key);
if (key->location().is_constant()) { ASSERT(key->location().is_temporary());
__ push(Immediate(key->handle()));
}
Visit(value); Visit(value);
ASSERT(value->location().is_temporary()); ASSERT(value->location().is_temporary());
__ CallRuntime(Runtime::kSetProperty, 3); __ CallRuntime(Runtime::kSetProperty, 3);
@ -301,9 +305,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
__ push(eax); __ push(eax);
Visit(key); Visit(key);
if (key->location().is_constant()) { ASSERT(key->location().is_temporary());
__ push(Immediate(key->handle()));
}
__ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) : Smi::FromInt(1) :
Smi::FromInt(0))); Smi::FromInt(0)));
@ -427,31 +429,26 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FastCodeGenerator::VisitAssignment(Assignment* expr) { void FastCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment"); Comment cmnt(masm_, "[ Assignment");
ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 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. // Left-hand side can only be a global or a (parameter or local) slot.
Variable* var = expr->target()->AsVariableProxy()->AsVariable(); Variable* var = expr->target()->AsVariableProxy()->AsVariable();
ASSERT(var != NULL); ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL); ASSERT(var->is_global() || var->slot() != NULL);
// Complete the assignment based on the location of the right-hand-side Expression* rhs = expr->value();
// value and the desired location of the assignment value.
Location destination = expr->location(); Location destination = expr->location();
Location source = rhs->location();
ASSERT(!destination.is_constant());
ASSERT(!source.is_nowhere());
if (var->is_global()) { if (var->is_global()) {
// Assignment to a global variable, use inline caching. Right-hand-side // Assignment to a global variable, use inline caching. Right-hand-side
// value is passed in eax, variable name in ecx, and the global object // value is passed in eax, variable name in ecx, and the global object
// on the stack. // on the stack.
if (source.is_temporary()) {
__ pop(eax); // Code for the right-hand-side expression depends on its type.
} else { if (rhs->AsLiteral() != NULL) {
ASSERT(source.is_constant());
ASSERT(rhs->AsLiteral() != NULL);
__ mov(eax, rhs->AsLiteral()->handle()); __ mov(eax, rhs->AsLiteral()->handle());
} else {
ASSERT(rhs->location().is_temporary());
Visit(rhs);
__ pop(eax);
} }
__ mov(ecx, var->name()); __ mov(ecx, var->name());
__ push(CodeGenerator::GlobalObject()); __ push(CodeGenerator::GlobalObject());
@ -464,10 +461,22 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
ASSERT(destination.is_nowhere()); ASSERT(destination.is_nowhere());
__ add(Operand(esp), Immediate(kPointerSize)); __ add(Operand(esp), Immediate(kPointerSize));
} }
} else { } else {
// Local or parameter assignment. // 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()) { if (destination.is_temporary()) {
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack. // temporary on the stack.
@ -478,17 +487,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// Case 'var = temp'. Discard right-hand-side temporary. // Case 'var = temp'. Discard right-hand-side temporary.
__ pop(Operand(ebp, SlotOffset(var->slot()))); __ 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(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
Visit(args->at(i)); Visit(args->at(i));
ASSERT(!args->at(i)->location().is_nowhere()); ASSERT(args->at(i)->location().is_temporary());
if (args->at(i)->location().is_constant()) {
ASSERT(args->at(i)->AsLiteral() != NULL);
__ push(Immediate(args->at(i)->AsLiteral()->handle()));
}
} }
// Record source position for debugger // Record source position for debugger
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
@ -542,15 +536,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
Visit(args->at(i)); Visit(args->at(i));
ASSERT(!args->at(i)->location().is_nowhere()); ASSERT(args->at(i)->location().is_temporary());
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); __ CallRuntime(function, arg_count);
@ -571,21 +557,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Label eval_right, done; Label eval_right, done;
Location destination = expr->location(); Location destination = expr->location();
ASSERT(!destination.is_constant());
Expression* left = expr->left(); Expression* left = expr->left();
Location left_source = left->location();
ASSERT(!left_source.is_nowhere());
Expression* right = expr->right(); 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 // Use the shared ToBoolean stub to find the boolean value of the
// left-hand subexpression. Load the value into eax to perform some // left-hand subexpression. Load the value into eax to perform some
// inlined checks assumed by the stub. // 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()) { if (destination.is_temporary()) {
// Copy the left-hand value into eax because we may need it as the // Copy the left-hand value into eax because we may need it as the
// final result. // final result.
@ -595,12 +581,6 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
// final result. // final result.
__ pop(eax); __ 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 // The left-hand value is in eax. It is also on the stack iff the
// destination location is temporary. // destination location is temporary.
@ -630,14 +610,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
if (destination.is_temporary()) { if (destination.is_temporary()) {
__ add(Operand(esp), Immediate(kPointerSize)); __ add(Operand(esp), Immediate(kPointerSize));
} }
Visit(right);
// Save or discard the right-hand value as needed. // Save or discard the right-hand value as needed.
if (destination.is_temporary() && right_source.is_constant()) { if (right->AsLiteral() != NULL) {
ASSERT(right->AsLiteral() != NULL); if (destination.is_temporary()) {
__ push(Immediate(right->AsLiteral()->handle())); __ push(Immediate(right->AsLiteral()->handle()));
} else if (destination.is_nowhere() && right_source.is_temporary()) { } else {
__ add(Operand(esp), Immediate(kPointerSize)); 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); __ bind(&done);

View File

@ -37,14 +37,12 @@ class Location BASE_EMBEDDED {
public: public:
static Location Temporary() { return Location(TEMP); } static Location Temporary() { return Location(TEMP); }
static Location Nowhere() { return Location(NOWHERE); } static Location Nowhere() { return Location(NOWHERE); }
static Location Constant() { return Location(CONSTANT); }
bool is_temporary() { return type_ == TEMP; } bool is_temporary() { return type_ == TEMP; }
bool is_nowhere() { return type_ == NOWHERE; } bool is_nowhere() { return type_ == NOWHERE; }
bool is_constant() { return type_ == CONSTANT; }
private: private:
enum Type { TEMP, NOWHERE, CONSTANT }; enum Type { TEMP, NOWHERE };
explicit Location(Type type) : type_(type) {} explicit Location(Type type) : type_(type) {}

View File

@ -144,18 +144,15 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
Expression* expr = stmt->expression(); Expression* expr = stmt->expression();
Visit(expr); // Complete the statement based on the type of the subexpression.
if (expr->AsLiteral() != NULL) {
// 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()); __ Move(rax, expr->AsLiteral()->handle());
} else {
Visit(expr);
ASSERT(expr->location().is_temporary());
__ pop(rax);
} }
if (FLAG_trace) { if (FLAG_trace) {
__ push(rax); __ push(rax);
__ CallRuntime(Runtime::kTraceExit, 1); __ 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) { void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
Label boilerplate_exists; Label boilerplate_exists;
@ -301,9 +307,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE: case ObjectLiteral::Property::PROTOTYPE:
__ push(rax); __ push(rax);
Visit(key); Visit(key);
if (key->location().is_constant()) { ASSERT(key->location().is_temporary());
__ Push(key->handle());
}
Visit(value); Visit(value);
ASSERT(value->location().is_temporary()); ASSERT(value->location().is_temporary());
__ CallRuntime(Runtime::kSetProperty, 3); __ CallRuntime(Runtime::kSetProperty, 3);
@ -313,9 +317,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER: case ObjectLiteral::Property::GETTER:
__ push(rax); __ push(rax);
Visit(key); Visit(key);
if (key->location().is_constant()) { ASSERT(key->location.is_temporary());
__ Push(key->handle());
}
__ Push(property->kind() == ObjectLiteral::Property::SETTER ? __ Push(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) : Smi::FromInt(1) :
Smi::FromInt(0)); Smi::FromInt(0));
@ -439,31 +441,26 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FastCodeGenerator::VisitAssignment(Assignment* expr) { void FastCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment"); Comment cmnt(masm_, "[ Assignment");
ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 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. // Left-hand side can only be a global or a (parameter or local) slot.
Variable* var = expr->target()->AsVariableProxy()->AsVariable(); Variable* var = expr->target()->AsVariableProxy()->AsVariable();
ASSERT(var != NULL); ASSERT(var != NULL);
ASSERT(var->is_global() || var->slot() != NULL); ASSERT(var->is_global() || var->slot() != NULL);
// Complete the assignment based on the location of the right-hand-side Expression* rhs = expr->value();
// value and the desired location of the assignment value.
Location destination = expr->location(); Location destination = expr->location();
Location source = rhs->location();
ASSERT(!destination.is_constant());
ASSERT(!source.is_nowhere());
if (var->is_global()) { if (var->is_global()) {
// Assignment to a global variable, use inline caching. Right-hand-side // Assignment to a global variable, use inline caching. Right-hand-side
// value is passed in rax, variable name in rcx, and the global object // value is passed in rax, variable name in rcx, and the global object
// on the stack. // on the stack.
if (source.is_temporary()) {
__ pop(rax); // Code for the right-hand-side expression depends on its type.
} else { if (rhs->AsLiteral() != NULL) {
ASSERT(source.is_constant());
ASSERT(rhs->AsLiteral() != NULL);
__ Move(rax, rhs->AsLiteral()->handle()); __ Move(rax, rhs->AsLiteral()->handle());
} else {
ASSERT(rhs->location().is_temporary());
Visit(rhs);
__ pop(rax);
} }
__ Move(rcx, var->name()); __ Move(rcx, var->name());
__ push(CodeGenerator::GlobalObject()); __ push(CodeGenerator::GlobalObject());
@ -476,7 +473,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
__ addq(rsp, Immediate(kPointerSize)); __ addq(rsp, Immediate(kPointerSize));
} }
} else { } 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()) { if (destination.is_temporary()) {
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary
// on the stack. // on the stack.
@ -487,17 +498,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// Case 'var = temp'. Discard right-hand-side temporary. // Case 'var = temp'. Discard right-hand-side temporary.
__ pop(Operand(rbp, SlotOffset(var->slot()))); __ 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(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
Visit(args->at(i)); Visit(args->at(i));
ASSERT(!args->at(i)->location().is_nowhere()); ASSERT(args->at(i)->location().is_temporary());
if (args->at(i)->location().is_constant()) {
ASSERT(args->at(i)->AsLiteral() != NULL);
__ Push(args->at(i)->AsLiteral()->handle());
}
} }
// Record source position for debugger // Record source position for debugger
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
@ -551,15 +547,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
Visit(args->at(i)); Visit(args->at(i));
ASSERT(!args->at(i)->location().is_nowhere()); ASSERT(args->at(i)->location().is_temporary());
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); __ CallRuntime(function, arg_count);
@ -580,21 +568,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Label eval_right, done; Label eval_right, done;
Location destination = expr->location(); Location destination = expr->location();
ASSERT(!destination.is_constant());
Expression* left = expr->left(); Expression* left = expr->left();
Location left_source = left->location();
ASSERT(!left_source.is_nowhere());
Expression* right = expr->right(); 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 // Use the shared ToBoolean stub to find the boolean value of the
// left-hand subexpression. Load the value into rax to perform some // left-hand subexpression. Load the value into rax to perform some
// inlined checks assumed by the stub. // 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()) { if (destination.is_temporary()) {
// Copy the left-hand value into rax because we may need it as the // Copy the left-hand value into rax because we may need it as the
// final result. // final result.
@ -604,12 +592,6 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
// final result. // final result.
__ pop(rax); __ 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 // The left-hand value is in rax. It is also on the stack iff the
// destination location is temporary. // destination location is temporary.
@ -640,14 +622,21 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
if (destination.is_temporary()) { if (destination.is_temporary()) {
__ addq(rsp, Immediate(kPointerSize)); __ addq(rsp, Immediate(kPointerSize));
} }
Visit(right);
// Save or discard the right-hand value as needed. // Save or discard the right-hand value as needed.
if (destination.is_temporary() && right_source.is_constant()) { if (right->AsLiteral() != NULL) {
ASSERT(right->AsLiteral() != NULL); if (destination.is_temporary()) {
__ Push(right->AsLiteral()->handle()); __ Push(right->AsLiteral()->handle());
} else if (destination.is_nowhere() && right_source.is_temporary()) { } else {
__ addq(rsp, Immediate(kPointerSize)); 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); __ bind(&done);