From 845490bda68f7d025ea7f45775c847d2932e00dc Mon Sep 17 00:00:00 2001 From: Brian Carlstrom Date: Mon, 19 Sep 2011 15:56:53 -0700 Subject: 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 --- src/compiler/codegen/arm/MethodCodegenDriver.cc | 87 ++++++++++++++----------- 1 file changed, 50 insertions(+), 37 deletions(-) (limited to 'src/compiler/codegen/arm/MethodCodegenDriver.cc') 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 -- cgit v1.2.3-59-g8ed1b