From 715fdc2c99f688f97c684978632f311a284ba43c Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 18 Apr 2016 17:07:30 -0700 Subject: [PATCH] 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 --- runtime/interpreter/unstarted_runtime.cc | 46 ++++++++++++++++++++++++++++ runtime/interpreter/unstarted_runtime_list.h | 2 ++ runtime/mirror/class.cc | 11 +++++++ runtime/mirror/class.h | 3 ++ runtime/native/java_lang_Class.cc | 9 +----- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 5de0863d1..6d00ce1c5 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 @@ void UnstartedRuntime::UnstartedClassGetEnclosingClass( 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 klass(hs.NewHandle( + reinterpret_cast(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 FindAndExtractEntry(const std::string& jar_file, const char* entry_name, size_t* size, @@ -1357,6 +1367,36 @@ void UnstartedRuntime::UnstartedLongParseLong( 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 java_method(env, + java_method_obj == nullptr ? nullptr :env->AddLocalReference(java_method_obj)); + + mirror::Object* java_receiver_obj = shadow_frame->GetVRegReference(arg_offset + 1); + ScopedLocalRef java_receiver(env, + java_receiver_obj == nullptr ? nullptr : env->AddLocalReference(java_receiver_obj)); + + mirror::Object* java_args_obj = shadow_frame->GetVRegReference(arg_offset + 2); + ScopedLocalRef java_args(env, + java_args_obj == nullptr ? nullptr : env->AddLocalReference(java_args_obj)); + + ScopedLocalRef 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 @@ void UnstartedRuntime::Invoke(Thread* self, const DexFile::CodeItem* code_item, 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 63425c055..379d76012 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)") \ diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 42f003dc8..b4a23badb 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -1165,5 +1165,16 @@ template mirror::Constructor* Class::GetDeclaredConstructorInternal( mirror::Class* klass, mirror::ObjectArray* args); +int32_t Class::GetInnerClassFlags(Handle h_this, int32_t default_value) { + if (h_this->IsProxyClass() || h_this->GetDexCache() == nullptr) { + return default_value; + } + uint32_t flags; + if (!h_this->GetDexFile().GetInnerClassFlags(h_this, &flags)) { + return default_value; + } + return flags; +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 57c3590a2..5b6ded162 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1223,6 +1223,9 @@ class MANAGED Class FINAL : public Object { Thread* self, Handle> args, size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_); + static int32_t GetInnerClassFlags(Handle h_this, int32_t default_value) + SHARED_REQUIRES(Locks::mutator_lock_); + // Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore // fence. class InitializeClassVisitor { diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index c1899afc4..6b7ca40be 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -517,14 +517,7 @@ static jint Class_getInnerClassFlags(JNIEnv* env, jobject javaThis, jint default ScopedFastNativeObjectAccess soa(env); StackHandleScope<1> hs(soa.Self()); Handle klass(hs.NewHandle(DecodeClass(soa, javaThis))); - if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) { - return defaultValue; - } - uint32_t flags; - if (!klass->GetDexFile().GetInnerClassFlags(klass, &flags)) { - return defaultValue; - } - return flags; + return mirror::Class::GetInnerClassFlags(klass, defaultValue); } static jstring Class_getInnerClassName(JNIEnv* env, jobject javaThis) { -- 2.11.0