entrypoint_utils.cc revision 262e251e56d66bd309c6165964ac0a0be24447fe
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 172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao#include "runtime_support.h" 182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 195bb8601175bbb9cd761c715f4ba04f84d65e913bTDYa#include "ScopedLocalRef.h" 20eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "well_known_classes.h" 215bb8601175bbb9cd761c715f4ba04f84d65e913bTDYa 2241005ddb5576b8630a1084fbb3979ffa602c0599jeffhaodouble art_l2d(int64_t l) { 23748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return static_cast<double>(l); 2441005ddb5576b8630a1084fbb3979ffa602c0599jeffhao} 2541005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 2641005ddb5576b8630a1084fbb3979ffa602c0599jeffhaofloat art_l2f(int64_t l) { 27748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return static_cast<float>(l); 2841005ddb5576b8630a1084fbb3979ffa602c0599jeffhao} 292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 30776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers/* 31776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers * Float/double conversion requires clamping to min and max of integer form. If 32776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers * target doesn't support this normally, use these. 33776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers */ 3441005ddb5576b8630a1084fbb3979ffa602c0599jeffhaoint64_t art_d2l(double d) { 35748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL)); 36748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL)); 37776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers if (d >= kMaxLong) { 38008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int64_t>(0x7fffffffffffffffULL); 39776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (d <= kMinLong) { 40008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int64_t>(0x8000000000000000ULL); 41776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (d != d) { // NaN case 42776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers return 0; 43776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else { 44748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return static_cast<int64_t>(d); 45776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } 46776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers} 47776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers 4841005ddb5576b8630a1084fbb3979ffa602c0599jeffhaoint64_t art_f2l(float f) { 49748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL)); 50748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL)); 51776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers if (f >= kMaxLong) { 52008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int64_t>(0x7fffffffffffffffULL); 53776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (f <= kMinLong) { 54008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int64_t>(0x8000000000000000ULL); 55776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (f != f) { // NaN case 56776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers return 0; 57776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else { 58748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return static_cast<int64_t>(f); 59776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } 60776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers} 61776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers 6241005ddb5576b8630a1084fbb3979ffa602c0599jeffhaoint32_t art_d2i(double d) { 63008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL)); 64008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL)); 65776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers if (d >= kMaxInt) { 66008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int32_t>(0x7fffffffUL); 67776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (d <= kMinInt) { 68008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int32_t>(0x80000000UL); 69776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (d != d) { // NaN case 70776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers return 0; 71776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else { 72748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return static_cast<int32_t>(d); 73776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } 74776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers} 75776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers 7641005ddb5576b8630a1084fbb3979ffa602c0599jeffhaoint32_t art_f2i(float f) { 77008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL)); 78008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL)); 79776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers if (f >= kMaxInt) { 80008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int32_t>(0x7fffffffUL); 81776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (f <= kMinInt) { 82008fa5114f356861f74f086f0b0c50fe42ef2891Logan Chien return static_cast<int32_t>(0x80000000UL); 83776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else if (f != f) { // NaN case 84776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers return 0; 85776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } else { 86748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes return static_cast<int32_t>(f); 87776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers } 88776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers} 89776ac1fa61237db645adb4370a4aab888530caf4Ian Rogers 9041005ddb5576b8630a1084fbb3979ffa602c0599jeffhaonamespace art { 9141005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 9257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers// Helper function to allocate array for FILLED_NEW_ARRAY. 9366f19258f9728d4ffe026074d8fd429d639802faMathieu ChartierArray* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count, 9457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Thread* self, bool access_check) { 9557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(component_count < 0)) { 9657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); 9757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure 98ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 9957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 10057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 10157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 10257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass == NULL) { // Error 10350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers DCHECK(self->IsExceptionPending()); 10457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure 105ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 106ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 10757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) { 10857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { 10950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers self->ThrowNewExceptionF("Ljava/lang/RuntimeException;", 11050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers "Bad filled array request for type %s", 11150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers PrettyDescriptor(klass).c_str()); 112573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } else { 11350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers self->ThrowNewExceptionF("Ljava/lang/InternalError;", 11450b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers "Found type %s; filled-new-array not implemented for anything but \'int\'", 11550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers PrettyDescriptor(klass).c_str()); 116573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } 11757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure 118ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } else { 11957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (access_check) { 12057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* referrer = method->GetDeclaringClass(); 12157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(!referrer->CanAccess(klass))) { 12287e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorClass(referrer, klass); 12357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure 12457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 12557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 12657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers DCHECK(klass->IsArrayClass()) << PrettyClass(klass); 12750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers return Array::Alloc(self, klass, component_count); 128ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 129ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 130ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 13166f19258f9728d4ffe026074d8fd429d639802faMathieu ChartierField* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thread* self, 13208f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers FindFieldType type, size_t expected_size) { 13308f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers bool is_primitive; 13408f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers bool is_set; 13508f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers bool is_static; 13608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers switch (type) { 13708f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break; 13808f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break; 13908f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break; 14008f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break; 14108f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break; 14208f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break; 14308f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break; 14408f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers case StaticPrimitiveWrite: // Keep GCC happy by having a default handler, fall-through. 14508f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers default: is_primitive = true; is_set = true; is_static = true; break; 14608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers } 14757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 14857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); 14957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(resolved_field == NULL)) { 15008f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 15108f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 15257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 15308f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers if (resolved_field->IsStatic() != is_static) { 15487e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer); 15508f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; 15608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers } 15757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* fields_class = resolved_field->GetDeclaringClass(); 15857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* referring_class = referrer->GetDeclaringClass(); 159e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers if (UNLIKELY(!referring_class->CanAccess(fields_class) || 160e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers !referring_class->CanAccessMember(fields_class, 161e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers resolved_field->GetAccessFlags()))) { 162e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers // The referring class can't access the resolved field, this may occur as a result of a 163e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers // protected field being made public by a sub-class. Resort to the dex file to determine 164e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers // the correct class for the access check. 1654445a7e3398a6143939168097a3aa275b734504dIan Rogers const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile(); 166e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers fields_class = class_linker->ResolveType(dex_file, 167e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers dex_file.GetFieldId(field_idx).class_idx_, 168e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers referring_class); 169e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers if (UNLIKELY(!referring_class->CanAccess(fields_class))) { 17087e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorClass(referring_class, fields_class); 171e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers return NULL; // failure 172e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class, 173e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers resolved_field->GetAccessFlags()))) { 17487e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorField(referring_class, resolved_field); 175e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers return NULL; // failure 176e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers } 177e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers } 178e2645d3e2db211bfd75775a2185c135ff387161aIan Rogers if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) { 17987e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorFinalField(referrer, resolved_field); 18057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // failure 18157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 18257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers FieldHelper fh(resolved_field); 18357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(fh.IsPrimitiveType() != is_primitive || 18457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers fh.FieldSize() != expected_size)) { 18557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 18657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers "Attempted read of %zd-bit %s on field '%s'", 18757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers expected_size * (32 / sizeof(int32_t)), 18857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers is_primitive ? "primitive" : "non-primitive", 18957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers PrettyField(resolved_field, true).c_str()); 19057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // failure 19157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else if (!is_static) { 19257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // instance fields must be being accessed on an initialized class 19357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return resolved_field; 19460db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers } else { 19557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // If the class is already initializing, we must be inside <clinit>, or 19657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // we'd still be waiting for the lock. 19757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (fields_class->IsInitializing()) { 19857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return resolved_field; 1990045a290e6b79a274250e3112880c04bde437d4aIan Rogers } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) { 20057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return resolved_field; 20160db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers } else { 20257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers DCHECK(self->IsExceptionPending()); // Throw exception and unwind 20357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // failure 20460db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers } 20560db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers } 20660db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers } 20760db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers } 208ddbd01ac1660d57416879d5a576482f1048dde64Shih-wei Liao} 209ddbd01ac1660d57416879d5a576482f1048dde64Shih-wei Liao 21057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers// Slow path method resolution 211262e251e56d66bd309c6165964ac0a0be24447fejeffhaoAbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, AbstractMethod* referrer, 21257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Thread* self, bool access_check, InvokeType type) { 21357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 21457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers bool is_direct = type == kStatic || type == kDirect; 21566f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type); 21657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(resolved_method == NULL)) { 21708f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers DCHECK(self->IsExceptionPending()); // Throw exception and unwind. 21808f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 219262e251e56d66bd309c6165964ac0a0be24447fejeffhao } else if (UNLIKELY(this_object == NULL && type != kStatic)) { 220262e251e56d66bd309c6165964ac0a0be24447fejeffhao // Maintain interpreter-like semantics where NullPointerException is thrown 221262e251e56d66bd309c6165964ac0a0be24447fejeffhao // after potential NoSuchMethodError from class linker. 222262e251e56d66bd309c6165964ac0a0be24447fejeffhao ThrowNullPointerExceptionForMethodAccess(referrer, method_idx, type); 223262e251e56d66bd309c6165964ac0a0be24447fejeffhao return NULL; // Failure. 224466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 22557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (!access_check) { 22657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (is_direct) { 22757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return resolved_method; 22857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else if (type == kInterface) { 22966f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier AbstractMethod* interface_method = 23057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); 23157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(interface_method == NULL)) { 23287e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object, 23387e552db94588455c081efd87dbde0cd96d02942Ian Rogers referrer); 23408f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 23557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 23657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return interface_method; 23757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 23857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 23966f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier ObjectArray<AbstractMethod>* vtable; 24057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers uint16_t vtable_index = resolved_method->GetMethodIndex(); 24157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (type == kSuper) { 24257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable(); 24357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 24457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = this_object->GetClass()->GetVTable(); 24557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 24657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // TODO: eliminate bounds check? 24757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return vtable->Get(vtable_index); 248051c9fc1de07bbc265af38cf60f061394163c68fElliott Hughes } 249466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 25008f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers // Incompatible class change should have been handled in resolve method. 25108f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) { 2522fc1427ee9c534ed44d72184ad6d74ea65f3d5b3Ian Rogers ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method, 2532fc1427ee9c534ed44d72184ad6d74ea65f3d5b3Ian Rogers referrer); 25408f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 25508f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers } 25657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* methods_class = resolved_method->GetDeclaringClass(); 25757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* referring_class = referrer->GetDeclaringClass(); 25857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(!referring_class->CanAccess(methods_class) || 25957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers !referring_class->CanAccessMember(methods_class, 26057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers resolved_method->GetAccessFlags()))) { 26157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // The referring class can't access the resolved method, this may occur as a result of a 26257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // protected method being made public by implementing an interface that re-declares the 26357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // method public. Resort to the dex file to determine the correct class for the access check 2644445a7e3398a6143939168097a3aa275b734504dIan Rogers const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile(); 26557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers methods_class = class_linker->ResolveType(dex_file, 26657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers dex_file.GetMethodId(method_idx).class_idx_, 26757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers referring_class); 26857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(!referring_class->CanAccess(methods_class))) { 26987e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class, 27087e552db94588455c081efd87dbde0cd96d02942Ian Rogers referrer, resolved_method, type); 27108f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 27257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class, 27357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers resolved_method->GetAccessFlags()))) { 27487e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorMethod(referring_class, resolved_method); 27508f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 276c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers } 277c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers } 27857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (is_direct) { 27957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return resolved_method; 28057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else if (type == kInterface) { 28166f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier AbstractMethod* interface_method = 28257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); 28357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(interface_method == NULL)) { 28487e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object, 28587e552db94588455c081efd87dbde0cd96d02942Ian Rogers referrer); 28608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 28757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 28857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return interface_method; 28957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 290466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 29166f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier ObjectArray<AbstractMethod>* vtable; 29257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers uint16_t vtable_index = resolved_method->GetMethodIndex(); 29357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (type == kSuper) { 29457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* super_class = referring_class->GetSuperClass(); 29557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (LIKELY(super_class != NULL)) { 29657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = referring_class->GetSuperClass()->GetVTable(); 29757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 29857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = NULL; 29957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 30057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 30157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = this_object->GetClass()->GetVTable(); 30257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 30357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (LIKELY(vtable != NULL && 30457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable_index < static_cast<uint32_t>(vtable->GetLength()))) { 30557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return vtable->GetWithoutChecks(vtable_index); 30657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 30708f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers // Behavior to agree with that of the verifier. 30808f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers MethodHelper mh(resolved_method); 30908f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(), 3102fc1427ee9c534ed44d72184ad6d74ea65f3d5b3Ian Rogers mh.GetSignature(), referrer); 31108f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 31257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 313466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 314466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 315dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 316dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers} 317dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers 31866f19258f9728d4ffe026074d8fd429d639802faMathieu ChartierClass* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self, 31957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers bool can_run_clinit, bool verify_access) { 32057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 32157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* klass = class_linker->ResolveType(type_idx, referrer); 32257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass == NULL)) { 32357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers CHECK(self->IsExceptionPending()); 32457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 32557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 32657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // Perform access check if necessary. 32757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* referring_class = referrer->GetDeclaringClass(); 32857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) { 32987e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorClass(referring_class, klass); 33057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 33157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 33257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // If we're just implementing const-class, we shouldn't call <clinit>. 33357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (!can_run_clinit) { 33457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return klass; 33557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 33657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // If we are the <clinit> of this class, just return our storage. 33757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // 33857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished 33957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // running. 34057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) { 34157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return klass; 34257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 3430045a290e6b79a274250e3112880c04bde437d4aIan Rogers if (!class_linker->EnsureInitialized(klass, true, true)) { 34457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers CHECK(self->IsExceptionPending()); 34557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 346a433b2e8edf91c8124abd8eb5b3bd558a40fc987Ian Rogers } 34757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass); 34857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return klass; 3492d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 3502d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 351d752132c73072084a3def9257cca4fcee76047b6jeffhaovoid ThrowStackOverflowError(Thread* self) { 352d752132c73072084a3def9257cca4fcee76047b6jeffhao CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow."; 353d752132c73072084a3def9257cca4fcee76047b6jeffhao // Remove extra entry pushed onto second stack during method tracing. 354d752132c73072084a3def9257cca4fcee76047b6jeffhao if (Runtime::Current()->IsMethodTracingActive()) { 355d752132c73072084a3def9257cca4fcee76047b6jeffhao InstrumentationMethodUnwindFromCode(self); 356d752132c73072084a3def9257cca4fcee76047b6jeffhao } 357d752132c73072084a3def9257cca4fcee76047b6jeffhao self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. 358d752132c73072084a3def9257cca4fcee76047b6jeffhao JNIEnvExt* env = self->GetJniEnv(); 359d752132c73072084a3def9257cca4fcee76047b6jeffhao std::string msg("stack size "); 360d752132c73072084a3def9257cca4fcee76047b6jeffhao msg += PrettySize(self->GetStackSize()); 361d752132c73072084a3def9257cca4fcee76047b6jeffhao // Use low-level JNI routine and pre-baked error class to avoid class linking operations that 362d752132c73072084a3def9257cca4fcee76047b6jeffhao // would consume more stack. 363d752132c73072084a3def9257cca4fcee76047b6jeffhao int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError, 364d752132c73072084a3def9257cca4fcee76047b6jeffhao msg.c_str(), NULL); 365d752132c73072084a3def9257cca4fcee76047b6jeffhao if (rc != JNI_OK) { 366d752132c73072084a3def9257cca4fcee76047b6jeffhao // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME 367d752132c73072084a3def9257cca4fcee76047b6jeffhao // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError 368d752132c73072084a3def9257cca4fcee76047b6jeffhao // instead. 369d752132c73072084a3def9257cca4fcee76047b6jeffhao LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed."; 370d752132c73072084a3def9257cca4fcee76047b6jeffhao CHECK(self->IsExceptionPending()); 371d752132c73072084a3def9257cca4fcee76047b6jeffhao } 372d752132c73072084a3def9257cca4fcee76047b6jeffhao self->ResetDefaultStackEnd(); // Return to default stack size. 373d752132c73072084a3def9257cca4fcee76047b6jeffhao} 374d752132c73072084a3def9257cca4fcee76047b6jeffhao 3752d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} // namespace art 376