Index: runtime/vm/stub_code_x64.cc |
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc |
index 2b2029197aafec7bdf44adefb71c11030eab8da4..57b2f1424d0d0d89157178c07ac6c2e0f57a5baf 100644 |
--- a/runtime/vm/stub_code_x64.cc |
+++ b/runtime/vm/stub_code_x64.cc |
@@ -470,7 +470,7 @@ void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
intptr_t deopt_reason, |
- intptr_t* saved_registers_address); |
+ uword saved_registers_address); |
DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); |
@@ -482,6 +482,8 @@ DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); |
// - Call C routine to copy the stack and saved registers into temporary buffer. |
// - Adjust caller's frame to correct unoptimized frame size. |
// - Fill the unoptimized frame. |
+// - Materialize objects that require allocation (e.g. Double instances). |
+// GC can occur only after frame is fully rewritten. |
// Stack: |
// +------------------+ |
// | 0 as PC marker | <- TOS |
@@ -500,6 +502,14 @@ void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { |
__ pushq(static_cast<Register>(i)); |
} |
+ __ subq(RSP, Immediate(kNumberOfXmmRegisters * kDoubleSize)); |
+ intptr_t offset = 0; |
+ for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
+ XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
+ __ movsd(Address(RSP, offset), xmm_reg); |
+ offset += kDoubleSize; |
+ } |
+ |
__ movq(RCX, RSP); // Saved saved registers block. |
__ ReserveAlignedFrameSpace(0); |
__ SmiUntag(RAX); |
@@ -519,6 +529,14 @@ void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
__ movq(RDI, RCX); // Set up argument 1 last_fp. |
__ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); |
__ LeaveFrame(); |
+ |
+ // 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. |
+ __ EnterFrame(0); |
+ __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); |
+ __ LeaveFrame(); |
+ |
__ ret(); |
} |