Merge "ART: Fix Quick-style LR vs PC core spill mask bug"
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index eb8730c..868d9a4 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -547,27 +547,28 @@
cfi_.RestoreMany(DwarfFpReg(0), fp_spill_mask_);
}
bool unspill_LR_to_PC = (core_spill_mask_ & (1 << rs_rARM_LR.GetRegNum())) != 0;
+ uint32_t core_unspill_mask = core_spill_mask_;
if (unspill_LR_to_PC) {
- core_spill_mask_ &= ~(1 << rs_rARM_LR.GetRegNum());
- core_spill_mask_ |= (1 << rs_rARM_PC.GetRegNum());
+ core_unspill_mask &= ~(1 << rs_rARM_LR.GetRegNum());
+ core_unspill_mask |= (1 << rs_rARM_PC.GetRegNum());
}
- if (core_spill_mask_ != 0u) {
- if ((core_spill_mask_ & ~(0xffu | (1u << rs_rARM_PC.GetRegNum()))) == 0u) {
+ if (core_unspill_mask != 0u) {
+ if ((core_unspill_mask & ~(0xffu | (1u << rs_rARM_PC.GetRegNum()))) == 0u) {
// Unspilling only low regs and/or PC, use 16-bit POP.
constexpr int pc_bit_shift = rs_rARM_PC.GetRegNum() - 8;
NewLIR1(kThumbPop,
- (core_spill_mask_ & ~(1u << rs_rARM_PC.GetRegNum())) |
- ((core_spill_mask_ & (1u << rs_rARM_PC.GetRegNum())) >> pc_bit_shift));
- } else if (IsPowerOfTwo(core_spill_mask_)) {
+ (core_unspill_mask & ~(1u << rs_rARM_PC.GetRegNum())) |
+ ((core_unspill_mask & (1u << rs_rARM_PC.GetRegNum())) >> pc_bit_shift));
+ } else if (IsPowerOfTwo(core_unspill_mask)) {
// kThumb2Pop cannot be used to unspill a single register.
- NewLIR1(kThumb2Pop1, CTZ(core_spill_mask_));
+ NewLIR1(kThumb2Pop1, CTZ(core_unspill_mask));
} else {
- NewLIR1(kThumb2Pop, core_spill_mask_);
+ NewLIR1(kThumb2Pop, core_unspill_mask);
}
// If we pop to PC, there is no further epilogue code.
if (!unspill_LR_to_PC) {
cfi_.AdjustCFAOffset(-num_core_spills_ * kArmPointerSize);
- cfi_.RestoreMany(DwarfCoreReg(0), core_spill_mask_);
+ cfi_.RestoreMany(DwarfCoreReg(0), core_unspill_mask);
DCHECK_EQ(cfi_.GetCurrentCFAOffset(), 0); // empty stack.
}
}
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 438ef69..a4c58b0 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -48,7 +48,7 @@
// with baseline.
static constexpr Register kCoreSavedRegisterForBaseline = R5;
static constexpr Register kCoreCalleeSaves[] =
- { R5, R6, R7, R8, R10, R11, PC };
+ { R5, R6, R7, R8, R10, R11, LR };
static constexpr SRegister kFpuCalleeSaves[] =
{ S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31 };
@@ -409,8 +409,8 @@
method_patches_(MethodReferenceComparator(), graph->GetArena()->Adapter()),
call_patches_(MethodReferenceComparator(), graph->GetArena()->Adapter()),
relative_call_patches_(graph->GetArena()->Adapter()) {
- // Save the PC register to mimic Quick.
- AddAllocatedRegister(Location::RegisterLocation(PC));
+ // Always save the LR register to mimic Quick.
+ AddAllocatedRegister(Location::RegisterLocation(LR));
}
void CodeGeneratorARM::Finalize(CodeAllocator* allocator) {
@@ -599,12 +599,9 @@
RecordPcInfo(nullptr, 0);
}
- // PC is in the list of callee-save to mimic Quick, but we need to push
- // LR at entry instead.
- uint32_t push_mask = (core_spill_mask_ & (~(1 << PC))) | 1 << LR;
- __ PushList(push_mask);
- __ cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(push_mask));
- __ cfi().RelOffsetForMany(DWARFReg(kMethodRegisterArgument), 0, push_mask, kArmWordSize);
+ __ PushList(core_spill_mask_);
+ __ cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(core_spill_mask_));
+ __ cfi().RelOffsetForMany(DWARFReg(kMethodRegisterArgument), 0, core_spill_mask_, kArmWordSize);
if (fpu_spill_mask_ != 0) {
SRegister start_register = SRegister(LeastSignificantBit(fpu_spill_mask_));
__ vpushs(start_register, POPCOUNT(fpu_spill_mask_));
@@ -632,7 +629,10 @@
__ cfi().AdjustCFAOffset(-kArmPointerSize * POPCOUNT(fpu_spill_mask_));
__ cfi().RestoreMany(DWARFReg(SRegister(0)), fpu_spill_mask_);
}
- __ PopList(core_spill_mask_);
+ // Pop LR into PC to return.
+ DCHECK_NE(core_spill_mask_ & (1 << LR), 0U);
+ uint32_t pop_mask = (core_spill_mask_ & (~(1 << LR))) | 1 << PC;
+ __ PopList(pop_mask);
__ cfi().RestoreState();
__ cfi().DefCFAOffset(GetFrameSize());
}
diff --git a/runtime/oat.h b/runtime/oat.h
index 1520a9b..b8b8d30 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- static constexpr uint8_t kOatVersion[] = { '0', '6', '9', '\0' };
+ static constexpr uint8_t kOatVersion[] = { '0', '7', '0', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";