summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ian Rogers <irogers@google.com> 2014-06-18 16:07:20 -0700
committer Ian Rogers <irogers@google.com> 2014-06-18 16:39:29 -0700
commit6c5cb212fa7010ae7caf9dc765533aa967c95342 (patch)
treec31c46eb7b284b317455fdab48317de92b81dd28
parent241fd1192dfc0f7322660343179f9fc0591ed9ff (diff)
Ensure classes are initialized rather than initializing.
A class can be being initialized on a different thread, in that case other threads should block trying to access the class. The initializing state shows the class is being initialized but not that its safe for other threads to access. Change occurances of IsInitializing to IsInitialized primarily in slow-path code. Bug: 15347354 Change-Id: Ib586d0a385be6086a890dfbf8868d76f16767fac
-rw-r--r--runtime/entrypoints/entrypoint_utils.h23
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc2
-rw-r--r--runtime/entrypoints/portable/portable_trampoline_entrypoints.cc2
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc2
-rw-r--r--runtime/interpreter/interpreter.cc4
-rw-r--r--runtime/jni_internal.cc3
6 files changed, 19 insertions, 17 deletions
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 3d8b29fd24..ff836a4745 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -511,13 +511,8 @@ static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtField* resolved_field =
referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
- if (UNLIKELY(resolved_field == NULL)) {
- return NULL;
- }
- mirror::Class* fields_class = resolved_field->GetDeclaringClass();
- // Check class is initiliazed or initializing.
- if (UNLIKELY(!fields_class->IsInitializing())) {
- return NULL;
+ if (UNLIKELY(resolved_field == nullptr)) {
+ return nullptr;
}
// Check for incompatible class change.
bool is_primitive;
@@ -541,7 +536,15 @@ static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
}
if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
// Incompatible class change.
- return NULL;
+ return nullptr;
+ }
+ mirror::Class* fields_class = resolved_field->GetDeclaringClass();
+ if (is_static) {
+ // Check class is initialized else fail so that we can contend to initialize the class with
+ // other threads that may be racing to do this.
+ if (UNLIKELY(!fields_class->IsInitialized())) {
+ return nullptr;
+ }
}
mirror::Class* referring_class = referrer->GetDeclaringClass();
if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
@@ -549,11 +552,11 @@ static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
resolved_field->GetAccessFlags()) ||
(is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) {
// Illegal access.
- return NULL;
+ return nullptr;
}
if (UNLIKELY(resolved_field->IsPrimitiveType() != is_primitive ||
resolved_field->FieldSize() != expected_size)) {
- return NULL;
+ return nullptr;
}
return resolved_field;
}
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index f2e2bf7aa9..329c175986 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -33,7 +33,7 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& m
// Ensure static methods are initialized.
if (method->IsStatic()) {
mirror::Class* declaringClass = method->GetDeclaringClass();
- if (UNLIKELY(!declaringClass->IsInitializing())) {
+ if (UNLIKELY(!declaringClass->IsInitialized())) {
self->PushShadowFrame(shadow_frame);
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(declaringClass));
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index 6825e783a7..2da016f798 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -213,7 +213,7 @@ extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Th
self->PushShadowFrame(shadow_frame);
self->EndAssertNoThreadSuspension(old_cause);
- if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
+ if (method->IsStatic() && !method->GetDeclaringClass()->IsInitialized()) {
// Ensure static method's class is initialized.
Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(h_class, true, true)) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 514d1aa26d..7a144b6d72 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -484,7 +484,7 @@ extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Threa
self->PushShadowFrame(shadow_frame);
self->EndAssertNoThreadSuspension(old_cause);
- if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
+ if (method->IsStatic() && !method->GetDeclaringClass()->IsInitialized()) {
// Ensure static method's class is initialized.
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 6dbc6a05ea..cb4d444517 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -454,7 +454,7 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive
}
self->EndAssertNoThreadSuspension(old_cause);
// Do this after populating the shadow frame in case EnsureInitialized causes a GC.
- if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
+ if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitialized())) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
@@ -527,7 +527,7 @@ extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh
// Ensure static methods are initialized.
if (method->IsStatic()) {
mirror::Class* declaring_class = method->GetDeclaringClass();
- if (UNLIKELY(!declaring_class->IsInitializing())) {
+ if (UNLIKELY(!declaring_class->IsInitialized())) {
StackHandleScope<1> hs(self);
HandleWrapper<Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class));
if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index fc5d5905cb..5606d47832 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -3314,8 +3314,7 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path,
void* JavaVMExt::FindCodeForNativeMethod(mirror::ArtMethod* m) {
CHECK(m->IsNative());
mirror::Class* c = m->GetDeclaringClass();
- // If this is a static method, it could be called before the class
- // has been initialized.
+ // If this is a static method, it could be called before the class has been initialized.
if (m->IsStatic()) {
c = EnsureInitialized(Thread::Current(), c);
if (c == nullptr) {