ART: Additional initialization for MethodHandle accessors.
Ensure classes are initialized before static fields are touched by
MethodHandle setters and getters.
Bug: 30550796
Test: m test-art-host-run-test-979-invoke-polymorphic-accessors
Change-Id: Ibac4372607ecbb4e6f7347b89cef6d280632c835
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 1a99100..b5843fd 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -774,6 +774,24 @@
return is_invoke_exact;
}
+inline static ObjPtr<mirror::Class> GetAndInitializeDeclaringClass(Thread* self, ArtField* field)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Method handle invocations on static fields should ensure class is
+ // initialized. This usually happens when an instance is constructed
+ // or class members referenced, but this is not guaranteed when
+ // looking up method handles.
+ ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
+ if (UNLIKELY(!klass->IsInitialized())) {
+ StackHandleScope<1> hs(self);
+ HandleWrapperObjPtr<mirror::Class> h(hs.NewHandleWrapper(&klass));
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h, true, true)) {
+ DCHECK(self->IsExceptionPending());
+ return nullptr;
+ }
+ }
+ return klass;
+}
+
template<bool is_range, bool do_access_check>
inline bool DoInvokePolymorphic(Thread* self,
ShadowFrame& shadow_frame,
@@ -943,12 +961,20 @@
return DoFieldPutForInvokePolymorphic(self, shadow_frame, obj, field, field_type, arg[1]);
}
case kStaticGet: {
- ObjPtr<mirror::Object> obj = field->GetDeclaringClass();
+ ObjPtr<mirror::Object> obj = GetAndInitializeDeclaringClass(self, field);
+ if (obj == nullptr) {
+ DCHECK(self->IsExceptionPending());
+ return false;
+ }
DoFieldGetForInvokePolymorphic(self, shadow_frame, obj, field, field_type, result);
return true;
}
case kStaticPut: {
- ObjPtr<mirror::Object> obj = field->GetDeclaringClass();
+ ObjPtr<mirror::Object> obj = GetAndInitializeDeclaringClass(self, field);
+ if (obj == nullptr) {
+ DCHECK(self->IsExceptionPending());
+ return false;
+ }
return DoFieldPutForInvokePolymorphic(self, shadow_frame, obj, field, field_type, arg[0]);
}
default: