Merge "Verifier now generates register maps, though nothing uses them yet." into dalvik-dev
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 0df0cb7..01e283e 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2114,10 +2114,10 @@
const char* name = dex_file.dexStringById(method_id.name_idx_);
std::string signature(dex_file.CreateMethodDescriptor(method_id.proto_idx_, NULL));
- if (klass->IsInterface()) {
- resolved = klass->FindInterfaceMethod(name, signature);
- } else if (is_direct) {
+ if (is_direct) {
resolved = klass->FindDirectMethod(name, signature);
+ } else if (klass->IsInterface()) {
+ resolved = klass->FindInterfaceMethod(name, signature);
} else {
resolved = klass->FindVirtualMethod(name, signature);
}
diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h
index c702204..67ed6ee 100644
--- a/src/compiler/codegen/Ralloc.h
+++ b/src/compiler/codegen/Ralloc.h
@@ -171,6 +171,8 @@
/* To be used when explicitly managing register use */
extern void oatLockCallTemps(CompilationUnit* cUnit);
+extern void oatFreeCallTemps(CompilationUnit* cUnit);
+
extern void oatFlushAllRegs(CompilationUnit* cUnit);
extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit);
diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc
index 5951ad4..1fe680f 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -712,6 +712,16 @@
oatLockTemp(cUnit, r3);
}
+/* To be used when explicitly managing register use */
+extern void oatFreeCallTemps(CompilationUnit* cUnit)
+{
+ //TODO: Arm specific - move to target dependent code
+ oatFreeTemp(cUnit, r0);
+ oatFreeTemp(cUnit, r1);
+ oatFreeTemp(cUnit, r2);
+ oatFreeTemp(cUnit, r3);
+}
+
// Make sure nothing is live and dirty
static void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
int numRegs)
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 44cbc0e..cf1ad04 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-#define FORCE_SLOW 0
-#define DISPLAY_MISSING_TARGETS
-
static const RegLocation badLoc = {kLocDalvikFrame, 0, 0, INVALID_REG,
INVALID_REG, INVALID_SREG, 0,
kLocDalvikFrame, INVALID_REG, INVALID_REG,
@@ -146,6 +143,8 @@
Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
if (field == NULL) {
// Slow path
+ LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
+ << " unresolved at compile time";
int funcOffset = isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic)
: OFFSETOF_MEMBER(Thread, pSet32Static);
oatFlushAllRegs(cUnit);
@@ -203,7 +202,9 @@
{
int fieldIdx = mir->dalvikInsn.vB;
Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
- if (FORCE_SLOW || field == NULL) {
+ if (SLOW_FIELD_PATH || field == NULL) {
+ LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
+ << " unresolved at compile time";
oatFlushAllRegs(cUnit);
loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pSet64Static), rLR);
loadConstant(cUnit, r0, mir->dalvikInsn.vB);
@@ -259,7 +260,9 @@
{
int fieldIdx = mir->dalvikInsn.vB;
Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
- if (FORCE_SLOW || field == NULL) {
+ if (SLOW_FIELD_PATH || field == NULL) {
+ LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
+ << " unresolved at compile time";
oatFlushAllRegs(cUnit);
loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pGet64Static), rLR);
loadConstant(cUnit, r0, mir->dalvikInsn.vB);
@@ -317,7 +320,9 @@
Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
bool isObject = ((mir->dalvikInsn.opcode == OP_SGET_OBJECT) ||
(mir->dalvikInsn.opcode == OP_SGET_OBJECT_VOLATILE));
- if (FORCE_SLOW || field == NULL) {
+ if (SLOW_FIELD_PATH || field == NULL) {
+ LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
+ << " unresolved at compile time";
// Slow path
int funcOffset = isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic)
: OFFSETOF_MEMBER(Thread, pGet32Static);
@@ -950,7 +955,7 @@
// Explicit register usage
oatLockCallTemps(cUnit);
- if (FORCE_SLOW || baseMethod == NULL) {
+ if (SLOW_INVOKE_PATH || baseMethod == NULL) {
fastPath = false;
} else {
Class* superClass = cUnit->method->GetDeclaringClass()->GetSuperClass();
@@ -1001,7 +1006,7 @@
// Explicit register usage
oatLockCallTemps(cUnit);
- if (FORCE_SLOW || method == NULL) {
+ if (SLOW_INVOKE_PATH || method == NULL) {
// Slow path
nextCallInsn = nextVCallInsnSP;
// If we need a slow-path callout, we'll restart here
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index dbaf9ea..ce1c9a7 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -22,6 +22,22 @@
*
*/
+#define SLOW_FIELD_PATH 0
+#define SLOW_INVOKE_PATH 0
+#define DISPLAY_MISSING_TARGETS
+//#define EXERCISE_SLOWEST_FIELD_PATH
+
+std::string fieldNameFromIndex(const Method* method, uint32_t fieldIdx)
+{
+ art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+ const art::DexFile& dex_file = class_linker->FindDexFile(
+ method->GetDeclaringClass()->GetDexCache());
+ const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
+ std::string class_name = dex_file.dexStringById(field_id.class_idx_);
+ std::string field_name = dex_file.dexStringById(field_id.name_idx_);
+ return class_name + "." + field_name;
+}
+
/*
* Construct an s4 from two consecutive half-words of switch data.
* This needs to check endianness because the DEX optimizer only swaps
@@ -361,9 +377,8 @@
*/
static void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
{
-#if 1
- UNIMPLEMENTED(WARNING);
-#else
+#if 0
+ // TODO: re-enable when concurrent collector is active
int regCardBase = oatAllocTemp(cUnit);
int regCardNo = oatAllocTemp(cUnit);
ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondEq, valReg, 0);
@@ -380,33 +395,80 @@
#endif
}
+/*
+ * Helper function for Iget/put when field not resolved at compile time.
+ * Will trash call temps and return with the field offset in r0.
+ */
+static void getFieldOffset(CompilationUnit* cUnit, MIR* mir)
+{
+ int fieldIdx = mir->dalvikInsn.vC;
+ LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
+ << " unresolved at compile time";
+ oatLockCallTemps(cUnit); // Explicit register usage
+ loadCurrMethodDirect(cUnit, r1); // arg1 <= Method*
+ loadWordDisp(cUnit, r1,
+ Method::DexCacheResolvedFieldsOffset().Int32Value(), r0);
+ loadWordDisp(cUnit, r0, art::Array::DataOffset().Int32Value() +
+ sizeof(int32_t*)* fieldIdx, r0);
+ /*
+ * For testing, omit the test for run-time resolution. This will
+ * force all accesses to go through the runtime resolution path.
+ */
+#ifndef EXERCISE_SLOWEST_FIELD_PATH
+ ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
+#endif
+ // Resolve
+ loadWordDisp(cUnit, rSELF,
+ OFFSETOF_MEMBER(Thread, pFindFieldFromCode), rLR);
+ loadConstant(cUnit, r0, fieldIdx);
+ opReg(cUnit, kOpBlx, rLR); // resolveTypeFromCode(idx, method)
+ ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target->defMask = ENCODE_ALL;
+#ifndef EXERCISE_SLOWEST_FIELD_PATH
+ branchOver->generic.target = (LIR*)target;
+#endif
+ // Free temps (except for r0)
+ oatFreeTemp(cUnit, r1);
+ oatFreeTemp(cUnit, r2);
+ oatFreeTemp(cUnit, r3);
+ loadWordDisp(cUnit, r0, art::Field::OffsetOffset().Int32Value(), r0);
+}
+
static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size,
RegLocation rlDest, RegLocation rlObj)
{
Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
GetResolvedField(mir->dalvikInsn.vC);
- if (fieldPtr == NULL) {
- UNIMPLEMENTED(FATAL) << "Need to handle unresolved field";
- }
-#if ANDROID_SMP != 0
- bool isVolatile = dvmIsVolatileField(fieldPtr);
-#else
- bool isVolatile = false;
-#endif
- int fieldOffset = fieldPtr->GetOffset().Int32Value();
RegLocation rlResult;
RegisterClass regClass = oatRegClassBySize(size);
- rlObj = loadValue(cUnit, rlObj, kCoreReg);
- rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
- NULL);/* null object? */
- loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
- size, rlObj.sRegLow);
- if (isVolatile) {
+ if (SLOW_FIELD_PATH || fieldPtr == NULL) {
+ getFieldOffset(cUnit, mir);
+ // Field offset in r0
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
+ loadBaseIndexed(cUnit, rlObj.lowReg, r0, rlResult.lowReg, 0, size);
oatGenMemBarrier(cUnit, kSY);
+ storeValue(cUnit, rlDest, rlResult);
+ } else {
+#if ANDROID_SMP != 0
+ bool isVolatile = dvmIsVolatileField(fieldPtr);
+#else
+ bool isVolatile = false;
+#endif
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ rlResult = oatEvalLoc(cUnit, rlDest, regClass, true);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
+ loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
+ size, rlObj.sRegLow);
+ if (isVolatile) {
+ oatGenMemBarrier(cUnit, kSY);
+ }
+ storeValue(cUnit, rlDest, rlResult);
}
-
- storeValue(cUnit, rlDest, rlResult);
}
static void genIPutX(CompilationUnit* cUnit, MIR* mir, OpSize size,
@@ -414,25 +476,33 @@
{
Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
GetResolvedField(mir->dalvikInsn.vC);
- if (fieldPtr == NULL) {
- UNIMPLEMENTED(FATAL) << "Need to handle unresolved field";
- }
-#if ANDROID_SMP != 0
- bool isVolatile = dvmIsVolatileField(fieldPtr);
-#else
- bool isVolatile = false;
-#endif
- int fieldOffset = fieldPtr->GetOffset().Int32Value();
RegisterClass regClass = oatRegClassBySize(size);
- rlObj = loadValue(cUnit, rlObj, kCoreReg);
- rlSrc = loadValue(cUnit, rlSrc, regClass);
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
- NULL);/* null object? */
-
- if (isVolatile) {
+ if (SLOW_FIELD_PATH || fieldPtr == NULL) {
+ getFieldOffset(cUnit, mir);
+ // Field offset in r0
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ rlSrc = loadValue(cUnit, rlSrc, regClass);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
oatGenMemBarrier(cUnit, kSY);
+ storeBaseIndexed(cUnit, rlObj.lowReg, r0, rlSrc.lowReg, 0, size);
+ } else {
+#if ANDROID_SMP != 0
+ bool isVolatile = dvmIsVolatileField(fieldPtr);
+#else
+ bool isVolatile = false;
+#endif
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ rlSrc = loadValue(cUnit, rlSrc, regClass);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
+
+ if (isVolatile) {
+ oatGenMemBarrier(cUnit, kSY);
+ }
+ storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
}
- storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
if (isObject) {
/* NOTE: marking card based on object head */
markGCCard(cUnit, rlSrc.lowReg, rlObj.lowReg);
@@ -444,34 +514,44 @@
{
Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
GetResolvedField(mir->dalvikInsn.vC);
- if (fieldPtr == NULL) {
- UNIMPLEMENTED(FATAL) << "Need to handle unresolved field";
- }
-#if ANDROID_SMP != 0
- bool isVolatile = dvmIsVolatileField(fieldPtr);
-#else
- bool isVolatile = false;
-#endif
- int fieldOffset = fieldPtr->GetOffset().Int32Value();
RegLocation rlResult;
- rlObj = loadValue(cUnit, rlObj, kCoreReg);
- int regPtr = oatAllocTemp(cUnit);
-
- assert(rlDest.wide);
-
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
- NULL);/* null object? */
- opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
- rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
-
- loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
-
- if (isVolatile) {
+ if (fieldPtr == NULL) {
+ getFieldOffset(cUnit, mir);
+ // Field offset in r0
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
+ opRegReg(cUnit, kOpAdd, r0, rlObj.lowReg);
+ loadPair(cUnit, r0, rlResult.lowReg, rlResult.highReg);
oatGenMemBarrier(cUnit, kSY);
- }
+ storeValue(cUnit, rlDest, rlResult);
+ } else {
+#if ANDROID_SMP != 0
+ bool isVolatile = dvmIsVolatileField(fieldPtr);
+#else
+ bool isVolatile = false;
+#endif
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ int regPtr = oatAllocTemp(cUnit);
- oatFreeTemp(cUnit, regPtr);
- storeValueWide(cUnit, rlDest, rlResult);
+ assert(rlDest.wide);
+
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
+ opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
+ rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
+
+ loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
+
+ if (isVolatile) {
+ oatGenMemBarrier(cUnit, kSY);
+ }
+
+ oatFreeTemp(cUnit, regPtr);
+ storeValueWide(cUnit, rlDest, rlResult);
+ }
}
static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
@@ -480,29 +560,38 @@
Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
GetResolvedField(mir->dalvikInsn.vC);
if (fieldPtr == NULL) {
- UNIMPLEMENTED(FATAL) << "Need to handle unresolved field";
- }
-#if ANDROID_SMP != 0
- bool isVolatile = dvmIsVolatileField(fieldPtr);
-#else
- bool isVolatile = false;
-#endif
- int fieldOffset = fieldPtr->GetOffset().Int32Value();
-
- rlObj = loadValue(cUnit, rlObj, kCoreReg);
- int regPtr;
- rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
- genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
- NULL);/* null object? */
- regPtr = oatAllocTemp(cUnit);
- opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
-
- if (isVolatile) {
+ getFieldOffset(cUnit, mir);
+ // Field offset in r0
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
+ opRegReg(cUnit, kOpAdd, r0, rlObj.lowReg);
oatGenMemBarrier(cUnit, kSY);
- }
- storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
+ storePair(cUnit, r0, rlSrc.lowReg, rlSrc.highReg);
+ } else {
+#if ANDROID_SMP != 0
+ bool isVolatile = dvmIsVolatileField(fieldPtr);
+#else
+ bool isVolatile = false;
+#endif
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
- oatFreeTemp(cUnit, regPtr);
+ rlObj = loadValue(cUnit, rlObj, kCoreReg);
+ int regPtr;
+ rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
+ genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
+ NULL);/* null object? */
+ regPtr = oatAllocTemp(cUnit);
+ opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
+
+ if (isVolatile) {
+ oatGenMemBarrier(cUnit, kSY);
+ }
+ storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
+
+ oatFreeTemp(cUnit, regPtr);
+ }
}
static void genConstClass(CompilationUnit* cUnit, MIR* mir,
@@ -1618,22 +1707,22 @@
return false;
}
-/*
- * Fetch *self->info.breakFlags. If the breakFlags are non-zero,
- * punt to the interpreter.
- */
+/* Check for pending suspend request. */
static void genSuspendPoll(CompilationUnit* cUnit, MIR* mir)
{
- UNIMPLEMENTED(WARNING);
-#if 0
- int rTemp = oatAllocTemp(cUnit);
+ oatLockCallTemps(cUnit); // Explicit register usage
+ int rSuspendCount = r1;
ArmLIR* ld;
- ld = loadBaseDisp(cUnit, NULL, rSELF,
- offsetof(Thread, interpBreak.ctl.breakFlags),
- rTemp, kUnsignedByte, INVALID_SREG);
+ ld = loadWordDisp(cUnit, rSELF,
+ art::Thread::SuspendCountOffset().Int32Value(), rSuspendCount);
setMemRefType(ld, true /* isLoad */, kMustNotAlias);
- genRegImmCheck(cUnit, kArmCondNe, rTemp, 0, mir->offset, NULL);
-#endif
+ loadWordDisp(cUnit, rSELF,
+ OFFSETOF_MEMBER(Thread, pCheckSuspendFromCode), rLR);
+ genRegCopy(cUnit, r0, rSELF);
+ opRegImm(cUnit, kOpCmp, rSuspendCount, 0);
+ genIT(cUnit, kArmCondNe, "");
+ opReg(cUnit, kOpBlx, rLR); // CheckSuspendFromCode(self)
+ oatFreeCallTemps(cUnit);
}
/*
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index e232858..5766a4f 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -56,7 +56,7 @@
}
};
-// TODO renenable when compiler can handle libcore
+// Disabled due to 10 second runtime on host
TEST_F(CompilerTest, DISABLED_CompileDexLibCore) {
Compiler compiler;
compiler.CompileAll(NULL);
@@ -67,22 +67,27 @@
EXPECT_EQ(dex->NumStringIds(), dex_cache->NumStrings());
for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
const String* string = dex_cache->GetResolvedString(i);
- EXPECT_TRUE(string != NULL);
+ EXPECT_TRUE(string != NULL) << "string_idx=" << i;
}
EXPECT_EQ(dex->NumTypeIds(), dex_cache->NumResolvedTypes());
for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
Class* type = dex_cache->GetResolvedType(i);
- EXPECT_TRUE(type != NULL);
+ EXPECT_TRUE(type != NULL) << "type_idx=" << i
+ << " " << dex->GetTypeDescriptor(dex->GetTypeId(i));
}
EXPECT_EQ(dex->NumMethodIds(), dex_cache->NumResolvedMethods());
for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
Method* method = dex_cache->GetResolvedMethod(i);
- EXPECT_TRUE(method != NULL);
+ EXPECT_TRUE(method != NULL) << "method_idx=" << i
+ << " " << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
+ << " " << dex->GetMethodName(dex->GetMethodId(i));
}
EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields());
for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
Field* field = dex_cache->GetResolvedField(i);
- EXPECT_TRUE(field != NULL);
+ EXPECT_TRUE(field != NULL) << "field_idx=" << i
+ << " " << dex->GetFieldClassDescriptor(dex->GetFieldId(i))
+ << " " << dex->GetFieldName(dex->GetFieldId(i));
}
// TODO check Class::IsVerified for all classes
@@ -93,8 +98,13 @@
CodeAndDirectMethods* code_and_direct_methods = dex_cache->GetCodeAndDirectMethods();
for (size_t i = 0; i < dex_cache->NumCodeAndDirectMethods(); i++) {
Method* method = dex_cache->GetResolvedMethod(i);
- EXPECT_EQ(method->GetCode(), code_and_direct_methods->GetResolvedCode(i));
- EXPECT_EQ(method, code_and_direct_methods->GetResolvedMethod(i));
+ if (method->IsDirect()) {
+ EXPECT_EQ(method->GetCode(), code_and_direct_methods->GetResolvedCode(i));
+ EXPECT_EQ(method, code_and_direct_methods->GetResolvedMethod(i));
+ } else {
+ EXPECT_EQ(0U, code_and_direct_methods->GetResolvedCode(i));
+ EXPECT_TRUE(code_and_direct_methods->GetResolvedMethod(i) == NULL);
+ }
}
}
diff --git a/src/dex_file.h b/src/dex_file.h
index 98e79a7..cf0bf20 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -428,6 +428,17 @@
return dexStringById(field_id.name_idx_);
}
+ // Returns the class descriptor string of a method id.
+ const char* GetMethodClassDescriptor(const MethodId& method_id) const {
+ const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
+ return GetTypeDescriptor(type_id);
+ }
+
+ // Returns the name of a method id.
+ const char* GetMethodName(const MethodId& method_id) const {
+ return dexStringById(method_id.name_idx_);
+ }
+
// Returns the StringId at the specified index.
const StringId& GetStringId(uint32_t idx) const {
CHECK_LT(idx, NumStringIds());
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index b3d21a3..307a804 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -31,6 +31,8 @@
// TODO: if concurrent, clear the card table.
+ // TODO: if concurrent, enable card marking in compiler
+
// TODO: check that the mark bitmap is entirely clear.
return true;
diff --git a/src/object.cc b/src/object.cc
index 7c27ec7..c66791b 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -56,7 +56,7 @@
return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
}
-Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer) {
+Field* Field::FindFieldFromCode(uint32_t field_idx, const Method* referrer) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Field* f = class_linker->ResolveField(field_idx, referrer);
if (f != NULL) {
diff --git a/src/object.h b/src/object.h
index 9e5cf2d..72a03ba 100644
--- a/src/object.h
+++ b/src/object.h
@@ -524,6 +524,12 @@
// Offset to field within an Object
MemberOffset GetOffset() const;
+ static MemberOffset OffsetOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Field, offset_));
+ }
+
+ static Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer);
+
MemberOffset GetOffsetDuringLinking() const;
void SetOffset(MemberOffset num_bytes);
@@ -778,6 +784,10 @@
return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_);
}
+ static MemberOffset DexCacheResolvedFieldsOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_);
+ }
+
static MemberOffset DexCacheInitializedStaticStorageOffset() {
return OFFSET_OF_OBJECT_MEMBER(Method,
dex_cache_initialized_static_storage_);
diff --git a/src/thread.cc b/src/thread.cc
index 3081d91..6109825 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -127,6 +127,15 @@
obj->MonitorEnter(thread);
}
+// TODO: placeholder
+static void CheckSuspendFromCode(Thread* thread) {
+ /*
+ * Code is at a safe point, suspend if needed.
+ * Also, this is where a pending safepoint callback
+ * would be fired.
+ */
+}
+
void Thread::InitFunctionPointers() {
#if defined(__arm__)
pShlLong = art_shl_long;
@@ -177,6 +186,8 @@
pCheckCastFromCode = CheckCastFromCode;
pLockObjectFromCode = LockObjectFromCode;
pUnlockObjectFromCode = UnlockObjectFromCode;
+ pFindFieldFromCode = Field::FindFieldFromCode;
+ pCheckSuspendFromCode = CheckSuspendFromCode;
pDebugMe = DebugMe;
}
diff --git a/src/thread.h b/src/thread.h
index df162b9..ba5d6ef 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -229,6 +229,8 @@
void (*pResolveMethodFromCode)(Method*, uint32_t);
void (*pInvokeInterfaceTrampoline)(void*, void*, void*, void*);
StaticStorageBase* (*pInitializeStaticStorage)(uint32_t, const Method*);
+ Field* (*pFindFieldFromCode)(uint32_t, const Method*);
+ void (*pCheckSuspendFromCode)(Thread*);
class StackVisitor {
public: