| 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);
|
|
|