| Index: runtime/vm/stub_code_arm.cc
|
| ===================================================================
|
| --- runtime/vm/stub_code_arm.cc (revision 21886)
|
| +++ runtime/vm/stub_code_arm.cc (working copy)
|
| @@ -198,6 +198,8 @@
|
| // Input parameters:
|
| // R4: arguments descriptor array.
|
| void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
|
| + // Create a stub frame as we are pushing some objects on the stack before
|
| + // calling into the runtime.
|
| __ EnterStubFrame();
|
| // Setup space on stack for return value and preserve arguments descriptor.
|
| __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
|
| @@ -205,17 +207,34 @@
|
| __ CallRuntime(kPatchStaticCallRuntimeEntry);
|
| // Get Code object result and restore arguments descriptor array.
|
| __ PopList((1 << R0) | (1 << R4));
|
| - // Remove the stub frame as we are about to jump to the dart function.
|
| + // Remove the stub frame.
|
| __ LeaveStubFrame();
|
| -
|
| + // Jump to the dart function.
|
| __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
|
| __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
|
| __ bx(R0);
|
| }
|
|
|
|
|
| +// Called from a static call only when an invalid code has been entered
|
| +// (invalid because its function was optimized or deoptimized).
|
| +// R4: arguments descriptor array.
|
| void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
|
| - __ Unimplemented("FixCallersTarget stub");
|
| + // Create a stub frame as we are pushing some objects on the stack before
|
| + // calling into the runtime.
|
| + __ EnterStubFrame();
|
| + // Setup space on stack for return value and preserve arguments descriptor.
|
| + __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
|
| + __ PushList((1 << R0) | (1 << R4));
|
| + __ CallRuntime(kFixCallersTargetRuntimeEntry);
|
| + // Get Code object result and restore arguments descriptor array.
|
| + __ PopList((1 << R0) | (1 << R4));
|
| + // Remove the stub frame.
|
| + __ LeaveStubFrame();
|
| + // Jump to the dart function.
|
| + __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
|
| + __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
|
| + __ bx(R0);
|
| }
|
|
|
|
|
| @@ -1385,18 +1404,66 @@
|
| }
|
|
|
|
|
| +// LR: return address (Dart code).
|
| +// R4: Arguments descriptor array.
|
| void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
|
| - __ Unimplemented("BreakpointStatic stub");
|
| + // Create a stub frame as we are pushing some objects on the stack before
|
| + // calling into the runtime.
|
| + __ EnterStubFrame();
|
| + __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
|
| + // // Preserve arguments descriptor and make room for result.
|
| + __ PushList((1 << R0) | (1 << R4));
|
| + __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
|
| + // Pop code object result and restore arguments descriptor.
|
| + __ PopList((1 << R0) | (1 << R4));
|
| + __ LeaveStubFrame();
|
| +
|
| + // Now call the static function. The breakpoint handler function
|
| + // ensures that the call target is compiled.
|
| + __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
|
| + __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag);
|
| + __ bx(R0);
|
| }
|
|
|
|
|
| +// R0: return value.
|
| void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) {
|
| - __ Unimplemented("BreakpointReturn stub");
|
| + // Create a stub frame as we are pushing some objects on the stack before
|
| + // calling into the runtime.
|
| + __ EnterStubFrame();
|
| + __ Push(R0);
|
| + __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry);
|
| + __ Pop(R0);
|
| + __ LeaveStubFrame();
|
| +
|
| + // Instead of returning to the patched Dart function, emulate the
|
| + // smashed return code pattern and return to the function's caller.
|
| + __ LeaveDartFrame();
|
| + __ Ret();
|
| }
|
|
|
|
|
| +// LR: return address (Dart code).
|
| +// R5: Inline cache data array.
|
| +// R4: Arguments descriptor array.
|
| void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
|
| - __ Unimplemented("BreakpointDynamic stub");
|
| + // Create a stub frame as we are pushing some objects on the stack before
|
| + // calling into the runtime.
|
| + __ EnterStubFrame();
|
| + __ PushList((1 << R4) | (1 << R5));
|
| + __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry);
|
| + __ PopList((1 << R4) | (1 << R5));
|
| + __ LeaveStubFrame();
|
| +
|
| + // Find out which dispatch stub to call.
|
| + __ ldr(IP, FieldAddress(R5, ICData::num_args_tested_offset()));
|
| + __ cmp(IP, ShifterOperand(1));
|
| + __ Branch(&StubCode::OneArgCheckInlineCacheLabel(), EQ);
|
| + __ cmp(IP, ShifterOperand(2));
|
| + __ Branch(&StubCode::TwoArgsCheckInlineCacheLabel(), EQ);
|
| + __ cmp(IP, ShifterOperand(3));
|
| + __ Branch(&StubCode::ThreeArgsCheckInlineCacheLabel(), EQ);
|
| + __ Stop("Unsupported number of arguments tested.");
|
| }
|
|
|
|
|
|
|