Make it more pleasant to work with expression locations in the

top-level code generator backend.  Introduce function to move one
location to another (source cannot be nowhere); to move registers,
slots, and literals into a location; and to move a location to a
register or slot.

Review URL: http://codereview.chromium.org/338043

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3146 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c433b4db
...@@ -120,6 +120,42 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) { ...@@ -120,6 +120,42 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
} }
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
__ ldr(ip, MemOperand(fp, SlotOffset(source)));
__ push(ip);
break;
}
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
__ mov(ip, Operand(expr->handle()));
__ push(ip);
break;
}
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
case Location::NOWHERE:
UNREACHABLE();
case Location::TEMP:
__ pop(ip);
__ str(ip, MemOperand(fp, SlotOffset(destination)));
break;
}
}
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals. // Call the runtime to declare the globals.
// The context is the first argument. // The context is the first argument.
...@@ -131,20 +167,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { ...@@ -131,20 +167,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
} }
void FastCodeGenerator::VisitBlock(Block* stmt) {
Comment cmnt(masm_, "[ Block");
SetStatementPosition(stmt);
VisitStatements(stmt->statements());
}
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Comment cmnt(masm_, "[ ExpressionStatement");
SetStatementPosition(stmt);
Visit(stmt->expression());
}
void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
...@@ -154,8 +176,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { ...@@ -154,8 +176,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
__ mov(r0, Operand(expr->AsLiteral()->handle())); __ mov(r0, Operand(expr->AsLiteral()->handle()));
} else { } else {
Visit(expr); Visit(expr);
ASSERT(expr->location().is_temporary()); Move(r0, expr->location());
__ pop(r0);
} }
if (FLAG_trace) { if (FLAG_trace) {
...@@ -185,12 +206,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -185,12 +206,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ mov(r0, Operand(boilerplate)); __ mov(r0, Operand(boilerplate));
__ stm(db_w, sp, cp.bit() | r0.bit()); __ stm(db_w, sp, cp.bit() | r0.bit());
__ CallRuntime(Runtime::kNewClosure, 2); __ CallRuntime(Runtime::kNewClosure, 2);
Move(expr->location(), r0);
if (expr->location().is_temporary()) {
__ push(r0);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -206,34 +222,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { ...@@ -206,34 +222,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
__ mov(r2, Operand(expr->name())); __ mov(r2, Operand(expr->name()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
if (expr->location().is_temporary()) { switch (expr->location().type()) {
case Location::NOWHERE:
__ pop();
break;
case Location::TEMP:
// Replace the global object with the result. // Replace the global object with the result.
__ str(r0, MemOperand(sp)); __ str(r0, MemOperand(sp));
} else { break;
ASSERT(expr->location().is_nowhere());
__ pop();
} }
} else { } else {
Comment cmnt(masm_, "Stack slot"); Comment cmnt(masm_, "Stack slot");
Slot* slot = rewrite->AsSlot(); Move(expr->location(), rewrite->AsSlot());
ASSERT(slot != NULL);
if (expr->location().is_temporary()) {
__ ldr(ip, MemOperand(fp, SlotOffset(slot)));
__ push(ip);
} else {
ASSERT(expr->location().is_nowhere());
}
}
}
void FastCodeGenerator::VisitLiteral(Literal* expr) {
if (expr->location().is_temporary()) {
__ mov(ip, Operand(expr->AsLiteral()->handle()));
__ push(ip);
} else {
ASSERT(expr->location().is_nowhere());
} }
} }
...@@ -315,11 +316,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -315,11 +316,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
if (expr->location().is_nowhere() && result_saved) { switch (expr->location().type()) {
__ pop(); case Location::NOWHERE:
} else if (expr->location().is_temporary() && !result_saved) { if (result_saved) __ pop();
ASSERT(expr->location().is_temporary()); break;
__ push(r0); case Location::TEMP:
if (!result_saved) __ push(r0);
break;
} }
} }
...@@ -347,11 +350,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -347,11 +350,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ bind(&done); __ bind(&done);
if (expr->location().is_temporary()) { Move(expr->location(), r0);
__ push(r0);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -419,11 +418,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -419,11 +418,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ RecordWrite(r1, r2, r0); __ RecordWrite(r1, r2, r0);
} }
Location destination = expr->location(); switch (expr->location().type()) {
if (destination.is_nowhere() && result_saved) { case Location::NOWHERE:
__ pop(); if (result_saved) __ pop();
} else if (destination.is_temporary() && !result_saved) { break;
__ push(r0); case Location::TEMP:
if (!result_saved) __ push(r0);
break;
} }
} }
...@@ -458,11 +459,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -458,11 +459,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
// Overwrite the global object on the stack with the result if needed. // Overwrite the global object on the stack with the result if needed.
if (destination.is_temporary()) { switch (expr->location().type()) {
__ str(r0, MemOperand(sp)); case Location::NOWHERE:
} else {
ASSERT(destination.is_nowhere());
__ pop(); __ pop();
break;
case Location::TEMP:
__ str(r0, MemOperand(sp));
break;
} }
} else { } else {
...@@ -474,22 +477,23 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -474,22 +477,23 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// discarded result. Always perform the assignment. // discarded result. Always perform the assignment.
__ mov(ip, Operand(rhs->AsLiteral()->handle())); __ mov(ip, Operand(rhs->AsLiteral()->handle()));
__ str(ip, MemOperand(fp, SlotOffset(var->slot()))); __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
if (destination.is_temporary()) { Move(expr->location(), ip);
// Case 'temp <- (var = constant)'. Save result.
__ push(ip);
}
} else { } else {
ASSERT(rhs->location().is_temporary()); ASSERT(rhs->location().is_temporary());
Visit(rhs); Visit(rhs);
if (destination.is_temporary()) { // Load right-hand side into ip.
switch (expr->location().type()) {
case Location::NOWHERE:
// Case 'var = temp'. Discard right-hand-side temporary.
__ pop(ip);
break;
case Location::TEMP:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack. // temporary on the stack.
__ ldr(ip, MemOperand(sp)); __ ldr(ip, MemOperand(sp));
} else { break;
ASSERT(destination.is_nowhere());
// Case 'var = temp'. Discard right-hand-side temporary.
__ pop(ip);
} }
// Do the slot assignment.
__ str(ip, MemOperand(fp, SlotOffset(var->slot()))); __ str(ip, MemOperand(fp, SlotOffset(var->slot())));
} }
} }
...@@ -521,11 +525,13 @@ void FastCodeGenerator::VisitCall(Call* expr) { ...@@ -521,11 +525,13 @@ void FastCodeGenerator::VisitCall(Call* expr) {
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
// Restore context register. // Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
if (expr->location().is_temporary()) { switch (expr->location().type()) {
__ str(r0, MemOperand(sp)); case Location::NOWHERE:
} else {
ASSERT(expr->location().is_nowhere());
__ pop(); __ pop();
break;
case Location::TEMP:
__ str(r0, MemOperand(sp));
break;
} }
} }
...@@ -545,11 +551,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -545,11 +551,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
} }
__ CallRuntime(function, arg_count); __ CallRuntime(function, arg_count);
if (expr->location().is_temporary()) { Move(expr->location(), r0);
__ push(r0);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -591,20 +593,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -591,20 +593,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
if (destination.is_temporary()) __ pop(); if (destination.is_temporary()) __ pop();
// Save or discard the right-hand value as needed. // Save or discard the right-hand value as needed.
if (right->AsLiteral() != NULL) { if (right->AsLiteral() != NULL) {
if (destination.is_temporary()) { Move(destination, right->AsLiteral());
__ mov(ip, Operand(right->AsLiteral()->handle()));
__ push(ip);
} else {
ASSERT(destination.is_nowhere());
}
} else { } else {
Visit(right); Visit(right);
ASSERT(right->location().is_temporary()); Move(destination, right->location());
if (destination.is_nowhere()) {
__ pop();
} else {
ASSERT(destination.is_temporary());
}
} }
__ bind(&done); __ bind(&done);
......
...@@ -53,6 +53,7 @@ Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun, ...@@ -53,6 +53,7 @@ Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
int FastCodeGenerator::SlotOffset(Slot* slot) { int FastCodeGenerator::SlotOffset(Slot* slot) {
ASSERT(slot != NULL);
// Offset is negative because higher indexes are at lower addresses. // Offset is negative because higher indexes are at lower addresses.
int offset = -slot->index() * kPointerSize; int offset = -slot->index() * kPointerSize;
// Adjust by a (parameter or local) base offset. // Adjust by a (parameter or local) base offset.
...@@ -70,6 +71,48 @@ int FastCodeGenerator::SlotOffset(Slot* slot) { ...@@ -70,6 +71,48 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
} }
void FastCodeGenerator::Move(Location destination, Location source) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
switch (source.type()) {
case Location::NOWHERE:
UNREACHABLE();
case Location::TEMP:
break;
}
break;
}
}
// All platform macro assemblers in {ia32,x64,arm} have a push(Register)
// function.
void FastCodeGenerator::Move(Location destination, Register source) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
masm_->push(source);
break;
}
}
// All platform macro assemblers in {ia32,x64,arm} have a pop(Register)
// function.
void FastCodeGenerator::Move(Register destination, Location source) {
switch (source.type()) {
case Location::NOWHERE:
UNREACHABLE();
case Location::TEMP:
masm_->pop(destination);
}
}
void FastCodeGenerator::VisitDeclarations( void FastCodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) { ZoneList<Declaration*>* declarations) {
int length = declarations->length(); int length = declarations->length();
...@@ -191,6 +234,20 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) { ...@@ -191,6 +234,20 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
} }
void FastCodeGenerator::VisitBlock(Block* stmt) {
Comment cmnt(masm_, "[ Block");
SetStatementPosition(stmt);
VisitStatements(stmt->statements());
}
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Comment cmnt(masm_, "[ ExpressionStatement");
SetStatementPosition(stmt);
Visit(stmt->expression());
}
void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
Comment cmnt(masm_, "[ EmptyStatement"); Comment cmnt(masm_, "[ EmptyStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
...@@ -279,6 +336,11 @@ void FastCodeGenerator::VisitSlot(Slot* expr) { ...@@ -279,6 +336,11 @@ void FastCodeGenerator::VisitSlot(Slot* expr) {
} }
void FastCodeGenerator::VisitLiteral(Literal* expr) {
Move(expr->location(), expr);
}
void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -51,6 +51,15 @@ class FastCodeGenerator: public AstVisitor { ...@@ -51,6 +51,15 @@ class FastCodeGenerator: public AstVisitor {
private: private:
int SlotOffset(Slot* slot); int SlotOffset(Slot* slot);
void Move(Location destination, Location source);
void Move(Location destination, Register source);
void Move(Location destination, Slot* source);
void Move(Location destination, Literal* source);
void Move(Register destination, Location source);
void Move(Slot* destination, Location source);
void VisitDeclarations(ZoneList<Declaration*>* declarations); void VisitDeclarations(ZoneList<Declaration*>* declarations);
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* fun); Handle<JSFunction> BuildBoilerplate(FunctionLiteral* fun);
void DeclareGlobals(Handle<FixedArray> pairs); void DeclareGlobals(Handle<FixedArray> pairs);
......
...@@ -108,6 +108,39 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) { ...@@ -108,6 +108,39 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
} }
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
__ push(Operand(ebp, SlotOffset(source)));
break;
}
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
__ push(Immediate(expr->handle()));
break;
}
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
case Location::NOWHERE:
UNREACHABLE();
case Location::TEMP:
__ pop(Operand(ebp, SlotOffset(destination)));
break;
}
}
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals. // Call the runtime to declare the globals.
__ push(esi); // The context is the first argument. __ push(esi); // The context is the first argument.
...@@ -118,20 +151,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { ...@@ -118,20 +151,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
} }
void FastCodeGenerator::VisitBlock(Block* stmt) {
Comment cmnt(masm_, "[ Block");
SetStatementPosition(stmt);
VisitStatements(stmt->statements());
}
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Comment cmnt(masm_, "[ ExpressionStatement");
SetStatementPosition(stmt);
Visit(stmt->expression());
}
void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
...@@ -141,8 +160,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { ...@@ -141,8 +160,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
__ mov(eax, expr->AsLiteral()->handle()); __ mov(eax, expr->AsLiteral()->handle());
} else { } else {
Visit(expr); Visit(expr);
ASSERT(expr->location().is_temporary()); Move(eax, expr->location());
__ pop(eax);
} }
if (FLAG_trace) { if (FLAG_trace) {
...@@ -172,12 +190,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -172,12 +190,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ push(esi); __ push(esi);
__ push(Immediate(boilerplate)); __ push(Immediate(boilerplate));
__ CallRuntime(Runtime::kNewClosure, 2); __ CallRuntime(Runtime::kNewClosure, 2);
Move(expr->location(), eax);
if (expr->location().is_temporary()) {
__ push(eax);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -197,32 +210,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { ...@@ -197,32 +210,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
// indicate that the inobject property case was inlined. Ensure there // indicate that the inobject property case was inlined. Ensure there
// is no test eax instruction here. Remember that the assembler may // is no test eax instruction here. Remember that the assembler may
// choose to do peephole optimization (eg, push/pop elimination). // choose to do peephole optimization (eg, push/pop elimination).
if (expr->location().is_temporary()) { switch (expr->location().type()) {
case Location::NOWHERE:
__ add(Operand(esp), Immediate(kPointerSize));
break;
case Location::TEMP:
// Replace the global object with the result. // Replace the global object with the result.
__ mov(Operand(esp, 0), eax); __ mov(Operand(esp, 0), eax);
} else { break;
ASSERT(expr->location().is_nowhere());
__ add(Operand(esp), Immediate(kPointerSize));
} }
} else { } else {
Comment cmnt(masm_, "Stack slot"); Comment cmnt(masm_, "Stack slot");
Slot* slot = rewrite->AsSlot(); Move(expr->location(), rewrite->AsSlot());
ASSERT(slot != NULL);
if (expr->location().is_temporary()) {
__ push(Operand(ebp, SlotOffset(slot)));
} else {
ASSERT(expr->location().is_nowhere());
}
}
}
void FastCodeGenerator::VisitLiteral(Literal* expr) {
if (expr->location().is_temporary()) {
__ push(Immediate(expr->handle()));
} else {
ASSERT(expr->location().is_nowhere());
} }
} }
...@@ -283,8 +283,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -283,8 +283,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::COMPUTED: case ObjectLiteral::Property::COMPUTED:
if (key->handle()->IsSymbol()) { if (key->handle()->IsSymbol()) {
Visit(value); Visit(value);
ASSERT(value->location().is_temporary()); Move(eax, value->location());
__ pop(eax);
__ mov(ecx, Immediate(key->handle())); __ mov(ecx, Immediate(key->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
...@@ -317,10 +316,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -317,10 +316,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
if (expr->location().is_nowhere() && result_saved) { switch (expr->location().type()) {
__ add(Operand(esp), Immediate(kPointerSize)); case Location::NOWHERE:
} else if (expr->location().is_temporary() && !result_saved) { if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
__ push(eax); break;
case Location::TEMP:
if (!result_saved) __ push(eax);
break;
} }
} }
...@@ -348,11 +350,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -348,11 +350,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
// Label done: // Label done:
__ bind(&done); __ bind(&done);
if (expr->location().is_temporary()) { Move(expr->location(), eax);
__ push(eax);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -417,11 +415,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -417,11 +415,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ RecordWrite(ebx, offset, eax, ecx); __ RecordWrite(ebx, offset, eax, ecx);
} }
Location destination = expr->location(); switch (expr->location().type()) {
if (destination.is_nowhere() && result_saved) { case Location::NOWHERE:
__ add(Operand(esp), Immediate(kPointerSize)); if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
} else if (destination.is_temporary() && !result_saved) { break;
__ push(eax); case Location::TEMP:
if (!result_saved) __ push(eax);
break;
} }
} }
...@@ -436,7 +436,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -436,7 +436,6 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
ASSERT(var->is_global() || var->slot() != NULL); ASSERT(var->is_global() || var->slot() != NULL);
Expression* rhs = expr->value(); Expression* rhs = expr->value();
Location destination = expr->location();
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
...@@ -455,11 +454,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -455,11 +454,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
// Overwrite the global object on the stack with the result if needed. // Overwrite the global object on the stack with the result if needed.
if (destination.is_temporary()) { switch (expr->location().type()) {
__ mov(Operand(esp, 0), eax); case Location::NOWHERE:
} else {
ASSERT(destination.is_nowhere());
__ add(Operand(esp), Immediate(kPointerSize)); __ add(Operand(esp), Immediate(kPointerSize));
break;
case Location::TEMP:
__ mov(Operand(esp, 0), eax);
break;
} }
} else { } else {
// Local or parameter assignment. // Local or parameter assignment.
...@@ -470,22 +471,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -470,22 +471,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// discarded result. Always perform the assignment. // discarded result. Always perform the assignment.
__ mov(eax, rhs->AsLiteral()->handle()); __ mov(eax, rhs->AsLiteral()->handle());
__ mov(Operand(ebp, SlotOffset(var->slot())), eax); __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
if (destination.is_temporary()) { Move(expr->location(), eax);
// Case 'temp <- (var = constant)'. Save result.
__ push(eax);
}
} else { } else {
ASSERT(rhs->location().is_temporary()); ASSERT(rhs->location().is_temporary());
Visit(rhs); Visit(rhs);
if (destination.is_temporary()) { switch (expr->location().type()) {
case Location::NOWHERE:
// Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
break;
case Location::TEMP:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack. // temporary on the stack.
__ mov(eax, Operand(esp, 0)); __ mov(eax, Operand(esp, 0));
__ mov(Operand(ebp, SlotOffset(var->slot())), eax); __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
} else { break;
ASSERT(destination.is_nowhere());
// Case 'var = temp'. Discard right-hand-side temporary.
__ pop(Operand(ebp, SlotOffset(var->slot())));
} }
} }
} }
...@@ -516,11 +516,13 @@ void FastCodeGenerator::VisitCall(Call* expr) { ...@@ -516,11 +516,13 @@ void FastCodeGenerator::VisitCall(Call* expr) {
// Restore context register. // Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS. // Discard the function left on TOS.
if (expr->location().is_temporary()) { switch (expr->location().type()) {
__ mov(Operand(esp, 0), eax); case Location::NOWHERE:
} else {
ASSERT(expr->location().is_nowhere());
__ add(Operand(esp), Immediate(kPointerSize)); __ add(Operand(esp), Immediate(kPointerSize));
break;
case Location::TEMP:
__ mov(Operand(esp, 0), eax);
break;
} }
} }
...@@ -540,11 +542,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -540,11 +542,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
} }
__ CallRuntime(function, arg_count); __ CallRuntime(function, arg_count);
if (expr->location().is_temporary()) { Move(expr->location(), eax);
__ push(eax);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -572,14 +570,17 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -572,14 +570,17 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
} else { } else {
Visit(left); Visit(left);
ASSERT(left->location().is_temporary()); ASSERT(left->location().is_temporary());
if (destination.is_temporary()) { switch (destination.type()) {
// Copy the left-hand value into eax because we may need it as the case Location::NOWHERE:
// final result.
__ mov(eax, Operand(esp, 0));
} else {
// Pop the left-hand value into eax because we will not need it as the // Pop the left-hand value into eax because we will not need it as the
// final result. // final result.
__ pop(eax); __ pop(eax);
break;
case Location::TEMP:
// Copy the left-hand value into eax because we may need it as the
// final result.
__ mov(eax, Operand(esp, 0));
break;
} }
} }
// 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
...@@ -612,19 +613,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -612,19 +613,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
} }
// Save or discard the right-hand value as needed. // Save or discard the right-hand value as needed.
if (right->AsLiteral() != NULL) { if (right->AsLiteral() != NULL) {
if (destination.is_temporary()) { Move(destination, right->AsLiteral());
__ push(Immediate(right->AsLiteral()->handle()));
} else {
ASSERT(destination.is_nowhere());
}
} else { } else {
Visit(right); Visit(right);
ASSERT(right->location().is_temporary()); Move(destination, right->location());
if (destination.is_nowhere()) {
__ add(Operand(esp), Immediate(kPointerSize));
} else {
ASSERT(destination.is_temporary());
}
} }
__ bind(&done); __ bind(&done);
......
...@@ -35,15 +35,17 @@ namespace internal { ...@@ -35,15 +35,17 @@ namespace internal {
class Location BASE_EMBEDDED { class Location BASE_EMBEDDED {
public: public:
enum Type { NOWHERE, TEMP };
static Location Temporary() { return Location(TEMP); } static Location Temporary() { return Location(TEMP); }
static Location Nowhere() { return Location(NOWHERE); } static Location Nowhere() { return Location(NOWHERE); }
bool is_temporary() { return type_ == TEMP; } bool is_temporary() { return type_ == TEMP; }
bool is_nowhere() { return type_ == NOWHERE; } bool is_nowhere() { return type_ == NOWHERE; }
private: Type type() { return type_; }
enum Type { TEMP, NOWHERE };
private:
explicit Location(Type type) : type_(type) {} explicit Location(Type type) : type_(type) {}
Type type_; Type type_;
......
...@@ -116,6 +116,39 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) { ...@@ -116,6 +116,39 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
} }
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
__ push(Operand(rbp, SlotOffset(source)));
break;
}
}
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
case Location::NOWHERE:
break;
case Location::TEMP:
__ Push(expr->handle());
break;
}
}
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
case Location::NOWHERE:
UNREACHABLE();
case Location::TEMP:
__ pop(Operand(rbp, SlotOffset(destination)));
break;
}
}
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals. // Call the runtime to declare the globals.
__ push(rsi); // The context is the first argument. __ push(rsi); // The context is the first argument.
...@@ -126,20 +159,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { ...@@ -126,20 +159,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
} }
void FastCodeGenerator::VisitBlock(Block* stmt) {
Comment cmnt(masm_, "[ Block");
SetStatementPosition(stmt);
VisitStatements(stmt->statements());
}
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Comment cmnt(masm_, "[ ExpressionStatement");
SetStatementPosition(stmt);
Visit(stmt->expression());
}
void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
...@@ -149,8 +168,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { ...@@ -149,8 +168,7 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
__ Move(rax, expr->AsLiteral()->handle()); __ Move(rax, expr->AsLiteral()->handle());
} else { } else {
Visit(expr); Visit(expr);
ASSERT(expr->location().is_temporary()); Move(rax, expr->location());
__ pop(rax);
} }
if (FLAG_trace) { if (FLAG_trace) {
...@@ -189,12 +207,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -189,12 +207,7 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
__ push(rsi); __ push(rsi);
__ Push(boilerplate); __ Push(boilerplate);
__ CallRuntime(Runtime::kNewClosure, 2); __ CallRuntime(Runtime::kNewClosure, 2);
Move(expr->location(), rax);
if (expr->location().is_temporary()) {
__ push(rax);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -213,32 +226,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { ...@@ -213,32 +226,19 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
// A test rax instruction following the call is used by the IC to // A test rax instruction following the call is used by the IC to
// indicate that the inobject property case was inlined. Ensure there // indicate that the inobject property case was inlined. Ensure there
// is no test rax instruction here. // is no test rax instruction here.
if (expr->location().is_temporary()) { switch (expr->location().type()) {
case Location::NOWHERE:
__ addq(rsp, Immediate(kPointerSize));
break;
case Location::TEMP:
// Replace the global object with the result. // Replace the global object with the result.
__ movq(Operand(rsp, 0), rax); __ movq(Operand(rsp, 0), rax);
} else { break;
ASSERT(expr->location().is_nowhere());
__ addq(rsp, Immediate(kPointerSize));
} }
} else { } else {
Comment cmnt(masm_, "Stack slot"); Comment cmnt(masm_, "Stack slot");
Slot* slot = rewrite->AsSlot(); Move(expr->location(), rewrite->AsSlot());
ASSERT(slot != NULL);
if (expr->location().is_temporary()) {
__ push(Operand(rbp, SlotOffset(slot)));
} else {
ASSERT(expr->location().is_nowhere());
}
}
}
void FastCodeGenerator::VisitLiteral(Literal* expr) {
if (expr->location().is_temporary()) {
__ Push(expr->handle());
} else {
ASSERT(expr->location().is_nowhere());
} }
} }
...@@ -329,10 +329,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -329,10 +329,13 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
if (expr->location().is_nowhere() && result_saved) { switch (expr->location().type()) {
__ addq(rsp, Immediate(kPointerSize)); case Location::NOWHERE:
} else if (expr->location().is_temporary() && !result_saved) { if (result_saved) __ addq(rsp, Immediate(kPointerSize));
__ push(rax); break;
case Location::TEMP:
if (!result_saved) __ push(rax);
break;
} }
} }
...@@ -360,11 +363,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -360,11 +363,7 @@ void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
// Label done: // Label done:
__ bind(&done); __ bind(&done);
if (expr->location().is_temporary()) { Move(expr->location(), rax);
__ push(rax);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -429,11 +428,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -429,11 +428,13 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ RecordWrite(rbx, offset, rax, rcx); __ RecordWrite(rbx, offset, rax, rcx);
} }
Location destination = expr->location(); switch (expr->location().type()) {
if (destination.is_nowhere() && result_saved) { case Location::NOWHERE:
__ addq(rsp, Immediate(kPointerSize)); if (result_saved) __ addq(rsp, Immediate(kPointerSize));
} else if (destination.is_temporary() && !result_saved) { break;
__ push(rax); case Location::TEMP:
if (!result_saved) __ push(rax);
break;
} }
} }
...@@ -467,10 +468,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -467,10 +468,13 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
// Overwrite the global object on the stack with the result if needed. // Overwrite the global object on the stack with the result if needed.
if (destination.is_temporary()) { switch (expr->location().type()) {
__ movq(Operand(rsp, 0), rax); case Location::NOWHERE:
} else {
__ addq(rsp, Immediate(kPointerSize)); __ addq(rsp, Immediate(kPointerSize));
break;
case Location::TEMP:
__ movq(Operand(rsp, 0), rax);
break;
} }
} else { } else {
// Local or parameter assignment. // Local or parameter assignment.
...@@ -481,22 +485,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -481,22 +485,21 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// discarded result. Always perform the assignment. // discarded result. Always perform the assignment.
__ Move(kScratchRegister, rhs->AsLiteral()->handle()); __ Move(kScratchRegister, rhs->AsLiteral()->handle());
__ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
if (destination.is_temporary()) { Move(expr->location(), kScratchRegister);
// Case 'temp <- (var = constant)'. Save result.
__ push(kScratchRegister);
}
} else { } else {
ASSERT(rhs->location().is_temporary()); ASSERT(rhs->location().is_temporary());
Visit(rhs); Visit(rhs);
if (destination.is_temporary()) { switch (expr->location().type()) {
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary case Location::NOWHERE:
// on the stack. // Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
break;
case Location::TEMP:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ movq(kScratchRegister, Operand(rsp, 0)); __ movq(kScratchRegister, Operand(rsp, 0));
__ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
} else { break;
ASSERT(destination.is_nowhere());
// Case 'var = temp'. Discard right-hand-side temporary.
__ pop(Operand(rbp, SlotOffset(var->slot())));
} }
} }
} }
...@@ -527,11 +530,13 @@ void FastCodeGenerator::VisitCall(Call* expr) { ...@@ -527,11 +530,13 @@ void FastCodeGenerator::VisitCall(Call* expr) {
// Restore context register. // Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
// Discard the function left on TOS. // Discard the function left on TOS.
if (expr->location().is_temporary()) { switch (expr->location().type()) {
__ movq(Operand(rsp, 0), rax); case Location::NOWHERE:
} else {
ASSERT(expr->location().is_nowhere());
__ addq(rsp, Immediate(kPointerSize)); __ addq(rsp, Immediate(kPointerSize));
break;
case Location::TEMP:
__ movq(Operand(rsp, 0), rax);
break;
} }
} }
...@@ -551,11 +556,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -551,11 +556,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
} }
__ CallRuntime(function, arg_count); __ CallRuntime(function, arg_count);
if (expr->location().is_temporary()) { Move(expr->location(), rax);
__ push(rax);
} else {
ASSERT(expr->location().is_nowhere());
}
} }
...@@ -583,14 +584,17 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -583,14 +584,17 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
} else { } else {
Visit(left); Visit(left);
ASSERT(left->location().is_temporary()); ASSERT(left->location().is_temporary());
if (destination.is_temporary()) { switch (destination.type()) {
// Copy the left-hand value into rax because we may need it as the case Location::NOWHERE:
// final result.
__ movq(rax, Operand(rsp, 0));
} else {
// Pop the left-hand value into rax because we will not need it as the // Pop the left-hand value into rax because we will not need it as the
// final result. // final result.
__ pop(rax); __ pop(rax);
break;
case Location::TEMP:
// Copy the left-hand value into rax because we may need it as the
// final result.
__ movq(rax, Operand(rsp, 0));
break;
} }
} }
// 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
...@@ -624,19 +628,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { ...@@ -624,19 +628,10 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
} }
// Save or discard the right-hand value as needed. // Save or discard the right-hand value as needed.
if (right->AsLiteral() != NULL) { if (right->AsLiteral() != NULL) {
if (destination.is_temporary()) { Move(destination, right->AsLiteral());
__ Push(right->AsLiteral()->handle());
} else {
ASSERT(destination.is_nowhere());
}
} else { } else {
Visit(right); Visit(right);
ASSERT(right->location().is_temporary()); Move(destination, right->location());
if (destination.is_nowhere()) {
__ addq(rsp, Immediate(kPointerSize));
} else {
ASSERT(destination.is_temporary());
}
} }
__ bind(&done); __ bind(&done);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment