Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 5263) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -519,6 +519,7 @@ |
void CodeGenerator::Load(Expression* expr) { |
+ frame_->AssertIsNotSpilled(); |
#ifdef DEBUG |
int original_height = frame_->height(); |
#endif |
@@ -675,6 +676,7 @@ |
expression_(expression), |
type_(ILLEGAL), |
persist_after_get_(persist_after_get) { |
+ cgen->frame()->AssertIsNotSpilled(); |
cgen->LoadReference(this); |
} |
@@ -1885,19 +1887,17 @@ |
void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
- frame_->SpillAll(); |
Comment cmnt(masm_, "[ ReturnStatement"); |
CodeForStatementPosition(node); |
Load(node->expression()); |
+ frame_->PopToR0(); |
+ frame_->PrepareForReturn(); |
if (function_return_is_shadowed_) { |
- frame_->EmitPop(r0); |
function_return_.Jump(); |
} else { |
// Pop the result from the frame and prepare the frame for |
// returning thus making it easier to merge. |
- frame_->PopToR0(); |
- frame_->PrepareForReturn(); |
if (function_return_.is_bound()) { |
// If the function return label is already bound we reuse the |
// code by jumping to the return site. |
@@ -2293,7 +2293,6 @@ |
#ifdef DEBUG |
int original_height = frame_->height(); |
#endif |
- VirtualFrame::SpilledScope spilled_scope(frame_); |
Comment cmnt(masm_, "[ ForInStatement"); |
CodeForStatementPosition(node); |
@@ -2307,6 +2306,7 @@ |
// Get the object to enumerate over (converted to JSObject). |
Load(node->enumerable()); |
+ VirtualFrame::SpilledScope spilled_scope(frame_); |
// Both SpiderMonkey and kjs ignore null and undefined in contrast |
// to the specification. 12.6.4 mandates a call to ToObject. |
frame_->EmitPop(r0); |
@@ -2476,25 +2476,31 @@ |
// 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) |
frame_->EmitPush(r3); // push entry |
- { Reference each(this, node->each()); |
+ { VirtualFrame::RegisterAllocationScope scope(this); |
+ Reference each(this, node->each()); |
if (!each.is_illegal()) { |
if (each.size() > 0) { |
+ // Loading a reference may leave the frame in an unspilled state. |
+ frame_->SpillAll(); // Sync stack to memory. |
+ // Get the value (under the reference on the stack) from memory. |
__ ldr(r0, frame_->ElementAt(each.size())); |
frame_->EmitPush(r0); |
each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); |
- frame_->Drop(2); |
+ frame_->Drop(2); // The result of the set and the extra pushed value. |
} else { |
// 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, ebx pushed above) is |
// right on top of or right underneath a zero-sized reference. |
each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); |
- frame_->Drop(); |
+ frame_->Drop(1); // Drop the result of the set operation. |
} |
} |
} |
// Body. |
CheckStack(); // TODO(1222600): ignore if body contains calls. |
- Visit(node->body()); |
+ { VirtualFrame::RegisterAllocationScope scope(this); |
+ Visit(node->body()); |
+ } |
// Next. Reestablish a spilled frame in case we are coming here via |
// a continue in the body. |
@@ -2541,7 +2547,9 @@ |
// Remove the exception from the stack. |
frame_->Drop(); |
- VisitStatements(node->catch_block()->statements()); |
+ { VirtualFrame::RegisterAllocationScope scope(this); |
+ VisitStatements(node->catch_block()->statements()); |
+ } |
if (frame_ != NULL) { |
exit.Jump(); |
} |
@@ -2576,7 +2584,9 @@ |
} |
// Generate code for the statements in the try block. |
- VisitStatements(node->try_block()->statements()); |
+ { VirtualFrame::RegisterAllocationScope scope(this); |
+ VisitStatements(node->try_block()->statements()); |
+ } |
// Stop the introduced shadowing and count the number of required unlinks. |
// After shadowing stops, the original labels are unshadowed and the |
@@ -2623,7 +2633,7 @@ |
frame_->Forget(frame_->height() - handler_height); |
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
- frame_->EmitPop(r1); |
+ frame_->EmitPop(r1); // r0 can contain the return value. |
__ str(r1, MemOperand(r3)); |
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
@@ -2690,7 +2700,9 @@ |
} |
// Generate code for the statements in the try block. |
- VisitStatements(node->try_block()->statements()); |
+ { VirtualFrame::RegisterAllocationScope scope(this); |
+ VisitStatements(node->try_block()->statements()); |
+ } |
// Stop the introduced shadowing and count the number of required unlinks. |
// After shadowing stops, the original labels are unshadowed and the |
@@ -2780,7 +2792,9 @@ |
// and the state - while evaluating the finally block. |
// |
// Generate code for the statements in the finally block. |
- VisitStatements(node->finally_block()->statements()); |
+ { VirtualFrame::RegisterAllocationScope scope(this); |
+ VisitStatements(node->finally_block()->statements()); |
+ } |
if (has_valid_frame()) { |
// Restore state and return value or faked TOS. |
@@ -3960,7 +3974,6 @@ |
} else if (var != NULL && var->slot() != NULL && |
var->slot()->type() == Slot::LOOKUP) { |
- VirtualFrame::SpilledScope spilled_scope(frame_); |
// ---------------------------------- |
// JavaScript examples: |
// |
@@ -3973,8 +3986,6 @@ |
// } |
// ---------------------------------- |
- // JumpTargets do not yet support merging frames so the frame must be |
- // spilled when jumping to these targets. |
JumpTarget slow, done; |
// Generate fast case for loading functions from slots that |
@@ -3988,8 +3999,7 @@ |
slow.Bind(); |
// Load the function |
frame_->EmitPush(cp); |
- __ mov(r0, Operand(var->name())); |
- frame_->EmitPush(r0); |
+ frame_->EmitPush(Operand(var->name())); |
frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
// r0: slot value; r1: receiver |
@@ -4005,7 +4015,7 @@ |
call.Jump(); |
done.Bind(); |
frame_->EmitPush(r0); // function |
- LoadGlobalReceiver(r1); // receiver |
+ LoadGlobalReceiver(VirtualFrame::scratch0()); // receiver |
call.Bind(); |
} |
@@ -4060,8 +4070,6 @@ |
// ------------------------------------------- |
// JavaScript example: 'array[index](1, 2, 3)' |
// ------------------------------------------- |
- VirtualFrame::SpilledScope spilled_scope(frame_); |
- |
Load(property->obj()); |
if (property->is_synthetic()) { |
Load(property->key()); |
@@ -4069,7 +4077,7 @@ |
// Put the function below the receiver. |
// Use the global receiver. |
frame_->EmitPush(r0); // Function. |
- LoadGlobalReceiver(r0); |
+ LoadGlobalReceiver(VirtualFrame::scratch0()); |
// Call the function. |
CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
frame_->EmitPush(r0); |
@@ -4082,6 +4090,7 @@ |
// Set the name register and call the IC initialization code. |
Load(property->key()); |
+ frame_->SpillAll(); |
frame_->EmitPop(r2); // Function name. |
InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
@@ -4101,10 +4110,8 @@ |
// Load the function. |
Load(function); |
- VirtualFrame::SpilledScope spilled_scope(frame_); |
- |
// Pass the global proxy as the receiver. |
- LoadGlobalReceiver(r0); |
+ LoadGlobalReceiver(VirtualFrame::scratch0()); |
// Call the function. |
CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
@@ -4159,8 +4166,8 @@ |
void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
- JumpTarget leave, null, function, non_function_constructor; |
Register scratch = VirtualFrame::scratch0(); |
+ JumpTarget null, function, leave, non_function_constructor; |
// Load the object into register. |
ASSERT(args->length() == 1); |