entrypoint_utils.cc revision 57b86d47b66322693a070185fadfb43cb9c12eab
12d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/*
257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers * Copyright 2012 Google Inc. All Rights Reserved.
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
192d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaonamespace art {
202d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao
2157b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNewIllegalAccessErrorClass(Thread* self,
2257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                     Class* referrer,
2357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                     Class* accessed) {
2457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
2557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "illegal class access: '%s' -> '%s'",
2657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(referrer).c_str(),
2757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(accessed).c_str());
2857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
2957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
3057b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
3157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                      Class* referrer,
3257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                      Class* accessed,
3357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                      const Method* caller,
3457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                      const Method* called,
3557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                      InvokeType type) {
3657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  std::ostringstream type_stream;
3757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  type_stream << type;
3857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
3957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "illegal class access ('%s' -> '%s')"
4057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "in attempt to invoke %s method '%s' from '%s'",
4157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(referrer).c_str(),
4257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(accessed).c_str(),
4357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           type_stream.str().c_str(),
4457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyMethod(called).c_str(),
4557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyMethod(caller).c_str());
4657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
4757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
4857b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
4957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                                   const Method* referrer,
5057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                                   const Method* interface_method,
5157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                                   Object* this_object) {
5257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
5357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "class '%s' does not implement interface '%s' in call to '%s' from '%s'",
5457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(this_object->GetClass()).c_str(),
5557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(interface_method->GetDeclaringClass()).c_str(),
5657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyMethod(interface_method).c_str(), PrettyMethod(referrer).c_str());
5757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
5857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
5957b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNewIllegalAccessErrorField(Thread* self,
6057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                     Class* referrer,
6157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                     Field* accessed) {
6257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
6357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "Field '%s' is inaccessible to class '%s'",
6457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyField(accessed, false).c_str(),
6557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(referrer).c_str());
6657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
6757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
6857b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNewIllegalAccessErrorFinalField(Thread* self,
6957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                          const Method* referrer,
7057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                          Field* accessed) {
7157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
7257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "Final field '%s' cannot be written to by method '%s'",
7357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyField(accessed, false).c_str(),
7457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyMethod(referrer).c_str());
7557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
7657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
7757b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNewIllegalAccessErrorMethod(Thread* self,
7857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                      Class* referrer,
7957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                      Method* accessed) {
8057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
8157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "Method '%s' is inaccessible to class '%s'",
8257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyMethod(accessed).c_str(),
8357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyDescriptor(referrer).c_str());
8457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
8557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
8657b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNullPointerExceptionForFieldAccess(Thread* self,
8757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                           Field* field,
8857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                           bool is_read) {
8957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
9057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "Attempt to %s field '%s' on a null object reference",
9157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           is_read ? "read from" : "write to",
9257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyField(field, true).c_str());
9357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
9457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
9557b86d47b66322693a070185fadfb43cb9c12eabIan Rogersvoid ThrowNullPointerExceptionForMethodAccess(Thread* self,
9657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                              Method* caller,
9757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                              uint32_t method_idx,
9857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                              InvokeType type) {
9957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  const DexFile& dex_file =
10057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
10157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  std::ostringstream type_stream;
10257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  type_stream << type;
10357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
10457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           "Attempt to invoke %s method '%s' on a null object reference",
10557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           type_stream.str().c_str(),
10657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           PrettyMethod(method_idx, dex_file, true).c_str());
10757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers}
10857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers
10957b86d47b66322693a070185fadfb43cb9c12eabIan Rogersstd::string FieldNameFromIndex(const Method* method, uint32_t ref,
11057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                               verifier::VerifyErrorRefType ref_type, bool access) {
111d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers  CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD));
1126c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
1136c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1146c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
1156c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
1166c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  const DexFile::FieldId& id = dex_file.GetFieldId(ref);
1176b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom  std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
1180571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
1196c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  if (!access) {
1206c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes    return class_name + "." + field_name;
1216c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  }
1226c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
1236c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  std::string result;
1246c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  result += "tried to access field ";
1256c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  result += class_name + "." + field_name;
1266c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  result += " from class ";
1276d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  result += PrettyDescriptor(method->GetDeclaringClass());
1286c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  return result;
1296c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes}
1306c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
13157b86d47b66322693a070185fadfb43cb9c12eabIan Rogersstd::string MethodNameFromIndex(const Method* method, uint32_t ref,
13257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                verifier::VerifyErrorRefType ref_type, bool access) {
133d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers  CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
1346c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
1356c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1366c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
1376c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
1386c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  const DexFile::MethodId& id = dex_file.GetMethodId(ref);
1396b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom  std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
1400571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers  const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
1416c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  if (!access) {
1426c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes    return class_name + "." + method_name;
1436c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  }
1446c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
1456c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  std::string result;
1466c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  result += "tried to access method ";
1474f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  result += class_name + "." + method_name + ":" +
1480571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      dex_file.CreateMethodSignature(id.proto_idx_, NULL);
1496c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  result += " from class ";
1506d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  result += PrettyDescriptor(method->GetDeclaringClass());
1516c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes  return result;
1526c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes}
1536c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes
15457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers// Helper function to allocate array for FILLED_NEW_ARRAY.
15557b86d47b66322693a070185fadfb43cb9c12eabIan RogersArray* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
15657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                  Thread* self, bool access_check) {
15757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (UNLIKELY(component_count < 0)) {
15857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
15957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return NULL;  // Failure
160ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers  }
16157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
16257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
16357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
16457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    if (klass == NULL) {  // Error
16557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      DCHECK(Thread::Current()->IsExceptionPending());
16657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      return NULL;  // Failure
167ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    }
168ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers  }
16957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
17057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
17157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
17257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                            "Bad filled array request for type %s",
17357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                            PrettyDescriptor(klass).c_str());
174573db4a2077380d81fa74ee2309162530db87a98Ian Rogers    } else {
17557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
17657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                            "Found type %s; filled-new-array not implemented for anything but \'int\'",
17757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                            PrettyDescriptor(klass).c_str());
178573db4a2077380d81fa74ee2309162530db87a98Ian Rogers    }
17957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return NULL;  // Failure
180ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  } else {
18157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    if (access_check) {
18257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      Class* referrer = method->GetDeclaringClass();
18357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      if (UNLIKELY(!referrer->CanAccess(klass))) {
18457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        ThrowNewIllegalAccessErrorClass(self, referrer, klass);
18557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        return NULL;  // Failure
18657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      }
18757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    }
18857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
18957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return Array::Alloc(klass, component_count);
190ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  }
191ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers}
192ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
19357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers// Slow path field resolution and declaring class initialization
19457b86d47b66322693a070185fadfb43cb9c12eabIan RogersField* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
19557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                         bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
19657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
19757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
19857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (UNLIKELY(resolved_field == NULL)) {
19957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    DCHECK(self->IsExceptionPending());  // Throw exception and unwind
20057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return NULL;  // failure
20157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  } else {
20257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    Class* fields_class = resolved_field->GetDeclaringClass();
20357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    Class* referring_class = referrer->GetDeclaringClass();
20457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
20557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
20657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      return NULL;  // failure
20757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
20857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                          resolved_field->GetAccessFlags()))) {
20957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
21057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      return NULL;  // failure
21157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    } else if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
21257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
21357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      return NULL;  // failure
21457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    } else {
21557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      FieldHelper fh(resolved_field);
21657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
21757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                   fh.FieldSize() != expected_size)) {
21857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
21957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                 "Attempted read of %zd-bit %s on field '%s'",
22057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                 expected_size * (32 / sizeof(int32_t)),
22157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                 is_primitive ? "primitive" : "non-primitive",
22257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                 PrettyField(resolved_field, true).c_str());
22357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        return NULL;  // failure
22457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      } else if (!is_static) {
22557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        // instance fields must be being accessed on an initialized class
22657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        return resolved_field;
22760db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers      } else {
22857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        // If the class is already initializing, we must be inside <clinit>, or
22957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        // we'd still be waiting for the lock.
23057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        if (fields_class->IsInitializing()) {
23157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return resolved_field;
23257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true)) {
23357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return resolved_field;
23460db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers        } else {
23557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          DCHECK(self->IsExceptionPending());  // Throw exception and unwind
23657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return NULL;  // failure
23760db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers        }
23860db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers      }
23960db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers    }
24060db5ab3a2e480db9236325a14cb5a867881d8bbIan Rogers  }
241ddbd01ac1660d57416879d5a576482f1048dde64Shih-wei Liao}
242ddbd01ac1660d57416879d5a576482f1048dde64Shih-wei Liao
24357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers// Slow path method resolution
24457b86d47b66322693a070185fadfb43cb9c12eabIan RogersMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
24557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                           Thread* self, bool access_check, InvokeType type) {
24657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
24757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  bool is_direct = type == kStatic || type == kDirect;
24857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
24957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (UNLIKELY(resolved_method == NULL)) {
25057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    DCHECK(self->IsExceptionPending());  // Throw exception and unwind
25157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return NULL;  // failure
252466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers  } else {
25357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    if (!access_check) {
25457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      if (is_direct) {
25557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        return resolved_method;
25657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      } else if (type == kInterface) {
25757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        Method* interface_method =
25857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
25957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        if (UNLIKELY(interface_method == NULL)) {
26057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
26157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                                        resolved_method,
26257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                                        this_object);
26357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return NULL;  // failure
26457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        } else {
26557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return interface_method;
26657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        }
26757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      } else {
26857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        ObjectArray<Method>* vtable;
26957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        uint16_t vtable_index = resolved_method->GetMethodIndex();
27057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        if (type == kSuper) {
27157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
27257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        } else {
27357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          vtable = this_object->GetClass()->GetVTable();
27457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        }
27557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        // TODO: eliminate bounds check?
27657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        return vtable->Get(vtable_index);
277051c9fc1de07bbc265af38cf60f061394163c68fElliott Hughes      }
278466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers    } else {
27957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      Class* methods_class = resolved_method->GetDeclaringClass();
28057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      Class* referring_class = referrer->GetDeclaringClass();
28157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
28257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                   !referring_class->CanAccessMember(methods_class,
28357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                     resolved_method->GetAccessFlags()))) {
28457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        // The referring class can't access the resolved method, this may occur as a result of a
28557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        // protected method being made public by implementing an interface that re-declares the
28657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        // method public. Resort to the dex file to determine the correct class for the access check
28757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
28857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        methods_class = class_linker->ResolveType(dex_file,
28957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                  dex_file.GetMethodId(method_idx).class_idx_,
29057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                  referring_class);
29157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
29257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
29357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                           referrer, resolved_method, type);
29457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return NULL;  // failure
29557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
29657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                              resolved_method->GetAccessFlags()))) {
29757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
29857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return NULL;  // failure
299c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers        }
300c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers      }
30157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      if (is_direct) {
30257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        return resolved_method;
30357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers      } else if (type == kInterface) {
30457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        Method* interface_method =
30557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
30657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        if (UNLIKELY(interface_method == NULL)) {
30757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
30857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                                        resolved_method,
30957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                                                        this_object);
31057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return NULL;  // failure
31157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        } else {
31257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return interface_method;
31357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        }
314466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers      } else {
31557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        ObjectArray<Method>* vtable;
31657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        uint16_t vtable_index = resolved_method->GetMethodIndex();
31757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        if (type == kSuper) {
31857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          Class* super_class = referring_class->GetSuperClass();
31957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          if (LIKELY(super_class != NULL)) {
32057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers            vtable = referring_class->GetSuperClass()->GetVTable();
32157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          } else {
32257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers            vtable = NULL;
32357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          }
32457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        } else {
32557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          vtable = this_object->GetClass()->GetVTable();
32657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        }
32757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        if (LIKELY(vtable != NULL &&
32857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                   vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
32957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return vtable->GetWithoutChecks(vtable_index);
33057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        } else {
33157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          // Behavior to agree with that of the verifier
33257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          self->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
33357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                   "attempt to invoke %s method '%s' from '%s'"
33457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                   " using incorrect form of method dispatch",
33557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                   (type == kSuper ? "super class" : "virtual"),
33657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                   PrettyMethod(resolved_method).c_str(),
33757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                                   PrettyMethod(referrer).c_str());
33857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers          return NULL;  // failure
33957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers        }
340466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers      }
341466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers    }
342dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers  }
343dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers}
344dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers
34557b86d47b66322693a070185fadfb43cb9c12eabIan RogersClass* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
34657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers                               bool can_run_clinit, bool verify_access) {
34757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
34857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  Class* klass = class_linker->ResolveType(type_idx, referrer);
34957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (UNLIKELY(klass == NULL)) {
35057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    CHECK(self->IsExceptionPending());
35157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return NULL;  // Failure - Indicate to caller to deliver exception
35257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  }
35357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  // Perform access check if necessary.
35457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  Class* referring_class = referrer->GetDeclaringClass();
35557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
35657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
35757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return NULL;  // Failure - Indicate to caller to deliver exception
35857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  }
35957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  // If we're just implementing const-class, we shouldn't call <clinit>.
36057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (!can_run_clinit) {
36157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return klass;
36257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  }
36357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  // If we are the <clinit> of this class, just return our storage.
36457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  //
36557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
36657b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  // running.
36757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
36857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return klass;
36957b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  }
37057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  if (!class_linker->EnsureInitialized(klass, true)) {
37157b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    CHECK(self->IsExceptionPending());
37257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers    return NULL;  // Failure - Indicate to caller to deliver exception
373a433b2e8edf91c8124abd8eb5b3bd558a40fc987Ian Rogers  }
37457b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
37557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers  return klass;
3762d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao}
3772d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao
3782d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao}  // namespace art
379