From 580667b8d9cf6943596efff4df64f5879c1529e3 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 23 Oct 2017 11:20:39 -0700 Subject: ART: Correct static invariant checks Instances of initializing classes may leak to other threads. It is legal to execute methods and access fields, as long as they are not static. However, the class should still be initializing (or already be erroneous). Replace checks with this weaker invariant. Follow-up to commit 4e99b3d8955131f3fc71aa113f0fa71f0092cb6f. Bug: 15899971 Bug: 62478025 Bug: 67719550 Test: m test-art-host Change-Id: I63190253759df95ca54e40fd4117a24e12e0c069 --- runtime/common_dex_operations.h | 16 ++++++++++++++-- runtime/interpreter/interpreter.cc | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/runtime/common_dex_operations.h b/runtime/common_dex_operations.h index 4d5bd3fdce..6a78637ab1 100644 --- a/runtime/common_dex_operations.h +++ b/runtime/common_dex_operations.h @@ -71,6 +71,18 @@ inline void PerformCall(Thread* self, } } +template +inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) { + if (kIsDebugBuild) { + ObjPtr klass = entity->GetDeclaringClass(); + if (entity->IsStatic()) { + klass->AssertInitializedOrInitializingInThread(self); + } else { + CHECK(klass->IsInitializing() || klass->IsErroneousResolved()); + } + } +} + template static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self, const ShadowFrame& shadow_frame, @@ -78,7 +90,7 @@ static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self, ArtField* field, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); + DCheckStaticState(self, field); // Report this field access to instrumentation if needed. instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); @@ -136,7 +148,7 @@ ALWAYS_INLINE bool DoFieldPutCommon(Thread* self, ArtField* field, JValue& value) REQUIRES_SHARED(Locks::mutator_lock_) { - field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); + DCheckStaticState(self, field); // Report this field access to instrumentation if needed. Since we only have the offset of // the field from the base of the object, we need to look for it first. diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 68a75b0196..2deb3b7cf5 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -18,6 +18,7 @@ #include +#include "common_dex_operations.h" #include "common_throws.h" #include "dex_file_types.h" #include "interpreter_common.h" @@ -287,11 +288,12 @@ static inline JValue Execute( } } - shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); + ArtMethod* method = shadow_frame.GetMethod(); + + DCheckStaticState(self, method); // Lock counting is a special version of accessibility checks, and for simplicity and // reduction of template parameters, we gate it behind access-checks mode. - ArtMethod* method = shadow_frame.GetMethod(); DCHECK(!method->SkipAccessChecks() || !method->MustCountLocks()); bool transaction_active = Runtime::Current()->IsActiveTransaction(); -- cgit v1.2.3-59-g8ed1b