entrypoint_utils.cc revision d752132c73072084a3def9257cca4fcee76047b6
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 21166f19258f9728d4ffe026074d8fd429d639802faMathieu ChartierAbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, const 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. 219466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 22057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (!access_check) { 22157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (is_direct) { 22257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return resolved_method; 22357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else if (type == kInterface) { 22466f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier AbstractMethod* interface_method = 22557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); 22657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(interface_method == NULL)) { 22787e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object, 22887e552db94588455c081efd87dbde0cd96d02942Ian Rogers referrer); 22908f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 23057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 23157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return interface_method; 23257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 23357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 23466f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier ObjectArray<AbstractMethod>* vtable; 23557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers uint16_t vtable_index = resolved_method->GetMethodIndex(); 23657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (type == kSuper) { 23757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable(); 23857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 23957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = this_object->GetClass()->GetVTable(); 24057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 24157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // TODO: eliminate bounds check? 24257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return vtable->Get(vtable_index); 243051c9fc1de07bbc265af38cf60f061394163c68fElliott Hughes } 244466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 24508f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers // Incompatible class change should have been handled in resolve method. 24608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) { 2472fc1427ee9c534ed44d72184ad6d74ea65f3d5b3Ian Rogers ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method, 2482fc1427ee9c534ed44d72184ad6d74ea65f3d5b3Ian Rogers referrer); 24908f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 25008f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers } 25157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* methods_class = resolved_method->GetDeclaringClass(); 25257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* referring_class = referrer->GetDeclaringClass(); 25357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(!referring_class->CanAccess(methods_class) || 25457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers !referring_class->CanAccessMember(methods_class, 25557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers resolved_method->GetAccessFlags()))) { 25657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // The referring class can't access the resolved method, this may occur as a result of a 25757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // protected method being made public by implementing an interface that re-declares the 25857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // method public. Resort to the dex file to determine the correct class for the access check 2594445a7e3398a6143939168097a3aa275b734504dIan Rogers const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile(); 26057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers methods_class = class_linker->ResolveType(dex_file, 26157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers dex_file.GetMethodId(method_idx).class_idx_, 26257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers referring_class); 26357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(!referring_class->CanAccess(methods_class))) { 26487e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class, 26587e552db94588455c081efd87dbde0cd96d02942Ian Rogers referrer, resolved_method, type); 26608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 26757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class, 26857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers resolved_method->GetAccessFlags()))) { 26987e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorMethod(referring_class, resolved_method); 27008f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 271c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers } 272c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers } 27357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (is_direct) { 27457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return resolved_method; 27557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else if (type == kInterface) { 27666f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier AbstractMethod* interface_method = 27757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers this_object->GetClass()->FindVirtualMethodForInterface(resolved_method); 27857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(interface_method == NULL)) { 27987e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object, 28087e552db94588455c081efd87dbde0cd96d02942Ian Rogers referrer); 28108f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 28257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 28357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return interface_method; 28457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 285466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 28666f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier ObjectArray<AbstractMethod>* vtable; 28757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers uint16_t vtable_index = resolved_method->GetMethodIndex(); 28857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (type == kSuper) { 28957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* super_class = referring_class->GetSuperClass(); 29057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (LIKELY(super_class != NULL)) { 29157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = referring_class->GetSuperClass()->GetVTable(); 29257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 29357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = NULL; 29457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 29557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 29657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable = this_object->GetClass()->GetVTable(); 29757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 29857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (LIKELY(vtable != NULL && 29957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers vtable_index < static_cast<uint32_t>(vtable->GetLength()))) { 30057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return vtable->GetWithoutChecks(vtable_index); 30157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } else { 30208f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers // Behavior to agree with that of the verifier. 30308f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers MethodHelper mh(resolved_method); 30408f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(), 3052fc1427ee9c534ed44d72184ad6d74ea65f3d5b3Ian Rogers mh.GetSignature(), referrer); 30608f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers return NULL; // Failure. 30757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 308466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 309466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 310dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 311dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers} 312dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers 31366f19258f9728d4ffe026074d8fd429d639802faMathieu ChartierClass* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self, 31457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers bool can_run_clinit, bool verify_access) { 31557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 31657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* klass = class_linker->ResolveType(type_idx, referrer); 31757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass == NULL)) { 31857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers CHECK(self->IsExceptionPending()); 31957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 32057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 32157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // Perform access check if necessary. 32257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers Class* referring_class = referrer->GetDeclaringClass(); 32357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) { 32487e552db94588455c081efd87dbde0cd96d02942Ian Rogers ThrowIllegalAccessErrorClass(referring_class, klass); 32557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 32657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 32757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // If we're just implementing const-class, we shouldn't call <clinit>. 32857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (!can_run_clinit) { 32957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return klass; 33057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 33157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // If we are the <clinit> of this class, just return our storage. 33257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // 33357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished 33457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers // running. 33557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) { 33657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return klass; 33757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 3380045a290e6b79a274250e3112880c04bde437d4aIan Rogers if (!class_linker->EnsureInitialized(klass, true, true)) { 33957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers CHECK(self->IsExceptionPending()); 34057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 341a433b2e8edf91c8124abd8eb5b3bd558a40fc987Ian Rogers } 34257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass); 34357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers return klass; 3442d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 3452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 346d752132c73072084a3def9257cca4fcee76047b6jeffhaovoid ThrowStackOverflowError(Thread* self) { 347d752132c73072084a3def9257cca4fcee76047b6jeffhao CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow."; 348d752132c73072084a3def9257cca4fcee76047b6jeffhao // Remove extra entry pushed onto second stack during method tracing. 349d752132c73072084a3def9257cca4fcee76047b6jeffhao if (Runtime::Current()->IsMethodTracingActive()) { 350d752132c73072084a3def9257cca4fcee76047b6jeffhao InstrumentationMethodUnwindFromCode(self); 351d752132c73072084a3def9257cca4fcee76047b6jeffhao } 352d752132c73072084a3def9257cca4fcee76047b6jeffhao self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. 353d752132c73072084a3def9257cca4fcee76047b6jeffhao JNIEnvExt* env = self->GetJniEnv(); 354d752132c73072084a3def9257cca4fcee76047b6jeffhao std::string msg("stack size "); 355d752132c73072084a3def9257cca4fcee76047b6jeffhao msg += PrettySize(self->GetStackSize()); 356d752132c73072084a3def9257cca4fcee76047b6jeffhao // Use low-level JNI routine and pre-baked error class to avoid class linking operations that 357d752132c73072084a3def9257cca4fcee76047b6jeffhao // would consume more stack. 358d752132c73072084a3def9257cca4fcee76047b6jeffhao int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError, 359d752132c73072084a3def9257cca4fcee76047b6jeffhao msg.c_str(), NULL); 360d752132c73072084a3def9257cca4fcee76047b6jeffhao if (rc != JNI_OK) { 361d752132c73072084a3def9257cca4fcee76047b6jeffhao // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME 362d752132c73072084a3def9257cca4fcee76047b6jeffhao // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError 363d752132c73072084a3def9257cca4fcee76047b6jeffhao // instead. 364d752132c73072084a3def9257cca4fcee76047b6jeffhao LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed."; 365d752132c73072084a3def9257cca4fcee76047b6jeffhao CHECK(self->IsExceptionPending()); 366d752132c73072084a3def9257cca4fcee76047b6jeffhao } 367d752132c73072084a3def9257cca4fcee76047b6jeffhao self->ResetDefaultStackEnd(); // Return to default stack size. 368d752132c73072084a3def9257cca4fcee76047b6jeffhao} 369d752132c73072084a3def9257cca4fcee76047b6jeffhao 3702d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} // namespace art 371