entrypoint_utils.cc revision 466bb25416b88fabd5d4387b7c7e5cc1ece78b8c
12d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/* 22d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Copyright 2011 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 19caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers#include "dex_cache.h" 206c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes#include "dex_verifier.h" 21caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers#include "macros.h" 22dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers#include "reflection.h" 23dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers#include "ScopedLocalRef.h" 246c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaonamespace art { 262d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 274f0d07c783afef89703dce32c94440fc8621a29bIan Rogers// Place a special frame at the TOS that will save the callee saves for the given type 284f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic void FinishCalleeSaveFrameSetup(Thread* self, Method** sp, Runtime::CalleeSaveType type) { 29ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers // Be aware the store below may well stomp on an incoming argument 304f0d07c783afef89703dce32c94440fc8621a29bIan Rogers *sp = Runtime::Current()->GetCalleeSaveMethod(type); 314f0d07c783afef89703dce32c94440fc8621a29bIan Rogers self->SetTopOfStack(sp, 0); 324f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 334f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Temporary debugging hook for compiler. 352d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern void DebugMe(Method* method, uint32_t info) { 362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(INFO) << "DebugMe"; 372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (method != NULL) { 382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(INFO) << PrettyMethod(method); 392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(INFO) << "Info: " << info; 412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 422d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 43caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogersvoid ObjectInitFromCode(Object* o) { 44caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* c = o->GetClass(); 45caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(c->IsFinalizable())) { 46caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Heap::AddFinalizerReference(o); 47caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 48caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers /* 49caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers * NOTE: once debugger/profiler support is added, we'll need to check 50caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers * here and branch to actual compiled object.<init> to handle any 51caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers * breakpoint/logging activites if either is active. 52caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers */ 53caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers} 54caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers 552d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Return value helper for jobject return types 562d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern Object* DecodeJObjectInThread(Thread* thread, jobject obj) { 576f495f2898a418f87e2a919e04fe23521bb0b9e9Brian Carlstrom if (thread->IsExceptionPending()) { 586f495f2898a418f87e2a919e04fe23521bb0b9e9Brian Carlstrom return NULL; 596f495f2898a418f87e2a919e04fe23521bb0b9e9Brian Carlstrom } 602d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return thread->DecodeJObject(obj); 612d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 622d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 632d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern void* FindNativeMethod(Thread* thread) { 642d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(Thread::Current() == thread); 652d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 662d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Method* method = const_cast<Method*>(thread->GetCurrentMethod()); 672d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(method != NULL); 682d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 692d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // Lookup symbol address for method, on failure we'll return NULL with an 702d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // exception set, otherwise we return the address of the method we found. 712d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao void* native_code = thread->GetJniEnv()->vm->FindCodeForNativeMethod(method); 722d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (native_code == NULL) { 732d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(thread->IsExceptionPending()); 742d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; 752d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 762d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // Register so that future calls don't come here 772d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao method->RegisterNative(native_code); 782d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return native_code; 792d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 802d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 812d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 822d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw an exception 832d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread, Method** sp) { 842d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao /* 852d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * exception may be NULL, in which case this routine should 862d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * throw NPE. NOTE: this is a convenience for generated code, 872d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * which previously did the null check inline and constructed 882d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * and threw a NPE if NULL. This routine responsible for setting 892d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * exception_ in thread and delivering the exception. 902d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 914f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 922d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (exception == NULL) { 932d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception"); 942d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 952d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->SetException(exception); 962d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 972d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 982d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 992d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1002d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Deliver an exception that's pending on thread helping set up a callee save frame on the way 1012d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artDeliverPendingExceptionFromCode(Thread* thread, Method** sp) { 1024f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1032d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1042d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1052d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1062d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw a NPE exception 1072d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowNullPointerExceptionFromCode(Thread* thread, Method** sp) { 1084f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1095cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewException("Ljava/lang/NullPointerException;", NULL); 1102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw an arithmetic divide by zero exception 1142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowDivZeroFromCode(Thread* thread, Method** sp) { 1154f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero"); 1172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1192d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1202d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw an arithmetic divide by zero exception 1212d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread, Method** sp) { 1224f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1234f0d07c783afef89703dce32c94440fc8621a29bIan Rogers thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", 1244f0d07c783afef89703dce32c94440fc8621a29bIan Rogers "length=%d; index=%d", limit, index); 1252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1262d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1272d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1282d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by the AbstractMethodError stub (not runtime support) 1292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) { 1304f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1314f0d07c783afef89703dce32c94440fc8621a29bIan Rogers thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;", 1324f0d07c783afef89703dce32c94440fc8621a29bIan Rogers "abstract method \"%s\"", PrettyMethod(method).c_str()); 1332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1352d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowStackOverflowFromCode(Method* method, Thread* thread, Method** sp) { 1374f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute 1395cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;", 1405cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes "stack size %zdkb; default stack size: %zdkb", 1414f0d07c783afef89703dce32c94440fc8621a29bIan Rogers thread->GetStackSize() / KB, Runtime::Current()->GetDefaultStackSize() / KB); 1422d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->ResetDefaultStackEnd(); // Return to default stack size 1432d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1442d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1464f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic std::string ClassNameFromIndex(Method* method, uint32_t ref, 1474f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DexVerifier::VerifyErrorRefType ref_type, bool access) { 1486c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 1496c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); 1506c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1516c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes uint16_t type_idx = 0; 1526c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes if (ref_type == DexVerifier::VERIFY_ERROR_REF_FIELD) { 1536c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::FieldId& id = dex_file.GetFieldId(ref); 1546c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes type_idx = id.class_idx_; 1556c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } else if (ref_type == DexVerifier::VERIFY_ERROR_REF_METHOD) { 1566c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::MethodId& id = dex_file.GetMethodId(ref); 1576c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes type_idx = id.class_idx_; 1586c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } else if (ref_type == DexVerifier::VERIFY_ERROR_REF_CLASS) { 1596c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes type_idx = ref; 1606c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } else { 1616c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes CHECK(false) << static_cast<int>(ref_type); 1626c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 1636c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1646c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(type_idx))); 1656c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes if (!access) { 1666c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return class_name; 1676c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 1686c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1696c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string result; 1706c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += "tried to access class "; 1716c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += class_name; 1726c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += " from class "; 1736c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()); 1746c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return result; 1756c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes} 1766c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1774f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic std::string FieldNameFromIndex(const Method* method, uint32_t ref, 1784f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DexVerifier::VerifyErrorRefType ref_type, bool access) { 1796c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(DexVerifier::VERIFY_ERROR_REF_FIELD)); 1806c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1816c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 1826c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); 1836c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1846c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::FieldId& id = dex_file.GetFieldId(ref); 18503a20ba67cfdc46f5ad8d77242a666a4cb0512f2Brian Carlstrom std::string class_name(PrettyDescriptor(dex_file.GetFieldClassDescriptor(id))); 1866c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const char* field_name = dex_file.dexStringById(id.name_idx_); 1876c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes if (!access) { 1886c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return class_name + "." + field_name; 1896c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 1906c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1916c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string result; 1926c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += "tried to access field "; 1936c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += class_name + "." + field_name; 1946c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += " from class "; 1956c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()); 1966c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return result; 1976c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes} 1986c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1994f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic std::string MethodNameFromIndex(const Method* method, uint32_t ref, 2004f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DexVerifier::VerifyErrorRefType ref_type, bool access) { 2016c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(DexVerifier::VERIFY_ERROR_REF_METHOD)); 2026c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2036c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 2046c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); 2056c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2066c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::MethodId& id = dex_file.GetMethodId(ref); 20703a20ba67cfdc46f5ad8d77242a666a4cb0512f2Brian Carlstrom std::string class_name(PrettyDescriptor(dex_file.GetMethodClassDescriptor(id))); 2086c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const char* method_name = dex_file.dexStringById(id.name_idx_); 2096c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes if (!access) { 2106c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return class_name + "." + method_name; 2116c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 2126c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2136c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string result; 2146c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += "tried to access method "; 2154f0d07c783afef89703dce32c94440fc8621a29bIan Rogers result += class_name + "." + method_name + ":" + 2164f0d07c783afef89703dce32c94440fc8621a29bIan Rogers dex_file.CreateMethodDescriptor(id.proto_idx_, NULL); 2176c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += " from class "; 2186c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()); 2196c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return result; 2206c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes} 2216c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2226c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughesextern "C" void artThrowVerificationErrorFromCode(int32_t kind, int32_t ref, Thread* self, Method** sp) { 2234f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); 2244f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Frame frame = self->GetTopOfStack(); // We need the calling method as context to interpret 'ref' 2256c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes frame.Next(); 2266c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes Method* method = frame.GetMethod(); 2276c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2284f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DexVerifier::VerifyErrorRefType ref_type = 2294f0d07c783afef89703dce32c94440fc8621a29bIan Rogers static_cast<DexVerifier::VerifyErrorRefType>(kind >> kVerifyErrorRefTypeShift); 2306c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2316c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const char* exception_class = "Ljava/lang/VerifyError;"; 2326c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string msg; 2336c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2346c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes switch (static_cast<DexVerifier::VerifyError>(kind & ~(0xff << kVerifyErrorRefTypeShift))) { 2356c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_NO_CLASS: 2366c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/NoClassDefFoundError;"; 2376c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, false); 2386c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2396c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_NO_FIELD: 2406c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/NoSuchFieldError;"; 2416c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = FieldNameFromIndex(method, ref, ref_type, false); 2426c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2436c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_NO_METHOD: 2446c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/NoSuchMethodError;"; 2456c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = MethodNameFromIndex(method, ref, ref_type, false); 2466c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2476c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_ACCESS_CLASS: 2486c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IllegalAccessError;"; 2496c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, true); 2506c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2516c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_ACCESS_FIELD: 2526c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IllegalAccessError;"; 2536c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = FieldNameFromIndex(method, ref, ref_type, true); 2546c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2556c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_ACCESS_METHOD: 2566c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IllegalAccessError;"; 2576c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = MethodNameFromIndex(method, ref, ref_type, true); 2586c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2596c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_CLASS_CHANGE: 2606c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IncompatibleClassChangeError;"; 2616c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, false); 2626c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2636c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_INSTANTIATION: 2646c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/InstantiationError;"; 2656c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, false); 2666c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2676c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_GENERIC: 2686c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes // Generic VerifyError; use default exception, no message. 2696c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2706c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes case DexVerifier::VERIFY_ERROR_NONE: 2716c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes CHECK(false); 2726c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2736c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 2746c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes self->ThrowNewException(exception_class, msg.c_str()); 2756c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes self->DeliverException(); 2762d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 2772d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 2782d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowInternalErrorFromCode(int32_t errnum, Thread* thread, Method** sp) { 2794f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 2802d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(WARNING) << "TODO: internal error detail message. errnum=" << errnum; 2815cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/InternalError;", "errnum=%d", errnum); 2822d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 2832d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 2842d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 2852d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowRuntimeExceptionFromCode(int32_t errnum, Thread* thread, Method** sp) { 2864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 2872d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(WARNING) << "TODO: runtime exception detail message. errnum=" << errnum; 2885cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "errnum=%d", errnum); 2892d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 2902d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 2912d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 292e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughesextern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, Method** sp) { 2934f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); 2944f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Frame frame = self->GetTopOfStack(); // We need the calling method as context for the method_idx 295e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes frame.Next(); 296e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes Method* method = frame.GetMethod(); 297e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes self->ThrowNewException("Ljava/lang/NoSuchMethodError;", 298e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes MethodNameFromIndex(method, method_idx, DexVerifier::VERIFY_ERROR_REF_METHOD, false).c_str()); 299e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes self->DeliverException(); 3002d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 3012d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 3022d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowNegArraySizeFromCode(int32_t size, Thread* thread, Method** sp) { 3034f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 3042d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(WARNING) << "UNTESTED artThrowNegArraySizeFromCode"; 3055cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", size); 3062d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 3072d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 3082d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 309ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogersvoid* UnresolvedDirectMethodTrampolineFromCode(int32_t method_idx, void* sp, Thread* thread, 3101cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers Runtime::TrampolineType type) { 311ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // TODO: this code is specific to ARM 312ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // On entry the stack pointed by sp is: 313ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | argN | | 314ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | ... | | 315ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg4 | | 316ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg3 spill | | Caller's frame 317ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg2 spill | | 318ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg1 spill | | 319ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | Method* | --- 320ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | LR | 321ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | R3 | arg3 322ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | R2 | arg2 323ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | R1 | arg1 324ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | R0 | <- sp 325ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers uintptr_t* regs = reinterpret_cast<uintptr_t*>(sp); 326ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers Method** caller_sp = reinterpret_cast<Method**>(®s[5]); 3271cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers uintptr_t caller_pc = regs[4]; 328ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Record the last top of the managed stack 3291cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers thread->SetTopOfStack(caller_sp, caller_pc); 330ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Start new JNI local reference state 331ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers JNIEnvExt* env = thread->GetJniEnv(); 332dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers ScopedJniEnvLocalRefState env_state(env); 333ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Discover shorty (avoid GCs) 3341cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers ClassLinker* linker = Runtime::Current()->GetClassLinker(); 335ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers const char* shorty = linker->MethodShorty(method_idx, *caller_sp); 336ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers size_t shorty_len = strlen(shorty); 33714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t args_in_regs = 0; 33814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers for (size_t i = 1; i < shorty_len; i++) { 33914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers char c = shorty[i]; 34014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1); 34114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (args_in_regs > 3) { 34214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs = 3; 34314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers break; 34414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 34514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 346ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers bool is_static; 3471cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers if (type == Runtime::kUnknownMethod) { 348ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers Method* caller = *caller_sp; 349df9a78201872d72adde40355a7020610b795def9Ian Rogers // less two as return address may span into next dex instruction 350df9a78201872d72adde40355a7020610b795def9Ian Rogers uint32_t dex_pc = caller->ToDexPC(caller_pc - 2); 351ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers const DexFile& dex_file = Runtime::Current()->GetClassLinker() 352ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers ->FindDexFile(caller->GetDeclaringClass()->GetDexCache()); 353ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers const DexFile::CodeItem* code = dex_file.GetCodeItem(caller->GetCodeItemOffset()); 354ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers CHECK_LT(dex_pc, code->insns_size_); 355ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers const Instruction* instr = Instruction::At(reinterpret_cast<const byte*>(&code->insns_[dex_pc])); 356ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers Instruction::Code instr_code = instr->Opcode(); 357ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers is_static = (instr_code == Instruction::INVOKE_STATIC) || 358ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers (instr_code == Instruction::INVOKE_STATIC_RANGE); 359ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers DCHECK(is_static || (instr_code == Instruction::INVOKE_DIRECT) || 360ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers (instr_code == Instruction::INVOKE_DIRECT_RANGE)); 3611cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers } else { 362ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers is_static = type == Runtime::kStaticMethod; 363ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 364caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Place into local references incoming arguments from the caller's register arguments 36514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1 366ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers if (!is_static) { 367ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); 368ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers cur_arg++; 36914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (args_in_regs < 3) { 37014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // If we thought we had fewer than 3 arguments in registers, account for the receiver 37114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs++; 37214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 373ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers AddLocalReference<jobject>(env, obj); 374ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 37514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t shorty_index = 1; // skip return value 37614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip 37714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // R0) 37814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) { 37914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers char c = shorty[shorty_index]; 38014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers shorty_index++; 381ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers if (c == 'L') { 382ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); 383ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers AddLocalReference<jobject>(env, obj); 384ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 385ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1); 386ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 387caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Place into local references incoming arguments from the caller's stack arguments 38814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg += 5; // skip LR, Method* and spills for R1 to R3 38914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (shorty_index < shorty_len) { 39014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers char c = shorty[shorty_index]; 39114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers shorty_index++; 392ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers if (c == 'L') { 39314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); 394ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers AddLocalReference<jobject>(env, obj); 395ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 396ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1); 397ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 398ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Resolve method filling in dex cache 399ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers Method* called = linker->ResolveMethod(method_idx, *caller_sp, true); 400caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(!thread->IsExceptionPending())) { 401ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // We got this far, ensure that the declaring class is initialized 402ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers linker->EnsureInitialized(called->GetDeclaringClass(), true); 403ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 404ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers void* code; 405caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(thread->IsExceptionPending())) { 406ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Something went wrong, go into deliver exception with the pending exception in r0 407ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers code = reinterpret_cast<void*>(art_deliver_exception_from_code); 408ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers regs[0] = reinterpret_cast<uintptr_t>(thread->GetException()); 409ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers thread->ClearException(); 410ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } else { 411ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Expect class to at least be initializing 412ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers CHECK(called->GetDeclaringClass()->IsInitializing()); 413ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Set up entry into main method 414ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers regs[0] = reinterpret_cast<uintptr_t>(called); 415ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers code = const_cast<void*>(called->GetCode()); 416ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 417ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers return code; 418ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 419ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 4202d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// TODO: placeholder. Helper function to type 4212d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei LiaoClass* InitializeTypeFromCode(uint32_t type_idx, Method* method) { 4222d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao /* 4232d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Should initialize & fix up method->dex_cache_resolved_types_[]. 4242d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Returns initialized type. Does not return normally if an exception 4252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * is thrown, but instead initiates the catch. Should be similar to 4262d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * ClassLinker::InitializeStaticStorageFromCode. 4272d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 4282d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao UNIMPLEMENTED(FATAL); 4292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; 4302d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 4312d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 4322d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// TODO: placeholder. Helper function to resolve virtual method 4332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaovoid ResolveMethodFromCode(Method* method, uint32_t method_idx) { 4342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao /* 4352d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Slow-path handler on invoke virtual method path in which 4362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * base method is unresolved at compile-time. Doesn't need to 4372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * return anything - just either ensure that 4382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * method->dex_cache_resolved_methods_(method_idx) != NULL or 4392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * throw and unwind. The caller will restart call sequence 4402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * from the beginning. 4412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 4422d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 4432d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 444caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers// Fast path field resolution that can't throw exceptions 445caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogersstatic Field* FindFieldFast(uint32_t field_idx, const Method* referrer) { 446caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* resolved_field = referrer->GetDexCacheResolvedFields()->Get(field_idx); 447caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(resolved_field == NULL)) { 448caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return NULL; 449caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 450caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* fields_class = resolved_field->GetDeclaringClass(); 451caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Check class is initilaized or initializing 452caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(!fields_class->IsInitializing())) { 453caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return NULL; 454caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 455caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 456caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers} 457caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers 458caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers// Slow path field resolution and declaring class initialization 459ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan RogersField* FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static) { 460ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 461caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); 462caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(resolved_field != NULL)) { 463caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* fields_class = resolved_field->GetDeclaringClass(); 464ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers // If the class is already initializing, we must be inside <clinit>, or 465ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers // we'd still be waiting for the lock. 466caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (fields_class->IsInitializing()) { 467caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 468caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 469caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if(Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true)) { 470caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 471ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 472ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 473ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers DCHECK(Thread::Current()->IsExceptionPending()); // Throw exception and unwind 474ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return NULL; 475ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 476ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 477ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" Field* artFindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer, 478ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 479caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* resolved_field = FindFieldFast(field_idx, referrer); 480caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(resolved_field == NULL)) { 481caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 482caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers resolved_field = FindFieldFromCode(field_idx, referrer, false); 483caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 484caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 485ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 486ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 487ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer, 488ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 489caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 490caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 491caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* type = field->GetType(); 492caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) { 493caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return field->Get32(NULL); 494caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 495caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 496ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 497caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 498ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 499ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Class* type = field->GetType(); 500caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) { 501ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 502ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted read of 32-bit primitive on field '%s'", 503ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 504ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 505ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return field->Get32(NULL); 506ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 507ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 508ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // Will throw exception by checking with Thread::Current 509ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 510ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 511ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer, 512ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 513caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 514caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 515caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* type = field->GetType(); 516caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) { 517caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return field->Get64(NULL); 518caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 519caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 520ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 521caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 522ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 523ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Class* type = field->GetType(); 524ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) { 525ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 526ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted read of 64-bit primitive on field '%s'", 527ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 528ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 529ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return field->Get64(NULL); 530ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 531ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 532ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // Will throw exception by checking with Thread::Current 533ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 534ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 535ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer, 536ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 537caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 538caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 539caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* type = field->GetType(); 540caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(!type->IsPrimitive())) { 541caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return field->GetObj(NULL); 542caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 543caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 544ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 545caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 546ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 547ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Class* type = field->GetType(); 548ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (type->IsPrimitive()) { 549ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 550ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted read of reference on primitive field '%s'", 551ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 552ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 553ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return field->GetObj(NULL); 554ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 555ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 556ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return NULL; // Will throw exception by checking with Thread::Current 557ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 558ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 559ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" int artSet32StaticFromCode(uint32_t field_idx, const Method* referrer, 560ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers uint32_t new_value, Thread* self, Method** sp) { 561caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 562caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 563caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* type = field->GetType(); 564caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) { 565caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field->Set32(NULL, new_value); 566caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; // success 567caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 568caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 569ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 570caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 571ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 572ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Class* type = field->GetType(); 573ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) { 574ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 575ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted write of 32-bit primitive to field '%s'", 576ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 577ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 578ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers field->Set32(NULL, new_value); 579ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // success 580ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 581ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 582ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return -1; // failure 583ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 584ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 585ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer, 586ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers uint64_t new_value, Thread* self, Method** sp) { 587caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 588caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 589caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* type = field->GetType(); 590caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) { 591caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field->Set64(NULL, new_value); 592caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; // success 593caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 594caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 595ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 596caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 597caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 598ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Class* type = field->GetType(); 599caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t))) { 600ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 601ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted write of 64-bit primitive to field '%s'", 602ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 603ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 604ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers field->Set64(NULL, new_value); 605ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // success 606ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 607ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 608ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return -1; // failure 609ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 610ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 611ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" int artSetObjStaticFromCode(uint32_t field_idx, const Method* referrer, 612ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Object* new_value, Thread* self, Method** sp) { 613caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 614caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 615caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* type = field->GetType(); 616caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(!type->IsPrimitive())) { 617caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field->SetObj(NULL, new_value); 618caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; // success 619caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 620caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 621ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 622caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 623ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 624ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Class* type = field->GetType(); 625ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (type->IsPrimitive()) { 626ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 627ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted write of reference to primitive field '%s'", 628ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 629ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 630ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers field->SetObj(NULL, new_value); 631ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // success 632ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 633ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 634ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return -1; // failure 635ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 636ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 6372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it 6382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// cannot be resolved, throw an error. If it can, use it to create an instance. 639caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogersextern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method, 640caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Thread* self, Method** sp) { 6414f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 6422d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 6434f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Runtime* runtime = Runtime::Current(); 644caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { 64533a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee klass = runtime->GetClassLinker()->ResolveType(type_idx, method); 6462d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass == NULL) { 64733a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee DCHECK(self->IsExceptionPending()); 6482d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6492d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6502d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 65133a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) { 65233a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee DCHECK(self->IsExceptionPending()); 6532d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6542d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6552d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return klass->AllocObject(); 6562d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 6572d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 658ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan RogersArray* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, 659ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self) { 660caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(component_count < 0)) { 661ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); 6622d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6632d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6642d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 665caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 6662d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 6672d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass == NULL) { // Error 6682d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(Thread::Current()->IsExceptionPending()); 6692d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6702d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6712d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 672caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) { 6732d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { 6745cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", 6752d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "Bad filled array request for type %s", 6762d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao PrettyDescriptor(klass->GetDescriptor()).c_str()); 6772d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 6785cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;", 6792d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "Found type %s; filled-new-array not implemented for anything but \'int\'", 6802d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao PrettyDescriptor(klass->GetDescriptor()).c_str()); 6812d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6822d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6832d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 684caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers DCHECK(klass->IsArrayClass()) << PrettyClass(klass); 6852d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return Array::Alloc(klass, component_count); 6862d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6872d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 6882d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 689ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers// Helper function to alloc array for OP_FILLED_NEW_ARRAY 690ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, 691ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers int32_t component_count, Thread* self, Method** sp) { 692ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 693ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return CheckAndAllocArrayFromCode(type_idx, method, component_count, self); 694ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 695ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 6962d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If 6972d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// it cannot be resolved, throw an error. If it can, use it to create an array. 6984f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" Array* artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, 6994f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 7004f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 701caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(component_count < 0)) { 7025cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", 7032d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao component_count); 7042d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 7052d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7062d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 707caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 7082d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 7092d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass == NULL) { // Error 7102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(Thread::Current()->IsExceptionPending()); 7112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 7122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao CHECK(klass->IsArrayClass()) << PrettyClass(klass); 7142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return Array::Alloc(klass, component_count); 7162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 718caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers// Assignable test for code, won't throw. Null and equality tests already performed 719caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogersuint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class) { 720caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers DCHECK(klass != NULL); 721caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers DCHECK(ref_class != NULL); 722caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return klass->IsAssignableFrom(ref_class) ? 1 : 0; 723caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers} 724caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers 7252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Check whether it is safe to cast one class to the other, throw exception and return -1 on failure 7264f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self, Method** sp) { 7272d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(a->IsClass()) << PrettyClass(a); 7282d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(b->IsClass()) << PrettyClass(b); 729caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(b->IsAssignableFrom(a))) { 7302d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; // Success 7312d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 732caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 7335cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;", 7342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "%s cannot be cast to %s", 7352d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao PrettyDescriptor(a->GetDescriptor()).c_str(), 7362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao PrettyDescriptor(b->GetDescriptor()).c_str()); 7372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Failure 7382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 7412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Tests whether 'element' can be assigned into an array of type 'array_class'. 7422d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Returns 0 on success and -1 if an exception is pending. 7434f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* array_class, 7444f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 7452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(array_class != NULL); 7462d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // element can't be NULL as we catch this is screened in runtime_support 7472d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* element_class = element->GetClass(); 7482d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* component_type = array_class->GetComponentType(); 749caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(component_type->IsAssignableFrom(element_class))) { 7502d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; // Success 7512d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 752caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 7535cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", 7542d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "Cannot store an object of type %s in to an array of type %s", 7552d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao PrettyDescriptor(element_class->GetDescriptor()).c_str(), 7562d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao PrettyDescriptor(array_class->GetDescriptor()).c_str()); 7572d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Failure 7582d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7592d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7602d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 7614f0d07c783afef89703dce32c94440fc8621a29bIan RogersClass* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self) { 7624f0d07c783afef89703dce32c94440fc8621a29bIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 7634f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Class* klass = class_linker->ResolveType(type_idx, referrer); 764caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { 7654f0d07c783afef89703dce32c94440fc8621a29bIan Rogers CHECK(self->IsExceptionPending()); 7664f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 7674f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 7684f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // If we are the <clinit> of this class, just return our storage. 7694f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // 7704f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished 7714f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // running. 7724f0d07c783afef89703dce32c94440fc8621a29bIan Rogers if (klass == referrer->GetDeclaringClass() && referrer->IsClassInitializer()) { 7734f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return klass; 7744f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 7754f0d07c783afef89703dce32c94440fc8621a29bIan Rogers if (!class_linker->EnsureInitialized(klass, true)) { 7764f0d07c783afef89703dce32c94440fc8621a29bIan Rogers CHECK(self->IsExceptionPending()); 7774f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 7784f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 7794f0d07c783afef89703dce32c94440fc8621a29bIan Rogers referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass); 7804f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return klass; 7812d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7822d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 7834f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const Method* referrer, 7844f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 7854f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 7864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return InitializeStaticStorage(type_idx, referrer, self); 7874f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 7884f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 789aded5f7ab991f3c1132851599d3bc60ff6707eedBrian CarlstromString* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) { 790aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 791aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return class_linker->ResolveString(string_idx, referrer); 792aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 793aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 794aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromextern "C" String* artResolveStringFromCode(Method* referrer, int32_t string_idx, 795aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom Thread* self, Method** sp) { 796aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 797aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return ResolveStringFromCode(referrer, string_idx); 798aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 799aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 8004f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, Method** sp) { 8014f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 8022d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(obj != NULL); // Assumed to have been checked before entry 8034f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // MonitorExit may throw exception 8044f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return obj->MonitorExit(self) ? 0 /* Success */ : -1 /* Failure */; 8054f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 8064f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 8074f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" void artLockObjectFromCode(Object* obj, Thread* thread, Method** sp) { 8084f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly); 8094f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DCHECK(obj != NULL); // Assumed to have been checked before entry 8104f0d07c783afef89703dce32c94440fc8621a29bIan Rogers obj->MonitorEnter(thread); // May block 8112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(thread->HoldsLock(obj)); 8122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // Only possible exception is NPE and is handled before entry 8132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(!thread->IsExceptionPending()); 8142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 8152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 8164a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogersvoid CheckSuspendFromCode(Thread* thread) { 8174a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogers // Called when thread->suspend_count_ != 0 8184f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Runtime::Current()->GetThreadList()->FullSuspendCheck(thread); 8194f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 8204f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 8214a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogersextern "C" void artTestSuspendFromCode(Thread* thread, Method** sp) { 8224a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogers // Called when suspend count check value is 0 and thread->suspend_count_ != 0 8234f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly); 8242d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Runtime::Current()->GetThreadList()->FullSuspendCheck(thread); 8252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 8262d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 8272d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/* 8282d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Fill the array with predefined constant values, throwing exceptions if the array is null or 8292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * not of sufficient length. 8302d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 8312d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * NOTE: When dealing with a raw dex file, the data to be copied uses 8322d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * little-endian ordering. Require that oat2dex do any required swapping 8332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * so this routine can get by with a memcpy(). 8342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 8352d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Format of the data: 8362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * ushort ident = 0x0300 magic value 8372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * ushort width width of each element in the table 8382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * uint size number of elements in the table 8392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * ubyte data[size*width] table of data values (may contain a single-byte 8402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * padding at the end) 8412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 8424f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artHandleFillArrayDataFromCode(Array* array, const uint16_t* table, 8434f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 8444f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 8452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK_EQ(table[0], 0x0300); 846caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(array == NULL)) { 8475cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;", 8485cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes "null array in fill array"); 8492d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Error 8502d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 8512d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(array->IsArrayInstance() && !array->IsObjectArray()); 8522d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16); 853caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(static_cast<int32_t>(size) > array->GetLength())) { 8545cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", 8555cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes "failed array fill. length=%d; index=%d", array->GetLength(), size); 8562d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Error 8572d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 8582d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint16_t width = table[1]; 8592d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint32_t size_in_bytes = size * width; 8602d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao memcpy((char*)array + Array::DataOffset().Int32Value(), (char*)&table[4], size_in_bytes); 8612d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; // Success 8622d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 8632d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 8642d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// See comments in runtime_support_asm.S 8652d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" uint64_t artFindInterfaceMethodInCacheFromCode(uint32_t method_idx, 866caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Object* this_object, 867caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Method* caller_method, 8684f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* thread, Method** sp) { 869caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Method* interface_method = caller_method->GetDexCacheResolvedMethods()->Get(method_idx); 870caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Method* found_method = NULL; // The found method 871caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(interface_method != NULL && this_object != NULL)) { 872caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method); 873caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 874caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(found_method == NULL)) { 875caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs); 876caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (this_object == NULL) { 877caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers thread->ThrowNewExceptionF("Ljava/lang/NullPointerException;", 878caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers "null receiver during interface dispatch"); 879caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; 880caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 881caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (interface_method == NULL) { 882caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 883caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers interface_method = class_linker->ResolveMethod(method_idx, caller_method, false); 884caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (interface_method == NULL) { 885caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Could not resolve interface method. Throw error and unwind 886caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers CHECK(thread->IsExceptionPending()); 887caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; 888caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 889caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 890caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method); 891caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (found_method == NULL) { 892caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers CHECK(thread->IsExceptionPending()); 893caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; 894caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 8952d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 896caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers const void* code = found_method->GetCode(); 8972d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 898caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers uint32_t method_uint = reinterpret_cast<uint32_t>(found_method); 8992d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint64_t code_uint = reinterpret_cast<uint32_t>(code); 9002d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint64_t result = ((code_uint << 32) | method_uint); 9012d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return result; 9022d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 9032d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 904466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogersstatic void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) { 905466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jclass> jlr_UTE_class(env, 906466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers env->FindClass("java/lang/reflect/UndeclaredThrowableException")); 907466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (jlr_UTE_class.get() == NULL) { 908466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\""; 909466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 910466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>", 911466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers "(Ljava/lang/Throwable;)V"); 912466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers jthrowable jexception = AddLocalReference<jthrowable>(env, exception); 913466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jthrowable> jlr_UTE(env, 914466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor, 915466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers jexception))); 916466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers int rc = env->Throw(jlr_UTE.get()); 917466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (rc != JNI_OK) { 918466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\""; 919466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 920466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 921466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers CHECK(self->IsExceptionPending()); 922466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers} 923466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers 924dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method 925dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// which is responsible for recording callee save registers. We explicitly handlerize incoming 926dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// reference arguments (so they survive GC) and create a boxed argument array. Finally we invoke 927dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// the invocation handler which is a field within the proxy object receiver. 928dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogersextern "C" void artProxyInvokeHandler(Method* proxy_method, Object* receiver, 929466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Thread* self, byte* stack_args) { 930dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Register the top of the managed stack 931466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Method** proxy_sp = reinterpret_cast<Method**>(stack_args - 12); 932466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers DCHECK_EQ(*proxy_sp, proxy_method); 933466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->SetTopOfStack(proxy_sp, 0); 934dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // TODO: ARM specific 935dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers DCHECK_EQ(proxy_method->GetFrameSizeInBytes(), 48u); 936dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Start new JNI local reference state 937dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers JNIEnvExt* env = self->GetJniEnv(); 938dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers ScopedJniEnvLocalRefState env_state(env); 939dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Create local ref. copies of proxy method and the receiver 940dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject rcvr_jobj = AddLocalReference<jobject>(env, receiver); 941dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject proxy_method_jobj = AddLocalReference<jobject>(env, proxy_method); 942dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers 94314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Placing into local references incoming arguments from the caller's register arguments, 94414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // replacing original Object* with jobject 94514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers const size_t num_params = proxy_method->NumArgs(); 94614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t args_in_regs = 0; 94714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers for (size_t i = 1; i < num_params; i++) { // skip receiver 94814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs = args_in_regs + (proxy_method->IsParamALongOrDouble(i) ? 2 : 1); 94914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (args_in_regs > 2) { 95014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs = 2; 95114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers break; 95214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 95314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 95414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t cur_arg = 0; // current stack location to read 95514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t param_index = 1; // skip receiver 95614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (cur_arg < args_in_regs && param_index < num_params) { 95714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (proxy_method->IsParamAReference(param_index)) { 95814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize)); 959dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject jobj = AddLocalReference<jobject>(env, obj); 96014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj; 961dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 96214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = cur_arg + (proxy_method->IsParamALongOrDouble(param_index) ? 2 : 1); 96314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 96414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 96514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Placing into local references incoming arguments from the caller's stack arguments 966466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers cur_arg += 11; // skip callee saves, LR, Method* and out arg spills for R1 to R3 96714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (param_index < num_params) { 96814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (proxy_method->IsParamAReference(param_index)) { 96914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize)); 97014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers jobject jobj = AddLocalReference<jobject>(env, obj); 97114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj; 972dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 97314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = cur_arg + (proxy_method->IsParamALongOrDouble(param_index) ? 2 : 1); 97414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 975dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 976dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Set up arguments array and place in local IRT during boxing (which may allocate/GC) 977dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jvalue args_jobj[3]; 978dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers args_jobj[0].l = rcvr_jobj; 979dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers args_jobj[1].l = proxy_method_jobj; 980466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // Args array, if no arguments then NULL (don't include receiver in argument count) 981466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args_jobj[2].l = NULL; 982466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ObjectArray<Object>* args = NULL; 983466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if ((num_params - 1) > 0) { 984466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1); 985466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if(args == NULL) { 986466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers CHECK(self->IsExceptionPending()); 987466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers return; 988466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 989466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args_jobj[2].l = AddLocalReference<jobjectArray>(env, args); 990466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 991466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // Convert proxy method into expected interface method 992466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Method* interface_method = proxy_method->FindOverriddenMethod(); 993466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers CHECK(interface_method != NULL); 994466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args_jobj[1].l = AddLocalReference<jobject>(env, interface_method); 995466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers LOG(INFO) << "Interface method is " << PrettyMethod(interface_method, true); 996dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Box arguments 99714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = 0; // reset stack location to read to start 99814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // reset index, will index into param type array which doesn't include the receiver 99914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index = 0; 1000466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ObjectArray<Class>* param_types = interface_method->GetJavaParameterTypes(); 100114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers CHECK(param_types != NULL); 100214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Check number of parameter types agrees with number from the Method - less 1 for the receiver. 100314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers CHECK_EQ(static_cast<size_t>(param_types->GetLength()), num_params - 1); 100414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (cur_arg < args_in_regs && param_index < (num_params - 1)) { 100514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Class* param_type = param_types->Get(param_index); 1006dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers Object* obj; 1007dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (!param_type->IsPrimitive()) { 100814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize))); 1009dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } else { 101014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize)); 101114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (cur_arg == 1 && (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble())) { 101214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // long/double split over regs and stack, mask in high half from stack arguments 1013466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args + (13 * kPointerSize)); 1014caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers val.j = (val.j & 0xffffffffULL) | (high_half << 32); 101514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 1016dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers BoxPrimitive(env, param_type, val); 1017dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (self->IsExceptionPending()) { 1018dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers return; 1019dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1020dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers obj = val.l; 1021dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 102214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args->Set(param_index, obj); 102314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1); 102414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 102514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 102614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Placing into local references incoming arguments from the caller's stack arguments 1027466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers cur_arg += 11; // skip callee saves, LR, Method* and out arg spills for R1 to R3 1028466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers while (param_index < (num_params - 1)) { 102914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Class* param_type = param_types->Get(param_index); 103014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj; 103114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (!param_type->IsPrimitive()) { 103214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize))); 103314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } else { 103414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize)); 103514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers BoxPrimitive(env, param_type, val); 103614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (self->IsExceptionPending()) { 103714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers return; 1038dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 103914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers obj = val.l; 1040dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 104114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args->Set(param_index, obj); 104214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1); 104314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 1044dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1045dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Get the InvocationHandler method and the field that holds it within the Proxy object 1046dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers static jmethodID inv_hand_invoke_mid = NULL; 1047dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers static jfieldID proxy_inv_hand_fid = NULL; 1048dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (proxy_inv_hand_fid == NULL) { 1049466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy")); 1050dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;"); 1051466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler")); 1052dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke", 1053dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"); 1054dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1055466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy"))); 1056dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid); 1057dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Call InvocationHandler.invoke 1058dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj); 1059dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Place result in stack args 1060dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (!self->IsExceptionPending()) { 1061dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers Object* result_ref = self->DecodeJObject(result); 1062dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (result_ref != NULL) { 1063dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers JValue result_unboxed; 1064466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers UnboxPrimitive(env, result_ref, interface_method->GetReturnType(), result_unboxed); 1065dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers *reinterpret_cast<JValue*>(stack_args) = result_unboxed; 1066dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } else { 1067dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers *reinterpret_cast<jobject*>(stack_args) = NULL; 1068dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1069466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 1070466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // In the case of checked exceptions that aren't declared, the exception must be wrapped by 1071466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // a UndeclaredThrowableException. 1072466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Throwable* exception = self->GetException(); 1073466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->ClearException(); 1074466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (!exception->IsCheckedException()) { 1075466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->SetException(exception); 1076466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 1077466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ObjectArray<Class>* declared_exceptions = proxy_method->GetExceptionTypes(); 1078466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Class* exception_class = exception->GetClass(); 1079466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers bool declares_exception = false; 1080466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) { 1081466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Class* declared_exception = declared_exceptions->Get(i); 1082466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers declares_exception = declared_exception->IsAssignableFrom(exception_class); 1083466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1084466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (declares_exception) { 1085466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->SetException(exception); 1086466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 1087466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ThrowNewUndeclaredThrowableException(self, env, exception); 1088466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1089466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1090dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1091dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers} 1092dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers 10932d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/* 10942d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Float/double conversion requires clamping to min and max of integer form. If 10952d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * target doesn't support this normally, use these. 10962d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 10972d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoint64_t D2L(double d) { 10982d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const double kMaxLong = (double)(int64_t)0x7fffffffffffffffULL; 10992d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const double kMinLong = (double)(int64_t)0x8000000000000000ULL; 11002d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (d >= kMaxLong) 11012d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x7fffffffffffffffULL; 11022d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (d <= kMinLong) 11032d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x8000000000000000ULL; 11042d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (d != d) // NaN case 11052d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; 11062d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else 11072d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)d; 11082d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 11092d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 11102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoint64_t F2L(float f) { 11112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const float kMaxLong = (float)(int64_t)0x7fffffffffffffffULL; 11122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const float kMinLong = (float)(int64_t)0x8000000000000000ULL; 11132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (f >= kMaxLong) 11142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x7fffffffffffffffULL; 11152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (f <= kMinLong) 11162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x8000000000000000ULL; 11172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (f != f) // NaN case 11182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; 11192d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else 11202d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)f; 11212d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 11222d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 11232d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} // namespace art 1124