| Index: runtime/vm/stub_code_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/stub_code_ia32.cc (revision 12092)
|
| +++ runtime/vm/stub_code_ia32.cc (working copy)
|
| @@ -9,6 +9,7 @@
|
| #include "vm/assembler_macros.h"
|
| #include "vm/compiler.h"
|
| #include "vm/flow_graph_compiler.h"
|
| +#include "vm/instructions.h"
|
| #include "vm/object_store.h"
|
| #include "vm/pages.h"
|
| #include "vm/resolver.h"
|
| @@ -481,6 +482,8 @@
|
|
|
| DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp);
|
|
|
| +
|
| +// Used by eager and lazy deoptimization. Preserve result in EAX 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.
|
| @@ -493,17 +496,22 @@
|
| // GC can occur only after frame is fully rewritten.
|
| // Stack:
|
| // +------------------+
|
| -// | 0 as PC marker | <- TOS
|
| +// | Saved FP | <- TOS
|
| // +------------------+
|
| -// | Saved FP |
|
| -// +------------------+
|
| // | return-address | (deoptimization point)
|
| // +------------------+
|
| // | optimized frame |
|
| // | ... |
|
| //
|
| -void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
|
| +// Parts of the code cannot GC, part of the code can GC.
|
| +static void GenerateDeoptimizationSequence(Assembler* assembler,
|
| + bool preserve_eax) {
|
| __ EnterFrame(0);
|
| + // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
|
| + // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
|
| + const intptr_t saved_eax_offset_from_ebp = -(kNumberOfCpuRegisters - EAX);
|
| + // Result in EAX is preserved as part of pushing all registers below.
|
| +
|
| // Push registers in their enumeration order: lowest register number at
|
| // lowest address.
|
| for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
|
| @@ -523,6 +531,12 @@
|
| __ movl(Address(ESP, 0), ECX); // Start of register block.
|
| __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry);
|
| // Result (EAX) is stack-size (FP - SP) in bytes, incl. the return address.
|
| +
|
| + if (preserve_eax) {
|
| + // Restore result into EBX temporarily.
|
| + __ movl(EBX, Address(EBP, saved_eax_offset_from_ebp * kWordSize));
|
| + }
|
| +
|
| __ LeaveFrame();
|
| __ popl(EDX); // Preserve return address.
|
| __ movl(ESP, EBP);
|
| @@ -531,21 +545,52 @@
|
|
|
| __ EnterFrame(0);
|
| __ movl(ECX, ESP); // Get last FP address.
|
| + if (preserve_eax) {
|
| + __ pushl(EBX); // Preserve result.
|
| + }
|
| __ ReserveAlignedFrameSpace(1 * kWordSize);
|
| __ movl(Address(ESP, 0), ECX);
|
| __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry);
|
| +
|
| + if (preserve_eax) {
|
| + // Restore result into EAX.
|
| + __ movl(EAX, Address(EBP, -1 * kWordSize));
|
| + }
|
| + // Code above cannot cause GC.
|
| __ 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);
|
| + if (preserve_eax) {
|
| + __ pushl(EAX); // Preserve result, it will be GC-d here.
|
| + }
|
| __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry);
|
| + if (preserve_eax) {
|
| + __ popl(EAX); // Restore result.
|
| + }
|
| __ LeaveFrame();
|
| __ ret();
|
| }
|
|
|
| +// TOS: return address + call-instruction-size (5 bytes).
|
| +// EAX: result, must be preserved
|
| +void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
|
| + // Correct return address to point just after the call that is being
|
| + // deoptimized.
|
| + __ popl(EBX);
|
| + __ subl(EBX, Immediate(CallPattern::InstructionLength()));
|
| + __ pushl(EBX);
|
| + GenerateDeoptimizationSequence(assembler, true); // Preserve EAX.
|
| +}
|
|
|
| +
|
| +void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
|
| + GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX.
|
| +}
|
| +
|
| +
|
| // Called for inline allocation of arrays.
|
| // Input parameters:
|
| // EDX : Array length as Smi.
|
|
|