Index: runtime/vm/stub_code_arm.cc |
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc |
index 9d2883b58d65b194d1cb612ba2591b19a494a377..0851085fbb84f53d2c1d6d87d21f7b60f1a95bc1 100644 |
--- a/runtime/vm/stub_code_arm.cc |
+++ b/runtime/vm/stub_code_arm.cc |
@@ -42,12 +42,11 @@ void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); |
const intptr_t argv_offset = NativeArguments::argv_offset(); |
const intptr_t retval_offset = NativeArguments::retval_offset(); |
- const intptr_t exitframe_last_param_slot_from_fp = 2; |
__ EnterStubFrame(); |
- COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R9)) != 0); |
- __ LoadIsolate(R9); |
+ COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R7)) != 0); |
+ __ LoadIsolate(R7); |
// Save exit frame information to enable stack walking as we are about |
// to transition to Dart VM C++ code. |
@@ -56,7 +55,7 @@ void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
#if defined(DEBUG) |
{ Label ok; |
// Check that we are always entering from Dart code. |
- __ LoadFromOffset(kWord, R6, R9, Isolate::vm_tag_offset()); |
+ __ LoadFromOffset(kWord, R6, R7, Isolate::vm_tag_offset()); |
__ CompareImmediate(R6, VMTag::kDartTagId); |
__ b(&ok, EQ); |
__ Stop("Not coming from Dart code."); |
@@ -65,7 +64,7 @@ void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
#endif |
// Mark that the isolate is executing VM code. |
- __ StoreToOffset(kWord, R5, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R5, R7, Isolate::vm_tag_offset()); |
// Reserve space for arguments and align frame before entering C++ world. |
// NativeArguments are passed in registers. |
@@ -87,7 +86,7 @@ void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
ASSERT(argv_offset == 2 * kWordSize); |
__ add(R2, FP, Operand(R4, LSL, 2)); // Compute argv. |
// Set argv in NativeArguments. |
- __ AddImmediate(R2, exitframe_last_param_slot_from_fp * kWordSize); |
+ __ AddImmediate(R2, kParamEndSlotFromFp * kWordSize); |
ASSERT(retval_offset == 3 * kWordSize); |
__ add(R3, R2, Operand(kWordSize)); // Retval is next to 1st argument. |
@@ -97,7 +96,7 @@ void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
// Mark that the isolate is executing Dart code. |
__ LoadImmediate(R2, VMTag::kDartTagId); |
- __ StoreToOffset(kWord, R2, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R2, R7, Isolate::vm_tag_offset()); |
// Reset exit frame information in Isolate structure. |
__ LoadImmediate(R2, 0); |
@@ -141,8 +140,8 @@ void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
__ EnterStubFrame(); |
- COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R9)) != 0); |
- __ LoadIsolate(R9); |
+ COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R7)) != 0); |
+ __ LoadIsolate(R7); |
// Save exit frame information to enable stack walking as we are about |
// to transition to native code. |
@@ -151,7 +150,7 @@ void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
#if defined(DEBUG) |
{ Label ok; |
// Check that we are always entering from Dart code. |
- __ LoadFromOffset(kWord, R6, R9, Isolate::vm_tag_offset()); |
+ __ LoadFromOffset(kWord, R6, R7, Isolate::vm_tag_offset()); |
__ CompareImmediate(R6, VMTag::kDartTagId); |
__ b(&ok, EQ); |
__ Stop("Not coming from Dart code."); |
@@ -160,7 +159,7 @@ void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
#endif |
// Mark that the isolate is executing Native code. |
- __ StoreToOffset(kWord, R5, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R5, R7, Isolate::vm_tag_offset()); |
// Reserve space for the native arguments structure passed on the stack (the |
// outgoing pointer parameter to the native arguments structure is passed in |
@@ -183,7 +182,8 @@ void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
// Set argv in NativeArguments: R2 already contains argv. |
ASSERT(retval_offset == 3 * kWordSize); |
- __ add(R3, FP, Operand(3 * kWordSize)); // Set retval in NativeArgs. |
+ // Set retval in NativeArgs. |
+ __ add(R3, FP, Operand(kCallerSpSlotFromFp * kWordSize)); |
// Passing the structure by value as in runtime calls would require changing |
// Dart API for native functions. |
@@ -195,17 +195,19 @@ void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
// Call native function invocation wrapper or redirection via simulator. |
#if defined(USING_SIMULATOR) |
uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper); |
- entry = Simulator::RedirectExternalReference( |
- entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
- __ LoadImmediate(R2, entry); |
+ const ExternalLabel label(Simulator::RedirectExternalReference( |
+ entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments)); |
+ __ LoadExternalLabel(R2, &label, kNotPatchable); |
__ blx(R2); |
#else |
- __ BranchLink(&NativeEntry::NativeCallWrapperLabel(), kNotPatchable); |
+ __ LoadExternalLabel( |
+ LR, &NativeEntry::NativeCallWrapperLabel(), kNotPatchable); |
+ __ blx(LR); |
#endif |
// Mark that the isolate is executing Dart code. |
__ LoadImmediate(R2, VMTag::kDartTagId); |
- __ StoreToOffset(kWord, R2, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R2, R7, Isolate::vm_tag_offset()); |
// Reset exit frame information in Isolate structure. |
__ LoadImmediate(R2, 0); |
@@ -230,8 +232,8 @@ void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { |
__ EnterStubFrame(); |
- COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R9)) != 0); |
- __ LoadIsolate(R9); |
+ COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R7)) != 0); |
+ __ LoadIsolate(R7); |
// Save exit frame information to enable stack walking as we are about |
// to transition to native code. |
@@ -240,7 +242,7 @@ void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { |
#if defined(DEBUG) |
{ Label ok; |
// Check that we are always entering from Dart code. |
- __ LoadFromOffset(kWord, R6, R9, Isolate::vm_tag_offset()); |
+ __ LoadFromOffset(kWord, R6, R7, Isolate::vm_tag_offset()); |
__ CompareImmediate(R6, VMTag::kDartTagId); |
__ b(&ok, EQ); |
__ Stop("Not coming from Dart code."); |
@@ -249,7 +251,7 @@ void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { |
#endif |
// Mark that the isolate is executing Native code. |
- __ StoreToOffset(kWord, R5, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R5, R7, Isolate::vm_tag_offset()); |
// Reserve space for the native arguments structure passed on the stack (the |
// outgoing pointer parameter to the native arguments structure is passed in |
@@ -272,7 +274,8 @@ void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { |
// Set argv in NativeArguments: R2 already contains argv. |
ASSERT(retval_offset == 3 * kWordSize); |
- __ add(R3, FP, Operand(3 * kWordSize)); // Set retval in NativeArgs. |
+ // Set retval in NativeArgs. |
+ __ add(R3, FP, Operand(kCallerSpSlotFromFp * kWordSize)); |
// Passing the structure by value as in runtime calls would require changing |
// Dart API for native functions. |
@@ -285,7 +288,7 @@ void StubCode::GenerateCallBootstrapCFunctionStub(Assembler* assembler) { |
// Mark that the isolate is executing Dart code. |
__ LoadImmediate(R2, VMTag::kDartTagId); |
- __ StoreToOffset(kWord, R2, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R2, R7, Isolate::vm_tag_offset()); |
// Reset exit frame information in Isolate structure. |
__ LoadImmediate(R2, 0); |
@@ -311,6 +314,7 @@ void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
// Remove the stub frame. |
__ LeaveStubFrame(); |
// Jump to the dart function. |
+ __ mov(CODE_REG, Operand(R0)); |
__ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
__ bx(R0); |
} |
@@ -320,6 +324,10 @@ void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
// (invalid because its function was optimized or deoptimized). |
// R4: arguments descriptor array. |
void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
+ // Load code pointer to this stub from the thread: |
+ // The one that is passed in, is not correct - it points to the code object |
+ // that needs to be replaced. |
+ __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); |
// Create a stub frame as we are pushing some objects on the stack before |
// calling into the runtime. |
__ EnterStubFrame(); |
@@ -332,6 +340,7 @@ void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
// Remove the stub frame. |
__ LeaveStubFrame(); |
// Jump to the dart function. |
+ __ mov(CODE_REG, Operand(R0)); |
__ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
__ bx(R0); |
} |
@@ -340,6 +349,10 @@ void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
// Called from object allocate instruction when the allocation stub has been |
// disabled. |
void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
+ // Load code pointer to this stub from the thread: |
+ // The one that is passed in, is not correct - it points to the code object |
+ // that needs to be replaced. |
+ __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset())); |
__ EnterStubFrame(); |
// Setup space on stack for return value. |
__ LoadObject(R0, Object::null_object()); |
@@ -350,6 +363,7 @@ void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
// Remove the stub frame. |
__ LeaveStubFrame(); |
// Jump to the dart function. |
+ __ mov(CODE_REG, Operand(R0)); |
__ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
__ bx(R0); |
} |
@@ -403,13 +417,15 @@ static void PushArgumentsArray(Assembler* assembler) { |
// +------------------+ |
// | Saved LR | (deoptimization point) |
// +------------------+ |
-// | PC marker | |
+// | pc marker | |
+// +------------------+ |
+// | Saved CODE_REG | |
// +------------------+ |
// | ... | <- SP of optimized frame |
// |
// Parts of the code cannot GC, part of the code can GC. |
static void GenerateDeoptimizationSequence(Assembler* assembler, |
- bool preserve_result) { |
+ DeoptStubKind kind) { |
// DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there |
// is no need to set the correct PC marker or load PP, since they get patched. |
@@ -419,21 +435,10 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, |
__ eor(LR, IP, Operand(LR)); |
__ eor(IP, IP, Operand(LR)); |
- // Set up the frame manually. We can't use EnterFrame because we can't |
- // clobber LR (or any other register) with 0, yet. |
- __ sub(SP, SP, Operand(kWordSize)); // Make room for PC marker of 0. |
- __ Push(IP); // Push return address. |
- __ Push(FP); |
- __ mov(FP, Operand(SP)); |
- __ Push(PP); |
- |
+ // Set up the frame manually with return address now stored in IP. |
+ __ EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << IP), 0); |
__ LoadPoolPointer(); |
- // Now that IP holding the return address has been written to the stack, |
- // we can clobber it with 0 to write the null PC marker. |
- __ mov(IP, Operand(0)); |
- __ str(IP, Address(SP, +3 * kWordSize)); |
- |
// The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
// and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
const intptr_t saved_result_slot_from_fp = |
@@ -442,7 +447,17 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, |
// Push registers in their enumeration order: lowest register number at |
// lowest address. |
- __ PushList(kAllCpuRegistersList); |
+ for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) { |
+ if (i == CODE_REG) { |
+ // Save the original value of CODE_REG pushed before invoking this stub |
+ // instead of the value used to call this stub. |
+ COMPILE_ASSERT(IP > CODE_REG); // Assert IP is pushed first. |
+ __ ldr(IP, Address(FP, kCallerSpSlotFromFp * kWordSize)); |
+ __ Push(IP); |
+ } else { |
+ __ Push(static_cast<Register>(i)); |
+ } |
+ } |
if (TargetCPUFeatures::vfp_supported()) { |
ASSERT(kFpuRegisterSize == 4 * kWordSize); |
@@ -457,15 +472,18 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, |
} |
__ mov(R0, Operand(SP)); // Pass address of saved registers block. |
+ __ mov(R1, Operand(kind == kLazyDeopt ? 1 : 0)); |
__ ReserveAlignedFrameSpace(0); |
- __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); |
+ __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); |
// Result (R0) is stack-size (FP - SP) in bytes. |
+ const bool preserve_result = (kind == kLazyDeopt); |
if (preserve_result) { |
// Restore result into R1 temporarily. |
__ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize)); |
} |
+ __ RestoreCodePointer(); |
__ LeaveDartFrame(); |
__ sub(SP, FP, Operand(R0)); |
@@ -483,6 +501,7 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, |
__ ldr(R1, Address(FP, kFirstLocalSlotFromFp * kWordSize)); |
} |
// Code above cannot cause GC. |
+ __ RestoreCodePointer(); |
__ LeaveStubFrame(); |
// Frame is fully rewritten at this point and it is safe to perform a GC. |
@@ -511,13 +530,16 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, |
void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { |
// Correct return address to point just after the call that is being |
// deoptimized. |
- __ AddImmediate(LR, -CallPattern::LengthInBytes()); |
- GenerateDeoptimizationSequence(assembler, true); // Preserve R0. |
+ __ AddImmediate(LR, -CallPattern::DeoptCallPatternLengthInBytes()); |
+ // Push zap value instead of CODE_REG for lazy deopt. |
+ __ LoadImmediate(IP, 0xf1f1f1f1); |
+ __ Push(IP); |
+ GenerateDeoptimizationSequence(assembler, kLazyDeopt); |
} |
void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
- GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0. |
+ GenerateDeoptimizationSequence(assembler, kEagerDeopt); |
} |
@@ -573,6 +595,7 @@ void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
// Restore IC data and arguments descriptor. |
__ PopList((1 << R4) | (1 << R5)); |
+ __ RestoreCodePointer(); |
__ LeaveStubFrame(); |
if (!FLAG_lazy_dispatchers) { |
@@ -582,6 +605,7 @@ void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
} |
// Tail-call to target function. |
+ __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
__ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
__ bx(R2); |
} |
@@ -620,24 +644,24 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
/* inline_isolate = */ false); |
const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
- __ LoadImmediate(R9, fixed_size); |
- __ add(R9, R9, Operand(R3, LSL, 1)); // R3 is a Smi. |
+ __ LoadImmediate(R5, fixed_size); |
+ __ add(R5, R5, Operand(R3, LSL, 1)); // R3 is a Smi. |
ASSERT(kSmiTagShift == 1); |
- __ bic(R9, R9, Operand(kObjectAlignment - 1)); |
+ __ bic(R5, R5, Operand(kObjectAlignment - 1)); |
- // R9: Allocation size. |
+ // R5: Allocation size. |
Heap::Space space = Heap::SpaceForAllocation(cid); |
__ LoadIsolate(R6); |
__ ldr(R6, Address(R6, Isolate::heap_offset())); |
// Potential new object start. |
__ ldr(R0, Address(R6, Heap::TopOffset(space))); |
- __ adds(R7, R0, Operand(R9)); // Potential next object start. |
+ __ adds(R7, R0, Operand(R5)); // Potential next object start. |
__ b(&slow_case, CS); // Branch if unsigned overflow. |
// Check if the allocation fits into the remaining space. |
// R0: potential new object start. |
// R7: potential next object start. |
- // R9: allocation size. |
+ // R5: allocation size. |
__ ldr(R3, Address(R6, Heap::EndOffset(space))); |
__ cmp(R7, Operand(R3)); |
__ b(&slow_case, CS); |
@@ -652,12 +676,12 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
// R0: new object start as a tagged pointer. |
// R3: allocation stats address. |
// R7: new object end address. |
- // R9: allocation size. |
+ // R5: allocation size. |
{ |
const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
- __ CompareImmediate(R9, RawObject::SizeTag::kMaxSizeTag); |
- __ mov(R6, Operand(R9, LSL, shift), LS); |
+ __ CompareImmediate(R5, RawObject::SizeTag::kMaxSizeTag); |
+ __ mov(R6, Operand(R5, LSL, shift), LS); |
__ mov(R6, Operand(0), HI); |
// Get the class index and insert it into the tags. |
@@ -686,13 +710,13 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
// R6: iterator which initially points to the start of the variable |
// data area to be initialized. |
// R7: new object end address. |
- // R9: allocation size. |
+ // R5: allocation size. |
+ __ IncrementAllocationStatsWithSize(R3, R5, space); |
__ LoadObject(R4, Object::null_object()); |
__ mov(R5, Operand(R4)); |
__ AddImmediate(R6, R0, sizeof(RawArray) - kHeapObjectTag); |
__ InitializeFieldsNoBarrier(R0, R6, R7, R4, R5); |
- __ IncrementAllocationStatsWithSize(R3, R9, space); |
__ Ret(); // Returns the newly allocated object in R0. |
// Unable to allocate the array using the fast inline code, just call |
// into the runtime. |
@@ -717,7 +741,7 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
// Called when invoking Dart code from C++ (VM code). |
// Input parameters: |
// LR : points to return address. |
-// R0 : entrypoint of the Dart function to call. |
+// R0 : code object of the Dart function to call. |
// R1 : arguments descriptor array. |
// R2 : arguments array. |
// R3 : current thread. |
@@ -725,6 +749,10 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
// Save frame pointer coming in. |
__ EnterFrame((1 << FP) | (1 << LR), 0); |
+ // Push code object to PC marker slot. |
+ __ ldr(IP, Address(R3, Thread::invoke_dart_code_stub_offset())); |
+ __ Push(IP); |
+ |
// Save new context and C++ ABI callee-saved registers. |
__ PushList(kAbiPreservedCpuRegs); |
@@ -737,24 +765,19 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
__ sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize)); |
} |
- // 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(); |
- |
// Set up THR, which caches the current thread in Dart code. |
if (THR != R3) { |
__ mov(THR, Operand(R3)); |
} |
- __ LoadIsolate(R9); |
+ __ LoadIsolate(R7); |
// Save the current VMTag on the stack. |
- __ LoadFromOffset(kWord, R5, R9, Isolate::vm_tag_offset()); |
+ __ LoadFromOffset(kWord, R5, R7, Isolate::vm_tag_offset()); |
__ Push(R5); |
// Mark that the isolate is executing Dart code. |
__ LoadImmediate(R5, VMTag::kDartTagId); |
- __ StoreToOffset(kWord, R5, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R5, R7, Isolate::vm_tag_offset()); |
// Save top resource and top exit frame info. Use R4-6 as temporary registers. |
// StackFrameIterator reads the top exit frame info saved in this frame. |
@@ -766,7 +789,7 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
// kExitLinkSlotFromEntryFp must be kept in sync with the code below. |
__ Push(R4); |
- ASSERT(kExitLinkSlotFromEntryFp == -26); |
+ ASSERT(kExitLinkSlotFromEntryFp == -27); |
__ Push(R5); |
// Load arguments descriptor array into R4, which is passed to Dart code. |
@@ -796,12 +819,15 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
__ Bind(&done_push_arguments); |
// Call the Dart code entrypoint. |
+ __ LoadImmediate(PP, 0); // GC safe value into PP. |
+ __ ldr(CODE_REG, Address(R0, VMHandles::kOffsetOfRawPtrInHandle)); |
+ __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset())); |
__ blx(R0); // R4 is the arguments descriptor array. |
// Get rid of arguments pushed on the stack. |
__ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize); |
- __ LoadIsolate(R9); |
+ __ LoadIsolate(R7); |
// Restore the saved top exit frame info and top resource back into the |
// Isolate structure. Uses R5 as a temporary register for this. |
__ Pop(R5); |
@@ -811,7 +837,7 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
// Restore the current VMTag from the stack. |
__ Pop(R4); |
- __ StoreToOffset(kWord, R4, R9, Isolate::vm_tag_offset()); |
+ __ StoreToOffset(kWord, R4, R7, Isolate::vm_tag_offset()); |
// Restore C++ ABI callee-saved registers. |
if (TargetCPUFeatures::vfp_supported()) { |
@@ -1030,12 +1056,11 @@ void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
// Input parameters: |
// LR : return address. |
// SP + 0 : type arguments object (only if class is parameterized). |
-// Returns patch_code_pc offset where patching code for disabling the stub |
-// has been generated (similar to regularly generated Dart code). |
-void StubCode::GenerateAllocationStubForClass( |
- Assembler* assembler, const Class& cls, |
- uword* entry_patch_offset, uword* patch_code_pc_offset) { |
- *entry_patch_offset = assembler->CodeSize(); |
+void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
+ const Class& cls) { |
+ // Must load pool pointer before being able to patch. |
+ Register new_pp = R7; |
+ __ LoadPoolPointer(new_pp); |
// The generated code is different if the class is parameterized. |
const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
ASSERT(!is_cls_parameterized || |
@@ -1161,8 +1186,6 @@ void StubCode::GenerateAllocationStubForClass( |
// Restore the frame pointer. |
__ LeaveStubFrame(); |
__ Ret(); |
- *patch_code_pc_offset = assembler->CodeSize(); |
- __ BranchPatchable(*StubCode::FixAllocationStubTarget_entry()); |
} |
@@ -1317,6 +1340,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub( |
Token::Kind kind, |
RangeCollectionMode range_collection_mode, |
bool optimized) { |
+ __ CheckCodePointer(); |
ASSERT(num_args > 0); |
#if defined(DEBUG) |
{ Label ok; |
@@ -1441,6 +1465,9 @@ void StubCode::GenerateNArgsCheckInlineCacheStub( |
// Pop returned function object into R0. |
// Restore arguments descriptor array and IC data array. |
__ PopList((1 << R0) | (1 << R4) | (1 << R5)); |
+ if (range_collection_mode == kCollectRanges) { |
+ __ RestoreCodePointer(); |
+ } |
__ LeaveStubFrame(); |
Label call_target_function; |
if (!FLAG_lazy_dispatchers) { |
@@ -1478,15 +1505,18 @@ void StubCode::GenerateNArgsCheckInlineCacheStub( |
} else { |
__ PushList((1 << R1) | (1 << R5)); |
} |
+ __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
__ blx(R2); |
Label done; |
__ ldr(R5, Address(FP, kFirstLocalSlotFromFp * kWordSize)); |
__ UpdateRangeFeedback(R0, 2, R5, R1, R4, &done); |
__ Bind(&done); |
+ __ RestoreCodePointer(); |
__ LeaveStubFrame(); |
__ Ret(); |
} else { |
+ __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
__ bx(R2); |
} |
@@ -1496,6 +1526,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub( |
__ Push(R5); // Preserve IC data. |
__ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
__ Pop(R5); |
+ __ RestoreCodePointer(); |
__ LeaveStubFrame(); |
__ b(&done_stepping); |
} |
@@ -1646,6 +1677,7 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
// Get function and call it, if possible. |
__ LoadFromOffset(kWord, R0, R6, target_offset); |
+ __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
__ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
__ bx(R2); |
@@ -1655,6 +1687,7 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
__ Push(R5); // Preserve IC data. |
__ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
__ Pop(R5); |
+ __ RestoreCodePointer(); |
__ LeaveStubFrame(); |
__ b(&done_stepping); |
} |
@@ -1691,6 +1724,7 @@ void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
__ PopList((1 << R4) | (1 << R5)); // Restore arg desc. and IC data. |
__ LeaveStubFrame(); |
+ __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
__ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
__ bx(R2); |
} |
@@ -1705,6 +1739,8 @@ void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
__ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
__ PopList((1 << R0) | (1 << R5)); |
__ LeaveStubFrame(); |
+ __ mov(CODE_REG, Operand(R0)); |
+ __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset())); |
__ bx(R0); |
} |
@@ -1715,8 +1751,9 @@ void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { |
// Make room for result. |
__ PushList((1 << R0)); |
__ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
- __ PopList((1 << R0)); |
+ __ PopList((1 << CODE_REG)); |
__ LeaveStubFrame(); |
+ __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset())); |
__ bx(R0); |
} |
@@ -1896,8 +1933,9 @@ void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
__ Pop(R0); // Discard argument. |
__ Pop(R0); // Get Code object |
__ Pop(R4); // Restore argument descriptor. |
- __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
__ LeaveStubFrame(); |
+ __ mov(CODE_REG, Operand(R0)); |
+ __ ldr(R0, FieldAddress(R0, Code::entry_point_offset())); |
__ bx(R0); |
__ bkpt(0); |
} |
@@ -1999,6 +2037,7 @@ void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
__ Bind(&stepping); |
__ EnterStubFrame(); |
__ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
+ __ RestoreCodePointer(); |
__ LeaveStubFrame(); |
__ b(&done_stepping); |
} |
@@ -2058,6 +2097,7 @@ void StubCode::EmitMegamorphicLookup( |
// be invoked as a normal Dart function. |
__ add(IP, R2, Operand(R3, LSL, 2)); |
__ ldr(R0, FieldAddress(IP, base + kWordSize)); |
+ __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
__ ldr(target, FieldAddress(R0, Function::entry_point_offset())); |
} |