Emit pushes and pops through the virtual frame on ARM. Merging of

frames is not yet handled.  The ARM code generator should be back in
line with the IA32 one.
Review URL: http://codereview.chromium.org/9182

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@706 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a6554f87
...@@ -49,6 +49,70 @@ VirtualFrame::VirtualFrame(CodeGenerator* cgen) { ...@@ -49,6 +49,70 @@ VirtualFrame::VirtualFrame(CodeGenerator* cgen) {
} }
void VirtualFrame::Enter() {
Comment cmnt(masm_, "[ Enter JS frame");
#ifdef DEBUG
{ Label done, fail;
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &fail);
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
__ cmp(r2, Operand(JS_FUNCTION_TYPE));
__ b(eq, &done);
__ bind(&fail);
__ stop("CodeGenerator::EnterJSFrame - r1 not a function");
__ bind(&done);
}
#endif // DEBUG
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
// Adjust FP to point to saved FP.
__ add(fp, sp, Operand(2 * kPointerSize));
}
void VirtualFrame::Exit() {
Comment cmnt(masm_, "[ Exit JS frame");
// Drop the execution stack down to the frame pointer and restore the caller
// frame pointer and return address.
__ mov(sp, fp);
__ ldm(ia_w, sp, fp.bit() | lr.bit());
}
void VirtualFrame::AllocateLocals() {
if (frame_local_count_ > 0) {
Comment cmnt(masm_, "[ Allocate space for locals");
// Initialize stack slots with 'undefined' value.
__ mov(ip, Operand(Factory::undefined_value()));
for (int i = 0; i < frame_local_count_; i++) {
__ push(ip);
}
}
}
void VirtualFrame::Drop(int count) {
ASSERT(count >= 0);
if (count > 0) {
__ add(sp, sp, Operand(count * kPointerSize));
}
}
void VirtualFrame::Pop() { Drop(1); }
void VirtualFrame::Pop(Register reg) {
__ pop(reg);
}
void VirtualFrame::Push(Register reg) {
__ push(reg);
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// CodeGenState implementation. // CodeGenState implementation.
...@@ -99,7 +163,6 @@ CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, ...@@ -99,7 +163,6 @@ CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
// Calling conventions: // Calling conventions:
// r0: the number of arguments // r0: the number of arguments
// fp: frame pointer // fp: frame pointer
// sp: stack pointer // sp: stack pointer
...@@ -127,9 +190,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -127,9 +190,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
// pp: caller's parameter pointer // pp: caller's parameter pointer
// cp: callee's context // cp: callee's context
{ Comment cmnt(masm_, "[ enter JS frame"); frame_->Enter();
EnterJSFrame();
}
// tos: code slot // tos: code slot
#ifdef DEBUG #ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 && if (strlen(FLAG_stop_at) > 0 &&
...@@ -139,20 +200,13 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -139,20 +200,13 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
#endif #endif
// Allocate space for locals and initialize them. // Allocate space for locals and initialize them.
if (scope_->num_stack_slots() > 0) { frame_->AllocateLocals();
Comment cmnt(masm_, "[ allocate space for locals");
// Initialize stack slots with 'undefined' value.
__ mov(ip, Operand(Factory::undefined_value()));
for (int i = 0; i < scope_->num_stack_slots(); i++) {
__ push(ip);
}
}
if (scope_->num_heap_slots() > 0) { if (scope_->num_heap_slots() > 0) {
// Allocate local context. // Allocate local context.
// Get outer context and create a new context based on it. // Get outer context and create a new context based on it.
__ ldr(r0, frame_->Function()); __ ldr(r0, frame_->Function());
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result __ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result
if (kDebug) { if (kDebug) {
...@@ -166,7 +220,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -166,7 +220,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
__ str(cp, frame_->Context()); __ str(cp, frame_->Context());
} }
// TODO(1241774): Improve this code!!! // TODO(1241774): Improve this code:
// 1) only needed if we have a context // 1) only needed if we have a context
// 2) no need to recompute context ptr every single time // 2) no need to recompute context ptr every single time
// 3) don't copy parameter operand code from SlotOperand! // 3) don't copy parameter operand code from SlotOperand!
...@@ -198,9 +252,9 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -198,9 +252,9 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
} }
} }
// Store the arguments object. // Store the arguments object. This must happen after context
// This must happen after context initialization because // initialization because the arguments object may be stored in the
// the arguments array may be stored in the context! // context.
if (scope_->arguments() != NULL) { if (scope_->arguments() != NULL) {
ASSERT(scope_->arguments_shadow() != NULL); ASSERT(scope_->arguments_shadow() != NULL);
Comment cmnt(masm_, "[ allocate arguments object"); Comment cmnt(masm_, "[ allocate arguments object");
...@@ -215,35 +269,31 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -215,35 +269,31 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
__ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
__ CallStub(&stub); __ CallStub(&stub);
__ push(r0); frame_->Push(r0);
arguments_ref.SetValue(NOT_CONST_INIT); arguments_ref.SetValue(NOT_CONST_INIT);
} }
shadow_ref.SetValue(NOT_CONST_INIT); shadow_ref.SetValue(NOT_CONST_INIT);
} }
__ pop(r0); // Value is no longer needed. frame_->Pop(); // Value is no longer needed.
} }
// Generate code to 'execute' declarations and initialize // Generate code to 'execute' declarations and initialize functions
// functions (source elements). In case of an illegal // (source elements). In case of an illegal redeclaration we need to
// redeclaration we need to handle that instead of processing the // handle that instead of processing the declarations.
// declarations.
if (scope_->HasIllegalRedeclaration()) { if (scope_->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations"); Comment cmnt(masm_, "[ illegal redeclarations");
scope_->VisitIllegalRedeclaration(this); scope_->VisitIllegalRedeclaration(this);
} else { } else {
Comment cmnt(masm_, "[ declarations"); Comment cmnt(masm_, "[ declarations");
// ProcessDeclarations calls DeclareGlobals indirectly
ProcessDeclarations(scope_->declarations()); ProcessDeclarations(scope_->declarations());
// Bail out if a stack-overflow exception occurred when processing
// Bail out if a stack-overflow exception occurred when // declarations.
// processing declarations.
if (HasStackOverflow()) return; if (HasStackOverflow()) return;
} }
if (FLAG_trace) { if (FLAG_trace) {
// Push a valid value as the parameter. The runtime call only uses
// it as the return value to indicate non-failure.
__ CallRuntime(Runtime::kTraceEnter, 0); __ CallRuntime(Runtime::kTraceEnter, 0);
// Ignore the return value.
} }
CheckStack(); CheckStack();
...@@ -258,6 +308,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -258,6 +308,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
if (should_trace) { if (should_trace) {
__ CallRuntime(Runtime::kDebugTrace, 0); __ CallRuntime(Runtime::kDebugTrace, 0);
// Ignore the return value.
} }
#endif #endif
VisitStatements(body); VisitStatements(body);
...@@ -276,13 +327,13 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -276,13 +327,13 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
if (FLAG_trace) { if (FLAG_trace) {
// Push the return value on the stack as the parameter. // Push the return value on the stack as the parameter.
// Runtime::TraceExit returns the parameter as it is. // Runtime::TraceExit returns the parameter as it is.
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kTraceExit, 1); __ CallRuntime(Runtime::kTraceExit, 1);
} }
// Tear down the frame which will restore the caller's frame pointer and the // Tear down the frame which will restore the caller's frame pointer and the
// link register. // link register.
ExitJSFrame(); frame_->Exit();
__ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
__ mov(pc, lr); __ mov(pc, lr);
...@@ -346,16 +397,17 @@ MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { ...@@ -346,16 +397,17 @@ MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
} }
// Loads a value on the stack. If it is a boolean value, the result may have // Loads a value on TOS. If it is a boolean value, the result may have been
// been (partially) translated into branches, or it may have set the condition // (partially) translated into branches, or it may have set the condition
// code register. If force_cc is set, the value is forced to set the condition // code register. If force_cc is set, the value is forced to set the
// code register and no value is pushed. If the condition code register was set, // condition code register and no value is pushed. If the condition code
// has_cc() is true and cc_reg_ contains the condition to test for 'true'. // register was set, has_cc() is true and cc_reg_ contains the condition to
// test for 'true'.
void CodeGenerator::LoadCondition(Expression* x, void CodeGenerator::LoadCondition(Expression* x,
TypeofState typeof_state, TypeofState typeof_state,
Label* true_target, Label* true_target,
Label* false_target, Label* false_target,
bool force_cc) { bool force_cc) {
ASSERT(!has_cc()); ASSERT(!has_cc());
{ CodeGenState new_state(this, typeof_state, true_target, false_target); { CodeGenState new_state(this, typeof_state, true_target, false_target);
...@@ -363,6 +415,13 @@ void CodeGenerator::LoadCondition(Expression* x, ...@@ -363,6 +415,13 @@ void CodeGenerator::LoadCondition(Expression* x,
} }
if (force_cc && !has_cc()) { if (force_cc && !has_cc()) {
// Convert the TOS value to a boolean in the condition code register. // Convert the TOS value to a boolean in the condition code register.
// Visiting an expression may possibly choose neither (a) to leave a
// value in the condition code register nor (b) to leave a value in TOS
// (eg, by compiling to only jumps to the targets). In that case the
// code generated by ToBoolean is wrong because it assumes the value of
// the expression in TOS. So long as there is always a value in TOS or
// the condition code register when control falls through to here (there
// is), the code generated by ToBoolean is dead and therefore safe.
ToBoolean(true_target, false_target); ToBoolean(true_target, false_target);
} }
ASSERT(has_cc() || !force_cc); ASSERT(has_cc() || !force_cc);
...@@ -379,11 +438,11 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -379,11 +438,11 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
Label loaded, materialize_true; Label loaded, materialize_true;
__ b(cc_reg_, &materialize_true); __ b(cc_reg_, &materialize_true);
__ mov(r0, Operand(Factory::false_value())); __ mov(r0, Operand(Factory::false_value()));
__ push(r0); frame_->Push(r0);
__ b(&loaded); __ b(&loaded);
__ bind(&materialize_true); __ bind(&materialize_true);
__ mov(r0, Operand(Factory::true_value())); __ mov(r0, Operand(Factory::true_value()));
__ push(r0); frame_->Push(r0);
__ bind(&loaded); __ bind(&loaded);
cc_reg_ = al; cc_reg_ = al;
} }
...@@ -399,7 +458,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -399,7 +458,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
if (true_target.is_linked()) { if (true_target.is_linked()) {
__ bind(&true_target); __ bind(&true_target);
__ mov(r0, Operand(Factory::true_value())); __ mov(r0, Operand(Factory::true_value()));
__ push(r0); frame_->Push(r0);
} }
// if both "true" and "false" need to be reincarnated, // if both "true" and "false" need to be reincarnated,
// jump across code for "false" // jump across code for "false"
...@@ -409,7 +468,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -409,7 +468,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
if (false_target.is_linked()) { if (false_target.is_linked()) {
__ bind(&false_target); __ bind(&false_target);
__ mov(r0, Operand(Factory::false_value())); __ mov(r0, Operand(Factory::false_value()));
__ push(r0); frame_->Push(r0);
} }
// everything is loaded at this point // everything is loaded at this point
__ bind(&loaded); __ bind(&loaded);
...@@ -420,14 +479,15 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -420,14 +479,15 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
void CodeGenerator::LoadGlobal() { void CodeGenerator::LoadGlobal() {
__ ldr(r0, GlobalObject()); __ ldr(r0, GlobalObject());
__ push(r0); frame_->Push(r0);
} }
void CodeGenerator::LoadGlobalReceiver(Register s) { void CodeGenerator::LoadGlobalReceiver(Register scratch) {
__ ldr(s, ContextOperand(cp, Context::GLOBAL_INDEX)); __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX));
__ ldr(s, FieldMemOperand(s, GlobalObject::kGlobalReceiverOffset)); __ ldr(scratch,
__ push(s); FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset));
frame_->Push(scratch);
} }
...@@ -465,7 +525,6 @@ Reference::~Reference() { ...@@ -465,7 +525,6 @@ Reference::~Reference() {
void CodeGenerator::LoadReference(Reference* ref) { void CodeGenerator::LoadReference(Reference* ref) {
Comment cmnt(masm_, "[ LoadReference"); Comment cmnt(masm_, "[ LoadReference");
Expression* e = ref->expression(); Expression* e = ref->expression();
Property* property = e->AsProperty(); Property* property = e->AsProperty();
Variable* var = e->AsVariableProxy()->AsVariable(); Variable* var = e->AsVariableProxy()->AsVariable();
...@@ -507,15 +566,15 @@ void CodeGenerator::LoadReference(Reference* ref) { ...@@ -507,15 +566,15 @@ void CodeGenerator::LoadReference(Reference* ref) {
void CodeGenerator::UnloadReference(Reference* ref) { void CodeGenerator::UnloadReference(Reference* ref) {
// Pop a reference from the stack while preserving TOS.
Comment cmnt(masm_, "[ UnloadReference"); Comment cmnt(masm_, "[ UnloadReference");
int size = ref->size(); int size = ref->size();
if (size <= 0) { if (size <= 0) {
// Do nothing. No popping is necessary. // Do nothing. No popping is necessary.
} else { } else {
__ pop(r0); frame_->Pop(r0);
__ add(sp, sp, Operand(size * kPointerSize)); frame_->Drop(size);
__ push(r0); frame_->Push(r0);
} }
} }
...@@ -524,10 +583,10 @@ void CodeGenerator::UnloadReference(Reference* ref) { ...@@ -524,10 +583,10 @@ void CodeGenerator::UnloadReference(Reference* ref) {
// register to a boolean in the condition code register. The code // register to a boolean in the condition code register. The code
// may jump to 'false_target' in case the register converts to 'false'. // may jump to 'false_target' in case the register converts to 'false'.
void CodeGenerator::ToBoolean(Label* true_target, void CodeGenerator::ToBoolean(Label* true_target,
Label* false_target) { Label* false_target) {
// Note: The generated code snippet does not change stack variables. // Note: The generated code snippet does not change stack variables.
// Only the condition code should be set. // Only the condition code should be set.
__ pop(r0); frame_->Pop(r0);
// Fast case checks // Fast case checks
...@@ -550,10 +609,9 @@ void CodeGenerator::ToBoolean(Label* true_target, ...@@ -550,10 +609,9 @@ void CodeGenerator::ToBoolean(Label* true_target,
__ b(eq, true_target); __ b(eq, true_target);
// Slow case: call the runtime. // Slow case: call the runtime.
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kToBool, 1); __ CallRuntime(Runtime::kToBool, 1);
// Convert the result (r0) to a condition code.
// Convert result (r0) to condition code
__ cmp(r0, Operand(Factory::false_value())); __ cmp(r0, Operand(Factory::false_value()));
cc_reg_ = ne; cc_reg_ = ne;
...@@ -654,8 +712,8 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op) { ...@@ -654,8 +712,8 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op) {
case Token::SHL: case Token::SHL:
case Token::SHR: case Token::SHR:
case Token::SAR: { case Token::SAR: {
__ pop(r0); // r0 : y frame_->Pop(r0); // r0 : y
__ pop(r1); // r1 : x frame_->Pop(r1); // r1 : x
GenericBinaryOpStub stub(op); GenericBinaryOpStub stub(op);
__ CallStub(&stub); __ CallStub(&stub);
break; break;
...@@ -674,9 +732,9 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op) { ...@@ -674,9 +732,9 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op) {
} }
case Token::COMMA: case Token::COMMA:
__ pop(r0); frame_->Pop(r0);
// simply discard left value // simply discard left value
__ pop(); frame_->Pop();
break; break;
default: default:
...@@ -764,8 +822,8 @@ class DeferredInlinedSmiOperation: public DeferredCode { ...@@ -764,8 +822,8 @@ class DeferredInlinedSmiOperation: public DeferredCode {
void CodeGenerator::SmiOperation(Token::Value op, void CodeGenerator::SmiOperation(Token::Value op,
Handle<Object> value, Handle<Object> value,
bool reversed) { bool reversed) {
// NOTE: This is an attempt to inline (a bit) more of the code for // NOTE: This is an attempt to inline (a bit) more of the code for
// some possible smi operations (like + and -) when (at least) one // some possible smi operations (like + and -) when (at least) one
// of the operands is a literal smi. With this optimization, the // of the operands is a literal smi. With this optimization, the
...@@ -778,7 +836,7 @@ void CodeGenerator::SmiOperation(Token::Value op, ...@@ -778,7 +836,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
int int_value = Smi::cast(*value)->value(); int int_value = Smi::cast(*value)->value();
Label exit; Label exit;
__ pop(r0); frame_->Pop(r0);
switch (op) { switch (op) {
case Token::ADD: { case Token::ADD: {
...@@ -831,8 +889,8 @@ void CodeGenerator::SmiOperation(Token::Value op, ...@@ -831,8 +889,8 @@ void CodeGenerator::SmiOperation(Token::Value op,
case Token::SAR: { case Token::SAR: {
if (reversed) { if (reversed) {
__ mov(ip, Operand(value)); __ mov(ip, Operand(value));
__ push(ip); frame_->Push(ip);
__ push(r0); frame_->Push(r0);
GenericBinaryOperation(op); GenericBinaryOperation(op);
} else { } else {
...@@ -882,13 +940,13 @@ void CodeGenerator::SmiOperation(Token::Value op, ...@@ -882,13 +940,13 @@ void CodeGenerator::SmiOperation(Token::Value op,
default: default:
if (!reversed) { if (!reversed) {
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(value)); __ mov(r0, Operand(value));
__ push(r0); frame_->Push(r0);
} else { } else {
__ mov(ip, Operand(value)); __ mov(ip, Operand(value));
__ push(ip); frame_->Push(ip);
__ push(r0); frame_->Push(r0);
} }
GenericBinaryOperation(op); GenericBinaryOperation(op);
break; break;
...@@ -910,18 +968,18 @@ void CodeGenerator::Comparison(Condition cc, bool strict) { ...@@ -910,18 +968,18 @@ void CodeGenerator::Comparison(Condition cc, bool strict) {
// Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
if (cc == gt || cc == le) { if (cc == gt || cc == le) {
cc = ReverseCondition(cc); cc = ReverseCondition(cc);
__ pop(r1); frame_->Pop(r1);
__ pop(r0); frame_->Pop(r0);
} else { } else {
__ pop(r0); frame_->Pop(r0);
__ pop(r1); frame_->Pop(r1);
} }
__ orr(r2, r0, Operand(r1)); __ orr(r2, r0, Operand(r1));
__ tst(r2, Operand(kSmiTagMask)); __ tst(r2, Operand(kSmiTagMask));
__ b(eq, &smi); __ b(eq, &smi);
// Perform non-smi comparison by runtime call. // Perform non-smi comparison by runtime call.
__ push(r1); frame_->Push(r1);
// Figure out which native to call and setup the arguments. // Figure out which native to call and setup the arguments.
Builtins::JavaScript native; Builtins::JavaScript native;
...@@ -938,14 +996,14 @@ void CodeGenerator::Comparison(Condition cc, bool strict) { ...@@ -938,14 +996,14 @@ void CodeGenerator::Comparison(Condition cc, bool strict) {
ASSERT(cc == gt || cc == ge); // remaining cases ASSERT(cc == gt || cc == ge); // remaining cases
ncr = LESS; ncr = LESS;
} }
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(Smi::FromInt(ncr))); __ mov(r0, Operand(Smi::FromInt(ncr)));
argc = 2; argc = 2;
} }
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater) // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer. // tagged as a small integer.
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(argc)); __ mov(r0, Operand(argc));
__ InvokeBuiltin(native, CALL_JS); __ InvokeBuiltin(native, CALL_JS);
__ cmp(r0, Operand(0)); __ cmp(r0, Operand(0));
...@@ -995,7 +1053,7 @@ void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, ...@@ -995,7 +1053,7 @@ void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
// Restore context and pop function from the stack. // Restore context and pop function from the stack.
__ ldr(cp, frame_->Context()); __ ldr(cp, frame_->Context());
__ pop(); // discard the TOS frame_->Pop(); // discard the TOS
} }
...@@ -1027,10 +1085,10 @@ void CodeGenerator::VisitBlock(Block* node) { ...@@ -1027,10 +1085,10 @@ void CodeGenerator::VisitBlock(Block* node) {
void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
__ mov(r0, Operand(pairs)); __ mov(r0, Operand(pairs));
__ push(r0); frame_->Push(r0);
__ push(cp); frame_->Push(cp);
__ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kDeclareGlobals, 3); __ CallRuntime(Runtime::kDeclareGlobals, 3);
// The result is discarded. // The result is discarded.
} }
...@@ -1050,26 +1108,26 @@ void CodeGenerator::VisitDeclaration(Declaration* node) { ...@@ -1050,26 +1108,26 @@ void CodeGenerator::VisitDeclaration(Declaration* node) {
// during variable resolution and must have mode DYNAMIC. // during variable resolution and must have mode DYNAMIC.
ASSERT(var->mode() == Variable::DYNAMIC); ASSERT(var->mode() == Variable::DYNAMIC);
// For now, just do a runtime call. // For now, just do a runtime call.
__ push(cp); frame_->Push(cp);
__ mov(r0, Operand(var->name())); __ mov(r0, Operand(var->name()));
__ push(r0); frame_->Push(r0);
// Declaration nodes are always declared in only two modes. // Declaration nodes are always declared in only two modes.
ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
__ mov(r0, Operand(Smi::FromInt(attr))); __ mov(r0, Operand(Smi::FromInt(attr)));
__ push(r0); frame_->Push(r0);
// Push initial value, if any. // Push initial value, if any.
// Note: For variables we must not push an initial value (such as // Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we // 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value. // must not destroy the current value.
if (node->mode() == Variable::CONST) { if (node->mode() == Variable::CONST) {
__ mov(r0, Operand(Factory::the_hole_value())); __ mov(r0, Operand(Factory::the_hole_value()));
__ push(r0); frame_->Push(r0);
} else if (node->fun() != NULL) { } else if (node->fun() != NULL) {
Load(node->fun()); Load(node->fun());
} else { } else {
__ mov(r0, Operand(0)); // no initial value! __ mov(r0, Operand(0)); // no initial value!
__ push(r0); frame_->Push(r0);
} }
__ CallRuntime(Runtime::kDeclareContextSlot, 4); __ CallRuntime(Runtime::kDeclareContextSlot, 4);
// Ignore the return value (declarations are statements). // Ignore the return value (declarations are statements).
...@@ -1096,7 +1154,7 @@ void CodeGenerator::VisitDeclaration(Declaration* node) { ...@@ -1096,7 +1154,7 @@ void CodeGenerator::VisitDeclaration(Declaration* node) {
// safe to pop the value lying on top of the reference before unloading // safe to pop the value lying on top of the reference before unloading
// the reference itself (which preserves the top of stack) because we // the reference itself (which preserves the top of stack) because we
// know it is a zero-sized reference. // know it is a zero-sized reference.
__ pop(); frame_->Pop();
} }
} }
...@@ -1107,7 +1165,7 @@ void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { ...@@ -1107,7 +1165,7 @@ void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
Expression* expression = node->expression(); Expression* expression = node->expression();
expression->MarkAsStatement(); expression->MarkAsStatement();
Load(expression); Load(expression);
__ pop(); frame_->Pop();
} }
...@@ -1172,7 +1230,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1172,7 +1230,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
if (has_cc()) { if (has_cc()) {
cc_reg_ = al; cc_reg_ = al;
} else { } else {
__ pop(r0); // __ Pop(no_reg) frame_->Pop();
} }
} }
...@@ -1182,10 +1240,8 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1182,10 +1240,8 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
void CodeGenerator::CleanStack(int num_bytes) { void CodeGenerator::CleanStack(int num_bytes) {
ASSERT(num_bytes >= 0); ASSERT(num_bytes % kPointerSize == 0);
if (num_bytes > 0) { frame_->Drop(num_bytes / kPointerSize);
__ add(sp, sp, Operand(num_bytes));
}
} }
...@@ -1210,7 +1266,7 @@ void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { ...@@ -1210,7 +1266,7 @@ void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
if (FLAG_debug_info) RecordStatementPosition(node); if (FLAG_debug_info) RecordStatementPosition(node);
Load(node->expression()); Load(node->expression());
// Move the function result into r0. // Move the function result into r0.
__ pop(r0); frame_->Pop(r0);
__ b(&function_return_); __ b(&function_return_);
} }
...@@ -1261,7 +1317,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable( ...@@ -1261,7 +1317,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
__ pop(r0); frame_->Pop(r0);
// Test for a Smi value in a HeapNumber. // Test for a Smi value in a HeapNumber.
Label is_smi; Label is_smi;
...@@ -1271,7 +1327,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable( ...@@ -1271,7 +1327,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
__ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag)); __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
__ cmp(r1, Operand(HEAP_NUMBER_TYPE)); __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
__ b(ne, fail_label); __ b(ne, fail_label);
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kNumberToSmi, 1); __ CallRuntime(Runtime::kNumberToSmi, 1);
__ bind(&is_smi); __ bind(&is_smi);
...@@ -1340,7 +1396,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -1340,7 +1396,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
__ bind(&next); __ bind(&next);
next.Unuse(); next.Unuse();
__ ldr(r0, frame_->Top()); __ ldr(r0, frame_->Top());
__ push(r0); // duplicate TOS frame_->Push(r0); // duplicate TOS
Load(clause->label()); Load(clause->label());
Comparison(eq, true); Comparison(eq, true);
Branch(false, &next); Branch(false, &next);
...@@ -1348,7 +1404,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -1348,7 +1404,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
// Entering the case statement for the first time. Remove the switch value // Entering the case statement for the first time. Remove the switch value
// from the stack. // from the stack.
__ pop(r0); frame_->Pop();
// Generate code for the body. // Generate code for the body.
// This is also the target for the fall through from the previous case's // This is also the target for the fall through from the previous case's
...@@ -1367,7 +1423,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -1367,7 +1423,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
__ b(&default_case); __ b(&default_case);
} else { } else {
// Remove the switch value from the stack. // Remove the switch value from the stack.
__ pop(r0); frame_->Pop();
} }
__ bind(&fall_through); __ bind(&fall_through);
...@@ -1463,7 +1519,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1463,7 +1519,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
// Get the object to enumerate over (converted to JSObject). // Get the object to enumerate over (converted to JSObject).
Load(node->enumerable()); Load(node->enumerable());
__ pop(r0); frame_->Pop(r0);
// Both SpiderMonkey and kjs ignore null and undefined in contrast // Both SpiderMonkey and kjs ignore null and undefined in contrast
// to the specification. 12.6.4 mandates a call to ToObject. // to the specification. 12.6.4 mandates a call to ToObject.
...@@ -1488,7 +1544,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1488,7 +1544,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
__ b(hs, &jsobject); __ b(hs, &jsobject);
__ bind(&primitive); __ bind(&primitive);
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(0)); __ mov(r0, Operand(0));
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
...@@ -1496,8 +1552,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1496,8 +1552,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
__ bind(&jsobject); __ bind(&jsobject);
// Get the set of properties (as a FixedArray or Map). // Get the set of properties (as a FixedArray or Map).
__ push(r0); // duplicate the object being enumerated frame_->Push(r0); // duplicate the object being enumerated
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1); __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
// If we got a Map, we can do a fast modification check. // If we got a Map, we can do a fast modification check.
...@@ -1514,28 +1570,28 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1514,28 +1570,28 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
__ ldr(r2, __ ldr(r2,
FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset)); FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
__ push(r0); // map frame_->Push(r0); // map
__ push(r2); // enum cache bridge cache frame_->Push(r2); // enum cache bridge cache
__ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset)); __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset));
__ mov(r0, Operand(r0, LSL, kSmiTagSize)); __ mov(r0, Operand(r0, LSL, kSmiTagSize));
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(Smi::FromInt(0))); __ mov(r0, Operand(Smi::FromInt(0)));
__ push(r0); frame_->Push(r0);
__ b(&entry); __ b(&entry);
__ bind(&fixed_array); __ bind(&fixed_array);
__ mov(r1, Operand(Smi::FromInt(0))); __ mov(r1, Operand(Smi::FromInt(0)));
__ push(r1); // insert 0 in place of Map frame_->Push(r1); // insert 0 in place of Map
__ push(r0); frame_->Push(r0);
// Push the length of the array and the initial index onto the stack. // Push the length of the array and the initial index onto the stack.
__ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset)); __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset));
__ mov(r0, Operand(r0, LSL, kSmiTagSize)); __ mov(r0, Operand(r0, LSL, kSmiTagSize));
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(Smi::FromInt(0))); // init index __ mov(r0, Operand(Smi::FromInt(0))); // init index
__ push(r0); frame_->Push(r0);
__ b(&entry); __ b(&entry);
...@@ -1546,9 +1602,9 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1546,9 +1602,9 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
// Next. // Next.
__ bind(node->continue_target()); __ bind(node->continue_target());
__ bind(&next); __ bind(&next);
__ pop(r0); frame_->Pop(r0);
__ add(r0, r0, Operand(Smi::FromInt(1))); __ add(r0, r0, Operand(Smi::FromInt(1)));
__ push(r0); frame_->Push(r0);
// Condition. // Condition.
__ bind(&entry); __ bind(&entry);
...@@ -1581,8 +1637,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1581,8 +1637,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
// Convert the entry to a string (or null if it isn't a property anymore). // Convert the entry to a string (or null if it isn't a property anymore).
__ ldr(r0, frame_->Element(4)); // push enumerable __ ldr(r0, frame_->Element(4)); // push enumerable
__ push(r0); frame_->Push(r0);
__ push(r3); // push entry frame_->Push(r3); // push entry
__ mov(r0, Operand(1)); __ mov(r0, Operand(1));
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
__ mov(r3, Operand(r0)); __ mov(r3, Operand(r0));
...@@ -1596,12 +1652,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1596,12 +1652,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
// Store the entry in the 'each' expression and take another spin in the loop. // Store the entry in the 'each' expression and take another spin in the loop.
// r3: i'th entry of the enum cache (or string there of) // r3: i'th entry of the enum cache (or string there of)
__ push(r3); // push entry frame_->Push(r3); // push entry
{ Reference each(this, node->each()); { Reference each(this, node->each());
if (!each.is_illegal()) { if (!each.is_illegal()) {
if (each.size() > 0) { if (each.size() > 0) {
__ ldr(r0, frame_->Element(each.size())); __ ldr(r0, frame_->Element(each.size()));
__ push(r0); frame_->Push(r0);
} }
// If the reference was to a slot we rely on the convenient property // If the reference was to a slot we rely on the convenient property
// that it doesn't matter whether a value (eg, r3 pushed above) is // that it doesn't matter whether a value (eg, r3 pushed above) is
...@@ -1613,20 +1669,20 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1613,20 +1669,20 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
// ie, now the topmost value of the non-zero sized reference), since // ie, now the topmost value of the non-zero sized reference), since
// we will discard the top of stack after unloading the reference // we will discard the top of stack after unloading the reference
// anyway. // anyway.
__ pop(r0); frame_->Pop(r0);
} }
} }
} }
// Discard the i'th entry pushed above or else the remainder of the // Discard the i'th entry pushed above or else the remainder of the
// reference, whichever is currently on top of the stack. // reference, whichever is currently on top of the stack.
__ pop(); frame_->Pop();
CheckStack(); // TODO(1222600): ignore if body contains calls. CheckStack(); // TODO(1222600): ignore if body contains calls.
__ jmp(&loop); __ jmp(&loop);
// Cleanup. // Cleanup.
__ bind(&cleanup); __ bind(&cleanup);
__ bind(node->break_target()); __ bind(node->break_target());
__ add(sp, sp, Operand(5 * kPointerSize)); frame_->Drop(5);
// Exit. // Exit.
__ bind(&exit); __ bind(&exit);
...@@ -1641,11 +1697,10 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -1641,11 +1697,10 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
Label try_block, exit; Label try_block, exit;
__ bl(&try_block); __ bl(&try_block);
// --- Catch block --- // --- Catch block ---
frame_->Push(r0);
// Store the caught exception in the catch variable. // Store the caught exception in the catch variable.
__ push(r0);
{ Reference ref(this, node->catch_var()); { Reference ref(this, node->catch_var());
ASSERT(ref.is_slot()); ASSERT(ref.is_slot());
// Here we make use of the convenient property that it doesn't matter // Here we make use of the convenient property that it doesn't matter
...@@ -1655,7 +1710,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -1655,7 +1710,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
} }
// Remove the exception from the stack. // Remove the exception from the stack.
__ pop(); frame_->Pop();
VisitStatements(node->catch_block()->statements()); VisitStatements(node->catch_block()->statements());
__ b(&exit); __ b(&exit);
...@@ -1682,7 +1737,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -1682,7 +1737,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Generate code for the statements in the try block. // Generate code for the statements in the try block.
VisitStatements(node->try_block()->statements()); VisitStatements(node->try_block()->statements());
__ pop(r0); // Discard the result. frame_->Pop(); // Discard the result.
// Stop the introduced shadowing and count the number of required unlinks. // Stop the introduced shadowing and count the number of required unlinks.
// After shadowing stops, the original labels are unshadowed and the // After shadowing stops, the original labels are unshadowed and the
...@@ -1702,7 +1757,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -1702,7 +1757,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
__ mov(r3, Operand(ExternalReference(Top::k_handler_address))); __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ str(r1, MemOperand(r3)); __ str(r1, MemOperand(r3));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
__ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Code slot popped. // Code slot popped.
if (nof_unlinks > 0) __ b(&exit); if (nof_unlinks > 0) __ b(&exit);
...@@ -1721,7 +1776,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -1721,7 +1776,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
__ ldr(r1, frame_->Element(kNextIndex)); __ ldr(r1, frame_->Element(kNextIndex));
__ str(r1, MemOperand(r3)); __ str(r1, MemOperand(r3));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
__ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Code slot popped. // Code slot popped.
__ b(shadows[i]->original_label()); __ b(shadows[i]->original_label());
...@@ -1744,7 +1799,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -1744,7 +1799,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
__ bl(&try_block); __ bl(&try_block);
__ push(r0); // save exception object on the stack frame_->Push(r0); // save exception object on the stack
// In case of thrown exceptions, this is where we continue. // In case of thrown exceptions, this is where we continue.
__ mov(r2, Operand(Smi::FromInt(THROWING))); __ mov(r2, Operand(Smi::FromInt(THROWING)));
__ b(&finally_block); __ b(&finally_block);
...@@ -1782,7 +1837,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -1782,7 +1837,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// Set the state on the stack to FALLING. // Set the state on the stack to FALLING.
__ mov(r0, Operand(Factory::undefined_value())); // fake TOS __ mov(r0, Operand(Factory::undefined_value())); // fake TOS
__ push(r0); frame_->Push(r0);
__ mov(r2, Operand(Smi::FromInt(FALLING))); __ mov(r2, Operand(Smi::FromInt(FALLING)));
if (nof_unlinks > 0) __ b(&unlink); if (nof_unlinks > 0) __ b(&unlink);
...@@ -1794,11 +1849,11 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -1794,11 +1849,11 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
if (shadows[i]->original_label() == &function_return_) { if (shadows[i]->original_label() == &function_return_) {
// If this label shadowed the function return, materialize the // If this label shadowed the function return, materialize the
// return value on the stack. // return value on the stack.
__ push(r0); frame_->Push(r0);
} else { } else {
// Fake TOS for labels that shadowed breaks and continues. // Fake TOS for labels that shadowed breaks and continues.
__ mov(r0, Operand(Factory::undefined_value())); __ mov(r0, Operand(Factory::undefined_value()));
__ push(r0); frame_->Push(r0);
} }
__ mov(r2, Operand(Smi::FromInt(JUMPING + i))); __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
__ b(&unlink); __ b(&unlink);
...@@ -1808,7 +1863,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -1808,7 +1863,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// Unlink from try chain; // Unlink from try chain;
__ bind(&unlink); __ bind(&unlink);
__ pop(r0); // Store TOS in r0 across stack manipulation frame_->Pop(r0); // Store TOS in r0 across stack manipulation
// Reload sp from the top handler, because some statements that we // Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack. // break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address))); __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
...@@ -1819,15 +1874,15 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -1819,15 +1874,15 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
__ ldr(r1, frame_->Element(kNextIndex)); __ ldr(r1, frame_->Element(kNextIndex));
__ str(r1, MemOperand(r3)); __ str(r1, MemOperand(r3));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
__ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Code slot popped. // Code slot popped.
__ push(r0); frame_->Push(r0);
// --- Finally block --- // --- Finally block ---
__ bind(&finally_block); __ bind(&finally_block);
// Push the state on the stack. // Push the state on the stack.
__ push(r2); frame_->Push(r2);
// We keep two elements on the stack - the (possibly faked) result // We keep two elements on the stack - the (possibly faked) result
// and the state - while evaluating the finally block. Record it, so // and the state - while evaluating the finally block. Record it, so
...@@ -1840,8 +1895,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -1840,8 +1895,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
VisitStatements(node->finally_block()->statements()); VisitStatements(node->finally_block()->statements());
// Restore state and return value or faked TOS. // Restore state and return value or faked TOS.
__ pop(r2); frame_->Pop(r2);
__ pop(r0); frame_->Pop(r0);
break_stack_height_ -= kFinallyStackSize; break_stack_height_ -= kFinallyStackSize;
// Generate code to jump to the right destination for all used (formerly) // Generate code to jump to the right destination for all used (formerly)
...@@ -1865,7 +1920,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -1865,7 +1920,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
__ b(ne, &exit); __ b(ne, &exit);
// Rethrow exception. // Rethrow exception.
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kReThrow, 1); __ CallRuntime(Runtime::kReThrow, 1);
// Done. // Done.
...@@ -1886,12 +1941,12 @@ void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { ...@@ -1886,12 +1941,12 @@ void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
// Push the boilerplate on the stack. // Push the boilerplate on the stack.
__ mov(r0, Operand(boilerplate)); __ mov(r0, Operand(boilerplate));
__ push(r0); frame_->Push(r0);
// Create a new closure. // Create a new closure.
__ push(cp); frame_->Push(cp);
__ CallRuntime(Runtime::kNewClosure, 2); __ CallRuntime(Runtime::kNewClosure, 2);
__ push(r0); frame_->Push(r0);
} }
...@@ -1932,16 +1987,16 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -1932,16 +1987,16 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
ASSERT(slot->var()->mode() == Variable::DYNAMIC); ASSERT(slot->var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call. // For now, just do a runtime call.
__ push(cp); frame_->Push(cp);
__ mov(r0, Operand(slot->var()->name())); __ mov(r0, Operand(slot->var()->name()));
__ push(r0); frame_->Push(r0);
if (typeof_state == INSIDE_TYPEOF) { if (typeof_state == INSIDE_TYPEOF) {
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
} else { } else {
__ CallRuntime(Runtime::kLoadContextSlot, 2); __ CallRuntime(Runtime::kLoadContextSlot, 2);
} }
__ push(r0); frame_->Push(r0);
} else { } else {
// Note: We would like to keep the assert below, but it fires because of // Note: We would like to keep the assert below, but it fires because of
...@@ -1950,16 +2005,16 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -1950,16 +2005,16 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// Special handling for locals allocated in registers. // Special handling for locals allocated in registers.
__ ldr(r0, SlotOperand(slot, r2)); __ ldr(r0, SlotOperand(slot, r2));
__ push(r0); frame_->Push(r0);
if (slot->var()->mode() == Variable::CONST) { if (slot->var()->mode() == Variable::CONST) {
// Const slots may contain 'the hole' value (the constant hasn't been // Const slots may contain 'the hole' value (the constant hasn't been
// initialized yet) which needs to be converted into the 'undefined' // initialized yet) which needs to be converted into the 'undefined'
// value. // value.
Comment cmnt(masm_, "[ Unhole const"); Comment cmnt(masm_, "[ Unhole const");
__ pop(r0); frame_->Pop(r0);
__ cmp(r0, Operand(Factory::the_hole_value())); __ cmp(r0, Operand(Factory::the_hole_value()));
__ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq); __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
__ push(r0); frame_->Push(r0);
} }
} }
} }
...@@ -1989,7 +2044,7 @@ void CodeGenerator::VisitVariableProxy(VariableProxy* node) { ...@@ -1989,7 +2044,7 @@ void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
void CodeGenerator::VisitLiteral(Literal* node) { void CodeGenerator::VisitLiteral(Literal* node) {
Comment cmnt(masm_, "[ Literal"); Comment cmnt(masm_, "[ Literal");
__ mov(r0, Operand(node->handle())); __ mov(r0, Operand(node->handle()));
__ push(r0); frame_->Push(r0);
} }
...@@ -2015,19 +2070,19 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { ...@@ -2015,19 +2070,19 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
// If the entry is undefined we call the runtime system to computed // If the entry is undefined we call the runtime system to computed
// the literal. // the literal.
__ push(r1); // literal array (0) frame_->Push(r1); // literal array (0)
__ mov(r0, Operand(Smi::FromInt(node->literal_index()))); __ mov(r0, Operand(Smi::FromInt(node->literal_index())));
__ push(r0); // literal index (1) frame_->Push(r0); // literal index (1)
__ mov(r0, Operand(node->pattern())); // RegExp pattern (2) __ mov(r0, Operand(node->pattern())); // RegExp pattern (2)
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(node->flags())); // RegExp flags (3) __ mov(r0, Operand(node->flags())); // RegExp flags (3)
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ mov(r2, Operand(r0)); __ mov(r2, Operand(r0));
__ bind(&done); __ bind(&done);
// Push the literal. // Push the literal.
__ push(r2); frame_->Push(r2);
} }
...@@ -2089,11 +2144,11 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { ...@@ -2089,11 +2144,11 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
__ bind(deferred->exit()); __ bind(deferred->exit());
// Push the object literal boilerplate. // Push the object literal boilerplate.
__ push(r2); frame_->Push(r2);
// Clone the boilerplate object. // Clone the boilerplate object.
__ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); __ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
__ push(r0); // save the result frame_->Push(r0); // save the result
// r0: cloned object literal // r0: cloned object literal
for (int i = 0; i < node->properties()->length(); i++) { for (int i = 0; i < node->properties()->length(); i++) {
...@@ -2104,7 +2159,7 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { ...@@ -2104,7 +2159,7 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
case ObjectLiteral::Property::CONSTANT: break; case ObjectLiteral::Property::CONSTANT: break;
case ObjectLiteral::Property::COMPUTED: // fall through case ObjectLiteral::Property::COMPUTED: // fall through
case ObjectLiteral::Property::PROTOTYPE: { case ObjectLiteral::Property::PROTOTYPE: {
__ push(r0); // dup the result frame_->Push(r0); // dup the result
Load(key); Load(key);
Load(value); Load(value);
__ CallRuntime(Runtime::kSetProperty, 3); __ CallRuntime(Runtime::kSetProperty, 3);
...@@ -2113,20 +2168,20 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { ...@@ -2113,20 +2168,20 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
break; break;
} }
case ObjectLiteral::Property::SETTER: { case ObjectLiteral::Property::SETTER: {
__ push(r0); frame_->Push(r0);
Load(key); Load(key);
__ mov(r0, Operand(Smi::FromInt(1))); __ mov(r0, Operand(Smi::FromInt(1)));
__ push(r0); frame_->Push(r0);
Load(value); Load(value);
__ CallRuntime(Runtime::kDefineAccessor, 4); __ CallRuntime(Runtime::kDefineAccessor, 4);
__ ldr(r0, frame_->Top()); __ ldr(r0, frame_->Top());
break; break;
} }
case ObjectLiteral::Property::GETTER: { case ObjectLiteral::Property::GETTER: {
__ push(r0); frame_->Push(r0);
Load(key); Load(key);
__ mov(r0, Operand(Smi::FromInt(0))); __ mov(r0, Operand(Smi::FromInt(0)));
__ push(r0); frame_->Push(r0);
Load(value); Load(value);
__ CallRuntime(Runtime::kDefineAccessor, 4); __ CallRuntime(Runtime::kDefineAccessor, 4);
__ ldr(r0, frame_->Top()); __ ldr(r0, frame_->Top());
...@@ -2142,15 +2197,15 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { ...@@ -2142,15 +2197,15 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
// Call runtime to create the array literal. // Call runtime to create the array literal.
__ mov(r0, Operand(node->literals())); __ mov(r0, Operand(node->literals()));
__ push(r0); frame_->Push(r0);
// Load the function of this frame. // Load the function of this frame.
__ ldr(r0, frame_->Function()); __ ldr(r0, frame_->Function());
__ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kCreateArrayLiteral, 2); __ CallRuntime(Runtime::kCreateArrayLiteral, 2);
// Push the resulting array literal on the stack. // Push the resulting array literal on the stack.
__ push(r0); frame_->Push(r0);
// Generate code to set the elements in the array that are not // Generate code to set the elements in the array that are not
// literals. // literals.
...@@ -2162,7 +2217,7 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { ...@@ -2162,7 +2217,7 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
if (value->AsLiteral() == NULL) { if (value->AsLiteral() == NULL) {
// The property must be set by generated code. // The property must be set by generated code.
Load(value); Load(value);
__ pop(r0); frame_->Pop(r0);
// Fetch the object literal // Fetch the object literal
__ ldr(r1, frame_->Top()); __ ldr(r1, frame_->Top());
...@@ -2198,12 +2253,12 @@ void CodeGenerator::VisitAssignment(Assignment* node) { ...@@ -2198,12 +2253,12 @@ void CodeGenerator::VisitAssignment(Assignment* node) {
Literal* literal = node->value()->AsLiteral(); Literal* literal = node->value()->AsLiteral();
if (literal != NULL && literal->handle()->IsSmi()) { if (literal != NULL && literal->handle()->IsSmi()) {
SmiOperation(node->binary_op(), literal->handle(), false); SmiOperation(node->binary_op(), literal->handle(), false);
__ push(r0); frame_->Push(r0);
} else { } else {
Load(node->value()); Load(node->value());
GenericBinaryOperation(node->binary_op()); GenericBinaryOperation(node->binary_op());
__ push(r0); frame_->Push(r0);
} }
} }
...@@ -2233,7 +2288,7 @@ void CodeGenerator::VisitThrow(Throw* node) { ...@@ -2233,7 +2288,7 @@ void CodeGenerator::VisitThrow(Throw* node) {
Load(node->exception()); Load(node->exception());
__ RecordPosition(node->position()); __ RecordPosition(node->position());
__ CallRuntime(Runtime::kThrow, 1); __ CallRuntime(Runtime::kThrow, 1);
__ push(r0); frame_->Push(r0);
} }
...@@ -2274,7 +2329,7 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2274,7 +2329,7 @@ void CodeGenerator::VisitCall(Call* node) {
// Push the name of the function and the receiver onto the stack. // Push the name of the function and the receiver onto the stack.
__ mov(r0, Operand(var->name())); __ mov(r0, Operand(var->name()));
__ push(r0); frame_->Push(r0);
// Pass the global object as the receiver and let the IC stub // Pass the global object as the receiver and let the IC stub
// patch the stack to use the global proxy as 'this' in the // patch the stack to use the global proxy as 'this' in the
...@@ -2290,8 +2345,8 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2290,8 +2345,8 @@ void CodeGenerator::VisitCall(Call* node) {
__ Call(stub, RelocInfo::CODE_TARGET_CONTEXT); __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT);
__ ldr(cp, frame_->Context()); __ ldr(cp, frame_->Context());
// Remove the function from the stack. // Remove the function from the stack.
__ pop(); frame_->Pop();
__ push(r0); frame_->Push(r0);
} else if (var != NULL && var->slot() != NULL && } else if (var != NULL && var->slot() != NULL &&
var->slot()->type() == Slot::LOOKUP) { var->slot()->type() == Slot::LOOKUP) {
...@@ -2300,19 +2355,19 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2300,19 +2355,19 @@ void CodeGenerator::VisitCall(Call* node) {
// ---------------------------------- // ----------------------------------
// Load the function // Load the function
__ push(cp); frame_->Push(cp);
__ mov(r0, Operand(var->name())); __ mov(r0, Operand(var->name()));
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kLoadContextSlot, 2); __ CallRuntime(Runtime::kLoadContextSlot, 2);
// r0: slot value; r1: receiver // r0: slot value; r1: receiver
// Load the receiver. // Load the receiver.
__ push(r0); // function frame_->Push(r0); // function
__ push(r1); // receiver frame_->Push(r1); // receiver
// Call the function. // Call the function.
CallWithArguments(args, node->position()); CallWithArguments(args, node->position());
__ push(r0); frame_->Push(r0);
} else if (property != NULL) { } else if (property != NULL) {
// Check if the key is a literal string. // Check if the key is a literal string.
...@@ -2325,7 +2380,7 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2325,7 +2380,7 @@ void CodeGenerator::VisitCall(Call* node) {
// Push the name of the function and the receiver onto the stack. // Push the name of the function and the receiver onto the stack.
__ mov(r0, Operand(literal->handle())); __ mov(r0, Operand(literal->handle()));
__ push(r0); frame_->Push(r0);
Load(property->obj()); Load(property->obj());
// Load the arguments. // Load the arguments.
...@@ -2338,9 +2393,9 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2338,9 +2393,9 @@ void CodeGenerator::VisitCall(Call* node) {
__ ldr(cp, frame_->Context()); __ ldr(cp, frame_->Context());
// Remove the function from the stack. // Remove the function from the stack.
__ pop(); frame_->Pop();
__ push(r0); // push after get rid of function from the stack frame_->Push(r0); // push after get rid of function from the stack
} else { } else {
// ------------------------------------------- // -------------------------------------------
...@@ -2353,10 +2408,10 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2353,10 +2408,10 @@ void CodeGenerator::VisitCall(Call* node) {
// Pass receiver to called function. // Pass receiver to called function.
__ ldr(r0, frame_->Element(ref.size())); __ ldr(r0, frame_->Element(ref.size()));
__ push(r0); frame_->Push(r0);
// Call the function. // Call the function.
CallWithArguments(args, node->position()); CallWithArguments(args, node->position());
__ push(r0); frame_->Push(r0);
} }
} else { } else {
...@@ -2372,7 +2427,7 @@ void CodeGenerator::VisitCall(Call* node) { ...@@ -2372,7 +2427,7 @@ void CodeGenerator::VisitCall(Call* node) {
// Call the function. // Call the function.
CallWithArguments(args, node->position()); CallWithArguments(args, node->position());
__ push(r0); frame_->Push(r0);
} }
} }
...@@ -2417,7 +2472,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { ...@@ -2417,7 +2472,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
Label leave; Label leave;
Load(args->at(0)); Load(args->at(0));
__ pop(r0); // r0 contains object. frame_->Pop(r0); // r0 contains object.
// if (object->IsSmi()) return the object. // if (object->IsSmi()) return the object.
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
__ b(eq, &leave); __ b(eq, &leave);
...@@ -2430,7 +2485,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { ...@@ -2430,7 +2485,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
// Load the value. // Load the value.
__ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
__ bind(&leave); __ bind(&leave);
__ push(r0); frame_->Push(r0);
} }
...@@ -2439,8 +2494,8 @@ void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { ...@@ -2439,8 +2494,8 @@ void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
Label leave; Label leave;
Load(args->at(0)); // Load the object. Load(args->at(0)); // Load the object.
Load(args->at(1)); // Load the value. Load(args->at(1)); // Load the value.
__ pop(r0); // r0 contains value frame_->Pop(r0); // r0 contains value
__ pop(r1); // r1 contains object frame_->Pop(r1); // r1 contains object
// if (object->IsSmi()) return object. // if (object->IsSmi()) return object.
__ tst(r1, Operand(kSmiTagMask)); __ tst(r1, Operand(kSmiTagMask));
__ b(eq, &leave); __ b(eq, &leave);
...@@ -2457,14 +2512,14 @@ void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { ...@@ -2457,14 +2512,14 @@ void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
__ RecordWrite(r1, r2, r3); __ RecordWrite(r1, r2, r3);
// Leave. // Leave.
__ bind(&leave); __ bind(&leave);
__ push(r0); frame_->Push(r0);
} }
void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
Load(args->at(0)); Load(args->at(0));
__ pop(r0); frame_->Pop(r0);
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
cc_reg_ = eq; cc_reg_ = eq;
} }
...@@ -2473,7 +2528,7 @@ void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { ...@@ -2473,7 +2528,7 @@ void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
Load(args->at(0)); Load(args->at(0));
__ pop(r0); frame_->Pop(r0);
__ tst(r0, Operand(kSmiTagMask | 0x80000000)); __ tst(r0, Operand(kSmiTagMask | 0x80000000));
cc_reg_ = eq; cc_reg_ = eq;
} }
...@@ -2485,7 +2540,7 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { ...@@ -2485,7 +2540,7 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
__ mov(r0, Operand(Factory::undefined_value())); __ mov(r0, Operand(Factory::undefined_value()));
__ push(r0); frame_->Push(r0);
} }
...@@ -2496,7 +2551,7 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { ...@@ -2496,7 +2551,7 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
// We need the CC bits to come out as not_equal in the case where the // We need the CC bits to come out as not_equal in the case where the
// object is a smi. This can't be done with the usual test opcode so // object is a smi. This can't be done with the usual test opcode so
// we use XOR to get the right CC bits. // we use XOR to get the right CC bits.
__ pop(r0); frame_->Pop(r0);
__ and_(r1, r0, Operand(kSmiTagMask)); __ and_(r1, r0, Operand(kSmiTagMask));
__ eor(r1, r1, Operand(kSmiTagMask), SetCC); __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
__ b(ne, &answer); __ b(ne, &answer);
...@@ -2520,7 +2575,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { ...@@ -2520,7 +2575,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
// Call the shared stub to get to the arguments.length. // Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
__ CallStub(&stub); __ CallStub(&stub);
__ push(r0); frame_->Push(r0);
} }
...@@ -2530,13 +2585,13 @@ void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { ...@@ -2530,13 +2585,13 @@ void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
// Satisfy contract with ArgumentsAccessStub: // Satisfy contract with ArgumentsAccessStub:
// Load the key into r1 and the formal parameters count into r0. // Load the key into r1 and the formal parameters count into r0.
Load(args->at(0)); Load(args->at(0));
__ pop(r1); frame_->Pop(r1);
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
// Call the shared stub to get to arguments[key]. // Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
__ CallStub(&stub); __ CallStub(&stub);
__ push(r0); frame_->Push(r0);
} }
...@@ -2546,8 +2601,8 @@ void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { ...@@ -2546,8 +2601,8 @@ void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
// Load the two objects into registers and perform the comparison. // Load the two objects into registers and perform the comparison.
Load(args->at(0)); Load(args->at(0));
Load(args->at(1)); Load(args->at(1));
__ pop(r0); frame_->Pop(r0);
__ pop(r1); frame_->Pop(r1);
__ cmp(r0, Operand(r1)); __ cmp(r0, Operand(r1));
cc_reg_ = eq; cc_reg_ = eq;
} }
...@@ -2566,16 +2621,16 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) { ...@@ -2566,16 +2621,16 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
// Call the C runtime function. // Call the C runtime function.
__ CallRuntime(function, args->length()); __ CallRuntime(function, args->length());
__ push(r0); frame_->Push(r0);
} else { } else {
// Prepare stack for calling JS runtime function. // Prepare stack for calling JS runtime function.
__ mov(r0, Operand(node->name())); __ mov(r0, Operand(node->name()));
__ push(r0); frame_->Push(r0);
// Push the builtins object found in the current global object. // Push the builtins object found in the current global object.
__ ldr(r1, GlobalObject()); __ ldr(r1, GlobalObject());
__ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
__ push(r0); frame_->Push(r0);
for (int i = 0; i < args->length(); i++) Load(args->at(i)); for (int i = 0; i < args->length(); i++) Load(args->at(i));
...@@ -2583,8 +2638,8 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) { ...@@ -2583,8 +2638,8 @@ void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
Handle<Code> stub = ComputeCallInitialize(args->length()); Handle<Code> stub = ComputeCallInitialize(args->length());
__ Call(stub, RelocInfo::CODE_TARGET); __ Call(stub, RelocInfo::CODE_TARGET);
__ ldr(cp, frame_->Context()); __ ldr(cp, frame_->Context());
__ pop(); frame_->Pop();
__ push(r0); frame_->Push(r0);
} }
} }
...@@ -2616,20 +2671,20 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -2616,20 +2671,20 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
if (variable->is_global()) { if (variable->is_global()) {
LoadGlobal(); LoadGlobal();
__ mov(r0, Operand(variable->name())); __ mov(r0, Operand(variable->name()));
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(1)); // not counting receiver __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin(Builtins::DELETE, CALL_JS); __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) { } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
// lookup the context holding the named variable // lookup the context holding the named variable
__ push(cp); frame_->Push(cp);
__ mov(r0, Operand(variable->name())); __ mov(r0, Operand(variable->name()));
__ push(r0); frame_->Push(r0);
__ CallRuntime(Runtime::kLookupContext, 2); __ CallRuntime(Runtime::kLookupContext, 2);
// r0: context // r0: context
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(variable->name())); __ mov(r0, Operand(variable->name()));
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(1)); // not counting receiver __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin(Builtins::DELETE, CALL_JS); __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
...@@ -2642,21 +2697,21 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -2642,21 +2697,21 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
} else { } else {
// Default: Result of deleting expressions is true. // Default: Result of deleting expressions is true.
Load(node->expression()); // may have side-effects Load(node->expression()); // may have side-effects
__ pop(); frame_->Pop();
__ mov(r0, Operand(Factory::true_value())); __ mov(r0, Operand(Factory::true_value()));
} }
__ push(r0); frame_->Push(r0);
} else if (op == Token::TYPEOF) { } else if (op == Token::TYPEOF) {
// Special case for loading the typeof expression; see comment on // Special case for loading the typeof expression; see comment on
// LoadTypeofExpression(). // LoadTypeofExpression().
LoadTypeofExpression(node->expression()); LoadTypeofExpression(node->expression());
__ CallRuntime(Runtime::kTypeof, 1); __ CallRuntime(Runtime::kTypeof, 1);
__ push(r0); // r0 has result frame_->Push(r0); // r0 has result
} else { } else {
Load(node->expression()); Load(node->expression());
__ pop(r0); frame_->Pop(r0);
switch (op) { switch (op) {
case Token::NOT: case Token::NOT:
case Token::DELETE: case Token::DELETE:
...@@ -2677,7 +2732,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -2677,7 +2732,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
__ b(eq, &smi_label); __ b(eq, &smi_label);
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(0)); // not counting receiver __ mov(r0, Operand(0)); // not counting receiver
__ InvokeBuiltin(Builtins::BIT_NOT, CALL_JS); __ InvokeBuiltin(Builtins::BIT_NOT, CALL_JS);
...@@ -2700,7 +2755,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -2700,7 +2755,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
Label continue_label; Label continue_label;
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
__ b(eq, &continue_label); __ b(eq, &continue_label);
__ push(r0); frame_->Push(r0);
__ mov(r0, Operand(0)); // not counting receiver __ mov(r0, Operand(0)); // not counting receiver
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
__ bind(&continue_label); __ bind(&continue_label);
...@@ -2709,7 +2764,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -2709,7 +2764,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
default: default:
UNREACHABLE(); UNREACHABLE();
} }
__ push(r0); // r0 has result frame_->Push(r0); // r0 has result
} }
} }
...@@ -2726,13 +2781,13 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) { ...@@ -2726,13 +2781,13 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
// Postfix: Make room for the result. // Postfix: Make room for the result.
if (is_postfix) { if (is_postfix) {
__ mov(r0, Operand(0)); __ mov(r0, Operand(0));
__ push(r0); frame_->Push(r0);
} }
{ Reference target(this, node->expression()); { Reference target(this, node->expression());
if (target.is_illegal()) return; if (target.is_illegal()) return;
target.GetValue(NOT_INSIDE_TYPEOF); target.GetValue(NOT_INSIDE_TYPEOF);
__ pop(r0); frame_->Pop(r0);
Label slow, exit; Label slow, exit;
...@@ -2787,12 +2842,12 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) { ...@@ -2787,12 +2842,12 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
// Store the new value in the target if not const. // Store the new value in the target if not const.
__ bind(&exit); __ bind(&exit);
__ push(r0); frame_->Push(r0);
if (!is_const) target.SetValue(NOT_CONST_INIT); if (!is_const) target.SetValue(NOT_CONST_INIT);
} }
// Postfix: Discard the new value and use the old. // Postfix: Discard the new value and use the old.
if (is_postfix) __ pop(r0); if (is_postfix) frame_->Pop(r0);
} }
...@@ -2834,7 +2889,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -2834,7 +2889,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
Label pop_and_continue, exit; Label pop_and_continue, exit;
__ ldr(r0, frame_->Top()); // dup the stack top __ ldr(r0, frame_->Top()); // dup the stack top
__ push(r0); frame_->Push(r0);
// Avoid popping the result if it converts to 'false' using the // Avoid popping the result if it converts to 'false' using the
// standard ToBoolean() conversion as described in ECMA-262, // standard ToBoolean() conversion as described in ECMA-262,
// section 9.2, page 30. // section 9.2, page 30.
...@@ -2843,7 +2898,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -2843,7 +2898,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// Pop the result of evaluating the first part. // Pop the result of evaluating the first part.
__ bind(&pop_and_continue); __ bind(&pop_and_continue);
__ pop(r0); frame_->Pop(r0);
// Evaluate right side expression. // Evaluate right side expression.
__ bind(&is_true); __ bind(&is_true);
...@@ -2875,7 +2930,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -2875,7 +2930,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
Label pop_and_continue, exit; Label pop_and_continue, exit;
__ ldr(r0, frame_->Top()); __ ldr(r0, frame_->Top());
__ push(r0); frame_->Push(r0);
// Avoid popping the result if it converts to 'true' using the // Avoid popping the result if it converts to 'true' using the
// standard ToBoolean() conversion as described in ECMA-262, // standard ToBoolean() conversion as described in ECMA-262,
// section 9.2, page 30. // section 9.2, page 30.
...@@ -2884,7 +2939,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -2884,7 +2939,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// Pop the result of evaluating the first part. // Pop the result of evaluating the first part.
__ bind(&pop_and_continue); __ bind(&pop_and_continue);
__ pop(r0); frame_->Pop(r0);
// Evaluate right side expression. // Evaluate right side expression.
__ bind(&is_false); __ bind(&is_false);
...@@ -2913,14 +2968,14 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -2913,14 +2968,14 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
Load(node->right()); Load(node->right());
GenericBinaryOperation(node->op()); GenericBinaryOperation(node->op());
} }
__ push(r0); frame_->Push(r0);
} }
} }
void CodeGenerator::VisitThisFunction(ThisFunction* node) { void CodeGenerator::VisitThisFunction(ThisFunction* node) {
__ ldr(r0, frame_->Function()); __ ldr(r0, frame_->Function());
__ push(r0); frame_->Push(r0);
} }
...@@ -2946,7 +3001,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) { ...@@ -2946,7 +3001,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
if (left_is_null || right_is_null) { if (left_is_null || right_is_null) {
Load(left_is_null ? right : left); Load(left_is_null ? right : left);
Label exit, undetectable; Label exit, undetectable;
__ pop(r0); frame_->Pop(r0);
__ cmp(r0, Operand(Factory::null_value())); __ cmp(r0, Operand(Factory::null_value()));
// The 'null' value is only equal to 'undefined' if using // The 'null' value is only equal to 'undefined' if using
...@@ -2990,7 +3045,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) { ...@@ -2990,7 +3045,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
// Load the operand, move it to register r1. // Load the operand, move it to register r1.
LoadTypeofExpression(operation->expression()); LoadTypeofExpression(operation->expression());
__ pop(r1); frame_->Pop(r1);
if (check->Equals(Heap::number_symbol())) { if (check->Equals(Heap::number_symbol())) {
__ tst(r1, Operand(kSmiTagMask)); __ tst(r1, Operand(kSmiTagMask));
...@@ -3102,7 +3157,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) { ...@@ -3102,7 +3157,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
case Token::IN: case Token::IN:
__ mov(r0, Operand(1)); // not counting receiver __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin(Builtins::IN, CALL_JS); __ InvokeBuiltin(Builtins::IN, CALL_JS);
__ push(r0); frame_->Push(r0);
break; break;
case Token::INSTANCEOF: case Token::INSTANCEOF:
...@@ -3127,34 +3182,6 @@ void CodeGenerator::RecordStatementPosition(Node* node) { ...@@ -3127,34 +3182,6 @@ void CodeGenerator::RecordStatementPosition(Node* node) {
} }
void CodeGenerator::EnterJSFrame() {
#if defined(DEBUG)
{ Label done, fail;
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &fail);
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
__ cmp(r2, Operand(JS_FUNCTION_TYPE));
__ b(eq, &done);
__ bind(&fail);
__ stop("CodeGenerator::EnterJSFrame - r1 not a function");
__ bind(&done);
}
#endif // DEBUG
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
__ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP.
}
void CodeGenerator::ExitJSFrame() {
// Drop the execution stack down to the frame pointer and restore the caller
// frame pointer and return address.
__ mov(sp, fp);
__ ldm(ia_w, sp, fp.bit() | lr.bit());
}
#undef __ #undef __
#define __ masm-> #define __ masm->
...@@ -3179,6 +3206,7 @@ void Reference::GetValue(TypeofState typeof_state) { ...@@ -3179,6 +3206,7 @@ void Reference::GetValue(TypeofState typeof_state) {
ASSERT(!is_illegal()); ASSERT(!is_illegal());
ASSERT(!cgen_->has_cc()); ASSERT(!cgen_->has_cc());
MacroAssembler* masm = cgen_->masm(); MacroAssembler* masm = cgen_->masm();
VirtualFrame* frame = cgen_->frame();
Property* property = expression_->AsProperty(); Property* property = expression_->AsProperty();
if (property != NULL) { if (property != NULL) {
__ RecordPosition(property->position()); __ RecordPosition(property->position());
...@@ -3212,7 +3240,7 @@ void Reference::GetValue(TypeofState typeof_state) { ...@@ -3212,7 +3240,7 @@ void Reference::GetValue(TypeofState typeof_state) {
} else { } else {
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
} }
__ push(r0); frame->Push(r0);
break; break;
} }
...@@ -3224,7 +3252,7 @@ void Reference::GetValue(TypeofState typeof_state) { ...@@ -3224,7 +3252,7 @@ void Reference::GetValue(TypeofState typeof_state) {
// TODO(1224671): Implement inline caching for keyed loads as on ia32. // TODO(1224671): Implement inline caching for keyed loads as on ia32.
GetPropertyStub stub; GetPropertyStub stub;
__ CallStub(&stub); __ CallStub(&stub);
__ push(r0); frame->Push(r0);
break; break;
} }
...@@ -3238,6 +3266,7 @@ void Reference::SetValue(InitState init_state) { ...@@ -3238,6 +3266,7 @@ void Reference::SetValue(InitState init_state) {
ASSERT(!is_illegal()); ASSERT(!is_illegal());
ASSERT(!cgen_->has_cc()); ASSERT(!cgen_->has_cc());
MacroAssembler* masm = cgen_->masm(); MacroAssembler* masm = cgen_->masm();
VirtualFrame* frame = cgen_->frame();
Property* property = expression_->AsProperty(); Property* property = expression_->AsProperty();
if (property != NULL) { if (property != NULL) {
__ RecordPosition(property->position()); __ RecordPosition(property->position());
...@@ -3252,9 +3281,9 @@ void Reference::SetValue(InitState init_state) { ...@@ -3252,9 +3281,9 @@ void Reference::SetValue(InitState init_state) {
ASSERT(slot->var()->mode() == Variable::DYNAMIC); ASSERT(slot->var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call. // For now, just do a runtime call.
__ push(cp); frame->Push(cp);
__ mov(r0, Operand(slot->var()->name())); __ mov(r0, Operand(slot->var()->name()));
__ push(r0); frame->Push(r0);
if (init_state == CONST_INIT) { if (init_state == CONST_INIT) {
// Same as the case for a normal store, but ignores attribute // Same as the case for a normal store, but ignores attribute
...@@ -3278,7 +3307,7 @@ void Reference::SetValue(InitState init_state) { ...@@ -3278,7 +3307,7 @@ void Reference::SetValue(InitState init_state) {
} }
// Storing a variable must keep the (new) value on the expression // Storing a variable must keep the (new) value on the expression
// stack. This is necessary for compiling assignment expressions. // stack. This is necessary for compiling assignment expressions.
__ push(r0); frame->Push(r0);
} else { } else {
ASSERT(slot->var()->mode() != Variable::DYNAMIC); ASSERT(slot->var()->mode() != Variable::DYNAMIC);
...@@ -3304,9 +3333,9 @@ void Reference::SetValue(InitState init_state) { ...@@ -3304,9 +3333,9 @@ void Reference::SetValue(InitState init_state) {
// initialize consts to 'the hole' value and by doing so, end up // initialize consts to 'the hole' value and by doing so, end up
// calling this code. r2 may be loaded with context; used below in // calling this code. r2 may be loaded with context; used below in
// RecordWrite. // RecordWrite.
__ pop(r0); frame->Pop(r0);
__ str(r0, cgen_->SlotOperand(slot, r2)); __ str(r0, cgen_->SlotOperand(slot, r2));
__ push(r0); frame->Push(r0);
if (slot->type() == Slot::CONTEXT) { if (slot->type() == Slot::CONTEXT) {
// Skip write barrier if the written value is a smi. // Skip write barrier if the written value is a smi.
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
...@@ -3329,13 +3358,13 @@ void Reference::SetValue(InitState init_state) { ...@@ -3329,13 +3358,13 @@ void Reference::SetValue(InitState init_state) {
case NAMED: { case NAMED: {
Comment cmnt(masm, "[ Store to named Property"); Comment cmnt(masm, "[ Store to named Property");
// Call the appropriate IC code. // Call the appropriate IC code.
__ pop(r0); // value frame->Pop(r0); // value
// Setup the name register. // Setup the name register.
Handle<String> name(GetName()); Handle<String> name(GetName());
__ mov(r2, Operand(name)); __ mov(r2, Operand(name));
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);
__ push(r0); frame->Push(r0);
break; break;
} }
...@@ -3344,10 +3373,10 @@ void Reference::SetValue(InitState init_state) { ...@@ -3344,10 +3373,10 @@ void Reference::SetValue(InitState init_state) {
Property* property = expression_->AsProperty(); Property* property = expression_->AsProperty();
ASSERT(property != NULL); ASSERT(property != NULL);
__ RecordPosition(property->position()); __ RecordPosition(property->position());
__ pop(r0); // value frame->Pop(r0); // value
SetPropertyStub stub; SetPropertyStub stub;
__ CallStub(&stub); __ CallStub(&stub);
__ push(r0); frame->Push(r0);
break; break;
} }
......
...@@ -49,6 +49,11 @@ class VirtualFrame BASE_EMBEDDED { ...@@ -49,6 +49,11 @@ class VirtualFrame BASE_EMBEDDED {
public: public:
explicit VirtualFrame(CodeGenerator* cgen); explicit VirtualFrame(CodeGenerator* cgen);
void Enter();
void Exit();
void AllocateLocals();
MemOperand Top() const { return MemOperand(sp, 0); } MemOperand Top() const { return MemOperand(sp, 0); }
MemOperand Element(int index) const { MemOperand Element(int index) const {
...@@ -70,6 +75,13 @@ class VirtualFrame BASE_EMBEDDED { ...@@ -70,6 +75,13 @@ class VirtualFrame BASE_EMBEDDED {
return MemOperand(fp, (1 + parameter_count_ - index) * kPointerSize); return MemOperand(fp, (1 + parameter_count_ - index) * kPointerSize);
} }
inline void Drop(int count);
inline void Pop();
inline void Pop(Register reg);
inline void Push(Register reg);
private: private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
...@@ -195,6 +207,8 @@ class CodeGenerator: public Visitor { ...@@ -195,6 +207,8 @@ class CodeGenerator: public Visitor {
// Accessors // Accessors
MacroAssembler* masm() { return masm_; } MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
CodeGenState* state() { return state_; } CodeGenState* state() { return state_; }
void set_state(CodeGenState* state) { state_ = state; } void set_state(CodeGenState* state) { state_ = state; }
...@@ -366,11 +380,6 @@ class CodeGenerator: public Visitor { ...@@ -366,11 +380,6 @@ class CodeGenerator: public Visitor {
// should be generated or not. // should be generated or not.
void RecordStatementPosition(Node* node); void RecordStatementPosition(Node* node);
// Activation frames.
void EnterJSFrame();
void ExitJSFrame();
bool is_eval_; // Tells whether code is generated for eval. bool is_eval_; // Tells whether code is generated for eval.
Handle<Script> script_; Handle<Script> script_;
List<DeferredCode*> deferred_; List<DeferredCode*> deferred_;
......
...@@ -99,9 +99,7 @@ void VirtualFrame::Drop(int count) { ...@@ -99,9 +99,7 @@ void VirtualFrame::Drop(int count) {
} }
void VirtualFrame::Pop() { void VirtualFrame::Pop() { Drop(1); }
__ add(Operand(esp), Immediate(kPointerSize));
}
void VirtualFrame::Pop(Register reg) { void VirtualFrame::Pop(Register reg) {
...@@ -267,10 +265,8 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -267,10 +265,8 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
__ int3(); __ int3();
__ bind(&verified_true); __ bind(&verified_true);
} }
// Update context local. // Update context local.
__ mov(frame_->Context(), esi); __ mov(frame_->Context(), esi);
// Restore the arguments array pointer, if any.
} }
// TODO(1241774): Improve this code: // TODO(1241774): Improve this code:
...@@ -310,10 +306,10 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -310,10 +306,10 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
// This section stores the pointer to the arguments object that // This section stores the pointer to the arguments object that
// was allocated and copied into above. If the address was not // was allocated and copied into above. If the address was not
// saved to TOS, we push ecx onto the stack. // saved to TOS, we push ecx onto the stack.
//
// Store the arguments object. // Store the arguments object. This must happen after context
// This must happen after context initialization because // initialization because the arguments object may be stored in the
// the arguments object may be stored in the context // context.
if (arguments_object_allocated) { if (arguments_object_allocated) {
ASSERT(scope_->arguments() != NULL); ASSERT(scope_->arguments() != NULL);
ASSERT(scope_->arguments_shadow() != NULL); ASSERT(scope_->arguments_shadow() != NULL);
...@@ -341,18 +337,17 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -341,18 +337,17 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
frame_->Pop(); // Value is no longer needed. frame_->Pop(); // Value is no longer needed.
} }
// Generate code to 'execute' declarations and initialize // Generate code to 'execute' declarations and initialize functions
// functions (source elements). In case of an illegal // (source elements). In case of an illegal redeclaration we need to
// redeclaration we need to handle that instead of processing the // handle that instead of processing the declarations.
// declarations.
if (scope_->HasIllegalRedeclaration()) { if (scope_->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations"); Comment cmnt(masm_, "[ illegal redeclarations");
scope_->VisitIllegalRedeclaration(this); scope_->VisitIllegalRedeclaration(this);
} else { } else {
Comment cmnt(masm_, "[ declarations"); Comment cmnt(masm_, "[ declarations");
ProcessDeclarations(scope_->declarations()); ProcessDeclarations(scope_->declarations());
// Bail out if a stack-overflow exception occurred when // Bail out if a stack-overflow exception occurred when processing
// processing declarations. // declarations.
if (HasStackOverflow()) return; if (HasStackOverflow()) return;
} }
...@@ -448,10 +443,11 @@ Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { ...@@ -448,10 +443,11 @@ Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
// Loads a value on TOS. If it is a boolean value, the result may have been // Loads a value on TOS. If it is a boolean value, the result may have been
// (partially) translated into branches, or it may have set the condition code // (partially) translated into branches, or it may have set the condition
// register. If force_cc is set, the value is forced to set the condition code // code register. If force_cc is set, the value is forced to set the
// register and no value is pushed. If the condition code register was set, // condition code register and no value is pushed. If the condition code
// has_cc() is true and cc_reg_ contains the condition to test for 'true'. // register was set, has_cc() is true and cc_reg_ contains the condition to
// test for 'true'.
void CodeGenerator::LoadCondition(Expression* x, void CodeGenerator::LoadCondition(Expression* x,
TypeofState typeof_state, TypeofState typeof_state,
Label* true_target, Label* true_target,
...@@ -463,6 +459,14 @@ void CodeGenerator::LoadCondition(Expression* x, ...@@ -463,6 +459,14 @@ void CodeGenerator::LoadCondition(Expression* x,
Visit(x); Visit(x);
} }
if (force_cc && !has_cc()) { if (force_cc && !has_cc()) {
// Convert the TOS value to a boolean in the condition code register.
// Visiting an expression may possibly choose neither (a) to leave a
// value in the condition code register nor (b) to leave a value in TOS
// (eg, by compiling to only jumps to the targets). In that case the
// code generated by ToBoolean is wrong because it assumes the value of
// the expression in TOS. So long as there is always a value in TOS or
// the condition code register when control falls through to here (there
// is), the code generated by ToBoolean is dead and therefore safe.
ToBoolean(true_target, false_target); ToBoolean(true_target, false_target);
} }
ASSERT(has_cc() || !force_cc); ASSERT(has_cc() || !force_cc);
...@@ -476,7 +480,6 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -476,7 +480,6 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
if (has_cc()) { if (has_cc()) {
// convert cc_reg_ into a bool // convert cc_reg_ into a bool
Label loaded, materialize_true; Label loaded, materialize_true;
__ j(cc_reg_, &materialize_true); __ j(cc_reg_, &materialize_true);
frame_->Push(Immediate(Factory::false_value())); frame_->Push(Immediate(Factory::false_value()));
...@@ -663,7 +666,7 @@ void CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { ...@@ -663,7 +666,7 @@ void CodeGenerator::ToBoolean(Label* true_target, Label* false_target) {
frame_->Push(eax); // Undo the pop(eax) from above. frame_->Push(eax); // Undo the pop(eax) from above.
ToBooleanStub stub; ToBooleanStub stub;
__ CallStub(&stub); __ CallStub(&stub);
// Convert result (eax) to condition code. // Convert the result (eax) to condition code.
__ test(eax, Operand(eax)); __ test(eax, Operand(eax));
ASSERT(not_equal == not_zero); ASSERT(not_equal == not_zero);
...@@ -2198,7 +2201,6 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -2198,7 +2201,6 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
frame_->Pop(Operand::StaticVariable(handler_address)); frame_->Pop(Operand::StaticVariable(handler_address));
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
// Next_sp popped. // Next_sp popped.
// Preserve the TOS in a register across stack manipulation.
frame_->Push(eax); frame_->Push(eax);
// --- Finally block --- // --- Finally block ---
......
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