ART: Add some reflection cutouts
Add Class.getInnerClassFlags and Method.invoke to unstarted runtime.
Allows to compile-time initialize:
* android.net.NetworkInfo
* android.net.wifi.WifiInfo
Bug: 27265238
(cherry picked from commit b3ffbe32b78c18739736fc998d65430b46c510e5)
Change-Id: I3e267519acf14b08c687f1e831e2027d37158767
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 5de0863..6d00ce1 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -44,6 +44,7 @@
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
#include "nth_caller_visitor.h"
+#include "reflection.h"
#include "thread.h"
#include "transaction.h"
#include "well_known_classes.h"
@@ -352,6 +353,15 @@
result->SetL(klass->GetDexFile().GetEnclosingClass(klass));
}
+void UnstartedRuntime::UnstartedClassGetInnerClassFlags(
+ Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+ StackHandleScope<1> hs(self);
+ Handle<mirror::Class> klass(hs.NewHandle(
+ reinterpret_cast<mirror::Class*>(shadow_frame->GetVRegReference(arg_offset))));
+ const int32_t default_value = shadow_frame->GetVReg(arg_offset + 1);
+ result->SetI(mirror::Class::GetInnerClassFlags(klass, default_value));
+}
+
static std::unique_ptr<MemMap> FindAndExtractEntry(const std::string& jar_file,
const char* entry_name,
size_t* size,
@@ -1357,6 +1367,36 @@
result->SetJ(l);
}
+void UnstartedRuntime::UnstartedMethodInvoke(
+ Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
+ JNIEnvExt* env = self->GetJniEnv();
+ ScopedObjectAccessUnchecked soa(self);
+
+ mirror::Object* java_method_obj = shadow_frame->GetVRegReference(arg_offset);
+ ScopedLocalRef<jobject> java_method(env,
+ java_method_obj == nullptr ? nullptr :env->AddLocalReference<jobject>(java_method_obj));
+
+ mirror::Object* java_receiver_obj = shadow_frame->GetVRegReference(arg_offset + 1);
+ ScopedLocalRef<jobject> java_receiver(env,
+ java_receiver_obj == nullptr ? nullptr : env->AddLocalReference<jobject>(java_receiver_obj));
+
+ mirror::Object* java_args_obj = shadow_frame->GetVRegReference(arg_offset + 2);
+ ScopedLocalRef<jobject> java_args(env,
+ java_args_obj == nullptr ? nullptr : env->AddLocalReference<jobject>(java_args_obj));
+
+ ScopedLocalRef<jobject> result_jobj(env,
+ InvokeMethod(soa, java_method.get(), java_receiver.get(), java_args.get()));
+
+ result->SetL(self->DecodeJObject(result_jobj.get()));
+
+ // Conservatively flag all exceptions as transaction aborts. This way we don't need to unwrap
+ // InvocationTargetExceptions.
+ if (self->IsExceptionPending()) {
+ AbortTransactionOrFail(self, "Failed Method.invoke");
+ }
+}
+
void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(
Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
@@ -1640,7 +1680,13 @@
if (iter != invoke_handlers_.end()) {
// Clear out the result in case it's not zeroed out.
result->SetL(0);
+
+ // Push the shadow frame. This is so the failing method can be seen in abort dumps.
+ self->PushShadowFrame(shadow_frame);
+
(*iter->second)(self, shadow_frame, result, arg_offset);
+
+ self->PopShadowFrame();
} else {
// Not special, continue with regular interpreter execution.
ArtInterpreterToInterpreterBridge(self, code_item, shadow_frame, result);
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index 63425c0..379d760 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -29,6 +29,7 @@
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(ClassGetInnerClassFlags, "int java.lang.Class.getInnerClassFlags(int)") \
V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \
V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \
V(VoidLookupType, "java.lang.Class java.lang.Void.lookupType()") \
@@ -50,6 +51,7 @@
V(MemoryPeekInt, "int libcore.io.Memory.peekIntNative(long)") \
V(MemoryPeekLong, "long libcore.io.Memory.peekLongNative(long)") \
V(MemoryPeekByteArray, "void libcore.io.Memory.peekByteArray(long, byte[], int, int)") \
+ V(MethodInvoke, "java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])") \
V(ReferenceGetReferent, "java.lang.Object java.lang.ref.Reference.getReferent()") \
V(RuntimeAvailableProcessors, "int java.lang.Runtime.availableProcessors()") \
V(StringGetCharsNoCheck, "void java.lang.String.getCharsNoCheck(int, int, char[], int)") \