Fix for issue 14790 - Crash when using dartium devtools

The stack frame iteration during GC was missing one slot in stub frames that
did not save the pool pointer.

- This change makes all stub frames uniform, i.e they always save/restore the pool pointer. This ensures that we will traverse all slots on the stack.

- A new constant called kFirstObjectSlotFromFp has been added which is used as the slot to start stack traversal.

(The ARM and MIPs changes will be in a different CL)

R=iposva@google.com, regis@google.com, zra@google.com

Review URL: https://codereview.chromium.org//63093003

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@30088 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
asiva@google.com
2013-11-08 00:25:40 +00:00
parent 91b5e131ee
commit eaebf15f43
13 changed files with 163 additions and 123 deletions
+19 -15
View File
@@ -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();
}
+10 -10
View File
@@ -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
+12 -15
View File
@@ -1625,13 +1625,11 @@ ASSEMBLER_TEST_RUN(PackedCompareNLE, test) {
ASSEMBLER_TEST_GENERATE(PackedNegate, assembler) {
__ EnterDartFrame(0);
__ movl(RAX, Immediate(bit_cast<int32_t, float>(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<int32_t, float>(-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<int32_t, float>(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<intptr_t>(&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();
}
+2 -2
View File
@@ -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();
+12 -4
View File
@@ -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());
+3 -2
View File
@@ -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();
}
+21 -5
View File
@@ -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<RawObject**>(sp());
RawObject** last = reinterpret_cast<RawObject**>(
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<RawObject**>(sp());
RawObject** last = reinterpret_cast<RawObject**>(
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<RawObject**>(
fp() + ((kFirstLocalSlotFromFp + 1) * kWordSize));
last = reinterpret_cast<RawObject**>(
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<RawObject**>(sp());
RawObject** last = reinterpret_cast<RawObject**>(
fp() + (kFirstObjectSlotFromFp * kWordSize));
visitor->VisitPointers(first, last);
}
+8 -4
View File
@@ -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_
+7 -3
View File
@@ -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_
+8 -4
View File
@@ -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_
+9 -6
View File
@@ -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_
+50 -51
View File
@@ -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(&not_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(&not_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, &not_stepping, Assembler::kNearJump);
__ EnterStubFrame();
__ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
__ LeaveFrame();
__ LeaveStubFrame();
__ Bind(&not_stepping);
const Register left = RAX;
+2 -2
View File
@@ -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();
}