entrypoint_utils.cc revision d2fe10a3a34af171bf1631219cd2d6ff6b7778b5
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 192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h" 204f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 211d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h" 22ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 23ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 26bd136a29f08486525d6abc7d0a0006ce5b4011c1Dragos Sbirlea#include "object_utils.h" 272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/proxy.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. 90e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier return mirror::Array::Alloc<false>(self, klass, component_count, heap->GetCurrentAllocator()); 913b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi} 923b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi 933b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi// Helper function to allocate array for FILLED_NEW_ARRAY. 943b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchimirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* referrer, 953b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi int32_t component_count, Thread* self, 96cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier bool access_check, 97e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier gc::AllocatorType /* allocator_type */) { 98cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier mirror::Class* klass = CheckFilledNewArrayAlloc(type_idx, referrer, component_count, self, 99cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier access_check); 100cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier if (UNLIKELY(klass == nullptr)) { 101cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; 1023b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi } 103e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 104e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier // Use the current allocator type in case CheckFilledNewArrayAlloc caused us to suspend and then 105e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier // the heap switched the allocator type while we were suspended. 106e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier return mirror::Array::Alloc<true>(self, klass, component_count, heap->GetCurrentAllocator()); 107ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 108ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 109d752132c73072084a3def9257cca4fcee76047b6jeffhaovoid ThrowStackOverflowError(Thread* self) { 1107571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom if (self->IsHandlingStackOverflow()) { 1117571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom LOG(ERROR) << "Recursive stack overflow."; 1127571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom // We don't fail here because SetStackEndForStackOverflow will print better diagnostics. 1137571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom } 11462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 11562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) { 11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Remove extra entry pushed onto second stack during method tracing. 11762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime::Current()->GetInstrumentation()->PopMethodForUnwind(self, false); 118d752132c73072084a3def9257cca4fcee76047b6jeffhao } 11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 120d752132c73072084a3def9257cca4fcee76047b6jeffhao self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. 121d752132c73072084a3def9257cca4fcee76047b6jeffhao JNIEnvExt* env = self->GetJniEnv(); 122d752132c73072084a3def9257cca4fcee76047b6jeffhao std::string msg("stack size "); 123d752132c73072084a3def9257cca4fcee76047b6jeffhao msg += PrettySize(self->GetStackSize()); 124d752132c73072084a3def9257cca4fcee76047b6jeffhao // Use low-level JNI routine and pre-baked error class to avoid class linking operations that 125d752132c73072084a3def9257cca4fcee76047b6jeffhao // would consume more stack. 126d752132c73072084a3def9257cca4fcee76047b6jeffhao int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError, 127d752132c73072084a3def9257cca4fcee76047b6jeffhao msg.c_str(), NULL); 128d752132c73072084a3def9257cca4fcee76047b6jeffhao if (rc != JNI_OK) { 129d752132c73072084a3def9257cca4fcee76047b6jeffhao // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME 130d752132c73072084a3def9257cca4fcee76047b6jeffhao // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError 131d752132c73072084a3def9257cca4fcee76047b6jeffhao // instead. 132d752132c73072084a3def9257cca4fcee76047b6jeffhao LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed."; 133d752132c73072084a3def9257cca4fcee76047b6jeffhao CHECK(self->IsExceptionPending()); 134d752132c73072084a3def9257cca4fcee76047b6jeffhao } 135d752132c73072084a3def9257cca4fcee76047b6jeffhao self->ResetDefaultStackEnd(); // Return to default stack size. 136d752132c73072084a3def9257cca4fcee76047b6jeffhao} 137d752132c73072084a3def9257cca4fcee76047b6jeffhao 138af6e67a4816d2593586115b89faa659225363246Ian RogersJValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty, 139af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject rcvr_jobj, jobject interface_method_jobj, 140af6e67a4816d2593586115b89faa659225363246Ian Rogers std::vector<jvalue>& args) { 141af6e67a4816d2593586115b89faa659225363246Ian Rogers DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy)); 142af6e67a4816d2593586115b89faa659225363246Ian Rogers 143af6e67a4816d2593586115b89faa659225363246Ian Rogers // Build argument array possibly triggering GC. 144af6e67a4816d2593586115b89faa659225363246Ian Rogers soa.Self()->AssertThreadSuspensionIsAllowable(); 145af6e67a4816d2593586115b89faa659225363246Ian Rogers jobjectArray args_jobj = NULL; 146af6e67a4816d2593586115b89faa659225363246Ian Rogers const JValue zero; 147af6e67a4816d2593586115b89faa659225363246Ian Rogers if (args.size() > 0) { 148af6e67a4816d2593586115b89faa659225363246Ian Rogers args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, NULL); 149af6e67a4816d2593586115b89faa659225363246Ian Rogers if (args_jobj == NULL) { 150af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK(soa.Self()->IsExceptionPending()); 151af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 152af6e67a4816d2593586115b89faa659225363246Ian Rogers } 153af6e67a4816d2593586115b89faa659225363246Ian Rogers for (size_t i = 0; i < args.size(); ++i) { 154af6e67a4816d2593586115b89faa659225363246Ian Rogers if (shorty[i + 1] == 'L') { 155af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject val = args.at(i).l; 156af6e67a4816d2593586115b89faa659225363246Ian Rogers soa.Env()->SetObjectArrayElement(args_jobj, i, val); 157af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 158af6e67a4816d2593586115b89faa659225363246Ian Rogers JValue jv; 159af6e67a4816d2593586115b89faa659225363246Ian Rogers jv.SetJ(args.at(i).j); 1602dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv); 161af6e67a4816d2593586115b89faa659225363246Ian Rogers if (val == NULL) { 162af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK(soa.Self()->IsExceptionPending()); 163af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 164af6e67a4816d2593586115b89faa659225363246Ian Rogers } 165d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set<false>(i, val); 166af6e67a4816d2593586115b89faa659225363246Ian Rogers } 167af6e67a4816d2593586115b89faa659225363246Ian Rogers } 168af6e67a4816d2593586115b89faa659225363246Ian Rogers } 169af6e67a4816d2593586115b89faa659225363246Ian Rogers 170ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom // Call Proxy.invoke(Proxy proxy, ArtMethod method, Object[] args). 171af6e67a4816d2593586115b89faa659225363246Ian Rogers jvalue invocation_args[3]; 172af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[0].l = rcvr_jobj; 173af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[1].l = interface_method_jobj; 174af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[2].l = args_jobj; 175af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject result = 176ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Env()->CallStaticObjectMethodA(WellKnownClasses::java_lang_reflect_Proxy, 177ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom WellKnownClasses::java_lang_reflect_Proxy_invoke, 178ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom invocation_args); 179af6e67a4816d2593586115b89faa659225363246Ian Rogers 180af6e67a4816d2593586115b89faa659225363246Ian Rogers // Unbox result and handle error conditions. 18162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (LIKELY(!soa.Self()->IsExceptionPending())) { 18262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (shorty[0] == 'V' || (shorty[0] == 'L' && result == NULL)) { 183af6e67a4816d2593586115b89faa659225363246Ian Rogers // Do nothing. 184af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 185af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 1862dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* result_ref = soa.Decode<mirror::Object*>(result); 18762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); 188ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* interface_method = 189ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Decode<mirror::ArtMethod*>(interface_method_jobj); 19062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Class* result_type = MethodHelper(interface_method).GetReturnType(); 191ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* proxy_method; 19262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (interface_method->GetDeclaringClass()->IsInterface()) { 19362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(interface_method); 19462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 19562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Proxy dispatch to a method defined in Object. 19662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DCHECK(interface_method->GetDeclaringClass()->IsObjectClass()); 19762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers proxy_method = interface_method; 19862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 19962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location(rcvr, proxy_method, -1); 20062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers JValue result_unboxed; 20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (!UnboxPrimitiveForResult(throw_location, result_ref, result_type, result_unboxed)) { 202530f71c040cb1a7b946d5566d5a746f08f2d082cIan Rogers DCHECK(soa.Self()->IsExceptionPending()); 20362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return zero; 204af6e67a4816d2593586115b89faa659225363246Ian Rogers } 205af6e67a4816d2593586115b89faa659225363246Ian Rogers return result_unboxed; 206af6e67a4816d2593586115b89faa659225363246Ian Rogers } 207af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 208af6e67a4816d2593586115b89faa659225363246Ian Rogers // In the case of checked exceptions that aren't declared, the exception must be wrapped by 209af6e67a4816d2593586115b89faa659225363246Ian Rogers // a UndeclaredThrowableException. 21062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception = soa.Self()->GetException(NULL); 211af6e67a4816d2593586115b89faa659225363246Ian Rogers if (exception->IsCheckedException()) { 2122dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); 2132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::SynthesizedProxyClass* proxy_class = 2142dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers down_cast<mirror::SynthesizedProxyClass*>(rcvr->GetClass()); 215ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* interface_method = 216ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Decode<mirror::ArtMethod*>(interface_method_jobj); 217ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* proxy_method = 218af6e67a4816d2593586115b89faa659225363246Ian Rogers rcvr->GetClass()->FindVirtualMethodForInterface(interface_method); 219af6e67a4816d2593586115b89faa659225363246Ian Rogers int throws_index = -1; 220af6e67a4816d2593586115b89faa659225363246Ian Rogers size_t num_virt_methods = proxy_class->NumVirtualMethods(); 221af6e67a4816d2593586115b89faa659225363246Ian Rogers for (size_t i = 0; i < num_virt_methods; i++) { 222af6e67a4816d2593586115b89faa659225363246Ian Rogers if (proxy_class->GetVirtualMethod(i) == proxy_method) { 223af6e67a4816d2593586115b89faa659225363246Ian Rogers throws_index = i; 224af6e67a4816d2593586115b89faa659225363246Ian Rogers break; 225af6e67a4816d2593586115b89faa659225363246Ian Rogers } 226af6e67a4816d2593586115b89faa659225363246Ian Rogers } 227af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK_NE(throws_index, -1); 2282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); 2292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* exception_class = exception->GetClass(); 230af6e67a4816d2593586115b89faa659225363246Ian Rogers bool declares_exception = false; 231af6e67a4816d2593586115b89faa659225363246Ian Rogers for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) { 2322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* declared_exception = declared_exceptions->Get(i); 233af6e67a4816d2593586115b89faa659225363246Ian Rogers declares_exception = declared_exception->IsAssignableFrom(exception_class); 234af6e67a4816d2593586115b89faa659225363246Ian Rogers } 235af6e67a4816d2593586115b89faa659225363246Ian Rogers if (!declares_exception) { 23662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location(rcvr, proxy_method, -1); 23762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers soa.Self()->ThrowNewWrappedException(throw_location, 23862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers "Ljava/lang/reflect/UndeclaredThrowableException;", 239af6e67a4816d2593586115b89faa659225363246Ian Rogers NULL); 240af6e67a4816d2593586115b89faa659225363246Ian Rogers } 241af6e67a4816d2593586115b89faa659225363246Ian Rogers } 242af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 243af6e67a4816d2593586115b89faa659225363246Ian Rogers } 244af6e67a4816d2593586115b89faa659225363246Ian Rogers} 2452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} // namespace art 246