summaryrefslogtreecommitdiff
path: root/src/compiler/codegen/arm/MethodCodegenDriver.cc
diff options
context:
space:
mode:
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