Store resolved types for AOT code in .bss.
Test: m test-art-host
Test: m test-art-target on Nexus 9.
Test: Nexus 9 boots.
Test: Build aosp_mips64-eng.
Bug: 30627598
Bug: 34193123
Change-Id: I8ec60a98eb488cb46ae3ea56341f5709dad4f623
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 035cead..bb88d72 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3307,6 +3307,7 @@
ReaderMutexLock mu(self, *Locks::dex_lock_);
ObjPtr<mirror::DexCache> dex_cache = FindDexCacheLocked(self, dex_file, true);
if (dex_cache != nullptr) {
+ // TODO: Check if the dex file was registered with the same class loader. Bug: 34193123
return dex_cache.Ptr();
}
}
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 469c45c..5ff95b4 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -122,11 +122,6 @@
return inlined_method;
}
-inline ArtMethod* GetCalleeSaveMethodCaller(Thread* self, Runtime::CalleeSaveType type) {
- return GetCalleeSaveMethodCaller(
- self->GetManagedStack()->GetTopQuickFrame(), type, true /* do_caller_check */);
-}
-
ALWAYS_INLINE inline mirror::Class* CheckObjectAlloc(mirror::Class* klass,
Thread* self,
bool* slow_path)
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 5390165..b17e1a8 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -261,11 +261,8 @@
return true;
}
-ArtMethod* GetCalleeSaveMethodCaller(ArtMethod** sp,
- Runtime::CalleeSaveType type,
- bool do_caller_check)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- ScopedAssertNoThreadSuspension ants(__FUNCTION__);
+static inline std::pair<ArtMethod*, uintptr_t> DoGetCalleeSaveMethodOuterCallerAndPc(
+ ArtMethod** sp, Runtime::CalleeSaveType type) REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(type));
const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, type);
@@ -275,6 +272,13 @@
uintptr_t caller_pc = *reinterpret_cast<uintptr_t*>(
(reinterpret_cast<uint8_t*>(sp) + callee_return_pc_offset));
ArtMethod* outer_method = *caller_sp;
+ return std::make_pair(outer_method, caller_pc);
+}
+
+static inline ArtMethod* DoGetCalleeSaveMethodCaller(ArtMethod* outer_method,
+ uintptr_t caller_pc,
+ bool do_caller_check)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
ArtMethod* caller = outer_method;
if (LIKELY(caller_pc != reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()))) {
if (outer_method != nullptr) {
@@ -308,8 +312,33 @@
visitor.WalkStack();
caller = visitor.caller;
}
-
return caller;
}
+ArtMethod* GetCalleeSaveMethodCaller(ArtMethod** sp,
+ Runtime::CalleeSaveType type,
+ bool do_caller_check)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
+ auto outer_caller_and_pc = DoGetCalleeSaveMethodOuterCallerAndPc(sp, type);
+ ArtMethod* outer_method = outer_caller_and_pc.first;
+ uintptr_t caller_pc = outer_caller_and_pc.second;
+ ArtMethod* caller = DoGetCalleeSaveMethodCaller(outer_method, caller_pc, do_caller_check);
+ return caller;
+}
+
+CallerAndOuterMethod GetCalleeSaveMethodCallerAndOuterMethod(Thread* self,
+ Runtime::CalleeSaveType type) {
+ CallerAndOuterMethod result;
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
+ ArtMethod** sp = self->GetManagedStack()->GetTopQuickFrame();
+ auto outer_caller_and_pc = DoGetCalleeSaveMethodOuterCallerAndPc(sp, type);
+ result.outer_method = outer_caller_and_pc.first;
+ uintptr_t caller_pc = outer_caller_and_pc.second;
+ result.caller =
+ DoGetCalleeSaveMethodCaller(result.outer_method, caller_pc, /* do_caller_check */ true);
+ return result;
+}
+
+
} // namespace art
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 4794610..d4cf83c 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -201,7 +201,13 @@
bool do_caller_check = false)
REQUIRES_SHARED(Locks::mutator_lock_);
-ArtMethod* GetCalleeSaveMethodCaller(Thread* self, Runtime::CalleeSaveType type)
+struct CallerAndOuterMethod {
+ ArtMethod* caller;
+ ArtMethod* outer_method;
+};
+
+CallerAndOuterMethod GetCalleeSaveMethodCallerAndOuterMethod(Thread* self,
+ Runtime::CalleeSaveType type)
REQUIRES_SHARED(Locks::mutator_lock_);
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 5dad43e..63340c0 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -31,22 +31,52 @@
namespace art {
+static inline void BssWriteBarrier(ArtMethod* outer_method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ // For AOT code, we need a write barrier for the class loader that holds
+ // the GC roots in the .bss.
+ const DexFile* dex_file = outer_method->GetDexFile();
+ if (dex_file != nullptr &&
+ dex_file->GetOatDexFile() != nullptr &&
+ !dex_file->GetOatDexFile()->GetOatFile()->GetBssGcRoots().empty()) {
+ mirror::ClassLoader* class_loader = outer_method->GetClassLoader();
+ DCHECK(class_loader != nullptr); // We do not use .bss GC roots for boot image.
+ DCHECK(!class_loader->GetClassTable()->InsertOatFile(dex_file->GetOatDexFile()->GetOatFile()))
+ << "Oat file with .bss GC roots was not registered in class table: "
+ << dex_file->GetOatDexFile()->GetOatFile()->GetLocation();
+ // Note that we emit the barrier before the compiled code stores the String or Class
+ // as a GC root. This is OK as there is no suspend point point in between.
+ Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
+ }
+}
+
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.
// A class may be accessing another class' fields when it doesn't have access, as access has been
// given by inheritance.
ScopedQuickEntrypointChecks sqec(self);
- auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kSaveRefsOnly);
- return ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, true, false);
+ auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, Runtime::kSaveRefsOnly);
+ ArtMethod* caller = caller_and_outer.caller;
+ mirror::Class* result =
+ ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, true, false);
+ if (LIKELY(result != nullptr)) {
+ BssWriteBarrier(caller_and_outer.outer_method);
+ }
+ return result;
}
extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
// Called when method->dex_cache_resolved_types_[] misses.
ScopedQuickEntrypointChecks sqec(self);
- auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kSaveRefsOnly);
- return ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, false);
+ auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, Runtime::kSaveRefsOnly);
+ ArtMethod* caller = caller_and_outer.caller;
+ mirror::Class* result =
+ ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, false);
+ if (LIKELY(result != nullptr)) {
+ BssWriteBarrier(caller_and_outer.outer_method);
+ }
+ return result;
}
extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, Thread* self)
@@ -54,36 +84,28 @@
// Called when caller isn't guaranteed to have access to a type and the dex cache may be
// unpopulated.
ScopedQuickEntrypointChecks sqec(self);
- auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kSaveRefsOnly);
- return ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, true);
+ auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(self, Runtime::kSaveRefsOnly);
+ ArtMethod* caller = caller_and_outer.caller;
+ mirror::Class* result =
+ ResolveVerifyAndClinit(dex::TypeIndex(type_idx), caller, self, false, true);
+ if (LIKELY(result != nullptr)) {
+ BssWriteBarrier(caller_and_outer.outer_method);
+ }
+ return result;
}
extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
- auto* caller = GetCalleeSaveMethodCaller(
+ auto caller_and_outer = GetCalleeSaveMethodCallerAndOuterMethod(
self,
// TODO: Change art_quick_resolve_string on MIPS and MIPS64 to kSaveEverything.
(kRuntimeISA == kMips || kRuntimeISA == kMips64) ? Runtime::kSaveRefsOnly
: Runtime::kSaveEverything);
+ ArtMethod* caller = caller_and_outer.caller;
mirror::String* result = ResolveStringFromCode(caller, dex::StringIndex(string_idx));
if (LIKELY(result != nullptr)) {
- // For AOT code, we need a write barrier for the class loader that holds
- // the GC roots in the .bss.
- const DexFile* dex_file = caller->GetDexFile();
- if (dex_file != nullptr &&
- dex_file->GetOatDexFile() != nullptr &&
- !dex_file->GetOatDexFile()->GetOatFile()->GetBssGcRoots().empty()) {
- mirror::ClassLoader* class_loader = caller->GetDeclaringClass()->GetClassLoader();
- DCHECK(class_loader != nullptr); // We do not use .bss GC roots for boot image.
- DCHECK(
- !class_loader->GetClassTable()->InsertOatFile(dex_file->GetOatDexFile()->GetOatFile()))
- << "Oat file with .bss GC roots was not registered in class table: "
- << dex_file->GetOatDexFile()->GetOatFile()->GetLocation();
- // Note that we emit the barrier before the compiled code stores the string as GC root.
- // This is OK as there is no suspend point point in between.
- Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);
- }
+ BssWriteBarrier(caller_and_outer.outer_method);
}
return result;
}