diff options
| -rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 46 | ||||
| -rw-r--r-- | runtime/interpreter/unstarted_runtime_list.h | 2 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 11 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 3 | ||||
| -rw-r--r-- | 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 5de0863d15..6d00ce1c56 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<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 @@ 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<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 @@ 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 63425c055a..379d76012c 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 42f003dc84..b4a23badba 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -1165,5 +1165,16 @@ template mirror::Constructor* Class::GetDeclaredConstructorInternal<true>( mirror::Class* klass, mirror::ObjectArray<mirror::Class>* args); +int32_t Class::GetInnerClassFlags(Handle<Class> 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 57c3590a2e..5b6ded162b 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1223,6 +1223,9 @@ class MANAGED Class FINAL : public Object { Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args, size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_); + static int32_t GetInnerClassFlags(Handle<Class> 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 c1899afc49..6b7ca40bee 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<mirror::Class> 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) { |