diff options
Diffstat (limited to 'runtime/entrypoints/entrypoint_utils.cc')
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.cc | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index 63d2aa4351..ae6e98a544 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -22,6 +22,7 @@ #include "base/mutex.h" #include "base/sdk_version.h" #include "class_linker-inl.h" +#include "class_root-inl.h" #include "dex/dex_file-inl.h" #include "dex/method_reference.h" #include "entrypoints/entrypoint_utils-inl.h" @@ -33,14 +34,14 @@ #include "mirror/class-inl.h" #include "mirror/method.h" #include "mirror/object-inl.h" -#include "mirror/object_array-inl.h" +#include "mirror/object_array-alloc-inl.h" #include "nth_caller_visitor.h" #include "oat_file.h" #include "oat_file-inl.h" #include "oat_quick_method_header.h" #include "reflection.h" #include "scoped_thread_state_change-inl.h" -#include "well_known_classes.h" +#include "well_known_classes-inl.h" namespace art { @@ -65,60 +66,70 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, jobject rcvr_jobj, jobject interface_method_jobj, std::vector<jvalue>& args) { - DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy)); + StackHandleScope<4u> hs(soa.Self()); + DCHECK(rcvr_jobj != nullptr); + Handle<mirror::Object> h_receiver = hs.NewHandle(soa.Decode<mirror::Object>(rcvr_jobj)); + DCHECK(h_receiver->InstanceOf(GetClassRoot(ClassRoot::kJavaLangReflectProxy))); + Handle<mirror::Method> h_interface_method = + hs.NewHandle(soa.Decode<mirror::Method>(interface_method_jobj)); // Build argument array possibly triggering GC. soa.Self()->AssertThreadSuspensionIsAllowable(); - jobjectArray args_jobj = nullptr; + auto h_args = hs.NewHandle<mirror::ObjectArray<mirror::Object>>(nullptr); const JValue zero; - uint32_t target_sdk_version = Runtime::Current()->GetTargetSdkVersion(); + Runtime* runtime = Runtime::Current(); + uint32_t target_sdk_version = runtime->GetTargetSdkVersion(); // Do not create empty arrays unless needed to maintain Dalvik bug compatibility. if (args.size() > 0 || IsSdkVersionSetAndAtMost(target_sdk_version, SdkVersion::kL)) { - args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, nullptr); - if (args_jobj == nullptr) { + h_args.Assign(mirror::ObjectArray<mirror::Object>::Alloc( + soa.Self(), GetClassRoot<mirror::ObjectArray<mirror::Object>>(), args.size())); + if (h_args == nullptr) { CHECK(soa.Self()->IsExceptionPending()); return zero; } for (size_t i = 0; i < args.size(); ++i) { + ObjPtr<mirror::Object> value; if (shorty[i + 1] == 'L') { - jobject val = args[i].l; - soa.Env()->SetObjectArrayElement(args_jobj, i, val); + value = soa.Decode<mirror::Object>(args[i].l); } else { JValue jv; jv.SetJ(args[i].j); - ObjPtr<mirror::Object> val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv); - if (val == nullptr) { + value = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv); + if (value == nullptr) { CHECK(soa.Self()->IsExceptionPending()); return zero; } - soa.Decode<mirror::ObjectArray<mirror::Object>>(args_jobj)->Set<false>(i, val); } + // We do not support `Proxy.invoke()` in a transaction. + h_args->SetWithoutChecks</*kActiveTransaction=*/ false>(i, value); } } // Call Proxy.invoke(Proxy proxy, Method method, Object[] args). - jvalue invocation_args[3]; - invocation_args[0].l = rcvr_jobj; - invocation_args[1].l = interface_method_jobj; - invocation_args[2].l = args_jobj; - jobject result = - soa.Env()->CallStaticObjectMethodA(WellKnownClasses::java_lang_reflect_Proxy, - WellKnownClasses::java_lang_reflect_Proxy_invoke, - invocation_args); + Handle<mirror::Object> h_result = hs.NewHandle( + WellKnownClasses::java_lang_reflect_Proxy_invoke->InvokeStatic<'L', 'L', 'L', 'L'>( + soa.Self(), h_receiver.Get(), h_interface_method.Get(), h_args.Get())); // Unbox result and handle error conditions. if (LIKELY(!soa.Self()->IsExceptionPending())) { - if (shorty[0] == 'V' || (shorty[0] == 'L' && result == nullptr)) { + if (shorty[0] == 'V' || (shorty[0] == 'L' && h_result == nullptr)) { // Do nothing. return zero; } else { - ArtMethod* interface_method = - soa.Decode<mirror::Method>(interface_method_jobj)->GetArtMethod(); - // This can cause thread suspension. - ObjPtr<mirror::Class> result_type = interface_method->ResolveReturnType(); - ObjPtr<mirror::Object> result_ref = soa.Decode<mirror::Object>(result); + ObjPtr<mirror::Class> result_type; + if (shorty[0] == 'L') { + // This can cause thread suspension. + result_type = h_interface_method->GetArtMethod()->ResolveReturnType(); + if (result_type == nullptr) { + DCHECK(soa.Self()->IsExceptionPending()); + return zero; + } + } else { + result_type = runtime->GetClassLinker()->LookupPrimitiveClass(shorty[0]); + DCHECK(result_type != nullptr); + } JValue result_unboxed; - if (!UnboxPrimitiveForResult(result_ref, result_type, &result_unboxed)) { + if (!UnboxPrimitiveForResult(h_result.Get(), result_type, &result_unboxed)) { DCHECK(soa.Self()->IsExceptionPending()); return zero; } |