summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc5
-rw-r--r--runtime/instrumentation.cc8
-rw-r--r--runtime/interpreter/mterp/arm64ng/main.S18
-rw-r--r--runtime/interpreter/mterp/armng/main.S13
-rw-r--r--runtime/interpreter/mterp/x86_64ng/main.S8
-rw-r--r--runtime/interpreter/mterp/x86ng/main.S14
-rw-r--r--runtime/mirror/class.h4
-rw-r--r--runtime/thread.h7
-rw-r--r--tools/cpp-define-generator/mirror_class.def5
-rw-r--r--tools/cpp-define-generator/thread.def2
10 files changed, 71 insertions, 13 deletions
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 9c8c2208ba..60bbde4e02 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1371,6 +1371,11 @@ extern "C" const void* artQuickResolutionTrampoline(
success = linker->EnsureInitialized(soa.Self(), h_called_class, true, true);
}
if (success) {
+ // When the clinit check is at entry of the AOT/nterp code, we do the clinit check
+ // before doing the suspend check. To ensure the code sees the latest
+ // version of the class (the code doesn't do a read barrier to reduce
+ // size), do a suspend check now.
+ self->CheckSuspend();
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
// Check if we need instrumented code here. Since resolution stubs could suspend, it is
// possible that we instrumented the entry points after we started executing the resolution
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 8735dcfc81..f4584adb7c 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -1308,14 +1308,10 @@ const void* Instrumentation::GetCodeForInvoke(ArtMethod* method) {
DCHECK(!method->IsProxyMethod()) << method->PrettyMethod();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
const void* code = method->GetEntryPointFromQuickCompiledCodePtrSize(kRuntimePointerSize);
- // If we don't have the instrumentation, the resolution stub, the
- // interpreter, or the nterp with clinit as entrypoint, just return the current entrypoint,
+ // If we don't have the instrumentation, the resolution stub, or the
+ // interpreter, just return the current entrypoint,
// assuming it's the most optimized.
- // We don't want to return the nterp with clinit entrypoint as it calls the
- // resolution stub, and the resolution stub will call `GetCodeForInvoke` to know the actual
- // code to invoke.
if (code != GetQuickInstrumentationEntryPoint() &&
- code != interpreter::GetNterpWithClinitEntryPoint() &&
!class_linker->IsQuickResolutionStub(code) &&
!class_linker->IsQuickToInterpreterBridge(code)) {
return code;
diff --git a/runtime/interpreter/mterp/arm64ng/main.S b/runtime/interpreter/mterp/arm64ng/main.S
index 81d6b7bd77..66432d1fa0 100644
--- a/runtime/interpreter/mterp/arm64ng/main.S
+++ b/runtime/interpreter/mterp/arm64ng/main.S
@@ -1591,10 +1591,20 @@ END \name
*/
OAT_ENTRY ExecuteNterpWithClinitImpl, EndExecuteNterpWithClinitImpl
- ldr wip, [x0, ART_METHOD_DECLARING_CLASS_OFFSET]
- ldrb wip, [ip, MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET]
- cmp ip, #MIRROR_CLASS_IS_VISIBLY_INITIALIZED_VALUE
- bcs ExecuteNterpImpl
+ // For simplicity, we don't do a read barrier here, but instead rely
+ // on art_quick_resolution_trampoline to always have a suspend point before
+ // calling back here.
+ ldr wip, [x0, #ART_METHOD_DECLARING_CLASS_OFFSET]
+ ldrb wip2, [ip, #MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET]
+ cmp ip2, #MIRROR_CLASS_IS_VISIBLY_INITIALIZED_VALUE
+ b.hs ExecuteNterpImpl
+ cmp ip2, #MIRROR_CLASS_IS_INITIALIZING_VALUE
+ b.lo .Lresolution_trampoline
+ ldr wip2, [ip, #MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET]
+ ldr wip, [xSELF, #THREAD_TID_OFFSET]
+ cmp wip, wip2
+ b.eq ExecuteNterpImpl
+.Lresolution_trampoline:
b art_quick_resolution_trampoline
EndExecuteNterpWithClinitImpl:
diff --git a/runtime/interpreter/mterp/armng/main.S b/runtime/interpreter/mterp/armng/main.S
index f89db40637..320a792807 100644
--- a/runtime/interpreter/mterp/armng/main.S
+++ b/runtime/interpreter/mterp/armng/main.S
@@ -1609,10 +1609,19 @@ END \name
*/
OAT_ENTRY ExecuteNterpWithClinitImpl, EndExecuteNterpWithClinitImpl
- ldr ip, [r0, ART_METHOD_DECLARING_CLASS_OFFSET]
- ldrb ip, [ip, MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET]
+ // For simplicity, we don't do a read barrier here, but instead rely
+ // on art_quick_resolution_trampoline to always have a suspend point before
+ // calling back here.
+ ldr r4, [r0, ART_METHOD_DECLARING_CLASS_OFFSET]
+ ldrb ip, [r4, MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET]
cmp ip, #MIRROR_CLASS_IS_VISIBLY_INITIALIZED_VALUE
bcs ExecuteNterpImpl
+ cmp ip, #MIRROR_CLASS_IS_INITIALIZING_VALUE
+ blo art_quick_resolution_trampoline
+ ldr r4, [r4, #MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET]
+ ldr ip, [rSELF, #THREAD_TID_OFFSET]
+ cmp r4, ip
+ beq ExecuteNterpImpl
b art_quick_resolution_trampoline
EndExecuteNterpWithClinitImpl:
diff --git a/runtime/interpreter/mterp/x86_64ng/main.S b/runtime/interpreter/mterp/x86_64ng/main.S
index 3e476db953..6fc1777245 100644
--- a/runtime/interpreter/mterp/x86_64ng/main.S
+++ b/runtime/interpreter/mterp/x86_64ng/main.S
@@ -1695,9 +1695,17 @@ END_FUNCTION \name
*/
OAT_ENTRY ExecuteNterpWithClinitImpl, EndExecuteNterpWithClinitImpl
+ // For simplicity, we don't do a read barrier here, but instead rely
+ // on art_quick_resolution_trampoline to always have a suspend point before
+ // calling back here.
movl ART_METHOD_DECLARING_CLASS_OFFSET(%rdi), %r10d
cmpb $$(MIRROR_CLASS_IS_VISIBLY_INITIALIZED_VALUE), MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET(%r10d)
jae ExecuteNterpImpl
+ cmpb $$(MIRROR_CLASS_IS_INITIALIZING_VALUE), MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET(%r10d)
+ jb art_quick_resolution_trampoline
+ movl MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET(%r10d), %r10d
+ cmpl %r10d, rSELF:THREAD_TID_OFFSET
+ je ExecuteNterpImpl
jmp art_quick_resolution_trampoline
EndExecuteNterpWithClinitImpl:
diff --git a/runtime/interpreter/mterp/x86ng/main.S b/runtime/interpreter/mterp/x86ng/main.S
index 7872520384..42e2d182c5 100644
--- a/runtime/interpreter/mterp/x86ng/main.S
+++ b/runtime/interpreter/mterp/x86ng/main.S
@@ -1759,11 +1759,23 @@ END_FUNCTION \name
OAT_ENTRY ExecuteNterpWithClinitImpl, EndExecuteNterpWithClinitImpl
push %esi
+ // For simplicity, we don't do a read barrier here, but instead rely
+ // on art_quick_resolution_trampoline to always have a suspend point before
+ // calling back here.
movl ART_METHOD_DECLARING_CLASS_OFFSET(%eax), %esi
cmpb $$(MIRROR_CLASS_IS_VISIBLY_INITIALIZED_VALUE), MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET(%esi)
+ jae .Lcontinue_execute_nterp
+ cmpb $$(MIRROR_CLASS_IS_INITIALIZING_VALUE), MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET(%esi)
+ jb .Linvoke_trampoline
+ movl MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET(%esi), %esi
+ cmpl %esi, rSELF:THREAD_TID_OFFSET
+ je .Lcontinue_execute_nterp
+.Linvoke_trampoline:
pop %esi
- jae ExecuteNterpImpl
jmp art_quick_resolution_trampoline
+.Lcontinue_execute_nterp:
+ pop %esi
+ jmp ExecuteNterpImpl
EndExecuteNterpWithClinitImpl:
OAT_ENTRY ExecuteNterpImpl, EndExecuteNterpImpl
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 39f32bccee..0b0ef488de 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -571,6 +571,10 @@ class MANAGED Class final : public Object {
return OFFSET_OF_OBJECT_MEMBER(Class, object_size_alloc_fast_path_);
}
+ static constexpr MemberOffset ClinitThreadIdOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_);
+ }
+
ALWAYS_INLINE void SetObjectSize(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_);
void SetObjectSizeAllocFastPath(uint32_t new_object_size) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/thread.h b/runtime/thread.h
index 183bc56951..fd978293fd 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -759,6 +759,13 @@ class Thread {
}
template<PointerSize pointer_size>
+ static constexpr ThreadOffset<pointer_size> TidOffset() {
+ return ThreadOffset<pointer_size>(
+ OFFSETOF_MEMBER(Thread, tls32_) +
+ OFFSETOF_MEMBER(tls_32bit_sized_values, tid));
+ }
+
+ template<PointerSize pointer_size>
static constexpr ThreadOffset<pointer_size> InterruptedOffset() {
return ThreadOffset<pointer_size>(
OFFSETOF_MEMBER(Thread, tls32_) +
diff --git a/tools/cpp-define-generator/mirror_class.def b/tools/cpp-define-generator/mirror_class.def
index c01aab387a..af396bfe10 100644
--- a/tools/cpp-define-generator/mirror_class.def
+++ b/tools/cpp-define-generator/mirror_class.def
@@ -56,3 +56,8 @@ ASM_DEFINE(MIRROR_CLASS_IS_VISIBLY_INITIALIZED_OFFSET,
ASM_DEFINE(MIRROR_CLASS_IS_VISIBLY_INITIALIZED_VALUE,
art::enum_cast<uint32_t>(art::ClassStatus::kVisiblyInitialized) <<
(art::SubtypeCheckBits::BitStructSizeOf() % art::kBitsPerByte))
+ASM_DEFINE(MIRROR_CLASS_IS_INITIALIZING_VALUE,
+ art::enum_cast<uint32_t>(art::ClassStatus::kInitializing) <<
+ (art::SubtypeCheckBits::BitStructSizeOf() % art::kBitsPerByte))
+ASM_DEFINE(MIRROR_CLASS_CLINIT_THREAD_ID_OFFSET,
+ art::mirror::Class::ClinitThreadIdOffset().Int32Value())
diff --git a/tools/cpp-define-generator/thread.def b/tools/cpp-define-generator/thread.def
index d796542a32..97033fcaf2 100644
--- a/tools/cpp-define-generator/thread.def
+++ b/tools/cpp-define-generator/thread.def
@@ -71,3 +71,5 @@ ASM_DEFINE(THREAD_READ_BARRIER_MARK_REG00_OFFSET,
art::Thread::ReadBarrierMarkEntryPointsOffset<art::kRuntimePointerSize>(0))
ASM_DEFINE(THREAD_SHARED_METHOD_HOTNESS_OFFSET,
art::Thread::SharedMethodHotnessOffset<art::kRuntimePointerSize>().Int32Value())
+ASM_DEFINE(THREAD_TID_OFFSET,
+ art::Thread::TidOffset<art::kRuntimePointerSize>().Int32Value())