diff options
| author | 2013-12-02 02:16:38 -0800 | |
|---|---|---|
| committer | 2013-12-02 02:16:38 -0800 | |
| commit | 2ad27aa8ab07e28e18d4facf9c2912b8226a154a (patch) | |
| tree | 98f9c11a928ce6e67c611bc6678279676aa9a25e | |
| parent | c1bb50e7e6de1e4185d16dcf0d32645fdf7db272 (diff) | |
| parent | 7ceee468756c8ba05fd8b6e82e98856a6d74bf51 (diff) | |
am 7ceee468: Merge "Unsafe.compareAndSwapInt()/Object() intrinsics for x86."
* commit '7ceee468756c8ba05fd8b6e82e98856a6d74bf51':
Unsafe.compareAndSwapInt()/Object() intrinsics for x86.
| -rw-r--r-- | compiler/dex/quick/x86/assemble_x86.cc | 1 | ||||
| -rw-r--r-- | compiler/dex/quick/x86/int_x86.cc | 46 | ||||
| -rw-r--r-- | compiler/dex/quick/x86/x86_dex_file_method_inliner.cc | 8 | ||||
| -rw-r--r-- | compiler/dex/quick/x86/x86_lir.h | 2 |
4 files changed, 49 insertions, 8 deletions
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc index 191c9c701b..1bf79cc46c 100644 --- a/compiler/dex/quick/x86/assemble_x86.cc +++ b/compiler/dex/quick/x86/assemble_x86.cc @@ -306,7 +306,6 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, { kX86CmpxchgRR, kRegRegStore, IS_BINARY_OP | REG_DEF0 | REG_USE01 | REG_DEFA_USEA | SETS_CCODES, { 0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Cmpxchg", "!0r,!1r" }, { kX86CmpxchgMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02 | REG_DEFA_USEA | SETS_CCODES, { 0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Cmpxchg", "[!0r+!1d],!2r" }, { kX86CmpxchgAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014 | REG_DEFA_USEA | SETS_CCODES, { 0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Cmpxchg", "[!0r+!1r<<!2d+!3d],!4r" }, - { kX86LockCmpxchgRR, kRegRegStore, IS_BINARY_OP | REG_DEF0 | REG_USE01 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "!0r,!1r" }, { kX86LockCmpxchgMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "[!0r+!1d],!2r" }, { kX86LockCmpxchgAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "[!0r+!1r<<!2d+!3d],!4r" }, diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 01d5c1770d..b65fe549c9 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -282,8 +282,50 @@ void X86Mir2Lir::OpTlsCmp(ThreadOffset offset, int val) { } bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) { - DCHECK_NE(cu_->instruction_set, kThumb2); - return false; + DCHECK_EQ(cu_->instruction_set, kX86); + // Unused - RegLocation rl_src_unsafe = info->args[0]; + RegLocation rl_src_obj = info->args[1]; // Object - known non-null + RegLocation rl_src_offset = info->args[2]; // long low + rl_src_offset.wide = 0; // ignore high half in info->args[3] + RegLocation rl_src_expected = info->args[4]; // int, long or Object + // If is_long, high half is in info->args[5] + RegLocation rl_src_new_value = info->args[is_long ? 6 : 5]; // int, long or Object + // If is_long, high half is in info->args[7] + + if (is_long) { + LOG(FATAL) << "CAS64: Not implemented"; + } else { + // EAX must hold expected for CMPXCHG. Neither rl_new_value, nor r_ptr may be in EAX. + FlushReg(r0); + LockTemp(r0); + + // Release store semantics, get the barrier out of the way. TODO: revisit + GenMemBarrier(kStoreLoad); + + RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg); + RegLocation rl_new_value = LoadValue(rl_src_new_value, kCoreReg); + + if (is_object && !mir_graph_->IsConstantNullRef(rl_new_value)) { + // Mark card for object assuming new value is stored. + FreeTemp(r0); // Temporarily release EAX for MarkGCCard(). + MarkGCCard(rl_new_value.low_reg, rl_object.low_reg); + LockTemp(r0); + } + + RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg); + LoadValueDirect(rl_src_expected, r0); + NewLIR5(kX86LockCmpxchgAR, rl_object.low_reg, rl_offset.low_reg, 0, 0, rl_new_value.low_reg); + + FreeTemp(r0); + } + + // Convert ZF to boolean + RegLocation rl_dest = InlineTarget(info); // boolean place for result + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + NewLIR2(kX86Set8R, rl_result.low_reg, kX86CondZ); + NewLIR2(kX86Movzx8RR, rl_result.low_reg, rl_result.low_reg); + StoreValue(rl_dest, rl_result); + return true; } LIR* X86Mir2Lir::OpPcRelLoad(int reg, LIR* target) { diff --git a/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc b/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc index b788c3ce05..f0e76c9e5e 100644 --- a/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc +++ b/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc @@ -64,12 +64,12 @@ const DexFileMethodInliner::IntrinsicDef X86DexFileMethodInliner::kIntrinsicMeth INTRINSIC(LibcoreIoMemory, PokeLongNative, JJ_V, kIntrinsicPoke, kLong), INTRINSIC(LibcoreIoMemory, PokeShortNative, JS_V, kIntrinsicPoke, kSignedHalf), - // INTRINSIC(SunMiscUnsafe, CompareAndSwapInt, ObjectJII_Z, kIntrinsicCas, - // kIntrinsicFlagNone), + INTRINSIC(SunMiscUnsafe, CompareAndSwapInt, ObjectJII_Z, kIntrinsicCas, + kIntrinsicFlagNone), // INTRINSIC(SunMiscUnsafe, CompareAndSwapLong, ObjectJJJ_Z, kIntrinsicCas, // kIntrinsicFlagIsLong), - // INTRINSIC(SunMiscUnsafe, CompareAndSwapObject, ObjectJObjectObject_Z, kIntrinsicCas, - // kIntrinsicFlagIsObject), + INTRINSIC(SunMiscUnsafe, CompareAndSwapObject, ObjectJObjectObject_Z, kIntrinsicCas, + kIntrinsicFlagIsObject), #define UNSAFE_GET_PUT(type, code, type_flags) \ INTRINSIC(SunMiscUnsafe, Get ## type, ObjectJ_ ## code, kIntrinsicUnsafeGet, \ diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h index 3518131cfe..bbcae92f7d 100644 --- a/compiler/dex/quick/x86/x86_lir.h +++ b/compiler/dex/quick/x86/x86_lir.h @@ -354,7 +354,7 @@ enum X86OpCode { Binary0fOpCode(kX86Imul16), // 16bit multiply Binary0fOpCode(kX86Imul32), // 32bit multiply kX86CmpxchgRR, kX86CmpxchgMR, kX86CmpxchgAR, // compare and exchange - kX86LockCmpxchgRR, kX86LockCmpxchgMR, kX86LockCmpxchgAR, // locked compare and exchange + kX86LockCmpxchgMR, kX86LockCmpxchgAR, // locked compare and exchange Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value |