diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc index 7e66cbf2a9f..5ad77f2c1a1 100644 --- a/runtime/vm/assembler_x64.cc +++ b/runtime/vm/assembler_x64.cc @@ -2667,17 +2667,11 @@ void Assembler::LeaveFrame() { } -void Assembler::LeaveFrameWithPP() { - movq(PP, Address(RBP, -2 * kWordSize)); - LeaveFrame(); -} - - void Assembler::ReturnPatchable() { // This sequence must have a fixed size so that it can be patched by the // debugger. intptr_t start = buffer_.GetPosition(); - LeaveFrameWithPP(); + LeaveDartFrame(); ret(); nop(4); ASSERT((buffer_.GetPosition() - start) == 13); @@ -2825,6 +2819,13 @@ void Assembler::EnterDartFrameWithInfo(intptr_t frame_size, } +void Assembler::LeaveDartFrame() { + // Restore caller's PP register that was pushed in EnterDartFrame. + movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize))); + LeaveFrame(); +} + + // On entry to a function compiled for OSR, the caller's frame pointer, the // stack locals, and any copied parameters are already in place. The frame // pointer is already set up. The PC marker is not correct for the @@ -2862,17 +2863,20 @@ void Assembler::EnterOsrFrame(intptr_t extra_size, } -void Assembler::EnterStubFrame() { - EnterFrame(0); - pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames. -} - - -void Assembler::EnterStubFrameWithPP() { +void Assembler::EnterStubFrame(bool load_pp) { EnterFrame(0); pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames. pushq(PP); // Save caller's pool pointer - LoadPoolPointer(PP); + if (load_pp) { + LoadPoolPointer(PP); + } +} + + +void Assembler::LeaveStubFrame() { + // Restore caller's PP register that was pushed in EnterStubFrame. + movq(PP, Address(RBP, (kSavedCallerPpSlotFromFp * kWordSize))); + LeaveFrame(); } diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h index b494e910285..9daaf6ca603 100644 --- a/runtime/vm/assembler_x64.h +++ b/runtime/vm/assembler_x64.h @@ -716,7 +716,6 @@ class Assembler : public ValueObject { void EnterFrame(intptr_t frame_space); void LeaveFrame(); - void LeaveFrameWithPP(); void ReturnPatchable(); void ReserveAlignedFrameSpace(intptr_t frame_space); @@ -776,11 +775,11 @@ class Assembler : public ValueObject { // to this frame. // The dart frame layout is as follows: // .... - // ret PC - // saved RBP <=== RBP - // pc (used to derive the RawInstruction Object of the dart code) - // saved PP // locals space <=== RSP + // saved PP + // pc (used to derive the RawInstruction Object of the dart code) + // saved RBP <=== RBP + // ret PC // ..... // This code sets this up with the sequence: // pushq rbp @@ -793,6 +792,7 @@ class Assembler : public ValueObject { void EnterDartFrame(intptr_t frame_size); void EnterDartFrameWithInfo(intptr_t frame_size, Register new_pp, Register new_pc); + void LeaveDartFrame(); // Set up a Dart frame for a function compiled for on-stack replacement. // The frame layout is a normal Dart frame, but the frame is partially set @@ -802,18 +802,18 @@ class Assembler : public ValueObject { // Set up a stub frame so that the stack traversal code can easily identify // a stub frame. // The stub frame layout is as follows: - // .... - // ret PC - // saved RBP + // .... <=== RSP // pc (used to derive the RawInstruction Object of the stub) + // saved RBP <=== RBP + // ret PC // ..... // This code sets this up with the sequence: // pushq rbp // movq rbp, rsp // pushq immediate(0) // ..... - void EnterStubFrame(); - void EnterStubFrameWithPP(); + void EnterStubFrame(bool load_pp = false); + void LeaveStubFrame(); // Instruction pattern from entrypoint is used in dart frame prologues // to set up the frame and save a PC which can be used to figure out the diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc index fd68d8e9341..bfd8464baae 100644 --- a/runtime/vm/assembler_x64_test.cc +++ b/runtime/vm/assembler_x64_test.cc @@ -1625,13 +1625,11 @@ ASSEMBLER_TEST_RUN(PackedCompareNLE, test) { ASSEMBLER_TEST_GENERATE(PackedNegate, assembler) { - __ EnterDartFrame(0); __ movl(RAX, Immediate(bit_cast(12.3f))); __ movd(XMM0, RAX); __ shufps(XMM0, XMM0, Immediate(0x0)); __ negateps(XMM0); __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes. - __ LeaveFrameWithPP(); __ ret(); } @@ -1644,13 +1642,11 @@ ASSEMBLER_TEST_RUN(PackedNegate, test) { ASSEMBLER_TEST_GENERATE(PackedAbsolute, assembler) { - __ EnterDartFrame(0); __ movl(RAX, Immediate(bit_cast(-15.3f))); __ movd(XMM0, RAX); __ shufps(XMM0, XMM0, Immediate(0x0)); __ absps(XMM0); __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes. - __ LeaveFrameWithPP(); __ ret(); } @@ -1663,11 +1659,9 @@ ASSEMBLER_TEST_RUN(PackedAbsolute, test) { ASSEMBLER_TEST_GENERATE(PackedSetWZero, assembler) { - __ EnterDartFrame(0); __ set1ps(XMM0, RAX, Immediate(bit_cast(12.3f))); __ zerowps(XMM0); __ shufps(XMM0, XMM0, Immediate(0xFF)); // Copy the W lane which is now 0.0. - __ LeaveFrameWithPP(); __ ret(); } @@ -1784,7 +1778,8 @@ ASSEMBLER_TEST_GENERATE(PackedLogicalNot, assembler) { uint32_t d; } constant1 = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; - __ EnterDartFrame(0); + __ pushq(PP); // Save caller's pool pointer and load a new one here. + __ LoadPoolPointer(PP); __ LoadImmediate(RAX, Immediate(reinterpret_cast(&constant1)), PP); __ movups(XMM9, Address(RAX, 0)); __ notps(XMM9); @@ -1792,7 +1787,7 @@ ASSEMBLER_TEST_GENERATE(PackedLogicalNot, assembler) { __ pushq(RAX); __ movss(Address(RSP, 0), XMM0); __ popq(RAX); - __ LeaveFrameWithPP(); + __ popq(PP); // Restore caller's pool pointer. __ ret(); } @@ -2189,7 +2184,9 @@ ASSEMBLER_TEST_GENERATE(TestObjectCompare, assembler) { ObjectStore* object_store = Isolate::Current()->object_store(); const Object& obj = Object::ZoneHandle(object_store->smi_class()); Label fail; - __ EnterDartFrame(0); + __ EnterFrame(0); + __ pushq(PP); // Save caller's pool pointer and load a new one here. + __ LoadPoolPointer(PP); __ LoadObject(RAX, obj, PP); __ CompareObject(RAX, obj, PP); __ j(NOT_EQUAL, &fail); @@ -2211,11 +2208,12 @@ ASSEMBLER_TEST_GENERATE(TestObjectCompare, assembler) { __ CompareObject(RCX, smi, PP); __ j(NOT_EQUAL, &fail); __ movl(RAX, Immediate(1)); // OK - __ LeaveFrameWithPP(); + __ LeaveDartFrame(); __ ret(); __ Bind(&fail); __ movl(RAX, Immediate(0)); // Fail. - __ LeaveFrameWithPP(); + __ popq(PP); // Restore caller's pool pointer. + __ LeaveFrame(); __ ret(); } @@ -2426,14 +2424,15 @@ ASSEMBLER_TEST_RUN(SquareRootDouble, test) { // Called from assembler_test.cc. ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) { - __ EnterDartFrame(0); + __ pushq(PP); // Save caller's pool pointer and load a new one here. + __ LoadPoolPointer(PP); __ pushq(CTX); __ movq(CTX, RDI); __ StoreIntoObject(RDX, FieldAddress(RDX, GrowableObjectArray::data_offset()), RSI); __ popq(CTX); - __ LeaveFrameWithPP(); + __ popq(PP); // Restore caller's pool pointer. __ ret(); } @@ -2547,9 +2546,7 @@ ASSEMBLER_TEST_RUN(DoubleToDoubleTrunc, test) { ASSEMBLER_TEST_GENERATE(DoubleAbs, assembler) { - __ EnterDartFrame(0); __ DoubleAbs(XMM0); - __ LeaveFrameWithPP(); __ ret(); } diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc index 1ac85f0cf41..a6538a23da2 100644 --- a/runtime/vm/flow_graph_compiler_x64.cc +++ b/runtime/vm/flow_graph_compiler_x64.cc @@ -977,7 +977,7 @@ void FlowGraphCompiler::CopyParameters() { ICData::New(function, Symbols::Call(), Object::empty_array(), Isolate::kNoDeoptId, kNumArgsChecked)); __ LoadObject(RBX, ic_data, PP); - __ LeaveFrameWithPP(); // The arguments are still on the stack. + __ LeaveDartFrame(); // The arguments are still on the stack. __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); // The noSuchMethod call may return to the caller, but not here. __ int3(); @@ -1176,7 +1176,7 @@ void FlowGraphCompiler::CompileGraph() { ICData::New(function, name, Object::empty_array(), Isolate::kNoDeoptId, kNumArgsChecked)); __ LoadObject(RBX, ic_data, PP); - __ LeaveFrameWithPP(); // The arguments are still on the stack. + __ LeaveDartFrame(); // The arguments are still on the stack. __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); // The noSuchMethod call may return to the caller, but not here. __ int3(); diff --git a/runtime/vm/instructions_x64_test.cc b/runtime/vm/instructions_x64_test.cc index 72d41ea9182..c9abf0f1774 100644 --- a/runtime/vm/instructions_x64_test.cc +++ b/runtime/vm/instructions_x64_test.cc @@ -27,21 +27,29 @@ ASSEMBLER_TEST_RUN(Call, test) { } +static intptr_t prologue_code_size = -1; + + ASSEMBLER_TEST_GENERATE(Jump, assembler) { - __ EnterDartFrame(0); // 20 bytes + ASSERT(assembler->CodeSize() == 0); + __ pushq(PP); + __ LoadPoolPointer(PP); + prologue_code_size = assembler->CodeSize(); __ JmpPatchable(&StubCode::InstanceFunctionLookupLabel(), PP); __ JmpPatchable(&StubCode::AllocateArrayLabel(), PP); - __ LeaveFrameWithPP(); + __ popq(PP); __ ret(); } ASSEMBLER_TEST_RUN(Jump, test) { - JumpPattern jump1(test->entry() + 20, test->code()); + ASSERT(prologue_code_size != -1); + JumpPattern jump1(test->entry() + prologue_code_size, test->code()); jump1.IsValid(); EXPECT_EQ(StubCode::InstanceFunctionLookupLabel().address(), jump1.TargetAddress()); - JumpPattern jump2(test->entry() + jump1.pattern_length_in_bytes() + 20, + JumpPattern jump2((test->entry() + + jump1.pattern_length_in_bytes() + prologue_code_size), test->code()); EXPECT_EQ(StubCode::AllocateArrayLabel().address(), jump2.TargetAddress()); diff --git a/runtime/vm/object_x64_test.cc b/runtime/vm/object_x64_test.cc index f24d1e520fd..b8914e0ab27 100644 --- a/runtime/vm/object_x64_test.cc +++ b/runtime/vm/object_x64_test.cc @@ -34,9 +34,10 @@ void GenerateIncrement(Assembler* assembler) { void GenerateEmbedStringInCode(Assembler* assembler, const char* str) { const String& string_object = String::ZoneHandle(String::New(str, Heap::kOld)); - __ EnterDartFrame(0); + __ pushq(PP); // Save caller's pool pointer and load a new one here. + __ LoadPoolPointer(PP); __ LoadObject(RAX, string_object, PP); - __ LeaveFrameWithPP(); + __ popq(PP); // Restore caller's pool pointer. __ ret(); } diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc index 4f70a5fd9a7..2e13ae00545 100644 --- a/runtime/vm/stack_frame.cc +++ b/runtime/vm/stack_frame.cc @@ -61,21 +61,24 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { // helper functions to the raw object interface. ASSERT(visitor != NULL); NoGCScope no_gc; - RawObject** first = reinterpret_cast(sp()); - RawObject** last = reinterpret_cast( - fp() + (kFirstLocalSlotFromFp * kWordSize)); Code code; code = LookupDartCode(); if (!code.IsNull()) { // Visit the code object. RawObject* raw_code = code.raw(); visitor->VisitPointer(&raw_code); - // Visit stack based on stack maps. + + // Optimized frames have a stack map. We need to visit the frame based + // on the stack map. Array maps; maps = Array::null(); Stackmap map; map = code.GetStackmap(pc(), &maps, &map); if (!map.IsNull()) { + RawObject** first = reinterpret_cast(sp()); + RawObject** last = reinterpret_cast( + fp() + (kFirstLocalSlotFromFp * kWordSize)); + // A stack map is present in the code object, use the stack map to // visit frame slots which are marked as having objects. // @@ -108,9 +111,22 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { // The last slot can be one slot (but not more) past the last slot // in the case that all slots were covered by the stack map. ASSERT((last + 1) >= first); + visitor->VisitPointers(first, last); + + // Now visit other slots which might be part of the calling convention. + first = reinterpret_cast( + fp() + ((kFirstLocalSlotFromFp + 1) * kWordSize)); + last = reinterpret_cast( + fp() + (kFirstObjectSlotFromFp * kWordSize)); + visitor->VisitPointers(first, last); + return; } } - // Each slot between the first and last included are tagged objects. + // For normal unoptimized Dart frames and Stub frames each slot + // between the first and last included are tagged objects. + RawObject** first = reinterpret_cast(sp()); + RawObject** last = reinterpret_cast( + fp() + (kFirstObjectSlotFromFp * kWordSize)); visitor->VisitPointers(first, last); } diff --git a/runtime/vm/stack_frame_arm.h b/runtime/vm/stack_frame_arm.h index 3bae90f2161..8149711477f 100644 --- a/runtime/vm/stack_frame_arm.h +++ b/runtime/vm/stack_frame_arm.h @@ -16,19 +16,24 @@ Callee frame | ... | | saved LR | (PC of current frame) | callee's PC marker | +--------------------+ -Current frame | ... | <- SP of current frame - | first local | - | caller's PP | +Current frame | ... T| <- SP of current frame + | first local T| + | caller's PP T| | caller's FP | <- FP of current frame | caller's LR | (PC of caller frame) | PC marker | (current frame's code entry + offset) +--------------------+ Caller frame | last parameter | <- SP of caller frame | ... | + + T against a slot indicates it needs to be traversed during GC. */ static const int kDartFrameFixedSize = 4; // PP, FP, LR, PC marker. static const int kSavedPcSlotFromSp = -2; + +static const int kFirstObjectSlotFromFp = -2; // Used by GC to traverse stack. + static const int kFirstLocalSlotFromFp = -2; static const int kSavedCallerPpSlotFromFp = -1; static const int kSavedCallerFpSlotFromFp = 0; @@ -44,4 +49,3 @@ static const int kExitLinkSlotFromEntryFp = -25; } // namespace dart #endif // VM_STACK_FRAME_ARM_H_ - diff --git a/runtime/vm/stack_frame_ia32.h b/runtime/vm/stack_frame_ia32.h index 4ef81aee64c..f36863bb272 100644 --- a/runtime/vm/stack_frame_ia32.h +++ b/runtime/vm/stack_frame_ia32.h @@ -14,18 +14,23 @@ Callee frame | ... | | saved EBP | (EBP of current frame) | saved PC | (PC of current frame) +--------------------+ -Current frame | ... | <- ESP of current frame - | first local | +Current frame | ... T| <- ESP of current frame + | first local T| | PC marker | (current frame's code entry + offset) | caller's EBP | <- EBP of current frame | caller's ret addr | (PC of caller frame) +--------------------+ Caller frame | last parameter | <- ESP of caller frame | ... | + + T against a slot indicates it needs to be traversed during GC. */ static const int kDartFrameFixedSize = 3; // PC marker, EBP, PC. static const int kSavedPcSlotFromSp = -1; + +static const int kFirstObjectSlotFromFp = -2; // Used by GC to traverse stack. + static const int kFirstLocalSlotFromFp = -2; static const int kPcMarkerSlotFromFp = -1; static const int kSavedCallerFpSlotFromFp = 0; @@ -43,4 +48,3 @@ static const int kExitLinkSlotFromEntryFp = -4; } // namespace dart #endif // VM_STACK_FRAME_IA32_H_ - diff --git a/runtime/vm/stack_frame_mips.h b/runtime/vm/stack_frame_mips.h index caeed8de7e1..0fda40ce5d2 100644 --- a/runtime/vm/stack_frame_mips.h +++ b/runtime/vm/stack_frame_mips.h @@ -14,19 +14,24 @@ Callee frame | ... | | current RA | (PC of current frame) | callee's PC marker | +--------------------+ -Current frame | ... | <- SP of current frame - | first local | - | caller's PP | +Current frame | ... T| <- SP of current frame + | first local T| + | caller's PP T| | caller's FP | <- FP of current frame | caller's RA | (PC of caller frame) | PC marker | (current frame's code entry + offset) +--------------------+ Caller frame | last parameter | <- SP of caller frame | ... | + + T against a slot indicates it needs to be traversed during GC. */ static const int kDartFrameFixedSize = 4; // PP, FP, RA, PC marker. static const int kSavedPcSlotFromSp = -2; + +static const int kFirstObjectSlotFromFp = -2; // Used by GC to traverse stack. + static const int kFirstLocalSlotFromFp = -2; static const int kSavedCallerPpSlotFromFp = -1; static const int kSavedCallerFpSlotFromFp = 0; @@ -42,4 +47,3 @@ static const int kExitLinkSlotFromEntryFp = -22; } // namespace dart #endif // VM_STACK_FRAME_MIPS_H_ - diff --git a/runtime/vm/stack_frame_x64.h b/runtime/vm/stack_frame_x64.h index 33c87b666a6..dcd964a7a54 100644 --- a/runtime/vm/stack_frame_x64.h +++ b/runtime/vm/stack_frame_x64.h @@ -16,20 +16,24 @@ Callee frame | ... | | saved RBP | (RBP of current frame) | saved PC | (PC of current frame) +--------------------+ -Current frame | ... | <- RSP of current frame - | first local | - | caller's PP | +Current frame | ... T| <- RSP of current frame + | first local T| + | caller's PP T| | PC marker | (current frame's code entry + offset) | caller's RBP | <- RBP of current frame | caller's ret addr | (PC of caller frame) +--------------------+ Caller frame | last parameter | <- RSP of caller frame | ... | + + T against a slot indicates it needs to be traversed during GC. */ static const int kDartFrameFixedSize = 4; // PC marker, RBP, PP, PC. static const int kSavedPcSlotFromSp = -1; +static const int kFirstObjectSlotFromFp = -2; // Used by GC to traverse stack. + static const int kFirstLocalSlotFromFp = -3; static const int kSavedCallerPpSlotFromFp = -2; static const int kPcMarkerSlotFromFp = -1; @@ -41,10 +45,9 @@ static const int kCallerSpSlotFromFp = 2; static const int kSavedAboveReturnAddress = 3; // Saved above return address. // Entry and exit frame layout. -static const int kSavedContextSlotFromEntryFp = -10; -static const int kExitLinkSlotFromEntryFp = -9; +static const int kSavedContextSlotFromEntryFp = -9; +static const int kExitLinkSlotFromEntryFp = -8; } // namespace dart #endif // VM_STACK_FRAME_X64_H_ - diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc index c357973ab4a..5e0b9af4301 100644 --- a/runtime/vm/stub_code_x64.cc +++ b/runtime/vm/stub_code_x64.cc @@ -260,7 +260,7 @@ void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { __ popq(RAX); // Get Code object result. __ popq(R10); // Restore arguments descriptor array. // Remove the stub frame as we are about to jump to the dart function. - __ LeaveFrame(); + __ LeaveStubFrame(); __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); @@ -281,7 +281,7 @@ void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { __ popq(R10); // Restore arguments descriptor array. __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); - __ LeaveFrame(); + __ LeaveStubFrame(); __ jmp(RAX); __ int3(); } @@ -323,7 +323,7 @@ static void PushArgumentsArray(Assembler* assembler) { // called, the stub accesses the receiver from this location directly // when trying to resolve the call. void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { - __ EnterStubFrameWithPP(); + __ EnterStubFrame(); __ PushObject(Object::null_object(), PP); // Space for the return value. // Push the receiver as an argument. Load the smi-tagged argument @@ -345,7 +345,7 @@ void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { // Remove arguments. __ Drop(4); __ popq(RAX); // Get result into RAX. - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); __ ret(); } @@ -418,9 +418,8 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); } - // There is a Dart Frame on the stack. We just need the PP. - __ movq(PP, Address(RBP, -2 * kWordSize)); - __ LeaveFrame(); + // There is a Dart Frame on the stack. We must restore PP and leave frame. + __ LeaveDartFrame(); __ popq(RCX); // Preserve return address. __ movq(RSP, RBP); // Discard optimized frame. @@ -444,9 +443,8 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); } // Code above cannot cause GC. - // There is a Dart Frame on the stack. We just need the PP. - __ movq(PP, Address(RBP, -2 * kWordSize)); - __ LeaveFrame(); + // There is a Dart Frame on the stack. We must restore PP and leave frame. + __ LeaveDartFrame(); // 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 @@ -466,7 +464,7 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ popq(RAX); // Restore result. __ Drop(1); // Workaround for dropped stack slot during GC. } - __ LeaveFrame(); + __ LeaveStubFrame(); __ popq(RCX); // Pop return address. __ addq(RSP, RBX); // Remove materialization arguments. @@ -493,7 +491,7 @@ void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { - __ EnterStubFrameWithPP(); + __ EnterStubFrame(); // Load the receiver into RAX. The argument count in the arguments // descriptor in R10 is a smi. __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); @@ -518,7 +516,7 @@ void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { __ popq(RAX); // Return value from the runtime call (instructions). __ popq(R10); // Restore arguments descriptor. __ popq(RBX); // Restore IC data. - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); Label lookup; __ CompareObject(RAX, Object::null_object(), PP); @@ -659,7 +657,7 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { __ popq(RAX); // Pop element type argument. __ popq(R10); // Pop array length argument. __ popq(RAX); // Pop return value from return slot. - __ LeaveFrame(); + __ LeaveStubFrame(); __ ret(); } @@ -717,7 +715,7 @@ void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { __ movq(RAX, FieldAddress(RBX, Function::code_offset())); // Remove the stub frame as we are about to jump to the closure function. - __ LeaveFrame(); + __ LeaveStubFrame(); __ Bind(&function_compiled); // RAX: Code. @@ -753,7 +751,7 @@ void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { __ popq(RAX); // Get result into RAX. // Remove the stub frame as we are about to return. - __ LeaveFrame(); + __ LeaveStubFrame(); __ ret(); } @@ -767,16 +765,13 @@ void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { // RCX : new context containing the current isolate pointer. void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { // Save frame pointer coming in. - __ EnterStubFrameWithPP(); + __ EnterFrame(0); // At this point, the stack looks like: - // | saved RC15/PP | <-- RSP / TOS - // | "saved PC area" = 0 | // | saved RBP | <-- RBP // | saved PC (return to DartEntry::InvokeFunction) | - // The old frame pointer, the return address, the old R15 (for PP). - const intptr_t kInitialOffset = 3; + const intptr_t kInitialOffset = 1; // Save arguments descriptor array and new context. const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize; __ pushq(RSI); @@ -788,7 +783,12 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { __ pushq(R12); __ pushq(R13); __ pushq(R14); - // R15 is already saved above by EnterStubFrameWithPP. + __ pushq(R15); + + // We now load the pool pointer(PP) as we are about to invoke dart code and we + // could potentially invoke some intrinsic functions which need the PP to be + // set up. + __ LoadPoolPointer(PP); // If any additional (or fewer) values are pushed, the offsets in // kExitLinkSlotFromEntryFp and kSavedContextSlotFromEntryFp will need to be @@ -810,7 +810,7 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { // StackFrameIterator reads the top exit frame info saved in this frame. // The constant kExitLinkSlotFromEntryFp must be kept in sync with the // code below. - ASSERT(kExitLinkSlotFromEntryFp == -9); + ASSERT(kExitLinkSlotFromEntryFp == -8); __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset())); __ pushq(RAX); __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0)); @@ -822,7 +822,7 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { // EntryFrame::SavedContext reads the context saved in this frame. // The constant kSavedContextSlotFromEntryFp must be kept in sync with // the code below. - ASSERT(kSavedContextSlotFromEntryFp == -10); + ASSERT(kSavedContextSlotFromEntryFp == -9); __ movq(RAX, Address(R8, Isolate::top_context_offset())); __ pushq(RAX); @@ -880,14 +880,14 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), RDX); // Restore C++ ABI callee-saved registers. - // R15 will be restored below by LeaveFrameWithPP. + __ popq(R15); __ popq(R14); __ popq(R13); __ popq(R12); __ popq(RBX); // Restore the frame pointer. - __ LeaveFrameWithPP(); + __ LeaveFrame(); __ ret(); } @@ -1011,7 +1011,7 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { __ popq(RAX); // Pop the new context object. // RAX: new object // Restore the frame pointer. - __ LeaveFrame(); + __ LeaveStubFrame(); __ ret(); } @@ -1228,7 +1228,7 @@ void StubCode::GenerateAllocationStubForClass(Assembler* assembler, __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); } // Create a stub frame. - __ EnterStubFrameWithPP(); + __ EnterStubFrame(true); // Uses PP to access class object. __ pushq(R12); // Setup space on stack for return value. __ PushObject(cls, PP); // Push class of object to be allocated. if (is_cls_parameterized) { @@ -1245,7 +1245,7 @@ void StubCode::GenerateAllocationStubForClass(Assembler* assembler, __ popq(RAX); // Pop result (newly allocated object). // RAX: new object // Restore the frame pointer. - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); __ ret(); } @@ -1264,7 +1264,7 @@ void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, const Class& cls = Class::ZoneHandle(func.signature_class()); const bool has_type_arguments = cls.NumTypeArguments() > 0; - __ EnterStubFrameWithPP(); // Uses pool pointer to refer to function. + __ EnterStubFrame(true); // Uses pool pointer to refer to function. __ LoadObject(R12, Object::null_object(), PP); const intptr_t kTypeArgumentsOffset = 4 * kWordSize; const intptr_t kReceiverOffset = 5 * kWordSize; @@ -1353,7 +1353,7 @@ void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, // Done allocating and initializing the instance. // RAX: new object. __ addq(RAX, Immediate(kHeapObjectTag)); - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); __ ret(); __ Bind(&slow_case); @@ -1388,7 +1388,7 @@ void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, __ popq(RAX); // Pop the result. // RAX: New closure object. // Restore the calling frame. - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); __ ret(); } @@ -1424,7 +1424,7 @@ void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { __ popq(RAX); // Get result into RAX. // Remove the stub frame as we are about to return. - __ LeaveFrame(); + __ LeaveStubFrame(); __ ret(); } @@ -1445,7 +1445,7 @@ void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { __ popq(RAX); // Discard argument; __ popq(ic_reg); // Restore. __ popq(func_reg); // Restore. - __ LeaveFrame(); + __ LeaveStubFrame(); } __ incq(FieldAddress(func_reg, Function::usage_counter_offset())); } @@ -1499,7 +1499,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub( __ pushq(RBX); __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); __ popq(RBX); - __ LeaveFrame(); + __ LeaveStubFrame(); __ Bind(¬_stepping); // Load arguments descriptor into R10. @@ -1580,7 +1580,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub( __ popq(RAX); // Pop returned code object into RAX (null if not found). __ popq(RBX); // Restore IC data array. __ popq(R10); // Restore arguments descriptor array. - __ LeaveFrame(); + __ LeaveStubFrame(); Label call_target_function; __ cmpq(RAX, R12); __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); @@ -1616,7 +1616,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub( __ popq(RAX); // Restore function. __ popq(RBX); // Restore IC data array. __ popq(R10); // Restore arguments descriptor array. - __ LeaveFrame(); + __ LeaveStubFrame(); __ movq(RCX, FieldAddress(RAX, Function::code_offset())); __ Bind(&is_compiled); } @@ -1746,7 +1746,7 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { __ pushq(RBX); // Preserve IC data object. __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); __ popq(RBX); - __ LeaveFrame(); + __ LeaveStubFrame(); __ Bind(¬_stepping); // RBX: IC data object (preserved). @@ -1781,7 +1781,7 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { __ popq(RAX); // Discard argument. __ popq(RBX); // Restore IC data object. __ popq(R13); // Restore target function. - __ LeaveFrame(); + __ LeaveStubFrame(); __ movq(RAX, FieldAddress(R13, Function::code_offset())); __ Bind(&target_is_compiled); @@ -1814,7 +1814,7 @@ void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { __ popq(RAX); // Restore function. __ popq(RCX); // Restore IC data array. __ popq(RDX); // Restore arguments descriptor array. - __ LeaveFrame(); + __ LeaveStubFrame(); __ ret(); } @@ -1822,7 +1822,7 @@ void StubCode::GenerateCompileFunctionRuntimeCallStub(Assembler* assembler) { // RBX, R10: May contain arguments to runtime stub. // TOS(0): return address (Dart code). void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { - __ EnterStubFrameWithPP(); + __ EnterStubFrame(); // Preserve runtime args. __ pushq(RBX); __ pushq(R10); @@ -1834,7 +1834,7 @@ void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { __ popq(RAX); // Address of original. __ popq(R10); // Restore arguments. __ popq(RBX); - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); __ jmp(RAX); // Jump to original stub. } @@ -1849,7 +1849,7 @@ void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry, 0); __ popq(RAX); // Code object. __ popq(RBX); // Restore IC data. - __ LeaveFrame(); + __ LeaveStubFrame(); // Load arguments descriptor into R10. __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); @@ -1863,14 +1863,13 @@ void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { // TOS(0): return address (Dart code). void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { - __ EnterStubFrameWithPP(); + __ EnterStubFrame(); __ pushq(RAX); __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry, 0); __ popq(RAX); - __ LeaveFrameWithPP(); - + __ LeaveStubFrame(); __ popq(R11); // discard return address of call to this stub. - __ LeaveFrameWithPP(); + __ LeaveDartFrame(); __ ret(); } @@ -1882,7 +1881,7 @@ void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { __ pushq(RBX); __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry, 0); __ popq(RBX); - __ LeaveFrame(); + __ LeaveStubFrame(); // Find out which dispatch stub to call. Label test_two, test_three, test_four; @@ -2044,7 +2043,7 @@ void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) { // RDI: function to be reoptimized. // R10: argument descriptor (preserved). void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { - __ EnterStubFrameWithPP(); + __ EnterStubFrame(); __ LoadObject(R12, Object::null_object(), PP); __ pushq(R10); __ pushq(R12); // Setup space on stack for return value. @@ -2055,7 +2054,7 @@ void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { __ popq(R10); // Restore argument descriptor. __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); __ jmp(RAX); __ int3(); } @@ -2141,7 +2140,7 @@ void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( __ j(EQUAL, ¬_stepping, Assembler::kNearJump); __ EnterStubFrame(); __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); - __ LeaveFrame(); + __ LeaveStubFrame(); __ Bind(¬_stepping); const Register left = RAX; diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc index cc0e3fb8106..8e4426eabb9 100644 --- a/runtime/vm/stub_code_x64_test.cc +++ b/runtime/vm/stub_code_x64_test.cc @@ -45,7 +45,7 @@ static void GenerateCallToCallRuntimeStub(Assembler* assembler, const Object& result = Object::ZoneHandle(); const Context& context = Context::ZoneHandle(Context::New(0, Heap::kOld)); ASSERT(context.isolate() == Isolate::Current()); - __ EnterStubFrameWithPP(); + __ EnterStubFrame(true); __ LoadObject(CTX, context, PP); __ PushObject(result, PP); // Push Null object for return value. __ PushObject(smi1, PP); // Push argument 1 smi1. @@ -54,7 +54,7 @@ static void GenerateCallToCallRuntimeStub(Assembler* assembler, __ CallRuntime(kTestSmiSubRuntimeEntry, argc); // Call SmiSub runtime func. __ AddImmediate(RSP, Immediate(argc * kWordSize), PP); __ popq(RAX); // Pop return value from return slot. - __ LeaveFrameWithPP(); + __ LeaveStubFrame(); __ ret(); }