[VM] Use one instruction to unwind frame and return instead of two on ARM

This reduces AOT flutter gallery RX size by 0.81 %.

Issue https://github.com/dart-lang/sdk/issues/33274

Change-Id: I1a3c3f48af9ae5d89d3d89da1d86c798145dbd99
Reviewed-on: https://dart-review.googlesource.com/72383
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Martin Kustermann 2018-08-31 12:23:54 +00:00 committed by commit-bot@chromium.org
parent ffdcc72678
commit c5295037c4
5 changed files with 37 additions and 18 deletions

View file

@ -3007,8 +3007,8 @@ void Assembler::EnterFrame(RegList regs, intptr_t frame_size) {
}
}
void Assembler::LeaveFrame(RegList regs) {
ASSERT((regs & (1 << PC)) == 0); // Must not pop PC.
void Assembler::LeaveFrame(RegList regs, bool allow_pop_pc) {
ASSERT(allow_pop_pc || (regs & (1 << PC)) == 0); // Must not pop PC.
if ((regs & (1 << FP)) != 0) {
// Use FP to set SP.
sub(SP, FP, Operand(4 * NumRegsBelowFP(regs)));
@ -3122,18 +3122,26 @@ void Assembler::EnterOsrFrame(intptr_t extra_size) {
AddImmediate(SP, -extra_size);
}
void Assembler::LeaveDartFrame(RestorePP restore_pp) {
if (restore_pp == kRestoreCallerPP) {
ldr(PP,
Address(FP, compiler_frame_layout.saved_caller_pp_from_fp * kWordSize));
set_constant_pool_allowed(false);
}
void Assembler::LeaveDartFrame() {
ldr(PP,
Address(FP, compiler_frame_layout.saved_caller_pp_from_fp * kWordSize));
set_constant_pool_allowed(false);
// This will implicitly drop saved PP, PC marker due to restoring SP from FP
// first.
LeaveFrame((1 << FP) | (1 << LR));
}
void Assembler::LeaveDartFrameAndReturn() {
ldr(PP,
Address(FP, compiler_frame_layout.saved_caller_pp_from_fp * kWordSize));
set_constant_pool_allowed(false);
// This will implicitly drop saved PP, PC marker due to restoring SP from FP
// first.
LeaveFrame((1 << FP) | (1 << PC), /*allow_pop_pc=*/true);
}
void Assembler::EnterStubFrame() {
EnterDartFrame(0);
}

View file

@ -1010,7 +1010,7 @@ class Assembler : public ValueObject {
// Function frame setup and tear down.
void EnterFrame(RegList regs, intptr_t frame_space);
void LeaveFrame(RegList regs);
void LeaveFrame(RegList regs, bool allow_pop_pc = false);
void Ret();
void ReserveAlignedFrameSpace(intptr_t frame_space);
@ -1026,7 +1026,22 @@ class Assembler : public ValueObject {
// enable easy access to the RawInstruction object of code corresponding
// to this frame.
void EnterDartFrame(intptr_t frame_size);
void LeaveDartFrame(RestorePP restore_pp = kRestoreCallerPP);
void LeaveDartFrame();
// Leaves the frame and returns.
//
// The difference to "LeaveDartFrame(); Ret();" is that we return using
//
// ldmia sp!, {fp, pc}
//
// instead of
//
// ldmia sp!, {fp, lr}
// blx lr
//
// This means that our return must go to ARM mode (and not thumb).
void LeaveDartFrameAndReturn();
// 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

View file

@ -138,8 +138,7 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ Bind(&stack_ok);
#endif
ASSERT(__ constant_pool_allowed());
__ LeaveDartFrame(); // Disallows constant pool use.
__ Ret();
__ LeaveDartFrameAndReturn(); // Disallows constant pool use.
// This ReturnInstr may be emitted out of order by the optimizer. The next
// block may be a target expecting a properly set constant pool pointer.
__ set_constant_pool_allowed(true);

View file

@ -36,8 +36,7 @@ void GenerateEmbedStringInCode(Assembler* assembler, const char* str) {
const String& string_object =
String::ZoneHandle(String::New(str, Heap::kOld));
__ LoadObject(R0, string_object);
__ LeaveDartFrame();
__ Ret();
__ LeaveDartFrameAndReturn();
}
// Generate a dart code sequence that embeds a smi object in it.

View file

@ -46,8 +46,7 @@ static void GenerateCallToCallRuntimeStub(Assembler* assembler, int length) {
__ CallRuntime(kAllocateArrayRuntimeEntry, argc);
__ AddImmediate(SP, argc * kWordSize);
__ Pop(R0); // Pop return value from return slot.
__ LeaveDartFrame();
__ Ret();
__ LeaveDartFrameAndReturn();
}
TEST_CASE(CallRuntimeStubCode) {
@ -83,8 +82,7 @@ static void GenerateCallToCallLeafRuntimeStub(Assembler* assembler,
__ LoadObject(R2, rhs_index);
__ LoadObject(R3, length);
__ CallRuntime(kCaseInsensitiveCompareUC16RuntimeEntry, 4);
__ LeaveDartFrame();
__ Ret(); // Return value is in R0.
__ LeaveDartFrameAndReturn(); // Return value is in R0.
}
TEST_CASE(CallLeafRuntimeStubCode) {