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