Merge "ART: Fix .bss index lookup in wrong dex file."
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 4ac9967..f756312 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -104,6 +104,25 @@
}
}
+static ALWAYS_INLINE bool CanReferenceBss(ArtMethod* outer_method, ArtMethod* caller)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // .bss references are used only for AOT-compiled code and only when the instruction
+ // originates from the outer method's dex file and the type or string index is tied to
+ // that dex file. As we do not want to check if the call is coming from AOT-compiled
+ // code (that could be expensive), simply check if the caller has the same dex file.
+ //
+ // If we've accepted running AOT-compiled code despite the runtime class loader
+ // resolving the caller to a different dex file, this check shall prevent us from
+ // filling the .bss slot and we shall keep going through the slow path. This is slow
+ // but correct; we do not really care that much about performance in this odd case.
+ //
+ // JIT can inline throwing instructions across dex files and this check prevents
+ // looking up the index in the wrong dex file in that case. If the caller and outer
+ // method have the same dex file, we may or may not find a .bss slot to update;
+ // if we do, this can still benefit AOT-compiled code executed later.
+ return outer_method->GetDexFile() == caller->GetDexFile();
+}
+
extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
// Called to ensure static storage base is initialized for direct static field reads and writes.
@@ -113,9 +132,12 @@
auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(
self, CalleeSaveType::kSaveEverythingForClinit);
ArtMethod* caller = caller_and_outer.caller;
- mirror::Class* result =
- ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, true, false);
- if (LIKELY(result != nullptr)) {
+ mirror::Class* result = ResolveVerifyAndClinit(dex::TypeIndex(type_idx),
+ caller,
+ self,
+ /* can_run_clinit */ true,
+ /* verify_access */ false);
+ if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) {
StoreTypeInBss(caller_and_outer.outer_method, dex::TypeIndex(type_idx), result);
}
return result;
@@ -128,9 +150,12 @@
auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(
self, CalleeSaveType::kSaveEverythingForClinit);
ArtMethod* caller = caller_and_outer.caller;
- mirror::Class* result =
- ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, false);
- if (LIKELY(result != nullptr)) {
+ mirror::Class* result = ResolveVerifyAndClinit(dex::TypeIndex(type_idx),
+ caller,
+ self,
+ /* can_run_clinit */ false,
+ /* verify_access */ false);
+ if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) {
StoreTypeInBss(caller_and_outer.outer_method, dex::TypeIndex(type_idx), result);
}
return result;
@@ -143,8 +168,11 @@
auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self,
CalleeSaveType::kSaveEverything);
ArtMethod* caller = caller_and_outer.caller;
- mirror::Class* result =
- ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, true);
+ mirror::Class* result = ResolveVerifyAndClinit(dex::TypeIndex(type_idx),
+ caller,
+ self,
+ /* can_run_clinit */ false,
+ /* verify_access */ true);
// Do not StoreTypeInBss(); access check entrypoint is never used together with .bss.
return result;
}
@@ -156,7 +184,7 @@
CalleeSaveType::kSaveEverything);
ArtMethod* caller = caller_and_outer.caller;
mirror::String* result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
- if (LIKELY(result != nullptr)) {
+ if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) {
StoreStringInBss(caller_and_outer.outer_method, dex::StringIndex(string_idx), result);
}
return result;