summaryrefslogtreecommitdiff
path: root/src/compiler/codegen/arm/MethodCodegenDriver.cc
diff options
context:
space:
mode:
author Brian Carlstrom <bdc@google.com> 2011-09-19 15:56:53 -0700
committer Brian Carlstrom <bdc@google.com> 2011-09-19 16:18:27 -0700
commit845490bda68f7d025ea7f45775c847d2932e00dc (patch)
tree2fc5c0f3fa40a491a3467dfc25d71fc2e23058f1 /src/compiler/codegen/arm/MethodCodegenDriver.cc
parent9d5ccec86d60c9ddd811836b9a2bc28d0b3d11fe (diff)
Cleanup resolution of type, field, method indexes
When resolving a type_idx of a static field, you cannot assume the type_idx refers to the class that actually provides the storage, it might be a subclass. The compiler now resolves to the storage class if possible at compile time, otherwise it reverts to the slow path. When resolve field and method indexes, you need to know if a field is static or instance and if a method is direct or virtual. Previously we tried to guess, which led to problems in classes that had one of each. Now the compiler resolves which kind of field and method based on the context of class definitions and dex instructions. Change-Id: I31826dc90562057eadd81f39d6369aa1216509af
Diffstat (limited to 'src/compiler/codegen/arm/MethodCodegenDriver.cc')
-rw-r--r--src/compiler/codegen/arm/MethodCodegenDriver.cc87
1 files changed, 50 insertions, 37 deletions
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index f42237a235..0af213f6fc 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -130,13 +130,47 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)
}
}
+Field* FindFieldWithResolvedStaticStorage(const Method* method,
+ const uint32_t fieldIdx,
+ uint32_t& resolvedTypeIdx) {
+ art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+ Field* field = class_linker->ResolveField(fieldIdx, method, true);
+ if (field == NULL) {
+ return NULL;
+ }
+ const art::DexFile& dex_file = class_linker->
+ FindDexFile(method->GetDeclaringClass()->GetDexCache());
+ const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
+ int type_idx = field_id.class_idx_;
+ Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+ // Check if storage class is the same as class referred to by type idx.
+ // They may not be if the FieldId refers a subclass, but storage is in super
+ if (field->GetDeclaringClass() == klass) {
+ resolvedTypeIdx = type_idx;
+ return field;
+ }
+ // See if we can find a dex reference for the storage class.
+ // we may not if the dex file never references the super class,
+ // but usually it will.
+ std::string descriptor = field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8();
+ for (size_t type_idx = 0; type_idx < dex_file.NumTypeIds(); type_idx++) {
+ const art::DexFile::TypeId& type_id = dex_file.GetTypeId(type_idx);
+ if (descriptor == dex_file.GetTypeDescriptor(type_id)) {
+ resolvedTypeIdx = type_idx;
+ return field;
+ }
+ }
+ return NULL; // resort to slow path
+}
+
static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
bool isObject = ((mir->dalvikInsn.opcode == OP_SPUT_OBJECT) ||
(mir->dalvikInsn.opcode == OP_SPUT_OBJECT_VOLATILE));
int fieldIdx = mir->dalvikInsn.vB;
- Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
- if (field == NULL) {
+ uint32_t typeIdx;
+ Field* field = FindFieldWithResolvedStaticStorage(cUnit->method, fieldIdx, typeIdx);
+ if (SLOW_FIELD_PATH || field == NULL) {
// Slow path
LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
<< " unresolved at compile time";
@@ -152,12 +186,6 @@ static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
} else {
// fast path
int fieldOffset = field->GetOffset().Int32Value();
- art::ClassLinker* class_linker = art::Runtime::Current()->
- GetClassLinker();
- const art::DexFile& dex_file = class_linker->
- FindDexFile(cUnit->method->GetDeclaringClass()->GetDexCache());
- const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
- int typeIdx = field_id.class_idx_;
// Using fixed register to sync with slow path
int rMethod = r1;
oatLockTemp(cUnit, rMethod);
@@ -196,7 +224,8 @@ static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
static void genSputWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
{
int fieldIdx = mir->dalvikInsn.vB;
- Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
+ uint32_t typeIdx;
+ Field* field = FindFieldWithResolvedStaticStorage(cUnit->method, fieldIdx, typeIdx);
if (SLOW_FIELD_PATH || field == NULL) {
LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
<< " unresolved at compile time";
@@ -210,12 +239,6 @@ static void genSputWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
} else {
// fast path
int fieldOffset = field->GetOffset().Int32Value();
- art::ClassLinker* class_linker = art::Runtime::Current()->
- GetClassLinker();
- const art::DexFile& dex_file = class_linker->
- FindDexFile(cUnit->method->GetDeclaringClass()->GetDexCache());
- const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
- int typeIdx = field_id.class_idx_;
// Using fixed register to sync with slow path
int rMethod = r1;
oatLockTemp(cUnit, rMethod);
@@ -254,7 +277,8 @@ static void genSgetWide(CompilationUnit* cUnit, MIR* mir,
RegLocation rlResult, RegLocation rlDest)
{
int fieldIdx = mir->dalvikInsn.vB;
- Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
+ uint32_t typeIdx;
+ Field* field = FindFieldWithResolvedStaticStorage(cUnit->method, fieldIdx, typeIdx);
if (SLOW_FIELD_PATH || field == NULL) {
LOG(INFO) << "Field " << fieldNameFromIndex(cUnit->method, fieldIdx)
<< " unresolved at compile time";
@@ -268,12 +292,6 @@ static void genSgetWide(CompilationUnit* cUnit, MIR* mir,
} else {
// Fast path
int fieldOffset = field->GetOffset().Int32Value();
- art::ClassLinker* class_linker = art::Runtime::Current()->
- GetClassLinker();
- const art::DexFile& dex_file = class_linker->
- FindDexFile(cUnit->method->GetDeclaringClass()->GetDexCache());
- const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
- int typeIdx = field_id.class_idx_;
// Using fixed register to sync with slow path
int rMethod = r1;
oatLockTemp(cUnit, rMethod);
@@ -312,7 +330,8 @@ static void genSget(CompilationUnit* cUnit, MIR* mir,
RegLocation rlResult, RegLocation rlDest)
{
int fieldIdx = mir->dalvikInsn.vB;
- Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx);
+ uint32_t typeIdx;
+ Field* field = FindFieldWithResolvedStaticStorage(cUnit->method, fieldIdx, typeIdx);
bool isObject = ((mir->dalvikInsn.opcode == OP_SGET_OBJECT) ||
(mir->dalvikInsn.opcode == OP_SGET_OBJECT_VOLATILE));
if (SLOW_FIELD_PATH || field == NULL) {
@@ -331,12 +350,6 @@ static void genSget(CompilationUnit* cUnit, MIR* mir,
} else {
// Fast path
int fieldOffset = field->GetOffset().Int32Value();
- art::ClassLinker* class_linker = art::Runtime::Current()->
- GetClassLinker();
- const art::DexFile& dex_file = class_linker->
- FindDexFile(cUnit->method->GetDeclaringClass()->GetDexCache());
- const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx);
- int typeIdx = field_id.class_idx_;
// Using fixed register to sync with slow path
int rMethod = r1;
oatLockTemp(cUnit, rMethod);
@@ -421,8 +434,8 @@ static int nextVCallInsn(CompilationUnit* cUnit, MIR* mir,
* This is the fast path in which the target virtual method is
* fully resolved at compile time.
*/
- Method* baseMethod = cUnit->method->GetDexCacheResolvedMethods()->
- Get(dInsn->vB);
+ art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+ Method* baseMethod = class_linker->ResolveMethod(dInsn->vB, cUnit->method, false);
CHECK(baseMethod != NULL);
uint32_t target_idx = baseMethod->GetMethodIndex();
switch(state) {
@@ -575,8 +588,8 @@ static int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir,
* that the check to verify that the target method index falls
* within the size of the super's vtable has been done at compile-time.
*/
- Method* baseMethod = cUnit->method->GetDexCacheResolvedMethods()->
- Get(dInsn->vB);
+ art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+ Method* baseMethod = class_linker->ResolveMethod(dInsn->vB, cUnit->method, false);
CHECK(baseMethod != NULL);
Class* superClass = cUnit->method->GetDeclaringClass()->GetSuperClass();
CHECK(superClass != NULL);
@@ -950,8 +963,8 @@ static void genInvokeSuper(CompilationUnit* cUnit, MIR* mir)
int callState = 0;
ArmLIR* nullCk;
ArmLIR* rollback;
- Method* baseMethod = cUnit->method->GetDexCacheResolvedMethods()->
- Get(dInsn->vB);
+ art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+ Method* baseMethod = class_linker->ResolveMethod(dInsn->vB, cUnit->method, false);
NextCallInsn nextCallInsn;
bool fastPath = true;
@@ -1002,8 +1015,8 @@ static void genInvokeVirtual(CompilationUnit* cUnit, MIR* mir)
int callState = 0;
ArmLIR* nullCk;
ArmLIR* rollback;
- Method* method = cUnit->method->GetDexCacheResolvedMethods()->
- Get(dInsn->vB);
+ art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
+ Method* method = class_linker->ResolveMethod(dInsn->vB, cUnit->method, false);
NextCallInsn nextCallInsn;
// Explicit register usage