| Index: runtime/vm/flow_graph_compiler_ia32.cc
|
| diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
|
| index f428f74e0ae9fb2bb6044f5d94881b9d65325a38..65161e0b060e5ee4cafdf6c21f804ae8d33aa679 100644
|
| --- a/runtime/vm/flow_graph_compiler_ia32.cc
|
| +++ b/runtime/vm/flow_graph_compiler_ia32.cc
|
| @@ -42,14 +42,9 @@ void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) {
|
| const intptr_t fixed_parameter_count =
|
| deoptimization_env_->fixed_parameter_count();
|
|
|
| - // 1. Set the stack pointer to the top of the non-optimized frame.
|
| const GrowableArray<Value*>& values = deoptimization_env_->values();
|
| - const intptr_t local_slot_count = values.length() - fixed_parameter_count;
|
| - const intptr_t top_offset =
|
| - ParsedFunction::kFirstLocalSlotIndex - (local_slot_count - 1);
|
| - __ leal(ESP, Address(EBP, top_offset * kWordSize));
|
|
|
| - // 2. Build and emit a parallel move representing the frame translation.
|
| + // 1. Build a parallel move representing the frame translation.
|
| ParallelMoveInstr* move = new ParallelMoveInstr();
|
| for (intptr_t i = 0; i < values.length(); i++) {
|
| Location destination = Location::StackSlot(i - fixed_parameter_count);
|
| @@ -60,7 +55,33 @@ void DeoptimizationStub::GenerateCode(FlowGraphCompiler* compiler) {
|
| }
|
| move->AddMove(destination, source);
|
| }
|
| +
|
| +
|
| + const intptr_t local_slot_count = values.length() - fixed_parameter_count;
|
| + const intptr_t top_offset =
|
| + ParsedFunction::kFirstLocalSlotIndex - (local_slot_count - 1);
|
| +
|
| + // ParallelMoveResolver will use push and pop to allocate internally a
|
| + // scratch register for memory to memory moves. This means we have to
|
| + // ensure that these stack manipulations will not interfere with actual
|
| + // moves. If number of local slots exceed number of spill slots we need
|
| + // to expand reserved stack area before resolving parallel move. Otherwise
|
| + // we need to shrink stack area after resolving parallel move. This
|
| + // guarantees that all moves happen below stack pointer and will not
|
| + // interfere with additional push/pops.
|
| + const intptr_t spill_slot_count = compiler->StackSize();
|
| +
|
| + if (local_slot_count > spill_slot_count) {
|
| + // Expand reserved stack area.
|
| + __ leal(ESP, Address(EBP, top_offset * kWordSize));
|
| + }
|
| +
|
| compiler->parallel_move_resolver()->EmitNativeCode(move);
|
| +
|
| + if (local_slot_count < spill_slot_count) {
|
| + // Shrink reserved stack area.
|
| + __ leal(ESP, Address(EBP, top_offset * kWordSize));
|
| + }
|
| }
|
|
|
| if (compiler->IsLeaf()) {
|
|
|