Split nterp frame alignment.
Make sure the dex PC pointer and caller FP are stored at
a pointer-aligned address.
Test: testrunner.py --host --interpreter
Change-Id: I7fe1be01b46558d871db24ce6cc08e35b68ec3fa
diff --git a/runtime/interpreter/mterp/x86_64ng/main.S b/runtime/interpreter/mterp/x86_64ng/main.S
index aeacec4..a890245 100644
--- a/runtime/interpreter/mterp/x86_64ng/main.S
+++ b/runtime/interpreter/mterp/x86_64ng/main.S
@@ -288,10 +288,13 @@
leaq -24(%rsp), %r10
subq %r11, %r10
// Alignment
+ // Note: There may be two pieces of alignment but there is no need to align
+ // out args to `kPointerSize` separately before aligning to kStackAlignment.
andq $$-16, %r10
- // Set reference and dex registers.
- leaq 24(%r10, \refs, 4), \refs
+ // Set reference and dex registers, align to pointer size for previous frame and dex pc.
+ leaq 24 + 4(%r10, \refs, 4), \refs
+ andq LITERAL(-__SIZEOF_POINTER__), \refs
leaq (\refs, %rbx, 4), \fp
// Now setup the stack pointer.
diff --git a/runtime/nterp_helpers.cc b/runtime/nterp_helpers.cc
index a2ec882..d622241 100644
--- a/runtime/nterp_helpers.cc
+++ b/runtime/nterp_helpers.cc
@@ -59,6 +59,8 @@
* ---------------- registers array for easy access from nterp when returning.
* | dex_pc_ptr | Pointer to the dex instruction being executed.
* ---------------- Stored whenever nterp goes into the runtime.
+ * | alignment | Pointer aligment for dex_pc_ptr and caller_fp.
+ * ----------------
* | | In case nterp calls compiled code, we reserve space
* | out | for out registers. This space will be used for
* | registers | arguments passed on stack.
@@ -97,6 +99,11 @@
const uint16_t num_regs = accessor.RegistersSize();
const uint16_t out_regs = accessor.OutsSize();
+ // Note: There may be two pieces of alignment but there is no need to align
+ // out args to `kPointerSize` separately before aligning to kStackAlignment.
+ static_assert(IsAligned<kPointerSize>(kStackAlignment));
+ static_assert(IsAligned<kPointerSize>(NterpGetFrameEntrySize()));
+ static_assert(IsAligned<kPointerSize>(kVRegSize * 2));
size_t frame_size =
NterpGetFrameEntrySize() +
(num_regs * kVRegSize) * 2 + // dex registers and reference registers
@@ -128,7 +135,7 @@
// The references array is just above the saved frame pointer.
return reinterpret_cast<uintptr_t>(frame) +
kPointerSize + // method
- (out_regs * kVRegSize) + // out arguments
+ RoundUp(out_regs * kVRegSize, kPointerSize) + // out arguments and pointer alignment
kPointerSize + // saved dex pc
kPointerSize; // previous frame.
}
@@ -138,7 +145,7 @@
const uint16_t out_regs = accessor.OutsSize();
uintptr_t dex_pc_ptr = reinterpret_cast<uintptr_t>(frame) +
kPointerSize + // method
- (out_regs * kVRegSize); // out arguments
+ RoundUp(out_regs * kVRegSize, kPointerSize); // out arguments and pointer alignment
CodeItemInstructionAccessor instructions((*frame)->DexInstructions());
return *reinterpret_cast<const uint16_t**>(dex_pc_ptr) - instructions.Insns();
}