From d3a2dfad0e1231b354e4bf77b67a4e179fa0e837 Mon Sep 17 00:00:00 2001 From: Yevgeny Rouban Date: Tue, 18 Mar 2014 15:55:16 +0700 Subject: [PATCH] Reuse promoted register temporarily AtomicLong (x86) is implemented as an intrinsic, which uses the cmpxchng8b instruction. This instruction requires 4 physical registers plus 2 more used for the memory operand. On x86 we have only 4 temporaries. The code tried to solve this by using MarkTemp utility, but this was not meant to be used with promoted registers. The problem is that MarkTemp does not spill anything and as a result we can lose VR. If the registers are promoted this patch just reuses the values pushed on the stack. Change-Id: Ifec9183e2483cf704d0d1166a1004a9aa07b4f1d Signed-off-by: Serguei Katkov Signed-off-by: Yevgeny Rouban --- compiler/dex/quick/x86/int_x86.cc | 16 ++++++++++++++-- test/083-compiler-regressions/expected.txt | 1 + test/083-compiler-regressions/src/Main.java | 13 +++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 1fe0af9a3..c92926566 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -734,6 +734,10 @@ void X86Mir2Lir::OpTlsCmp(ThreadOffset offset, int val) { NewLIR2(kX86Cmp16TI8, offset.Int32Value(), val); } +static bool IsInReg(X86Mir2Lir *pMir2Lir, const RegLocation &rl, int reg) { + return !rl.reg.IsInvalid() && rl.reg.GetReg() == reg && (pMir2Lir->IsLive(reg) || rl.home); +} + bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) { DCHECK_EQ(cu_->instruction_set, kX86); // Unused - RegLocation rl_src_unsafe = info->args[0]; @@ -746,6 +750,8 @@ bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) { // If is_long, high half is in info->args[7] if (is_long) { + // TODO: avoid unnecessary loads of SI and DI when the values are in registers. + // TODO: CFI support. FlushAllRegs(); LockCallTemps(); LoadValueDirectWideFixed(rl_src_expected, rAX, rDX); @@ -757,8 +763,14 @@ bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) { MarkTemp(rSI); LockTemp(rSI); const int push_offset = 4 /* push edi */ + 4 /* push esi */; - LoadWordDisp(TargetReg(kSp), SRegOffset(rl_src_obj.s_reg_low) + push_offset, rDI); - LoadWordDisp(TargetReg(kSp), SRegOffset(rl_src_offset.s_reg_low) + push_offset, rSI); + int srcObjSp = IsInReg(this, rl_src_obj, rSI) ? 0 + : (IsInReg(this, rl_src_obj, rDI) ? 4 + : (SRegOffset(rl_src_obj.s_reg_low) + push_offset)); + LoadWordDisp(TargetReg(kSp), srcObjSp, rDI); + int srcOffsetSp = IsInReg(this, rl_src_offset, rSI) ? 0 + : (IsInReg(this, rl_src_offset, rDI) ? 4 + : (SRegOffset(rl_src_offset.s_reg_low) + push_offset)); + LoadWordDisp(TargetReg(kSp), srcOffsetSp, rSI); NewLIR4(kX86LockCmpxchg8bA, rDI, rSI, 0, 0); FreeTemp(rSI); UnmarkTemp(rSI); diff --git a/test/083-compiler-regressions/expected.txt b/test/083-compiler-regressions/expected.txt index 90d863466..f6de0e77d 100644 --- a/test/083-compiler-regressions/expected.txt +++ b/test/083-compiler-regressions/expected.txt @@ -16,3 +16,4 @@ longDivTest passes longModTest passes testIfCcz passes ManyFloatArgs passes +atomicLong passes diff --git a/test/083-compiler-regressions/src/Main.java b/test/083-compiler-regressions/src/Main.java index 96c71cf0a..2745c27b8 100644 --- a/test/083-compiler-regressions/src/Main.java +++ b/test/083-compiler-regressions/src/Main.java @@ -15,6 +15,7 @@ */ import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicLong; /** * Test for Jit regressions. @@ -47,6 +48,18 @@ public class Main { ZeroTests.longModTest(); MirOpSelectTests.testIfCcz(); ManyFloatArgs(); + atomicLong(); + } + + public static void atomicLong() { + AtomicLong atomicLong = new AtomicLong(); + atomicLong.addAndGet(3); + atomicLong.addAndGet(2); + atomicLong.addAndGet(1); + long result = atomicLong.get(); + System.out.println(result == 6L ? "atomicLong passes" : + ("atomicLong failes: returns " + result + ", expected 6") + ); } public static void returnConstantTest() { -- 2.11.0