[Compiler] use Art indentation standard
First of several CLs to bring code closer to alignment with Art and LLVM
standards. Move to 2-space indenting. Sticking with 80-col line
length (which LLVM apparently also wants). LLVM also prefers camel
case names, so keeping Dalvik convention there as well (for now).
Change-Id: I351ab234e640678d97747377cccdd6df0a770f4a
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index b986e78..6d3c240 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -36,97 +36,97 @@
*/
void flushIns(CompilationUnit* cUnit)
{
- /*
- * Dummy up a RegLocation for the incoming Method*
- * It will attempt to keep rARG0 live (or copy it to home location
- * if promoted).
- */
- RegLocation rlSrc = cUnit->regLocation[cUnit->methodSReg];
- RegLocation rlMethod = cUnit->regLocation[cUnit->methodSReg];
- rlSrc.location = kLocPhysReg;
- rlSrc.lowReg = rARG0;
- rlSrc.home = false;
- oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
- storeValue(cUnit, rlMethod, rlSrc);
- // If Method* has been promoted, explicitly flush
- if (rlMethod.location == kLocPhysReg) {
- storeWordDisp(cUnit, rSP, 0, rARG0);
- }
+ /*
+ * Dummy up a RegLocation for the incoming Method*
+ * It will attempt to keep rARG0 live (or copy it to home location
+ * if promoted).
+ */
+ RegLocation rlSrc = cUnit->regLocation[cUnit->methodSReg];
+ RegLocation rlMethod = cUnit->regLocation[cUnit->methodSReg];
+ rlSrc.location = kLocPhysReg;
+ rlSrc.lowReg = rARG0;
+ rlSrc.home = false;
+ oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
+ storeValue(cUnit, rlMethod, rlSrc);
+ // If Method* has been promoted, explicitly flush
+ if (rlMethod.location == kLocPhysReg) {
+ storeWordDisp(cUnit, rSP, 0, rARG0);
+ }
- if (cUnit->numIns == 0)
- return;
- const int numArgRegs = 3;
- static int argRegs[] = {rARG1, rARG2, rARG3};
- int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
- /*
- * Copy incoming arguments to their proper home locations.
- * NOTE: an older version of dx had an issue in which
- * it would reuse static method argument registers.
- * This could result in the same Dalvik virtual register
- * being promoted to both core and fp regs. To account for this,
- * we only copy to the corresponding promoted physical register
- * if it matches the type of the SSA name for the incoming
- * argument. It is also possible that long and double arguments
- * end up half-promoted. In those cases, we must flush the promoted
- * half to memory as well.
- */
- for (int i = 0; i < cUnit->numIns; i++) {
- PromotionMap* vMap = &cUnit->promotionMap[startVReg + i];
- if (i < numArgRegs) {
- // If arriving in register
- bool needFlush = true;
- RegLocation* tLoc = &cUnit->regLocation[startVReg + i];
- if ((vMap->coreLocation == kLocPhysReg) && !tLoc->fp) {
- opRegCopy(cUnit, vMap->coreReg, argRegs[i]);
- needFlush = false;
- } else if ((vMap->fpLocation == kLocPhysReg) && tLoc->fp) {
- opRegCopy(cUnit, vMap->fpReg, argRegs[i]);
- needFlush = false;
- } else {
- needFlush = true;
- }
+ if (cUnit->numIns == 0)
+ return;
+ const int numArgRegs = 3;
+ static int argRegs[] = {rARG1, rARG2, rARG3};
+ int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
+ /*
+ * Copy incoming arguments to their proper home locations.
+ * NOTE: an older version of dx had an issue in which
+ * it would reuse static method argument registers.
+ * This could result in the same Dalvik virtual register
+ * being promoted to both core and fp regs. To account for this,
+ * we only copy to the corresponding promoted physical register
+ * if it matches the type of the SSA name for the incoming
+ * argument. It is also possible that long and double arguments
+ * end up half-promoted. In those cases, we must flush the promoted
+ * half to memory as well.
+ */
+ for (int i = 0; i < cUnit->numIns; i++) {
+ PromotionMap* vMap = &cUnit->promotionMap[startVReg + i];
+ if (i < numArgRegs) {
+ // If arriving in register
+ bool needFlush = true;
+ RegLocation* tLoc = &cUnit->regLocation[startVReg + i];
+ if ((vMap->coreLocation == kLocPhysReg) && !tLoc->fp) {
+ opRegCopy(cUnit, vMap->coreReg, argRegs[i]);
+ needFlush = false;
+ } else if ((vMap->fpLocation == kLocPhysReg) && tLoc->fp) {
+ opRegCopy(cUnit, vMap->fpReg, argRegs[i]);
+ needFlush = false;
+ } else {
+ needFlush = true;
+ }
- // For wide args, force flush if only half is promoted
- if (tLoc->wide) {
- PromotionMap* pMap = vMap + (tLoc->highWord ? -1 : +1);
- needFlush |= (pMap->coreLocation != vMap->coreLocation) ||
- (pMap->fpLocation != vMap->fpLocation);
- }
- if (needFlush) {
- storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- argRegs[i], kWord);
- }
- } else {
- // If arriving in frame & promoted
- if (vMap->coreLocation == kLocPhysReg) {
- loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- vMap->coreReg);
- }
- if (vMap->fpLocation == kLocPhysReg) {
- loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
- vMap->fpReg);
- }
- }
+ // For wide args, force flush if only half is promoted
+ if (tLoc->wide) {
+ PromotionMap* pMap = vMap + (tLoc->highWord ? -1 : +1);
+ needFlush |= (pMap->coreLocation != vMap->coreLocation) ||
+ (pMap->fpLocation != vMap->fpLocation);
+ }
+ if (needFlush) {
+ storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+ argRegs[i], kWord);
+ }
+ } else {
+ // If arriving in frame & promoted
+ if (vMap->coreLocation == kLocPhysReg) {
+ loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+ vMap->coreReg);
+ }
+ if (vMap->fpLocation == kLocPhysReg) {
+ loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i),
+ vMap->fpReg);
+ }
}
+ }
}
void scanMethodLiteralPool(CompilationUnit* cUnit, LIR** methodTarget, LIR** codeTarget, const DexFile* dexFile, uint32_t dexMethodIdx)
{
- LIR* curTarget = cUnit->methodLiteralList;
- LIR* nextTarget = curTarget != NULL ? curTarget->next : NULL;
- while (curTarget != NULL && nextTarget != NULL) {
- if (curTarget->operands[0] == (int)dexFile &&
- nextTarget->operands[0] == (int)dexMethodIdx) {
- *codeTarget = curTarget;
- *methodTarget = nextTarget;
- DCHECK((*codeTarget)->next == *methodTarget);
- DCHECK_EQ((*codeTarget)->operands[0], (int)dexFile);
- DCHECK_EQ((*methodTarget)->operands[0], (int)dexMethodIdx);
- break;
- }
- curTarget = nextTarget->next;
- nextTarget = curTarget != NULL ? curTarget->next : NULL;
+ LIR* curTarget = cUnit->methodLiteralList;
+ LIR* nextTarget = curTarget != NULL ? curTarget->next : NULL;
+ while (curTarget != NULL && nextTarget != NULL) {
+ if (curTarget->operands[0] == (int)dexFile &&
+ nextTarget->operands[0] == (int)dexMethodIdx) {
+ *codeTarget = curTarget;
+ *methodTarget = nextTarget;
+ DCHECK((*codeTarget)->next == *methodTarget);
+ DCHECK_EQ((*codeTarget)->operands[0], (int)dexFile);
+ DCHECK_EQ((*methodTarget)->operands[0], (int)dexMethodIdx);
+ break;
}
+ curTarget = nextTarget->next;
+ nextTarget = curTarget != NULL ? curTarget->next : NULL;
+ }
}
/*
@@ -139,96 +139,99 @@
InvokeType type)
{
#if !defined(TARGET_ARM)
- directCode = 0;
- directMethod = 0;
+ directCode = 0;
+ directMethod = 0;
#endif
- if (directCode != 0 && directMethod != 0) {
- switch (state) {
- case 0: // Get the current Method* [sets rARG0]
- if (directCode != (uintptr_t)-1) {
- loadConstant(cUnit, rINVOKE_TGT, directCode);
- } else {
- LIR* dataTarget = scanLiteralPool(cUnit->codeLiteralList, dexIdx, 0);
- if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx);
- dataTarget->operands[1] = type;
- }
-#if defined(TARGET_ARM)
- LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
- kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0, dataTarget);
- oatAppendLIR(cUnit, loadPcRel);
-#else
- UNIMPLEMENTED(FATAL) << (void*)dataTarget;
-#endif
- }
- if (directMethod != (uintptr_t)-1) {
- loadConstant(cUnit, rARG0, directMethod);
- } else {
- LIR* dataTarget = scanLiteralPool(cUnit->methodLiteralList, dexIdx, 0);
- if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, &cUnit->methodLiteralList, dexIdx);
- dataTarget->operands[1] = type;
- }
-#if defined(TARGET_ARM)
- LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
- kThumb2LdrPcRel12, rARG0, 0, 0, 0, 0, dataTarget);
- oatAppendLIR(cUnit, loadPcRel);
-#else
- UNIMPLEMENTED(FATAL) << (void*)dataTarget;
-#endif
- }
- break;
- default:
- return -1;
- }
- } else {
- switch (state) {
- case 0: // Get the current Method* [sets rARG0]
- // TUNING: we can save a reg copy if Method* has been promoted
- loadCurrMethodDirect(cUnit, rARG0);
- break;
- case 1: // Get method->dex_cache_resolved_methods_
- loadWordDisp(cUnit, rARG0,
- Method::DexCacheResolvedMethodsOffset().Int32Value(),
- rARG0);
- // Set up direct code if known.
- if (directCode != 0) {
- if (directCode != (uintptr_t)-1) {
- loadConstant(cUnit, rINVOKE_TGT, directCode);
- } else {
- LIR* dataTarget = scanLiteralPool(cUnit->codeLiteralList, dexIdx, 0);
- if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx);
- dataTarget->operands[1] = type;
- }
-#if defined(TARGET_ARM)
- LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
- kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0, dataTarget);
- oatAppendLIR(cUnit, loadPcRel);
-#else
- UNIMPLEMENTED(FATAL) << (void*)dataTarget;
-#endif
- }
- }
- break;
- case 2: // Grab target method*
- loadWordDisp(cUnit, rARG0,
- Array::DataOffset(sizeof(Object*)).Int32Value() + dexIdx * 4,
- rARG0);
- break;
-#if !defined(TARGET_X86)
- case 3: // Grab the code from the method*
- if (directCode == 0) {
- loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
- rINVOKE_TGT);
- }
- break;
-#endif
- default:
- return -1;
+ if (directCode != 0 && directMethod != 0) {
+ switch (state) {
+ case 0: // Get the current Method* [sets rARG0]
+ if (directCode != (uintptr_t)-1) {
+ loadConstant(cUnit, rINVOKE_TGT, directCode);
+ } else {
+ LIR* dataTarget = scanLiteralPool(cUnit->codeLiteralList, dexIdx, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx);
+ dataTarget->operands[1] = type;
}
+#if defined(TARGET_ARM)
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
+ kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0,
+ dataTarget);
+ oatAppendLIR(cUnit, loadPcRel);
+#else
+ UNIMPLEMENTED(FATAL) << (void*)dataTarget;
+#endif
+ }
+ if (directMethod != (uintptr_t)-1) {
+ loadConstant(cUnit, rARG0, directMethod);
+ } else {
+ LIR* dataTarget = scanLiteralPool(cUnit->methodLiteralList, dexIdx, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->methodLiteralList, dexIdx);
+ dataTarget->operands[1] = type;
+ }
+#if defined(TARGET_ARM)
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
+ kThumb2LdrPcRel12, rARG0, 0, 0, 0, 0,
+ dataTarget);
+ oatAppendLIR(cUnit, loadPcRel);
+#else
+ UNIMPLEMENTED(FATAL) << (void*)dataTarget;
+#endif
+ }
+ break;
+ default:
+ return -1;
}
- return state + 1;
+ } else {
+ switch (state) {
+ case 0: // Get the current Method* [sets rARG0]
+ // TUNING: we can save a reg copy if Method* has been promoted
+ loadCurrMethodDirect(cUnit, rARG0);
+ break;
+ case 1: // Get method->dex_cache_resolved_methods_
+ loadWordDisp(cUnit, rARG0,
+ Method::DexCacheResolvedMethodsOffset().Int32Value(),
+ rARG0);
+ // Set up direct code if known.
+ if (directCode != 0) {
+ if (directCode != (uintptr_t)-1) {
+ loadConstant(cUnit, rINVOKE_TGT, directCode);
+ } else {
+ LIR* dataTarget = scanLiteralPool(cUnit->codeLiteralList, dexIdx, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->codeLiteralList, dexIdx);
+ dataTarget->operands[1] = type;
+ }
+#if defined(TARGET_ARM)
+ LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
+ kThumb2LdrPcRel12, rINVOKE_TGT, 0, 0, 0, 0,
+ dataTarget);
+ oatAppendLIR(cUnit, loadPcRel);
+#else
+ UNIMPLEMENTED(FATAL) << (void*)dataTarget;
+#endif
+ }
+ }
+ break;
+ case 2: // Grab target method*
+ loadWordDisp(cUnit, rARG0,
+ Array::DataOffset(sizeof(Object*)).Int32Value() + dexIdx * 4,
+ rARG0);
+ break;
+#if !defined(TARGET_X86)
+ case 3: // Grab the code from the method*
+ if (directCode == 0) {
+ loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
+ rINVOKE_TGT);
+ }
+ break;
+#endif
+ default:
+ return -1;
+ }
+ }
+ return state + 1;
}
/*
@@ -242,60 +245,59 @@
int state, uint32_t dexIdx, uint32_t methodIdx,
uintptr_t unused, uintptr_t unused2, InvokeType unused3)
{
- RegLocation rlArg;
- /*
- * This is the fast path in which the target virtual method is
- * fully resolved at compile time.
- */
- switch (state) {
- case 0: // Get "this" [set rARG1]
- rlArg = oatGetSrc(cUnit, mir, 0);
- loadValueDirectFixed(cUnit, rlArg, rARG1);
- break;
- case 1: // Is "this" null? [use rARG1]
- genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
- // get this->klass_ [use rARG1, set rINVOKE_TGT]
- loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(),
- rINVOKE_TGT);
- break;
- case 2: // Get this->klass_->vtable [usr rINVOKE_TGT, set rINVOKE_TGT]
- loadWordDisp(cUnit, rINVOKE_TGT, Class::VTableOffset().Int32Value(),
- rINVOKE_TGT);
- break;
- case 3: // Get target method [use rINVOKE_TGT, set rARG0]
- loadWordDisp(cUnit, rINVOKE_TGT, (methodIdx * 4) +
- Array::DataOffset(sizeof(Object*)).Int32Value(),
- rARG0);
- break;
+ RegLocation rlArg;
+ /*
+ * This is the fast path in which the target virtual method is
+ * fully resolved at compile time.
+ */
+ switch (state) {
+ case 0: // Get "this" [set rARG1]
+ rlArg = oatGetSrc(cUnit, mir, 0);
+ loadValueDirectFixed(cUnit, rlArg, rARG1);
+ break;
+ case 1: // Is "this" null? [use rARG1]
+ genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
+ // get this->klass_ [use rARG1, set rINVOKE_TGT]
+ loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(),
+ rINVOKE_TGT);
+ break;
+ case 2: // Get this->klass_->vtable [usr rINVOKE_TGT, set rINVOKE_TGT]
+ loadWordDisp(cUnit, rINVOKE_TGT, Class::VTableOffset().Int32Value(),
+ rINVOKE_TGT);
+ break;
+ case 3: // Get target method [use rINVOKE_TGT, set rARG0]
+ loadWordDisp(cUnit, rINVOKE_TGT, (methodIdx * 4) +
+ Array::DataOffset(sizeof(Object*)).Int32Value(), rARG0);
+ break;
#if !defined(TARGET_X86)
- case 4: // Get the compiled code address [uses rARG0, sets rINVOKE_TGT]
- loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
- rINVOKE_TGT);
- break;
+ case 4: // Get the compiled code address [uses rARG0, sets rINVOKE_TGT]
+ loadWordDisp(cUnit, rARG0, Method::GetCodeOffset().Int32Value(),
+ rINVOKE_TGT);
+ break;
#endif
- default:
- return -1;
- }
- return state + 1;
+ default:
+ return -1;
+ }
+ return state + 1;
}
int nextInvokeInsnSP(CompilationUnit* cUnit, MIR* mir, int trampoline,
int state, uint32_t dexIdx, uint32_t methodIdx)
{
- /*
- * This handles the case in which the base method is not fully
- * resolved at compile time, we bail to a runtime helper.
- */
- if (state == 0) {
+ /*
+ * This handles the case in which the base method is not fully
+ * resolved at compile time, we bail to a runtime helper.
+ */
+ if (state == 0) {
#if !defined(TARGET_X86)
- // Load trampoline target
- loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT);
+ // Load trampoline target
+ loadWordDisp(cUnit, rSELF, trampoline, rINVOKE_TGT);
#endif
- // Load rARG0 with method index
- loadConstant(cUnit, rARG0, dexIdx);
- return 1;
- }
- return -1;
+ // Load rARG0 with method index
+ loadConstant(cUnit, rARG0, dexIdx);
+ return 1;
+ }
+ return -1;
}
int nextStaticCallInsnSP(CompilationUnit* cUnit, MIR* mir,
@@ -357,28 +359,28 @@
uint32_t methodIdx, uintptr_t directCode,
uintptr_t directMethod, InvokeType type, bool skipThis)
{
- int lastArgReg = rARG3;
- int nextReg = rARG1;
- int nextArg = 0;
- if (skipThis) {
- nextReg++;
- nextArg++;
+ int lastArgReg = rARG3;
+ int nextReg = rARG1;
+ int nextArg = 0;
+ if (skipThis) {
+ nextReg++;
+ nextArg++;
+ }
+ for (; (nextReg <= lastArgReg) && (nextArg < mir->ssaRep->numUses); nextReg++) {
+ RegLocation rlArg = oatGetRawSrc(cUnit, mir, nextArg++);
+ rlArg = oatUpdateRawLoc(cUnit, rlArg);
+ if (rlArg.wide && (nextReg <= rARG2)) {
+ loadValueDirectWideFixed(cUnit, rlArg, nextReg, nextReg + 1);
+ nextReg++;
+ nextArg++;
+ } else {
+ rlArg.wide = false;
+ loadValueDirectFixed(cUnit, rlArg, nextReg);
}
- for (; (nextReg <= lastArgReg) && (nextArg < mir->ssaRep->numUses); nextReg++) {
- RegLocation rlArg = oatGetRawSrc(cUnit, mir, nextArg++);
- rlArg = oatUpdateRawLoc(cUnit, rlArg);
- if (rlArg.wide && (nextReg <= rARG2)) {
- loadValueDirectWideFixed(cUnit, rlArg, nextReg, nextReg + 1);
- nextReg++;
- nextArg++;
- } else {
- rlArg.wide = false;
- loadValueDirectFixed(cUnit, rlArg, nextReg);
- }
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
- }
- return callState;
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+ }
+ return callState;
}
/*
@@ -395,86 +397,83 @@
uintptr_t directCode, uintptr_t directMethod,
InvokeType type, bool skipThis)
{
- RegLocation rlArg;
+ RegLocation rlArg;
- /* If no arguments, just return */
- if (dInsn->vA == 0)
- return callState;
-
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
-
- DCHECK_LE(dInsn->vA, 5U);
- if (dInsn->vA > 3) {
- uint32_t nextUse = 3;
- //Detect special case of wide arg spanning arg3/arg4
- RegLocation rlUse0 = oatGetRawSrc(cUnit, mir, 0);
- RegLocation rlUse1 = oatGetRawSrc(cUnit, mir, 1);
- RegLocation rlUse2 = oatGetRawSrc(cUnit, mir, 2);
- if (((!rlUse0.wide && !rlUse1.wide) || rlUse0.wide) &&
- rlUse2.wide) {
- int reg = -1;
- // Wide spans, we need the 2nd half of uses[2].
- rlArg = oatUpdateLocWide(cUnit, rlUse2);
- if (rlArg.location == kLocPhysReg) {
- reg = rlArg.highReg;
- } else {
- // rARG2 & rARG3 can safely be used here
- reg = rARG3;
- loadWordDisp(cUnit, rSP,
- oatSRegOffset(cUnit, rlArg.sRegLow) + 4, reg);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx,
- methodIdx, directCode, directMethod,
- type);
- }
- storeBaseDisp(cUnit, rSP, (nextUse + 1) * 4, reg, kWord);
- storeBaseDisp(cUnit, rSP, 16 /* (3+1)*4 */, reg, kWord);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
- nextUse++;
- }
- // Loop through the rest
- while (nextUse < dInsn->vA) {
- int lowReg;
- int highReg = -1;
- rlArg = oatGetRawSrc(cUnit, mir, nextUse);
- rlArg = oatUpdateRawLoc(cUnit, rlArg);
- if (rlArg.location == kLocPhysReg) {
- lowReg = rlArg.lowReg;
- highReg = rlArg.highReg;
- } else {
- lowReg = rARG2;
- if (rlArg.wide) {
- highReg = rARG3;
- loadValueDirectWideFixed(cUnit, rlArg, lowReg, highReg);
- } else {
- loadValueDirectFixed(cUnit, rlArg, lowReg);
- }
- callState = nextCallInsn(cUnit, mir, callState, dexIdx,
- methodIdx, directCode, directMethod,
- type);
- }
- int outsOffset = (nextUse + 1) * 4;
- if (rlArg.wide) {
- storeBaseDispWide(cUnit, rSP, outsOffset, lowReg, highReg);
- nextUse += 2;
- } else {
- storeWordDisp(cUnit, rSP, outsOffset, lowReg);
- nextUse++;
- }
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
- }
- }
-
- callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
- dexIdx, methodIdx, directCode, directMethod,
- type, skipThis);
-
- if (pcrLabel) {
- *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
- }
+ /* If no arguments, just return */
+ if (dInsn->vA == 0)
return callState;
+
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+
+ DCHECK_LE(dInsn->vA, 5U);
+ if (dInsn->vA > 3) {
+ uint32_t nextUse = 3;
+ //Detect special case of wide arg spanning arg3/arg4
+ RegLocation rlUse0 = oatGetRawSrc(cUnit, mir, 0);
+ RegLocation rlUse1 = oatGetRawSrc(cUnit, mir, 1);
+ RegLocation rlUse2 = oatGetRawSrc(cUnit, mir, 2);
+ if (((!rlUse0.wide && !rlUse1.wide) || rlUse0.wide) &&
+ rlUse2.wide) {
+ int reg = -1;
+ // Wide spans, we need the 2nd half of uses[2].
+ rlArg = oatUpdateLocWide(cUnit, rlUse2);
+ if (rlArg.location == kLocPhysReg) {
+ reg = rlArg.highReg;
+ } else {
+ // rARG2 & rARG3 can safely be used here
+ reg = rARG3;
+ loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, rlArg.sRegLow) + 4, reg);
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx,
+ methodIdx, directCode, directMethod, type);
+ }
+ storeBaseDisp(cUnit, rSP, (nextUse + 1) * 4, reg, kWord);
+ storeBaseDisp(cUnit, rSP, 16 /* (3+1)*4 */, reg, kWord);
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+ nextUse++;
+ }
+ // Loop through the rest
+ while (nextUse < dInsn->vA) {
+ int lowReg;
+ int highReg = -1;
+ rlArg = oatGetRawSrc(cUnit, mir, nextUse);
+ rlArg = oatUpdateRawLoc(cUnit, rlArg);
+ if (rlArg.location == kLocPhysReg) {
+ lowReg = rlArg.lowReg;
+ highReg = rlArg.highReg;
+ } else {
+ lowReg = rARG2;
+ if (rlArg.wide) {
+ highReg = rARG3;
+ loadValueDirectWideFixed(cUnit, rlArg, lowReg, highReg);
+ } else {
+ loadValueDirectFixed(cUnit, rlArg, lowReg);
+ }
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx,
+ methodIdx, directCode, directMethod, type);
+ }
+ int outsOffset = (nextUse + 1) * 4;
+ if (rlArg.wide) {
+ storeBaseDispWide(cUnit, rSP, outsOffset, lowReg, highReg);
+ nextUse += 2;
+ } else {
+ storeWordDisp(cUnit, rSP, outsOffset, lowReg);
+ nextUse++;
+ }
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+ }
+ }
+
+ callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
+ dexIdx, methodIdx, directCode, directMethod,
+ type, skipThis);
+
+ if (pcrLabel) {
+ *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
+ }
+ return callState;
}
/*
@@ -499,297 +498,295 @@
uintptr_t directCode, uintptr_t directMethod,
InvokeType type, bool skipThis)
{
- int firstArg = dInsn->vC;
- int numArgs = dInsn->vA;
+ int firstArg = dInsn->vC;
+ int numArgs = dInsn->vA;
- // If we can treat it as non-range (Jumbo ops will use range form)
- if (numArgs <= 5)
- return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
- nextCallInsn, dexIdx, methodIdx,
- directCode, directMethod, type, skipThis);
- /*
- * Make sure range list doesn't span the break between in normal
- * Dalvik vRegs and the ins.
- */
- int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
- int boundaryReg = cUnit->numDalvikRegisters - cUnit->numIns;
- if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) {
- LOG(FATAL) << "Argument list spanned locals & args";
+ // If we can treat it as non-range (Jumbo ops will use range form)
+ if (numArgs <= 5)
+ return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
+ nextCallInsn, dexIdx, methodIdx,
+ directCode, directMethod, type, skipThis);
+ /*
+ * Make sure range list doesn't span the break between in normal
+ * Dalvik vRegs and the ins.
+ */
+ int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
+ int boundaryReg = cUnit->numDalvikRegisters - cUnit->numIns;
+ if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) {
+ LOG(FATAL) << "Argument list spanned locals & args";
+ }
+
+ /*
+ * First load the non-register arguments. Both forms expect all
+ * of the source arguments to be in their home frame location, so
+ * scan the sReg names and flush any that have been promoted to
+ * frame backing storage.
+ */
+ // Scan the rest of the args - if in physReg flush to memory
+ for (int nextArg = 0; nextArg < numArgs;) {
+ RegLocation loc = oatGetRawSrc(cUnit, mir, nextArg);
+ if (loc.wide) {
+ loc = oatUpdateLocWide(cUnit, loc);
+ if ((nextArg >= 2) && (loc.location == kLocPhysReg)) {
+ storeBaseDispWide(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
+ loc.lowReg, loc.highReg);
+ }
+ nextArg += 2;
+ } else {
+ loc = oatUpdateLoc(cUnit, loc);
+ if ((nextArg >= 3) && (loc.location == kLocPhysReg)) {
+ storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
+ loc.lowReg, kWord);
+ }
+ nextArg++;
}
+ }
- /*
- * First load the non-register arguments. Both forms expect all
- * of the source arguments to be in their home frame location, so
- * scan the sReg names and flush any that have been promoted to
- * frame backing storage.
- */
- // Scan the rest of the args - if in physReg flush to memory
- for (int nextArg = 0; nextArg < numArgs;) {
- RegLocation loc = oatGetRawSrc(cUnit, mir, nextArg);
- if (loc.wide) {
- loc = oatUpdateLocWide(cUnit, loc);
- if ((nextArg >= 2) && (loc.location == kLocPhysReg)) {
- storeBaseDispWide(cUnit, rSP,
- oatSRegOffset(cUnit, loc.sRegLow),
- loc.lowReg, loc.highReg);
- }
- nextArg += 2;
- } else {
- loc = oatUpdateLoc(cUnit, loc);
- if ((nextArg >= 3) && (loc.location == kLocPhysReg)) {
- storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow),
- loc.lowReg, kWord);
- }
- nextArg++;
- }
- }
-
- int startOffset = oatSRegOffset(cUnit,
- cUnit->regLocation[mir->ssaRep->uses[3]].sRegLow);
- int outsOffset = 4 /* Method* */ + (3 * 4);
+ int startOffset = oatSRegOffset(cUnit,
+ cUnit->regLocation[mir->ssaRep->uses[3]].sRegLow);
+ int outsOffset = 4 /* Method* */ + (3 * 4);
#if defined(TARGET_MIPS) || defined(TARGET_X86)
+ // Generate memcpy
+ opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
+ opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
+ callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy),
+ rARG0, rARG1, (numArgs - 3) * 4);
+#else
+ if (numArgs >= 20) {
// Generate memcpy
opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy),
rARG0, rARG1, (numArgs - 3) * 4);
-#else
- if (numArgs >= 20) {
- // Generate memcpy
- opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
- opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
- callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy),
- rARG0, rARG1, (numArgs - 3) * 4);
- } else {
- // Use vldm/vstm pair using rARG3 as a temp
- int regsLeft = std::min(numArgs - 3, 16);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
- opRegRegImm(cUnit, kOpAdd, rARG3, rSP, startOffset);
- LIR* ld = newLIR3(cUnit, kThumb2Vldms, rARG3, fr0, regsLeft);
- //TUNING: loosen barrier
- ld->defMask = ENCODE_ALL;
- setMemRefType(ld, true /* isLoad */, kDalvikReg);
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
- opRegRegImm(cUnit, kOpAdd, rARG3, rSP, 4 /* Method* */ + (3 * 4));
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
- LIR* st = newLIR3(cUnit, kThumb2Vstms, rARG3, fr0, regsLeft);
- setMemRefType(st, false /* isLoad */, kDalvikReg);
- st->defMask = ENCODE_ALL;
- callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
- directCode, directMethod, type);
-
- }
-#endif
-
- callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
- dexIdx, methodIdx, directCode, directMethod,
- type, skipThis);
-
+ } else {
+ // Use vldm/vstm pair using rARG3 as a temp
+ int regsLeft = std::min(numArgs - 3, 16);
callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
directCode, directMethod, type);
- if (pcrLabel) {
- *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
- }
- return callState;
+ opRegRegImm(cUnit, kOpAdd, rARG3, rSP, startOffset);
+ LIR* ld = newLIR3(cUnit, kThumb2Vldms, rARG3, fr0, regsLeft);
+ //TUNING: loosen barrier
+ ld->defMask = ENCODE_ALL;
+ setMemRefType(ld, true /* isLoad */, kDalvikReg);
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+ opRegRegImm(cUnit, kOpAdd, rARG3, rSP, 4 /* Method* */ + (3 * 4));
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+ LIR* st = newLIR3(cUnit, kThumb2Vstms, rARG3, fr0, regsLeft);
+ setMemRefType(st, false /* isLoad */, kDalvikReg);
+ st->defMask = ENCODE_ALL;
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+
+ }
+#endif
+
+ callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn,
+ dexIdx, methodIdx, directCode, directMethod,
+ type, skipThis);
+
+ callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx,
+ directCode, directMethod, type);
+ if (pcrLabel) {
+ *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), rARG1, mir);
+ }
+ return callState;
}
RegLocation inlineTarget(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
{
- RegLocation res;
- mir = oatFindMoveResult(cUnit, bb, mir, false);
- if (mir == NULL) {
- res = oatGetReturn(cUnit, false);
- } else {
- res = oatGetDest(cUnit, mir, 0);
- mir->dalvikInsn.opcode = Instruction::NOP;
- }
- return res;
+ RegLocation res;
+ mir = oatFindMoveResult(cUnit, bb, mir, false);
+ if (mir == NULL) {
+ res = oatGetReturn(cUnit, false);
+ } else {
+ res = oatGetDest(cUnit, mir, 0);
+ mir->dalvikInsn.opcode = Instruction::NOP;
+ }
+ return res;
}
RegLocation inlineTargetWide(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
{
- RegLocation res;
- mir = oatFindMoveResult(cUnit, bb, mir, true);
- if (mir == NULL) {
- res = oatGetReturnWide(cUnit, false);
- } else {
- res = oatGetDestWide(cUnit, mir, 0, 1);
- mir->dalvikInsn.opcode = Instruction::NOP;
- }
- return res;
+ RegLocation res;
+ mir = oatFindMoveResult(cUnit, bb, mir, true);
+ if (mir == NULL) {
+ res = oatGetReturnWide(cUnit, false);
+ } else {
+ res = oatGetDestWide(cUnit, mir, 0, 1);
+ mir->dalvikInsn.opcode = Instruction::NOP;
+ }
+ return res;
}
bool genInlinedCharAt(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
- InvokeType type, bool isRange)
+ InvokeType type, bool isRange)
{
#if defined(TARGET_ARM)
- // Location of reference to data array
- int valueOffset = String::ValueOffset().Int32Value();
- // Location of count
- int countOffset = String::CountOffset().Int32Value();
- // Starting offset within data array
- int offsetOffset = String::OffsetOffset().Int32Value();
- // Start of char data with array_
- int dataOffset = Array::DataOffset(sizeof(uint16_t)).Int32Value();
+ // Location of reference to data array
+ int valueOffset = String::ValueOffset().Int32Value();
+ // Location of count
+ int countOffset = String::CountOffset().Int32Value();
+ // Starting offset within data array
+ int offsetOffset = String::OffsetOffset().Int32Value();
+ // Start of char data with array_
+ int dataOffset = Array::DataOffset(sizeof(uint16_t)).Int32Value();
- RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
- RegLocation rlIdx = oatGetSrc(cUnit, mir, 1);
- rlObj = loadValue(cUnit, rlObj, kCoreReg);
- rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
- int regMax;
- int regOff = oatAllocTemp(cUnit);
- int regPtr = oatAllocTemp(cUnit);
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);
- bool rangeCheck = (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK));
- if (rangeCheck) {
- regMax = oatAllocTemp(cUnit);
- loadWordDisp(cUnit, rlObj.lowReg, countOffset, regMax);
- }
- loadWordDisp(cUnit, rlObj.lowReg, offsetOffset, regOff);
- loadWordDisp(cUnit, rlObj.lowReg, valueOffset, regPtr);
- LIR* launchPad = NULL;
- if (rangeCheck) {
- // Set up a launch pad to allow retry in case of bounds violation */
- launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
- oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
- (intptr_t)launchPad);
- opRegReg(cUnit, kOpCmp, rlIdx.lowReg, regMax);
- oatFreeTemp(cUnit, regMax);
- opCondBranch(cUnit, kCondCs, launchPad);
- }
- opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
- opRegReg(cUnit, kOpAdd, regOff, rlIdx.lowReg);
- RegLocation rlDest = inlineTarget(cUnit, bb, mir);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- loadBaseIndexed(cUnit, regPtr, regOff, rlResult.lowReg, 1, kUnsignedHalf);
- oatFreeTemp(cUnit, regOff);
- oatFreeTemp(cUnit, regPtr);
- storeValue(cUnit, rlDest, rlResult);
- if (rangeCheck) {
- launchPad->operands[2] = NULL; // no resumption
- launchPad->operands[3] = (uintptr_t)bb;
- }
- // Record that we've already inlined & null checked
- mir->optimizationFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
- return true;
+ RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
+ RegLocation rlIdx = oatGetSrc(cUnit, mir, 1);
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
+ int regMax;
+ int regOff = oatAllocTemp(cUnit);
+ int regPtr = oatAllocTemp(cUnit);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);
+ bool rangeCheck = (!(mir->optimizationFlags & MIR_IGNORE_RANGE_CHECK));
+ if (rangeCheck) {
+ regMax = oatAllocTemp(cUnit);
+ loadWordDisp(cUnit, rlObj.lowReg, countOffset, regMax);
+ }
+ loadWordDisp(cUnit, rlObj.lowReg, offsetOffset, regOff);
+ loadWordDisp(cUnit, rlObj.lowReg, valueOffset, regPtr);
+ LIR* launchPad = NULL;
+ if (rangeCheck) {
+ // Set up a launch pad to allow retry in case of bounds violation */
+ launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
+ oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
+ (intptr_t)launchPad);
+ opRegReg(cUnit, kOpCmp, rlIdx.lowReg, regMax);
+ oatFreeTemp(cUnit, regMax);
+ opCondBranch(cUnit, kCondCs, launchPad);
+ }
+ opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
+ opRegReg(cUnit, kOpAdd, regOff, rlIdx.lowReg);
+ RegLocation rlDest = inlineTarget(cUnit, bb, mir);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ loadBaseIndexed(cUnit, regPtr, regOff, rlResult.lowReg, 1, kUnsignedHalf);
+ oatFreeTemp(cUnit, regOff);
+ oatFreeTemp(cUnit, regPtr);
+ storeValue(cUnit, rlDest, rlResult);
+ if (rangeCheck) {
+ launchPad->operands[2] = NULL; // no resumption
+ launchPad->operands[3] = (uintptr_t)bb;
+ }
+ // Record that we've already inlined & null checked
+ mir->optimizationFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
+ return true;
#else
- return false;
+ return false;
#endif
}
bool genInlinedMinMaxInt(CompilationUnit *cUnit, BasicBlock* bb, MIR *mir,
- bool isMin)
+ bool isMin)
{
#if defined(TARGET_ARM)
- RegLocation rlSrc1 = oatGetSrc(cUnit, mir, 0);
- RegLocation rlSrc2 = oatGetSrc(cUnit, mir, 1);
- rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
- rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
- RegLocation rlDest = inlineTarget(cUnit, bb, mir);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
- opIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E");
- opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg);
- opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg);
- genBarrier(cUnit);
- storeValue(cUnit, rlDest, rlResult);
- return true;
+ RegLocation rlSrc1 = oatGetSrc(cUnit, mir, 0);
+ RegLocation rlSrc2 = oatGetSrc(cUnit, mir, 1);
+ rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
+ rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
+ RegLocation rlDest = inlineTarget(cUnit, bb, mir);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
+ opIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E");
+ opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg);
+ opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg);
+ genBarrier(cUnit);
+ storeValue(cUnit, rlDest, rlResult);
+ return true;
#else
- return false;
+ return false;
#endif
}
// Generates an inlined String.isEmpty or String.length.
bool genInlinedStringIsEmptyOrLength(CompilationUnit* cUnit,
- BasicBlock* bb, MIR* mir,
- bool isEmpty)
+ BasicBlock* bb, MIR* mir, bool isEmpty)
{
#if defined(TARGET_ARM)
- // dst = src.length();
- RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
- rlObj = loadValue(cUnit, rlObj, kCoreReg);
- RegLocation rlDest = inlineTarget(cUnit, bb, mir);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);
- loadWordDisp(cUnit, rlObj.lowReg, String::CountOffset().Int32Value(),
- rlResult.lowReg);
- if (isEmpty) {
- // dst = (dst == 0);
- int tReg = oatAllocTemp(cUnit);
- opRegReg(cUnit, kOpNeg, tReg, rlResult.lowReg);
- opRegRegReg(cUnit, kOpAdc, rlResult.lowReg, rlResult.lowReg, tReg);
- }
- storeValue(cUnit, rlDest, rlResult);
- return true;
+ // dst = src.length();
+ RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ RegLocation rlDest = inlineTarget(cUnit, bb, mir);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);
+ loadWordDisp(cUnit, rlObj.lowReg, String::CountOffset().Int32Value(),
+ rlResult.lowReg);
+ if (isEmpty) {
+ // dst = (dst == 0);
+ int tReg = oatAllocTemp(cUnit);
+ opRegReg(cUnit, kOpNeg, tReg, rlResult.lowReg);
+ opRegRegReg(cUnit, kOpAdc, rlResult.lowReg, rlResult.lowReg, tReg);
+ }
+ storeValue(cUnit, rlDest, rlResult);
+ return true;
#else
- return false;
+ return false;
#endif
}
bool genInlinedAbsInt(CompilationUnit *cUnit, BasicBlock* bb, MIR *mir)
{
#if defined(TARGET_ARM)
- RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
- rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
- RegLocation rlDest = inlineTarget(cUnit, bb, mir);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- int signReg = oatAllocTemp(cUnit);
- // abs(x) = y<=x>>31, (x+y)^y.
- opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.lowReg, 31);
- opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
- opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
- storeValue(cUnit, rlDest, rlResult);
- return true;
+ RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
+ rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
+ RegLocation rlDest = inlineTarget(cUnit, bb, mir);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ int signReg = oatAllocTemp(cUnit);
+ // abs(x) = y<=x>>31, (x+y)^y.
+ opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.lowReg, 31);
+ opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
+ opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
+ storeValue(cUnit, rlDest, rlResult);
+ return true;
#else
- return false;
+ return false;
#endif
}
bool genInlinedAbsLong(CompilationUnit *cUnit, BasicBlock* bb, MIR *mir)
{
#if defined(TARGET_ARM)
- RegLocation rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
- RegLocation rlDest = inlineTargetWide(cUnit, bb, mir);
- RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- int signReg = oatAllocTemp(cUnit);
- // abs(x) = y<=x>>31, (x+y)^y.
- opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31);
- opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
- opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc.highReg, signReg);
- opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
- opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
- storeValueWide(cUnit, rlDest, rlResult);
- return true;
+ RegLocation rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+ rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
+ RegLocation rlDest = inlineTargetWide(cUnit, bb, mir);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ int signReg = oatAllocTemp(cUnit);
+ // abs(x) = y<=x>>31, (x+y)^y.
+ opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31);
+ opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
+ opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc.highReg, signReg);
+ opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
+ opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
+ storeValueWide(cUnit, rlDest, rlResult);
+ return true;
#else
- return false;
+ return false;
#endif
}
bool genInlinedFloatCvt(CompilationUnit *cUnit, BasicBlock* bb, MIR *mir)
{
#if defined(TARGET_ARM)
- RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
- RegLocation rlDest = inlineTarget(cUnit, bb, mir);
- storeValue(cUnit, rlDest, rlSrc);
- return true;
+ RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
+ RegLocation rlDest = inlineTarget(cUnit, bb, mir);
+ storeValue(cUnit, rlDest, rlSrc);
+ return true;
#else
- return false;
+ return false;
#endif
}
bool genInlinedDoubleCvt(CompilationUnit *cUnit, BasicBlock* bb, MIR *mir)
{
#if defined(TARGET_ARM)
- RegLocation rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
- RegLocation rlDest = inlineTargetWide(cUnit, bb, mir);
- storeValueWide(cUnit, rlDest, rlSrc);
- return true;
+ RegLocation rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+ RegLocation rlDest = inlineTargetWide(cUnit, bb, mir);
+ storeValueWide(cUnit, rlDest, rlSrc);
+ return true;
#else
- return false;
+ return false;
#endif
}
@@ -802,37 +799,37 @@
{
#if defined(TARGET_ARM)
- oatClobberCalleeSave(cUnit);
- oatLockCallTemps(cUnit); // Using fixed registers
- int regPtr = rARG0;
- int regChar = rARG1;
- int regStart = rARG2;
+ oatClobberCalleeSave(cUnit);
+ oatLockCallTemps(cUnit); // Using fixed registers
+ int regPtr = rARG0;
+ int regChar = rARG1;
+ int regStart = rARG2;
- RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
- RegLocation rlChar = oatGetSrc(cUnit, mir, 1);
- RegLocation rlStart = oatGetSrc(cUnit, mir, 2);
- loadValueDirectFixed(cUnit, rlObj, regPtr);
- loadValueDirectFixed(cUnit, rlChar, regChar);
- if (zeroBased) {
- loadConstant(cUnit, regStart, 0);
- } else {
- loadValueDirectFixed(cUnit, rlStart, regStart);
- }
- int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pIndexOf));
- genNullCheck(cUnit, rlObj.sRegLow, regPtr, mir);
- LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
- oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
- (intptr_t)launchPad);
- opCmpImmBranch(cUnit, kCondGt, regChar, 0xFFFF, launchPad);
- opReg(cUnit, kOpBlx, rTgt);
- LIR* resumeTgt = newLIR0(cUnit, kPseudoTargetLabel);
- launchPad->operands[2] = (uintptr_t)resumeTgt;
- launchPad->operands[3] = (uintptr_t)bb;
- // Record that we've already inlined & null checked
- mir->optimizationFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
- return true;
+ RegLocation rlObj = oatGetSrc(cUnit, mir, 0);
+ RegLocation rlChar = oatGetSrc(cUnit, mir, 1);
+ RegLocation rlStart = oatGetSrc(cUnit, mir, 2);
+ loadValueDirectFixed(cUnit, rlObj, regPtr);
+ loadValueDirectFixed(cUnit, rlChar, regChar);
+ if (zeroBased) {
+ loadConstant(cUnit, regStart, 0);
+ } else {
+ loadValueDirectFixed(cUnit, rlStart, regStart);
+ }
+ int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pIndexOf));
+ genNullCheck(cUnit, rlObj.sRegLow, regPtr, mir);
+ LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
+ oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
+ (intptr_t)launchPad);
+ opCmpImmBranch(cUnit, kCondGt, regChar, 0xFFFF, launchPad);
+ opReg(cUnit, kOpBlx, rTgt);
+ LIR* resumeTgt = newLIR0(cUnit, kPseudoTargetLabel);
+ launchPad->operands[2] = (uintptr_t)resumeTgt;
+ launchPad->operands[3] = (uintptr_t)bb;
+ // Record that we've already inlined & null checked
+ mir->optimizationFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
+ return true;
#else
- return false;
+ return false;
#endif
}
@@ -841,93 +838,93 @@
MIR* mir, InvokeType type)
{
#if defined(TARGET_ARM)
- oatClobberCalleeSave(cUnit);
- oatLockCallTemps(cUnit); // Using fixed registers
- int regThis = rARG0;
- int regCmp = rARG1;
+ oatClobberCalleeSave(cUnit);
+ oatLockCallTemps(cUnit); // Using fixed registers
+ int regThis = rARG0;
+ int regCmp = rARG1;
- RegLocation rlThis = oatGetSrc(cUnit, mir, 0);
- RegLocation rlCmp = oatGetSrc(cUnit, mir, 1);
- loadValueDirectFixed(cUnit, rlThis, regThis);
- loadValueDirectFixed(cUnit, rlCmp, regCmp);
- int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pStringCompareTo));
- genNullCheck(cUnit, rlThis.sRegLow, regThis, mir);
- //TUNING: check if rlCmp.sRegLow is already null checked
- LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
- oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
- (intptr_t)launchPad);
- opCmpImmBranch(cUnit, kCondEq, regCmp, 0, launchPad);
- opReg(cUnit, kOpBlx, rTgt);
- launchPad->operands[2] = NULL; // No return possible
- launchPad->operands[3] = (uintptr_t)bb;
- // Record that we've already inlined & null checked
- mir->optimizationFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
- return true;
+ RegLocation rlThis = oatGetSrc(cUnit, mir, 0);
+ RegLocation rlCmp = oatGetSrc(cUnit, mir, 1);
+ loadValueDirectFixed(cUnit, rlThis, regThis);
+ loadValueDirectFixed(cUnit, rlCmp, regCmp);
+ int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pStringCompareTo));
+ genNullCheck(cUnit, rlThis.sRegLow, regThis, mir);
+ //TUNING: check if rlCmp.sRegLow is already null checked
+ LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
+ oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
+ (intptr_t)launchPad);
+ opCmpImmBranch(cUnit, kCondEq, regCmp, 0, launchPad);
+ opReg(cUnit, kOpBlx, rTgt);
+ launchPad->operands[2] = NULL; // No return possible
+ launchPad->operands[3] = (uintptr_t)bb;
+ // Record that we've already inlined & null checked
+ mir->optimizationFlags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
+ return true;
#else
- return false;
+ return false;
#endif
}
bool genIntrinsic(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
InvokeType type, bool isRange)
{
- if ((mir->optimizationFlags & MIR_INLINED) || isRange) {
- return false;
- }
- /*
- * TODO: move these to a target-specific structured constant array
- * and use a generic match function. The list of intrinsics may be
- * slightly different depending on target.
- * TODO: Fold this into a matching function that runs during
- * basic block building. This should be part of the action for
- * small method inlining and recognition of the special object init
- * method. By doing this during basic block construction, we can also
- * take advantage of/generate new useful dataflow info.
- */
- std::string tgtMethod(PrettyMethod(mir->dalvikInsn.vB, *cUnit->dex_file));
- if (tgtMethod.compare("char java.lang.String.charAt(int)") == 0) {
- return genInlinedCharAt(cUnit, bb, mir, type, isRange);
- }
- if (tgtMethod.compare("int java.lang.Math.min(int, int)") == 0) {
- return genInlinedMinMaxInt(cUnit, bb, mir, true /* isMin */);
- }
- if (tgtMethod.compare("int java.lang.Math.max(int, int)") == 0) {
- return genInlinedMinMaxInt(cUnit, bb, mir, false /* isMin */);
- }
- if (tgtMethod.compare("int java.lang.String.length()") == 0) {
- return genInlinedStringIsEmptyOrLength(cUnit, bb, mir, false /* isEmpty */);
- }
- if (tgtMethod.compare("boolean java.lang.String.isEmpty()") == 0) {
- return genInlinedStringIsEmptyOrLength(cUnit, bb, mir, true /* isEmpty */);
- }
- if (tgtMethod.compare("int java.lang.Math.abs(int)") == 0) {
- return genInlinedAbsInt(cUnit, bb, mir);
- }
- if (tgtMethod.compare("long java.lang.Math.abs(long)") == 0) {
- return genInlinedAbsLong(cUnit, bb, mir);
- }
- if (tgtMethod.compare("int java.lang.Float.floatToRawIntBits(float)") == 0) {
- return genInlinedFloatCvt(cUnit, bb, mir);
- }
- if (tgtMethod.compare("float java.lang.Float.intBitsToFloat(int)") == 0) {
- return genInlinedFloatCvt(cUnit, bb, mir);
- }
- if (tgtMethod.compare("long java.lang.Double.doubleToRawLongBits(double)") == 0) {
- return genInlinedDoubleCvt(cUnit, bb, mir);
- }
- if (tgtMethod.compare("double java.lang.Double.longBitsToDouble(long)") == 0) {
- return genInlinedDoubleCvt(cUnit, bb, mir);
- }
- if (tgtMethod.compare("int java.lang.String.indexOf(int, int)") == 0) {
- return genInlinedIndexOf(cUnit, bb, mir, type, false /* base 0 */);
- }
- if (tgtMethod.compare("int java.lang.String.indexOf(int)") == 0) {
- return genInlinedIndexOf(cUnit, bb, mir, type, true /* base 0 */);
- }
- if (tgtMethod.compare("int java.lang.String.compareTo(java.lang.String)") == 0) {
- return genInlinedStringCompareTo(cUnit, bb, mir, type);
- }
+ if ((mir->optimizationFlags & MIR_INLINED) || isRange) {
return false;
+ }
+ /*
+ * TODO: move these to a target-specific structured constant array
+ * and use a generic match function. The list of intrinsics may be
+ * slightly different depending on target.
+ * TODO: Fold this into a matching function that runs during
+ * basic block building. This should be part of the action for
+ * small method inlining and recognition of the special object init
+ * method. By doing this during basic block construction, we can also
+ * take advantage of/generate new useful dataflow info.
+ */
+ std::string tgtMethod(PrettyMethod(mir->dalvikInsn.vB, *cUnit->dex_file));
+ if (tgtMethod.compare("char java.lang.String.charAt(int)") == 0) {
+ return genInlinedCharAt(cUnit, bb, mir, type, isRange);
+ }
+ if (tgtMethod.compare("int java.lang.Math.min(int, int)") == 0) {
+ return genInlinedMinMaxInt(cUnit, bb, mir, true /* isMin */);
+ }
+ if (tgtMethod.compare("int java.lang.Math.max(int, int)") == 0) {
+ return genInlinedMinMaxInt(cUnit, bb, mir, false /* isMin */);
+ }
+ if (tgtMethod.compare("int java.lang.String.length()") == 0) {
+ return genInlinedStringIsEmptyOrLength(cUnit, bb, mir, false /* isEmpty */);
+ }
+ if (tgtMethod.compare("boolean java.lang.String.isEmpty()") == 0) {
+ return genInlinedStringIsEmptyOrLength(cUnit, bb, mir, true /* isEmpty */);
+ }
+ if (tgtMethod.compare("int java.lang.Math.abs(int)") == 0) {
+ return genInlinedAbsInt(cUnit, bb, mir);
+ }
+ if (tgtMethod.compare("long java.lang.Math.abs(long)") == 0) {
+ return genInlinedAbsLong(cUnit, bb, mir);
+ }
+ if (tgtMethod.compare("int java.lang.Float.floatToRawIntBits(float)") == 0) {
+ return genInlinedFloatCvt(cUnit, bb, mir);
+ }
+ if (tgtMethod.compare("float java.lang.Float.intBitsToFloat(int)") == 0) {
+ return genInlinedFloatCvt(cUnit, bb, mir);
+ }
+ if (tgtMethod.compare("long java.lang.Double.doubleToRawLongBits(double)") == 0) {
+ return genInlinedDoubleCvt(cUnit, bb, mir);
+ }
+ if (tgtMethod.compare("double java.lang.Double.longBitsToDouble(long)") == 0) {
+ return genInlinedDoubleCvt(cUnit, bb, mir);
+ }
+ if (tgtMethod.compare("int java.lang.String.indexOf(int, int)") == 0) {
+ return genInlinedIndexOf(cUnit, bb, mir, type, false /* base 0 */);
+ }
+ if (tgtMethod.compare("int java.lang.String.indexOf(int)") == 0) {
+ return genInlinedIndexOf(cUnit, bb, mir, type, true /* base 0 */);
+ }
+ if (tgtMethod.compare("int java.lang.String.compareTo(java.lang.String)") == 0) {
+ return genInlinedStringCompareTo(cUnit, bb, mir, type);
+ }
+ return false;
}