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