[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>
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index bf1f12f..397c4e9 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3007,8 +3007,8 @@
}
}
-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 @@
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);
}
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 90d554c..6669caa 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -1010,7 +1010,7 @@
// 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 @@
// 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
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 54d7abd..733efaf 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -138,8 +138,7 @@
__ 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);
diff --git a/runtime/vm/object_arm_test.cc b/runtime/vm/object_arm_test.cc
index 4bebaef..5f9f3d7 100644
--- a/runtime/vm/object_arm_test.cc
+++ b/runtime/vm/object_arm_test.cc
@@ -36,8 +36,7 @@
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.
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index e717208..a006d7a 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -46,8 +46,7 @@
__ 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 @@
__ 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) {