| Index: runtime/vm/stub_code_x64.cc
|
| ===================================================================
|
| --- runtime/vm/stub_code_x64.cc (revision 22714)
|
| +++ runtime/vm/stub_code_x64.cc (working copy)
|
| @@ -307,6 +307,7 @@
|
| DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp);
|
|
|
|
|
| +// Used by eager and lazy deoptimization. Preserve result in RAX if necessary.
|
| // This stub translates optimized frame into unoptimized frame. The optimized
|
| // frame can contain values in registers and on stack, the unoptimized
|
| // frame contains all values on stack.
|
| @@ -317,23 +318,26 @@
|
| // - Fill the unoptimized frame.
|
| // - Materialize objects that require allocation (e.g. Double instances).
|
| // GC can occur only after frame is fully rewritten.
|
| -// Stack after EnterFrame(0) below:
|
| +// Stack after EnterDartFrame(0) below:
|
| // +------------------+
|
| -// | Saved FP | <- TOS
|
| +// | PC marker | <- TOS
|
| // +------------------+
|
| +// | Saved FP | <- FP of stub
|
| +// +------------------+
|
| // | return-address | (deoptimization point)
|
| // +------------------+
|
| -// | optimized frame |
|
| -// | ... |
|
| +// | ... | <- SP of optimized frame
|
| //
|
| // Parts of the code cannot GC, part of the code can GC.
|
| static void GenerateDeoptimizationSequence(Assembler* assembler,
|
| - bool preserve_rax) {
|
| - __ EnterFrame(0);
|
| + bool preserve_result) {
|
| + // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
|
| + __ EnterDartFrame(0);
|
| // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
|
| // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
|
| - const intptr_t saved_rax_offset_from_ebp = -(kNumberOfCpuRegisters - RAX);
|
| - // Result in EAX is preserved as part of pushing all registers below.
|
| + const intptr_t saved_result_slot_from_fp =
|
| + kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX);
|
| + // Result in RAX is preserved as part of pushing all registers below.
|
|
|
| // Push registers in their enumeration order: lowest register number at
|
| // lowest address.
|
| @@ -351,41 +355,39 @@
|
| __ movq(RDI, RSP); // Pass address of saved registers block.
|
| __ ReserveAlignedFrameSpace(0);
|
| __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry);
|
| - // Result (RAX) is stack-size (FP - SP) in bytes, incl. the return address.
|
| + // Result (RAX) is stack-size (FP - SP) in bytes.
|
|
|
| - if (preserve_rax) {
|
| + if (preserve_result) {
|
| // Restore result into RBX temporarily.
|
| - __ movq(RBX, Address(RBP, saved_rax_offset_from_ebp * kWordSize));
|
| + __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize));
|
| }
|
|
|
| __ LeaveFrame();
|
| __ popq(RCX); // Preserve return address.
|
| - __ movq(RSP, RBP);
|
| - __ subq(RSP, RAX);
|
| - __ movq(Address(RSP, 0), RCX);
|
| + __ movq(RSP, RBP); // Discard optimized frame.
|
| + __ subq(RSP, RAX); // Reserve space for deoptimized frame.
|
| + __ pushq(RCX); // Restore return address.
|
|
|
| - __ EnterFrame(0);
|
| - __ movq(RCX, RSP); // Get last FP address.
|
| - if (preserve_rax) {
|
| - __ pushq(RBX); // Preserve result.
|
| + // Leaf runtime function DeoptimizeFillFrame expects a Dart frame.
|
| + __ EnterDartFrame(0);
|
| + if (preserve_result) {
|
| + __ pushq(RBX); // Preserve result as first local.
|
| }
|
| __ ReserveAlignedFrameSpace(0);
|
| - __ movq(RDI, RCX); // Set up argument 1 last_fp.
|
| + __ movq(RDI, RBP); // Pass last FP as parameter in RDI.
|
| __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry);
|
| - // Result (RAX) is our FP.
|
| - if (preserve_rax) {
|
| + if (preserve_result) {
|
| // Restore result into RBX.
|
| - __ movq(RBX, Address(RBP, -1 * kWordSize));
|
| + __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
|
| }
|
| // Code above cannot cause GC.
|
| __ LeaveFrame();
|
| - __ movq(RBP, RAX);
|
|
|
| // Frame is fully rewritten at this point and it is safe to perform a GC.
|
| // Materialize any objects that were deferred by FillFrame because they
|
| // require allocation.
|
| __ EnterStubFrame();
|
| - if (preserve_rax) {
|
| + if (preserve_result) {
|
| __ pushq(RBX); // Preserve result, it will be GC-d here.
|
| }
|
| __ pushq(Immediate(Smi::RawValue(0))); // Space for the result.
|
| @@ -394,7 +396,7 @@
|
| // of the bottom-most frame. They were used as materialization arguments.
|
| __ popq(RBX);
|
| __ SmiUntag(RBX);
|
| - if (preserve_rax) {
|
| + if (preserve_result) {
|
| __ popq(RAX); // Restore result.
|
| }
|
| __ LeaveFrame();
|
|
|