entrypoint_utils.cc revision e5877a12c30afe10a5c6a1afaff7a47ef44a2a5f
12d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/* 20f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Copyright (C) 2012 The Android Open Source Project 32d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 42d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License"); 52d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * you may not use this file except in compliance with the License. 62d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * You may obtain a copy of the License at 72d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 82d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * http://www.apache.org/licenses/LICENSE-2.0 92d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Unless required by applicable law or agreed to in writing, software 112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS, 122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * See the License for the specific language governing permissions and 142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * limitations under the License. 152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 177655f29fabc0a12765de828914a18314382e5a35Ian Rogers#include "entrypoints/entrypoint_utils.h" 182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang#include "base/mutex.h" 202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h" 214f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 221d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h" 23e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers#include "method_helper-inl.h" 24ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 25ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 29af6e67a4816d2593586115b89faa659225363246Ian Rogers#include "reflection.h" 30af6e67a4816d2593586115b89faa659225363246Ian Rogers#include "scoped_thread_state_change.h" 315bb8601175bbb9cd761c715f4ba04f84d65e913bTDYa#include "ScopedLocalRef.h" 32eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "well_known_classes.h" 335bb8601175bbb9cd761c715f4ba04f84d65e913bTDYa 3441005ddb5576b8630a1084fbb3979ffa602c0599jeffhaonamespace art { 3541005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 36cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartierstatic inline mirror::Class* CheckFilledNewArrayAlloc(uint32_t type_idx, mirror::ArtMethod* referrer, 37cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier int32_t component_count, Thread* self, 38cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier bool access_check) 393b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 4057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(component_count < 0)) { 4162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowNegativeArraySizeException(component_count); 42cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 43ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 443b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi mirror::Class* klass = referrer->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx); 4557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 4662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, referrer); 4757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass == NULL) { // Error 4850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers DCHECK(self->IsExceptionPending()); 49cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 50ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 51ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 5257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) { 5357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { 5462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowRuntimeException("Bad filled array request for type %s", 5562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(klass).c_str()); 56573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } else { 5762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 5862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DCHECK(throw_location.GetMethod() == referrer); 5962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;", 604fa0bcd2142793e1f105b24b658de3635652b957Brian Carlstrom "Found type %s; filled-new-array not implemented for anything but 'int'", 6150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers PrettyDescriptor(klass).c_str()); 62573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } 63cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 643b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi } 653b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi if (access_check) { 663b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi mirror::Class* referrer_klass = referrer->GetDeclaringClass(); 673b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi if (UNLIKELY(!referrer_klass->CanAccess(klass))) { 683b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi ThrowIllegalAccessErrorClass(referrer_klass, klass); 69cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 7057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 71ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 723b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi DCHECK(klass->IsArrayClass()) << PrettyClass(klass); 73cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return klass; 743b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi} 753b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi 763b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi// Helper function to allocate array for FILLED_NEW_ARRAY. 773b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchimirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* referrer, 783b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi int32_t component_count, Thread* self, 79cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier bool access_check, 80e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier gc::AllocatorType /* allocator_type */) { 81cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier mirror::Class* klass = CheckFilledNewArrayAlloc(type_idx, referrer, component_count, self, 82cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier access_check); 83cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier if (UNLIKELY(klass == nullptr)) { 84cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; 853b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi } 86e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier // Always go slow path for now, filled new array is not common. 87e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 88e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier // Use the current allocator type in case CheckFilledNewArrayAlloc caused us to suspend and then 89e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier // the heap switched the allocator type while we were suspended. 906fac447555dc94a935b78198479cce645c837b89Ian Rogers return mirror::Array::Alloc<false>(self, klass, component_count, klass->GetComponentSize(), 916fac447555dc94a935b78198479cce645c837b89Ian Rogers heap->GetCurrentAllocator()); 923b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi} 933b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi 943b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi// Helper function to allocate array for FILLED_NEW_ARRAY. 953b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchimirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* referrer, 963b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi int32_t component_count, Thread* self, 97cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier bool access_check, 98e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier gc::AllocatorType /* allocator_type */) { 99cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier mirror::Class* klass = CheckFilledNewArrayAlloc(type_idx, referrer, component_count, self, 100cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier access_check); 101cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier if (UNLIKELY(klass == nullptr)) { 102cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; 1033b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi } 104e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 105e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier // Use the current allocator type in case CheckFilledNewArrayAlloc caused us to suspend and then 106e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier // the heap switched the allocator type while we were suspended. 1076fac447555dc94a935b78198479cce645c837b89Ian Rogers return mirror::Array::Alloc<true>(self, klass, component_count, klass->GetComponentSize(), 1086fac447555dc94a935b78198479cce645c837b89Ian Rogers heap->GetCurrentAllocator()); 109ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 110ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 111d752132c73072084a3def9257cca4fcee76047b6jeffhaovoid ThrowStackOverflowError(Thread* self) { 1127571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom if (self->IsHandlingStackOverflow()) { 1137571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom LOG(ERROR) << "Recursive stack overflow."; 1147571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom // We don't fail here because SetStackEndForStackOverflow will print better diagnostics. 1157571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom } 11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 11762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) { 11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Remove extra entry pushed onto second stack during method tracing. 11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime::Current()->GetInstrumentation()->PopMethodForUnwind(self, false); 120d752132c73072084a3def9257cca4fcee76047b6jeffhao } 12162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 122d752132c73072084a3def9257cca4fcee76047b6jeffhao self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. 123d752132c73072084a3def9257cca4fcee76047b6jeffhao JNIEnvExt* env = self->GetJniEnv(); 124d752132c73072084a3def9257cca4fcee76047b6jeffhao std::string msg("stack size "); 125d752132c73072084a3def9257cca4fcee76047b6jeffhao msg += PrettySize(self->GetStackSize()); 126d752132c73072084a3def9257cca4fcee76047b6jeffhao // Use low-level JNI routine and pre-baked error class to avoid class linking operations that 127d752132c73072084a3def9257cca4fcee76047b6jeffhao // would consume more stack. 128d752132c73072084a3def9257cca4fcee76047b6jeffhao int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError, 129d752132c73072084a3def9257cca4fcee76047b6jeffhao msg.c_str(), NULL); 130d752132c73072084a3def9257cca4fcee76047b6jeffhao if (rc != JNI_OK) { 131d752132c73072084a3def9257cca4fcee76047b6jeffhao // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME 132d752132c73072084a3def9257cca4fcee76047b6jeffhao // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError 133d752132c73072084a3def9257cca4fcee76047b6jeffhao // instead. 134d752132c73072084a3def9257cca4fcee76047b6jeffhao LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed."; 135d752132c73072084a3def9257cca4fcee76047b6jeffhao CHECK(self->IsExceptionPending()); 136d752132c73072084a3def9257cca4fcee76047b6jeffhao } 137f943914730db8ad2ff03d49a2cacd31885d08fd7Dave Allison 138f943914730db8ad2ff03d49a2cacd31885d08fd7Dave Allison bool explicit_overflow_check = Runtime::Current()->ExplicitStackOverflowChecks(); 139f943914730db8ad2ff03d49a2cacd31885d08fd7Dave Allison self->ResetDefaultStackEnd(!explicit_overflow_check); // Return to default stack size. 140d752132c73072084a3def9257cca4fcee76047b6jeffhao} 141d752132c73072084a3def9257cca4fcee76047b6jeffhao 142e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogersvoid CheckReferenceResult(mirror::Object* o, Thread* self) { 143e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers if (o == NULL) { 144e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers return; 145e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers } 146e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers mirror::ArtMethod* m = self->GetCurrentMethod(NULL); 147e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers if (o == kInvalidIndirectRefObject) { 148e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers JniAbortF(NULL, "invalid reference returned from %s", PrettyMethod(m).c_str()); 149e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers } 150e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers // Make sure that the result is an instance of the type this method was expected to return. 151e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers StackHandleScope<1> hs(self); 152e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers Handle<mirror::ArtMethod> h_m(hs.NewHandle(m)); 153e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers mirror::Class* return_type = MethodHelper(h_m).GetReturnType(); 154e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers 155e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers if (!o->InstanceOf(return_type)) { 156e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers JniAbortF(NULL, "attempt to return an instance of %s from %s", PrettyTypeOf(o).c_str(), 157e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers PrettyMethod(h_m.Get()).c_str()); 158e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers } 159e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers} 160e5877a12c30afe10a5c6a1afaff7a47ef44a2a5fIan Rogers 1612b7c4d196c8abe32f4ca633534917da9de53c359Mathieu ChartierJValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, const char* shorty, 162af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject rcvr_jobj, jobject interface_method_jobj, 163af6e67a4816d2593586115b89faa659225363246Ian Rogers std::vector<jvalue>& args) { 164af6e67a4816d2593586115b89faa659225363246Ian Rogers DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy)); 165af6e67a4816d2593586115b89faa659225363246Ian Rogers 166af6e67a4816d2593586115b89faa659225363246Ian Rogers // Build argument array possibly triggering GC. 167af6e67a4816d2593586115b89faa659225363246Ian Rogers soa.Self()->AssertThreadSuspensionIsAllowable(); 168af6e67a4816d2593586115b89faa659225363246Ian Rogers jobjectArray args_jobj = NULL; 169af6e67a4816d2593586115b89faa659225363246Ian Rogers const JValue zero; 170f00571c4e1ae202b3b4acb6b47cbe23a65178f7fJeff Hao int32_t target_sdk_version = Runtime::Current()->GetTargetSdkVersion(); 171f00571c4e1ae202b3b4acb6b47cbe23a65178f7fJeff Hao // Do not create empty arrays unless needed to maintain Dalvik bug compatibility. 172f00571c4e1ae202b3b4acb6b47cbe23a65178f7fJeff Hao if (args.size() > 0 || (target_sdk_version > 0 && target_sdk_version <= 21)) { 173af6e67a4816d2593586115b89faa659225363246Ian Rogers args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, NULL); 174af6e67a4816d2593586115b89faa659225363246Ian Rogers if (args_jobj == NULL) { 175af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK(soa.Self()->IsExceptionPending()); 176af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 177af6e67a4816d2593586115b89faa659225363246Ian Rogers } 178af6e67a4816d2593586115b89faa659225363246Ian Rogers for (size_t i = 0; i < args.size(); ++i) { 179af6e67a4816d2593586115b89faa659225363246Ian Rogers if (shorty[i + 1] == 'L') { 180af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject val = args.at(i).l; 181af6e67a4816d2593586115b89faa659225363246Ian Rogers soa.Env()->SetObjectArrayElement(args_jobj, i, val); 182af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 183af6e67a4816d2593586115b89faa659225363246Ian Rogers JValue jv; 184af6e67a4816d2593586115b89faa659225363246Ian Rogers jv.SetJ(args.at(i).j); 1852dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv); 186af6e67a4816d2593586115b89faa659225363246Ian Rogers if (val == NULL) { 187af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK(soa.Self()->IsExceptionPending()); 188af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 189af6e67a4816d2593586115b89faa659225363246Ian Rogers } 190d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set<false>(i, val); 191af6e67a4816d2593586115b89faa659225363246Ian Rogers } 192af6e67a4816d2593586115b89faa659225363246Ian Rogers } 193af6e67a4816d2593586115b89faa659225363246Ian Rogers } 194af6e67a4816d2593586115b89faa659225363246Ian Rogers 195ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom // Call Proxy.invoke(Proxy proxy, ArtMethod method, Object[] args). 196af6e67a4816d2593586115b89faa659225363246Ian Rogers jvalue invocation_args[3]; 197af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[0].l = rcvr_jobj; 198af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[1].l = interface_method_jobj; 199af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[2].l = args_jobj; 200af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject result = 201ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Env()->CallStaticObjectMethodA(WellKnownClasses::java_lang_reflect_Proxy, 202ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom WellKnownClasses::java_lang_reflect_Proxy_invoke, 203ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom invocation_args); 204af6e67a4816d2593586115b89faa659225363246Ian Rogers 205af6e67a4816d2593586115b89faa659225363246Ian Rogers // Unbox result and handle error conditions. 20662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (LIKELY(!soa.Self()->IsExceptionPending())) { 20762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (shorty[0] == 'V' || (shorty[0] == 'L' && result == NULL)) { 208af6e67a4816d2593586115b89faa659225363246Ian Rogers // Do nothing. 209af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 210af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 211bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier StackHandleScope<1> hs(soa.Self()); 212bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier MethodHelper mh_interface_method( 213bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier hs.NewHandle(soa.Decode<mirror::ArtMethod*>(interface_method_jobj))); 214bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier // This can cause thread suspension. 215bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier mirror::Class* result_type = mh_interface_method.GetReturnType(); 2162dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* result_ref = soa.Decode<mirror::Object*>(result); 21762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); 218ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* proxy_method; 219bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier if (mh_interface_method.GetMethod()->GetDeclaringClass()->IsInterface()) { 220bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface( 221bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier mh_interface_method.GetMethod()); 22262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 22362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Proxy dispatch to a method defined in Object. 224bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier DCHECK(mh_interface_method.GetMethod()->GetDeclaringClass()->IsObjectClass()); 225bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier proxy_method = mh_interface_method.GetMethod(); 22662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 22762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location(rcvr, proxy_method, -1); 22862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers JValue result_unboxed; 22984956ff6c0ff150d86a08157216ded79217d860aIan Rogers if (!UnboxPrimitiveForResult(throw_location, result_ref, result_type, &result_unboxed)) { 230530f71c040cb1a7b946d5566d5a746f08f2d082cIan Rogers DCHECK(soa.Self()->IsExceptionPending()); 23162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return zero; 232af6e67a4816d2593586115b89faa659225363246Ian Rogers } 233af6e67a4816d2593586115b89faa659225363246Ian Rogers return result_unboxed; 234af6e67a4816d2593586115b89faa659225363246Ian Rogers } 235af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 236af6e67a4816d2593586115b89faa659225363246Ian Rogers // In the case of checked exceptions that aren't declared, the exception must be wrapped by 237af6e67a4816d2593586115b89faa659225363246Ian Rogers // a UndeclaredThrowableException. 23862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception = soa.Self()->GetException(NULL); 239af6e67a4816d2593586115b89faa659225363246Ian Rogers if (exception->IsCheckedException()) { 2402dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); 24198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang mirror::Class* proxy_class = rcvr->GetClass(); 242ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* interface_method = 243ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Decode<mirror::ArtMethod*>(interface_method_jobj); 244ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* proxy_method = 245af6e67a4816d2593586115b89faa659225363246Ian Rogers rcvr->GetClass()->FindVirtualMethodForInterface(interface_method); 246af6e67a4816d2593586115b89faa659225363246Ian Rogers int throws_index = -1; 247af6e67a4816d2593586115b89faa659225363246Ian Rogers size_t num_virt_methods = proxy_class->NumVirtualMethods(); 248af6e67a4816d2593586115b89faa659225363246Ian Rogers for (size_t i = 0; i < num_virt_methods; i++) { 249af6e67a4816d2593586115b89faa659225363246Ian Rogers if (proxy_class->GetVirtualMethod(i) == proxy_method) { 250af6e67a4816d2593586115b89faa659225363246Ian Rogers throws_index = i; 251af6e67a4816d2593586115b89faa659225363246Ian Rogers break; 252af6e67a4816d2593586115b89faa659225363246Ian Rogers } 253af6e67a4816d2593586115b89faa659225363246Ian Rogers } 254af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK_NE(throws_index, -1); 2552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); 2562dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* exception_class = exception->GetClass(); 257af6e67a4816d2593586115b89faa659225363246Ian Rogers bool declares_exception = false; 258af6e67a4816d2593586115b89faa659225363246Ian Rogers for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) { 2592dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* declared_exception = declared_exceptions->Get(i); 260af6e67a4816d2593586115b89faa659225363246Ian Rogers declares_exception = declared_exception->IsAssignableFrom(exception_class); 261af6e67a4816d2593586115b89faa659225363246Ian Rogers } 262af6e67a4816d2593586115b89faa659225363246Ian Rogers if (!declares_exception) { 26362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location(rcvr, proxy_method, -1); 26462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers soa.Self()->ThrowNewWrappedException(throw_location, 26562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers "Ljava/lang/reflect/UndeclaredThrowableException;", 266af6e67a4816d2593586115b89faa659225363246Ian Rogers NULL); 267af6e67a4816d2593586115b89faa659225363246Ian Rogers } 268af6e67a4816d2593586115b89faa659225363246Ian Rogers } 269af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 270af6e67a4816d2593586115b89faa659225363246Ian Rogers } 271af6e67a4816d2593586115b89faa659225363246Ian Rogers} 2722d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} // namespace art 273