ART: Add getDeclaredConstructor cutout for unstarted runtime
In the vein of getDeclaredMethod and getDeclaredField. Refactor
code from java_lang_Class to share code.
Allows to compile-time initialize:
* sun.security.x509.AVAKeyword
* sun.security.x509.X500Name
Bug: 27265238
(cherry picked from commit f72f19fac0016499d33fd75b0463d0128a58a9f4)
Change-Id: I075c1b11f3408f5b31e4f84140a24fd8d3eaa17e
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 2f22ac4..239b825 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -282,6 +282,23 @@
}
}
+// Special managed code cut-out to allow constructor lookup in a un-started runtime.
+void UnstartedRuntime::UnstartedClassGetDeclaredConstructor(
+ Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+ mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
+ if (klass == nullptr) {
+ ThrowNullPointerExceptionForMethodAccess(shadow_frame->GetMethod(), InvokeType::kVirtual);
+ return;
+ }
+ mirror::ObjectArray<mirror::Class>* args =
+ shadow_frame->GetVRegReference(arg_offset + 1)->AsObjectArray<mirror::Class>();
+ if (Runtime::Current()->IsActiveTransaction()) {
+ result->SetL(mirror::Class::GetDeclaredConstructorInternal<true>(self, klass, args));
+ } else {
+ result->SetL(mirror::Class::GetDeclaredConstructorInternal<false>(self, klass, args));
+ }
+}
+
void UnstartedRuntime::UnstartedClassGetEnclosingClass(
Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
StackHandleScope<1> hs(self);
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index cb614a1..7aeec61 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -25,6 +25,7 @@
V(ClassNewInstance, "java.lang.Object java.lang.Class.newInstance()") \
V(ClassGetDeclaredField, "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") \
V(ClassGetDeclaredMethod, "java.lang.reflect.Method java.lang.Class.getDeclaredMethodInternal(java.lang.String, java.lang.Class[])") \
+ V(ClassGetDeclaredConstructor, "java.lang.reflect.Constructor java.lang.Class.getDeclaredConstructorInternal(java.lang.Class[])") \
V(ClassGetEnclosingClass, "java.lang.Class java.lang.Class.getEnclosingClass()") \
V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \
V(VoidLookupType, "java.lang.Class java.lang.Void.lookupType()") \
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index a36091f..42f003d 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -1024,8 +1024,8 @@
// TODO: Move this to java_lang_Class.cc?
ArtMethod* Class::GetDeclaredConstructor(
- Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args) {
- for (auto& m : GetDirectMethods(sizeof(void*))) {
+ Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args, size_t pointer_size) {
+ for (auto& m : GetDirectMethods(pointer_size)) {
// Skip <clinit> which is a static constructor, as well as non constructors.
if (m.IsStatic() || !m.IsConstructor()) {
continue;
@@ -1139,5 +1139,31 @@
mirror::String* name,
mirror::ObjectArray<mirror::Class>* args);
+template <bool kTransactionActive>
+mirror::Constructor* Class::GetDeclaredConstructorInternal(
+ Thread* self,
+ mirror::Class* klass,
+ mirror::ObjectArray<mirror::Class>* args) {
+ StackHandleScope<1> hs(self);
+ const size_t pointer_size = kTransactionActive
+ ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
+ : sizeof(void*);
+ ArtMethod* result = klass->GetDeclaredConstructor(self, hs.NewHandle(args), pointer_size);
+ return result != nullptr
+ ? mirror::Constructor::CreateFromArtMethod<kTransactionActive>(self, result)
+ : nullptr;
+}
+
+// mirror::Constructor::CreateFromArtMethod<kTransactionActive>(self, result)
+
+template mirror::Constructor* Class::GetDeclaredConstructorInternal<false>(
+ Thread* self,
+ mirror::Class* klass,
+ mirror::ObjectArray<mirror::Class>* args);
+template mirror::Constructor* Class::GetDeclaredConstructorInternal<true>(
+ Thread* self,
+ mirror::Class* klass,
+ mirror::ObjectArray<mirror::Class>* args);
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 9808c3e..57c3590 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -768,6 +768,11 @@
mirror::String* name,
mirror::ObjectArray<mirror::Class>* args)
SHARED_REQUIRES(Locks::mutator_lock_);
+ template <bool kTransactionActive = false>
+ static Constructor* GetDeclaredConstructorInternal(Thread* self,
+ mirror::Class* klass,
+ mirror::ObjectArray<mirror::Class>* args)
+ SHARED_REQUIRES(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredVirtualMethodsSlice(size_t pointer_size)
@@ -1215,7 +1220,7 @@
// May cause thread suspension due to EqualParameters.
ArtMethod* GetDeclaredConstructor(
- Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args)
+ Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args, size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
// Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index 97973e6..9838b71 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -96,14 +96,18 @@
array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
}
+template <bool kTransactionActive>
Constructor* Constructor::CreateFromArtMethod(Thread* self, ArtMethod* method) {
DCHECK(method->IsConstructor()) << PrettyMethod(method);
auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
- static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+ static_cast<AbstractMethod*>(ret)->CreateFromArtMethod<kTransactionActive>(method);
}
return ret;
}
+template Constructor* Constructor::CreateFromArtMethod<false>(Thread* self, ArtMethod* method);
+template Constructor* Constructor::CreateFromArtMethod<true>(Thread* self, ArtMethod* method);
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
index 12a72fe..0b56964 100644
--- a/runtime/mirror/method.h
+++ b/runtime/mirror/method.h
@@ -60,6 +60,7 @@
// C++ mirror of java.lang.reflect.Constructor.
class MANAGED Constructor: public AbstractMethod {
public:
+ template <bool kTransactionActive = false>
static Constructor* CreateFromArtMethod(Thread* self, ArtMethod* method)
SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index bf24de5..54040cb 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -322,15 +322,11 @@
static jobject Class_getDeclaredConstructorInternal(
JNIEnv* env, jobject javaThis, jobjectArray args) {
ScopedFastNativeObjectAccess soa(env);
- auto* klass = DecodeClass(soa, javaThis);
- auto* params = soa.Decode<mirror::ObjectArray<mirror::Class>*>(args);
- StackHandleScope<1> hs(soa.Self());
- auto* declared_constructor = klass->GetDeclaredConstructor(soa.Self(), hs.NewHandle(params));
- if (declared_constructor != nullptr) {
- return soa.AddLocalReference<jobject>(
- mirror::Constructor::CreateFromArtMethod(soa.Self(), declared_constructor));
- }
- return nullptr;
+ mirror::Constructor* result = mirror::Class::GetDeclaredConstructorInternal(
+ soa.Self(),
+ DecodeClass(soa, javaThis),
+ soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
+ return soa.AddLocalReference<jobject>(result);
}
static ALWAYS_INLINE inline bool MethodMatchesConstructor(ArtMethod* m, bool public_only)
@@ -608,7 +604,8 @@
}
auto* constructor = klass->GetDeclaredConstructor(
soa.Self(),
- ScopedNullHandle<mirror::ObjectArray<mirror::Class>>());
+ ScopedNullHandle<mirror::ObjectArray<mirror::Class>>(),
+ sizeof(void*));
if (UNLIKELY(constructor == nullptr)) {
soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
"%s has no zero argument constructor",