Complete OP_CONST_STRING, OP_CONST_CLASS
Added dummy ThrowException & ResolveTypeFromCode routines. Fix
OP_CONST_STRING and OP_CONST_CLASS to be position independent. Misc.
bug fixes.
Created a dummy ThrowException compiler run-time helper function. It
should be replaced with the real version.
Change-Id: Iba6a11cf110d3da4fa36ca434fe1b2675b68434d
diff --git a/src/compiler/RuntimeUtilities.cc b/src/compiler/RuntimeUtilities.cc
index 53bd20e..298cef1 100644
--- a/src/compiler/RuntimeUtilities.cc
+++ b/src/compiler/RuntimeUtilities.cc
@@ -17,13 +17,14 @@
#include "Dalvik.h"
#include "CompilerInternals.h"
+namespace art {
/* FIXME - codegen helper functions, move to art runtime proper */
/*
* Float/double conversion requires clamping to min and max of integer form. If
* target doesn't support this normally, use these.
*/
-int64_t artD2L(double d)
+int64_t D2L(double d)
{
static const double kMaxLong = (double)(s8)0x7fffffffffffffffULL;
static const double kMinLong = (double)(s8)0x8000000000000000ULL;
@@ -37,7 +38,7 @@
return (s8)d;
}
-int64_t artF2L(float f)
+int64_t F2L(float f)
{
static const float kMaxLong = (float)(s8)0x7fffffffffffffffULL;
static const float kMinLong = (float)(s8)0x8000000000000000ULL;
@@ -54,7 +55,7 @@
/*
* Temporary placeholder. Should include run-time checks for size
* of fill data <= size of array. If not, throw arrayOutOfBoundsException.
- * As with other new "NoThrow" routines, this should return to the caller
+ * As with other new "FromCode" routines, this should return to the caller
* only if no exception has been thrown.
*
* NOTE: When dealing with a raw dex file, the data to be copied uses
@@ -68,7 +69,7 @@
* ubyte data[size*width] table of data values (may contain a single-byte
* padding at the end)
*/
-void artHandleFillArrayDataNoThrow(Array* array, const uint16_t* table)
+void HandleFillArrayDataFromCode(Array* array, const uint16_t* table)
{
uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16);
uint32_t size_in_bytes = size * table[1];
@@ -76,3 +77,5 @@
memcpy((char*)array + art::Array::DataOffset().Int32Value(),
(char*)&table[4], size_in_bytes);
}
+
+} // namespace art
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index c8c7e34..2438719 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -36,6 +36,17 @@
#endif
}
+static int loadCurrMethod(CompilationUnit *cUnit)
+{
+#if defined(METHOD_IN_REG)
+ return rMETHOD;
+#else
+ int mReg = oatAllocTemp(cUnit);
+ loadCurrMethodDirect(cUnit, mReg);
+ return mReg;
+#endif
+}
+
/*
* Perform a "reg cmp imm" operation and jump to the PCR region if condition
* satisfies.
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index c4b30b2..c69a27e 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -559,6 +559,8 @@
for (int i = 0; i < 3; i++) {
if (args[i] != INVALID_REG) {
RegLocation rlArg = oatGetSrc(cUnit, mir, i);
+ // Arguments are treated as a series of untyped 32-bit values.
+ rlArg.wide = false;
loadValueDirectFixed(cUnit, rlArg, r1 + i);
callState = nextCallInsn(cUnit, mir, dInsn, callState);
}
@@ -579,7 +581,7 @@
static int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir,
DecodedInstruction* dInsn, int state)
{
- UNIMPLEMENTED(FATAL) << "Update with new cache model";
+ UNIMPLEMENTED(FATAL) << "Need findInterfaceMethodInCache";
#if 0
RegLocation rlArg;
switch(state) {
@@ -628,7 +630,7 @@
static int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir,
DecodedInstruction* dInsn, int state)
{
- UNIMPLEMENTED(FATAL) << "Update with new cache model";
+ UNIMPLEMENTED(FATAL) << "Need INVOKE_SUPER implementation";
#if 0
RegLocation rlArg;
switch(state) {
@@ -763,10 +765,10 @@
* Make sure range list doesn't span the break between in normal
* Dalvik vRegs and the ins.
*/
- int highestVreg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
- if (highestVreg >= cUnit->method->num_registers_ -
- cUnit->method->num_ins_) {
- LOG(FATAL) << "Wide argument spanned locals & args";
+ int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
+ int boundaryReg = cUnit->method->num_registers_ - cUnit->method->num_ins_;
+ if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) {
+ LOG(FATAL) << "Argument list spanned locals & args";
}
/*
@@ -777,11 +779,21 @@
*/
// Scan the rest of the args - if in physReg flush to memory
for (int i = 4; i < numArgs; i++) {
- RegLocation loc = oatUpdateLoc(cUnit,
- oatGetSrc(cUnit, mir, i));
- if (loc.location == kLocPhysReg) { // TUNING: if dirty?
- storeBaseDisp(cUnit, rSP, loc.spOffset, loc.lowReg, kWord);
- callState = nextCallInsn(cUnit, mir, dInsn, callState);
+ RegLocation loc = oatGetSrc(cUnit, mir, i);
+ //TODO: generic loc flushing routine
+ if (loc.wide) {
+ loc = oatUpdateLocWide(cUnit, loc);
+ if (loc.location == kLocPhysReg) { // TUNING: if dirty?
+ storeBaseDispWide(cUnit, rSP, loc.spOffset, loc.lowReg,
+ loc.highReg);
+ callState = nextCallInsn(cUnit, mir, dInsn, callState);
+ }
+ } else {
+ loc = oatUpdateLoc(cUnit, loc);
+ if (loc.location == kLocPhysReg) { // TUNING: if dirty?
+ storeBaseDisp(cUnit, rSP, loc.spOffset, loc.lowReg, kWord);
+ callState = nextCallInsn(cUnit, mir, dInsn, callState);
+ }
}
}
@@ -799,11 +811,11 @@
int regsLeft = std::min(numArgs - 3, 16);
callState = nextCallInsn(cUnit, mir, dInsn, callState);
opRegRegImm(cUnit, kOpAdd, r3, rSP, startOffset);
- newLIR3(cUnit, kThumb2Vldms, r3, fr0 & FP_REG_MASK, regsLeft);
+ newLIR3(cUnit, kThumb2Vldms, r3, fr0, regsLeft);
callState = nextCallInsn(cUnit, mir, dInsn, callState);
opRegRegImm(cUnit, kOpAdd, r3, rSP, 4 /* Method* */ + (3 * 4));
callState = nextCallInsn(cUnit, mir, dInsn, callState);
- newLIR3(cUnit, kThumb2Vstms, r3, fr0 & FP_REG_MASK, regsLeft);
+ newLIR3(cUnit, kThumb2Vstms, r3, fr0, regsLeft);
callState = nextCallInsn(cUnit, mir, dInsn, callState);
}
@@ -1287,7 +1299,7 @@
genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
break;
case OP_APUT_OBJECT:
- genArrayPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
+ genArrayObjPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
break;
case OP_APUT_SHORT:
case OP_APUT_CHAR:
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 258b57b..11146f7 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -40,6 +40,14 @@
}
#endif
+/* Generate unconditional branch instructions */
+static ArmLIR* genUnconditionalBranch(CompilationUnit* cUnit, ArmLIR* target)
+{
+ ArmLIR* branch = opNone(cUnit, kOpUncondBr);
+ branch->generic.target = (LIR*) target;
+ return branch;
+}
+
/*
* Generate a Thumb2 IT instruction, which can nullify up to
* four subsequent instructions based on a condition and its
@@ -341,7 +349,7 @@
oatFlushAllRegs(cUnit); /* Everything to home location */
loadValueDirectFixed(cUnit, rlSrc, r0);
loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pArtHandleFillArrayDataNoThrow), rLR);
+ OFFSETOF_MEMBER(Thread, pHandleFillArrayDataFromCode), rLR);
// Materialize a pointer to the fill data image
newLIR3(cUnit, kThumb2AdrST, r1, 0, (intptr_t)tabRec);
opReg(cUnit, kOpBlx, rLR);
@@ -496,33 +504,60 @@
static void genConstClass(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest, RegLocation rlSrc)
{
- Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
- GetResolvedType(mir->dalvikInsn.vB);
-
- if (classPtr == NULL) {
- LOG(FATAL) << "Unexpected null class pointer";
- }
-
- UNIMPLEMENTED(WARNING) << "Not position independent. Fix";
+ art::Class* classPtr = cUnit->method->dex_cache_resolved_types_->
+ Get(mir->dalvikInsn.vB);
+ int mReg = loadCurrMethod(cUnit);
+ int resReg = oatAllocTemp(cUnit);
RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- loadConstantNoClobber(cUnit, rlResult.lowReg, (int) classPtr );
- storeValue(cUnit, rlDest, rlResult);
+ loadWordDisp(cUnit, mReg, OFFSETOF_MEMBER(Method, dex_cache_strings_),
+ resReg);
+ loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
+ (sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
+ if (classPtr != NULL) {
+ // Fast path, we're done - just store result
+ storeValue(cUnit, rlDest, rlResult);
+ } else {
+ // Slow path. Must test at runtime
+ ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, rlResult.lowReg,
+ 0);
+ // Resolved, store and hop over following code
+ storeValue(cUnit, rlDest, rlResult);
+ ArmLIR* branch2 = genUnconditionalBranch(cUnit,0);
+ // TUNING: move slow path to end & remove unconditional branch
+ ArmLIR* target1 = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target1->defMask = ENCODE_ALL;
+ // Call out to helper, which will return resolved type in r0
+ loadWordDisp(cUnit, rSELF,
+ OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR);
+ genRegCopy(cUnit, r1, mReg);
+ loadConstant(cUnit, r0, mir->dalvikInsn.vB);
+ opReg(cUnit, kOpBlx, rLR); // resolveTypeFromCode(idx, method)
+ oatClobberCallRegs(cUnit);
+ RegLocation rlResult = oatGetReturn(cUnit);
+ storeValue(cUnit, rlDest, rlResult);
+ // Rejoin code paths
+ ArmLIR* target2 = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target2->defMask = ENCODE_ALL;
+ branch1->generic.target = (LIR*)target1;
+ branch2->generic.target = (LIR*)target2;
+ }
}
static void genConstString(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest, RegLocation rlSrc)
{
- const String* strPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
- GetResolvedString(mir->dalvikInsn.vB);
+ /* All strings should be available at compile time */
+ const art::String* str = cUnit->method->dex_cache_strings_->
+ Get(mir->dalvikInsn.vB);
+ DCHECK(str != NULL);
- if (strPtr == NULL) {
- /* Shouldn't happen */
- LOG(FATAL) << "Unexpected null const string pointer";
- }
-
- UNIMPLEMENTED(WARNING) << "Not position indendent. Fix";
+ int mReg = loadCurrMethod(cUnit);
+ int resReg = oatAllocTemp(cUnit);
RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- loadConstantNoClobber(cUnit, rlResult.lowReg, (int) strPtr );
+ loadWordDisp(cUnit, mReg, OFFSETOF_MEMBER(Method, dex_cache_strings_),
+ resReg);
+ loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
+ (sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
storeValue(cUnit, rlDest, rlResult);
}
@@ -547,10 +582,10 @@
void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pArtAllocObjectNoThrow), rLR);
- loadValueDirectFixed(cUnit, rlSrc, r1); /* Exception object */
+ OFFSETOF_MEMBER(Thread, pThrowException), rLR);
+ loadValueDirectFixed(cUnit, rlSrc, r1); // Get exception object
genRegCopy(cUnit, r0, rSELF);
- opReg(cUnit, kOpBlx, rLR);
+ opReg(cUnit, kOpBlx, rLR); // artThrowException(thread, exception);
}
static void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
@@ -574,7 +609,7 @@
loadWordDisp(cUnit, r0, OFFSETOF_MEMBER(Object, klass_), r1);
/* r1 now contains object->clazz */
loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pArtInstanceofNonTrivial), rLR);
+ OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
loadConstant(cUnit, r0, 1); /* Assume true */
opRegReg(cUnit, kOpCmp, r1, r2);
ArmLIR* branch2 = opCondBranch(cUnit, kArmCondEq);
@@ -614,7 +649,7 @@
/* r0 now contains object->clazz */
loadWordDisp(cUnit, rlSrc.lowReg, OFFSETOF_MEMBER(Object, klass_), r0);
loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pArtInstanceofNonTrivialNoThrow), rLR);
+ OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
opRegReg(cUnit, kOpCmp, r0, r1);
ArmLIR* branch2 = opCondBranch(cUnit, kArmCondEq);
// Assume success - if not, artInstanceOfNonTrivial will handle throw
@@ -782,8 +817,8 @@
hopTarget->defMask = ENCODE_ALL;
hopBranch->generic.target = (LIR*)hopTarget;
- // Go expensive route - artLockObjectNoThrow(self, obj);
- loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtLockObjectNoThrow),
+ // Go expensive route - artLockObjectFromCode(self, obj);
+ loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pLockObjectFromCode),
rLR);
genRegCopy(cUnit, r0, rSELF);
newLIR1(cUnit, kThumbBlxR, rLR);
@@ -832,8 +867,8 @@
hopTarget->defMask = ENCODE_ALL;
hopBranch->generic.target = (LIR*)hopTarget;
- // Go expensive route - artUnlockObjectNoThrow(self, obj);
- loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtUnlockObjectNoThrow),
+ // Go expensive route - UnlockObjectFromCode(self, obj);
+ loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode),
rLR);
genRegCopy(cUnit, r0, rSELF);
newLIR1(cUnit, kThumbBlxR, rLR);
@@ -1057,13 +1092,13 @@
2, 1);
case OP_FLOAT_TO_LONG:
return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
- pArtF2l), 1, 2);
+ pF2l), 1, 2);
case OP_LONG_TO_FLOAT:
return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2f),
2, 1);
case OP_DOUBLE_TO_LONG:
return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
- pArtD2l), 2, 2);
+ pD2l), 2, 2);
case OP_LONG_TO_DOUBLE:
return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2d),
2, 2);
@@ -1095,9 +1130,9 @@
* Generate array store
*
*/
-static void genArrayPut(CompilationUnit* cUnit, MIR* mir,
- RegLocation rlArray, RegLocation rlIndex,
- RegLocation rlSrc, int scale)
+static void genArrayObjPut(CompilationUnit* cUnit, MIR* mir,
+ RegLocation rlArray, RegLocation rlIndex,
+ RegLocation rlSrc, int scale)
{
RegisterClass regClass = oatRegClassBySize(kWord);
int lenOffset = Array::LengthOffset().Int32Value();
@@ -1115,7 +1150,7 @@
mir->offset, NULL);
}
loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pArtCanPutArrayElementNoThrow), rLR);
+ OFFSETOF_MEMBER(Thread, pCanPutArrayElementFromCode), rLR);
/* Get the array's clazz */
loadWordDisp(cUnit, r1, OFFSETOF_MEMBER(Object, klass_), r1);
/* Get the object's clazz */
@@ -1546,14 +1581,6 @@
return false;
}
-/* Generate unconditional branch instructions */
-static ArmLIR* genUnconditionalBranch(CompilationUnit* cUnit, ArmLIR* target)
-{
- ArmLIR* branch = opNone(cUnit, kOpUncondBr);
- branch->generic.target = (LIR*) target;
- return branch;
-}
-
/*
* Fetch *self->info.breakFlags. If the breakFlags are non-zero,
* punt to the interpreter.