From e13eafa28bd58cb31e7a150c44d37aafa1ae1f61 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Fri, 7 Sep 2012 11:24:27 -0700 Subject: Support for 32bit CAS as an intrinsic. Change-Id: Ib7f345a8c54a518c7ce5c0765287417bec5a9ef1 --- src/compiler/codegen/GenInvoke.cc | 97 +++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 15 deletions(-) (limited to 'src/compiler/codegen/GenInvoke.cc') diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc index 29bd2a6c6d..7190a8b519 100644 --- a/src/compiler/codegen/GenInvoke.cc +++ b/src/compiler/codegen/GenInvoke.cc @@ -915,9 +915,70 @@ bool genInlinedStringCompareTo(CompilationUnit* cUnit, CallInfo* info) #endif } +bool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) { +#if defined(TARGET_ARM) + // Unused - RegLocation rlSrcUnsafe = info->args[0]; + RegLocation rlSrcObj= info->args[1]; // Object - known non-null + RegLocation rlSrcOffset= info->args[2]; // long low + rlSrcOffset.wide = 0; // ignore high half in info->args[3] + RegLocation rlSrcExpected= info->args[4]; // int or Object + RegLocation rlSrcNewValue= info->args[5]; // int or Object + RegLocation rlDest = inlineTarget(cUnit, info); // boolean place for result + + + // Release store semantics, get the barrier out of the way. + oatGenMemBarrier(cUnit, kSY); + + RegLocation rlObject = loadValue(cUnit, rlSrcObj, kCoreReg); + RegLocation rlNewValue = loadValue(cUnit, rlSrcNewValue, kCoreReg); + + if (need_write_barrier) { + // Mark card for object assuming new value is stored. + markGCCard(cUnit, rlNewValue.lowReg, rlObject.lowReg); + } + + RegLocation rlOffset = loadValue(cUnit, rlSrcOffset, kCoreReg); + + int rPtr = oatAllocTemp(cUnit); + opRegRegReg(cUnit, kOpAdd, rPtr, rlObject.lowReg, rlOffset.lowReg); + + // Free now unneeded rlObject and rlOffset to give more temps. + oatClobberSReg(cUnit, rlObject.sRegLow); + oatFreeTemp(cUnit, rlObject.lowReg); + oatClobberSReg(cUnit, rlOffset.sRegLow); + oatFreeTemp(cUnit, rlOffset.lowReg); + + int rOldValue = oatAllocTemp(cUnit); + newLIR3(cUnit, kThumb2Ldrex, rOldValue, rPtr, 0); // rOldValue := [rPtr] + + RegLocation rlExpected = loadValue(cUnit, rlSrcExpected, kCoreReg); + + // if (rOldValue == rExpected) { + // [rPtr] <- rNewValue && rResult := success ? 0 : 1 + // rResult ^= 1 + // } else { + // rResult := 0 + // } + opRegReg(cUnit, kOpCmp, rOldValue, rlExpected.lowReg); + oatFreeTemp(cUnit, rOldValue); // Now unneeded. + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + opIT(cUnit, kArmCondEq, "TE"); + newLIR4(cUnit, kThumb2Strex, rlResult.lowReg, rlNewValue.lowReg, rPtr, 0); + oatFreeTemp(cUnit, rPtr); // Now unneeded. + opRegImm(cUnit, kOpXor, rlResult.lowReg, 1); + opRegReg(cUnit, kOpXor, rlResult.lowReg, rlResult.lowReg); + + storeValue(cUnit, rlDest, rlResult); + + return true; +#else + return false; +#endif +} + bool genIntrinsic(CompilationUnit* cUnit, CallInfo* info) { - if ((info->optFlags & MIR_INLINED) || info->isRange) { + if (info->optFlags & MIR_INLINED) { return false; } /* @@ -931,48 +992,54 @@ bool genIntrinsic(CompilationUnit* cUnit, CallInfo* info) * take advantage of/generate new useful dataflow info. */ std::string tgtMethod(PrettyMethod(info->index, *cUnit->dex_file)); - if (tgtMethod.compare("char java.lang.String.charAt(int)") == 0) { + if (tgtMethod == "char java.lang.String.charAt(int)") { return genInlinedCharAt(cUnit, info); } - if (tgtMethod.compare("int java.lang.Math.min(int, int)") == 0) { + if (tgtMethod == "int java.lang.Math.min(int, int)") { return genInlinedMinMaxInt(cUnit, info, true /* isMin */); } - if (tgtMethod.compare("int java.lang.Math.max(int, int)") == 0) { + if (tgtMethod == "int java.lang.Math.max(int, int)") { return genInlinedMinMaxInt(cUnit, info, false /* isMin */); } - if (tgtMethod.compare("int java.lang.String.length()") == 0) { + if (tgtMethod == "int java.lang.String.length()") { return genInlinedStringIsEmptyOrLength(cUnit, info, false /* isEmpty */); } - if (tgtMethod.compare("boolean java.lang.String.isEmpty()") == 0) { + if (tgtMethod == "boolean java.lang.String.isEmpty()") { return genInlinedStringIsEmptyOrLength(cUnit, info, true /* isEmpty */); } - if (tgtMethod.compare("int java.lang.Math.abs(int)") == 0) { + if (tgtMethod == "int java.lang.Math.abs(int)") { return genInlinedAbsInt(cUnit, info); } - if (tgtMethod.compare("long java.lang.Math.abs(long)") == 0) { + if (tgtMethod == "long java.lang.Math.abs(long)") { return genInlinedAbsLong(cUnit, info); } - if (tgtMethod.compare("int java.lang.Float.floatToRawIntBits(float)") == 0) { + if (tgtMethod == "int java.lang.Float.floatToRawIntBits(float)") { return genInlinedFloatCvt(cUnit, info); } - if (tgtMethod.compare("float java.lang.Float.intBitsToFloat(int)") == 0) { + if (tgtMethod == "float java.lang.Float.intBitsToFloat(int)") { return genInlinedFloatCvt(cUnit, info); } - if (tgtMethod.compare("long java.lang.Double.doubleToRawLongBits(double)") == 0) { + if (tgtMethod == "long java.lang.Double.doubleToRawLongBits(double)") { return genInlinedDoubleCvt(cUnit, info); } - if (tgtMethod.compare("double java.lang.Double.longBitsToDouble(long)") == 0) { + if (tgtMethod == "double java.lang.Double.longBitsToDouble(long)") { return genInlinedDoubleCvt(cUnit, info); } - if (tgtMethod.compare("int java.lang.String.indexOf(int, int)") == 0) { + if (tgtMethod == "int java.lang.String.indexOf(int, int)") { return genInlinedIndexOf(cUnit, info, false /* base 0 */); } - if (tgtMethod.compare("int java.lang.String.indexOf(int)") == 0) { + if (tgtMethod == "int java.lang.String.indexOf(int)") { return genInlinedIndexOf(cUnit, info, true /* base 0 */); } - if (tgtMethod.compare("int java.lang.String.compareTo(java.lang.String)") == 0) { + if (tgtMethod == "int java.lang.String.compareTo(java.lang.String)") { return genInlinedStringCompareTo(cUnit, info); } + if (tgtMethod == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") { + return genInlinedCas32(cUnit, info, false); + } + if (tgtMethod == "boolean sun.misc.Unsafe.compareAndSwapObject(java.lang.Object, long, java.lang.Object, java.lang.Object)") { + return genInlinedCas32(cUnit, info, true); + } return false; } -- cgit v1.2.3-59-g8ed1b