entrypoint_utils.cc revision c2b4447ae9c0c1e77595620acac6508999df6698
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" 226d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object.h" 236d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 24dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers#include "reflection.h" 25e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "trace.h" 26dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers#include "ScopedLocalRef.h" 276c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 282d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaonamespace art { 292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 304f0d07c783afef89703dce32c94440fc8621a29bIan Rogers// Place a special frame at the TOS that will save the callee saves for the given type 314f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic void FinishCalleeSaveFrameSetup(Thread* self, Method** sp, Runtime::CalleeSaveType type) { 32ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers // Be aware the store below may well stomp on an incoming argument 334f0d07c783afef89703dce32c94440fc8621a29bIan Rogers *sp = Runtime::Current()->GetCalleeSaveMethod(type); 344f0d07c783afef89703dce32c94440fc8621a29bIan Rogers self->SetTopOfStack(sp, 0); 354f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 364f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Temporary debugging hook for compiler. 382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern void DebugMe(Method* method, uint32_t info) { 392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(INFO) << "DebugMe"; 402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (method != NULL) { 412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(INFO) << PrettyMethod(method); 422d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 432d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(INFO) << "Info: " << info; 442d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 466fd03fb67e4628689f0abf34edeacc0e35b6295eBrian Carlstromextern "C" uint32_t artObjectInitFromCode(Object* o, Thread* self, Method** sp) { 476fd03fb67e4628689f0abf34edeacc0e35b6295eBrian Carlstrom FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 48caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* c = o->GetClass(); 49caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(c->IsFinalizable())) { 505d4bdc29737a693027daaf6ed3f0792368eb4baeIan Rogers Heap::AddFinalizerReference(self, o); 51caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 52caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers /* 53caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers * NOTE: once debugger/profiler support is added, we'll need to check 54caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers * here and branch to actual compiled object.<init> to handle any 550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers * breakpoint/logging activities if either is active. 56caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers */ 576fd03fb67e4628689f0abf34edeacc0e35b6295eBrian Carlstrom return self->IsExceptionPending() ? -1 : 0; 58caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers} 59caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers 602d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Return value helper for jobject return types 612d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern Object* DecodeJObjectInThread(Thread* thread, jobject obj) { 626f495f2898a418f87e2a919e04fe23521bb0b9e9Brian Carlstrom if (thread->IsExceptionPending()) { 636f495f2898a418f87e2a919e04fe23521bb0b9e9Brian Carlstrom return NULL; 646f495f2898a418f87e2a919e04fe23521bb0b9e9Brian Carlstrom } 652d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return thread->DecodeJObject(obj); 662d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 672d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 682d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern void* FindNativeMethod(Thread* thread) { 692d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(Thread::Current() == thread); 702d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 712d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Method* method = const_cast<Method*>(thread->GetCurrentMethod()); 722d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(method != NULL); 732d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 742d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // Lookup symbol address for method, on failure we'll return NULL with an 752d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // exception set, otherwise we return the address of the method we found. 762d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao void* native_code = thread->GetJniEnv()->vm->FindCodeForNativeMethod(method); 772d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (native_code == NULL) { 782d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(thread->IsExceptionPending()); 792d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; 802d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 812d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // Register so that future calls don't come here 822d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao method->RegisterNative(native_code); 832d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return native_code; 842d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 852d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 862d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 872d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw an exception 882d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread, Method** sp) { 892d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao /* 902d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * exception may be NULL, in which case this routine should 912d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * throw NPE. NOTE: this is a convenience for generated code, 922d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * which previously did the null check inline and constructed 932d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * and threw a NPE if NULL. This routine responsible for setting 942d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * exception_ in thread and delivering the exception. 952d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 964f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 972d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (exception == NULL) { 982d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception"); 992d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 1002d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->SetException(exception); 1012d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 1022d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1032d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1042d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1052d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Deliver an exception that's pending on thread helping set up a callee save frame on the way 1062d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artDeliverPendingExceptionFromCode(Thread* thread, Method** sp) { 1074f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1082d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1092d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw a NPE exception 1122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowNullPointerExceptionFromCode(Thread* thread, Method** sp) { 1134f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1145cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewException("Ljava/lang/NullPointerException;", NULL); 1152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw an arithmetic divide by zero exception 1192d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowDivZeroFromCode(Thread* thread, Method** sp) { 1204f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1212d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero"); 1222d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1232d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1242d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by generated call to throw an arithmetic divide by zero exception 1262d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread, Method** sp) { 1274f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1284f0d07c783afef89703dce32c94440fc8621a29bIan Rogers thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", 1294f0d07c783afef89703dce32c94440fc8621a29bIan Rogers "length=%d; index=%d", limit, index); 1302d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1312d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1322d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Called by the AbstractMethodError stub (not runtime support) 1342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) { 1354f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 1364f0d07c783afef89703dce32c94440fc8621a29bIan Rogers thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;", 1374f0d07c783afef89703dce32c94440fc8621a29bIan Rogers "abstract method \"%s\"", PrettyMethod(method).c_str()); 1382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowStackOverflowFromCode(Method* method, Thread* thread, Method** sp) { 1424f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 143e343b76af81a005ef64f5e75a555389fd9147dabjeffhao // Remove extra entry pushed onto second stack during method tracing 144e343b76af81a005ef64f5e75a555389fd9147dabjeffhao if (Trace::IsMethodTracingActive()) { 145e343b76af81a005ef64f5e75a555389fd9147dabjeffhao artTraceMethodUnwindFromCode(thread); 146e343b76af81a005ef64f5e75a555389fd9147dabjeffhao } 1472d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute 1485cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;", 1495cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes "stack size %zdkb; default stack size: %zdkb", 1504f0d07c783afef89703dce32c94440fc8621a29bIan Rogers thread->GetStackSize() / KB, Runtime::Current()->GetDefaultStackSize() / KB); 1512d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->ResetDefaultStackEnd(); // Return to default stack size 1522d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 1532d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 1542d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 1554f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic std::string ClassNameFromIndex(Method* method, uint32_t ref, 156d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers verifier::VerifyErrorRefType ref_type, bool access) { 1576c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 1586c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); 1596c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1606c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes uint16_t type_idx = 0; 161d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers if (ref_type == verifier::VERIFY_ERROR_REF_FIELD) { 1626c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::FieldId& id = dex_file.GetFieldId(ref); 1636c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes type_idx = id.class_idx_; 164d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers } else if (ref_type == verifier::VERIFY_ERROR_REF_METHOD) { 1656c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::MethodId& id = dex_file.GetMethodId(ref); 1666c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes type_idx = id.class_idx_; 167d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers } else if (ref_type == verifier::VERIFY_ERROR_REF_CLASS) { 1686c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes type_idx = ref; 1696c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } else { 1706c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes CHECK(false) << static_cast<int>(ref_type); 1716c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 1726c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx))); 1746c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes if (!access) { 1756c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return class_name; 1766c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 1776c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1786c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string result; 1796c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += "tried to access class "; 1806c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += class_name; 1816c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += " from class "; 1826d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers result += PrettyDescriptor(method->GetDeclaringClass()); 1836c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return result; 1846c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes} 1856c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1864f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic std::string FieldNameFromIndex(const Method* method, uint32_t ref, 187d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers verifier::VerifyErrorRefType ref_type, bool access) { 188d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD)); 1896c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1906c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 1916c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); 1926c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 1936c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::FieldId& id = dex_file.GetFieldId(ref); 1946b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id))); 1950571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const char* field_name = dex_file.StringDataByIdx(id.name_idx_); 1966c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes if (!access) { 1976c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return class_name + "." + field_name; 1986c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 1996c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2006c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string result; 2016c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += "tried to access field "; 2026c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += class_name + "." + field_name; 2036c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += " from class "; 2046d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers result += PrettyDescriptor(method->GetDeclaringClass()); 2056c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return result; 2066c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes} 2076c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2084f0d07c783afef89703dce32c94440fc8621a29bIan Rogersstatic std::string MethodNameFromIndex(const Method* method, uint32_t ref, 209d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers verifier::VerifyErrorRefType ref_type, bool access) { 210d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD)); 2116c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2126c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 2136c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); 2146c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2156c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const DexFile::MethodId& id = dex_file.GetMethodId(ref); 2166b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id))); 2170571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers const char* method_name = dex_file.StringDataByIdx(id.name_idx_); 2186c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes if (!access) { 2196c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return class_name + "." + method_name; 2206c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 2216c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2226c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string result; 2236c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += "tried to access method "; 2244f0d07c783afef89703dce32c94440fc8621a29bIan Rogers result += class_name + "." + method_name + ":" + 2250571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers dex_file.CreateMethodSignature(id.proto_idx_, NULL); 2266c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes result += " from class "; 2276d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers result += PrettyDescriptor(method->GetDeclaringClass()); 2286c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes return result; 2296c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes} 2306c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2316c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughesextern "C" void artThrowVerificationErrorFromCode(int32_t kind, int32_t ref, Thread* self, Method** sp) { 2324f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); 2334f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Frame frame = self->GetTopOfStack(); // We need the calling method as context to interpret 'ref' 2346c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes frame.Next(); 2356c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes Method* method = frame.GetMethod(); 2366c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 237d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers verifier::VerifyErrorRefType ref_type = 238d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers static_cast<verifier::VerifyErrorRefType>(kind >> verifier::kVerifyErrorRefTypeShift); 2396c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 2406c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes const char* exception_class = "Ljava/lang/VerifyError;"; 2416c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes std::string msg; 2426c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes 243d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers switch (static_cast<verifier::VerifyError>(kind & ~(0xff << verifier::kVerifyErrorRefTypeShift))) { 244d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_NO_CLASS: 2456c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/NoClassDefFoundError;"; 2466c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, false); 2476c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 248d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_NO_FIELD: 2496c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/NoSuchFieldError;"; 2506c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = FieldNameFromIndex(method, ref, ref_type, false); 2516c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 252d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_NO_METHOD: 2536c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/NoSuchMethodError;"; 2546c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = MethodNameFromIndex(method, ref, ref_type, false); 2556c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 256d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_ACCESS_CLASS: 2576c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IllegalAccessError;"; 2586c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, true); 2596c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 260d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_ACCESS_FIELD: 2616c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IllegalAccessError;"; 2626c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = FieldNameFromIndex(method, ref, ref_type, true); 2636c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 264d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_ACCESS_METHOD: 2656c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IllegalAccessError;"; 2666c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = MethodNameFromIndex(method, ref, ref_type, true); 2676c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 268d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_CLASS_CHANGE: 2696c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/IncompatibleClassChangeError;"; 2706c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, false); 2716c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 272d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_INSTANTIATION: 2736c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes exception_class = "Ljava/lang/InstantiationError;"; 2746c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes msg = ClassNameFromIndex(method, ref, ref_type, false); 2756c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 276d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_GENERIC: 2776c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes // Generic VerifyError; use default exception, no message. 2786c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 279d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers case verifier::VERIFY_ERROR_NONE: 2806c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes CHECK(false); 2816c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes break; 2826c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes } 2836c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes self->ThrowNewException(exception_class, msg.c_str()); 2846c8867daab4af4667e0e816f6beafa7c5d13e043Elliott Hughes self->DeliverException(); 2852d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 2862d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 2872d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowInternalErrorFromCode(int32_t errnum, Thread* thread, Method** sp) { 2884f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 2892d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(WARNING) << "TODO: internal error detail message. errnum=" << errnum; 2905cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/InternalError;", "errnum=%d", errnum); 2912d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 2922d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 2932d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 2942d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowRuntimeExceptionFromCode(int32_t errnum, Thread* thread, Method** sp) { 2954f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 2962d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(WARNING) << "TODO: runtime exception detail message. errnum=" << errnum; 2975cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "errnum=%d", errnum); 2982d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 2992d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 3002d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 301e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughesextern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, Method** sp) { 3024f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); 3034f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Frame frame = self->GetTopOfStack(); // We need the calling method as context for the method_idx 304e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes frame.Next(); 305e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes Method* method = frame.GetMethod(); 306e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes self->ThrowNewException("Ljava/lang/NoSuchMethodError;", 307d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers MethodNameFromIndex(method, method_idx, verifier::VERIFY_ERROR_REF_METHOD, false).c_str()); 308e1410a2e47f4fc94de4e4f300308ee857bf1120aElliott Hughes self->DeliverException(); 3092d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 3102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 3112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" void artThrowNegArraySizeFromCode(int32_t size, Thread* thread, Method** sp) { 3124f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); 3132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao LOG(WARNING) << "UNTESTED artThrowNegArraySizeFromCode"; 3145cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes thread->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", size); 3152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao thread->DeliverException(); 3162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 3172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 3186a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstromvoid* UnresolvedDirectMethodTrampolineFromCode(int32_t method_idx, Method** sp, Thread* thread, 3191cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers Runtime::TrampolineType type) { 320ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // TODO: this code is specific to ARM 321ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // On entry the stack pointed by sp is: 322ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | argN | | 323ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | ... | | 324ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg4 | | 325ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg3 spill | | Caller's frame 326ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg2 spill | | 327ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | arg1 spill | | 328ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | Method* | --- 329ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | LR | 3306a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom // | ... | callee saves 331ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | R3 | arg3 332ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | R2 | arg2 333ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // | R1 | arg1 3346a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom // | R0 | 3356a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom // | Method* | <- sp 3366a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize); 3376a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes()); 3386a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 48); 3396a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom uintptr_t caller_pc = regs[10]; 3406a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs); 341ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Start new JNI local reference state 342ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers JNIEnvExt* env = thread->GetJniEnv(); 343dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers ScopedJniEnvLocalRefState env_state(env); 344ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Discover shorty (avoid GCs) 3451cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers ClassLinker* linker = Runtime::Current()->GetClassLinker(); 346ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers const char* shorty = linker->MethodShorty(method_idx, *caller_sp); 347ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers size_t shorty_len = strlen(shorty); 34814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t args_in_regs = 0; 34914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers for (size_t i = 1; i < shorty_len; i++) { 35014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers char c = shorty[i]; 35114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1); 35214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (args_in_regs > 3) { 35314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs = 3; 35414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers break; 35514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 35614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 357ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers bool is_static; 3581cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers if (type == Runtime::kUnknownMethod) { 359ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers Method* caller = *caller_sp; 360df9a78201872d72adde40355a7020610b795def9Ian Rogers // less two as return address may span into next dex instruction 361df9a78201872d72adde40355a7020610b795def9Ian Rogers uint32_t dex_pc = caller->ToDexPC(caller_pc - 2); 3626d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem(); 363d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers CHECK_LT(dex_pc, code->insns_size_in_code_units_); 364d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers const Instruction* instr = Instruction::At(&code->insns_[dex_pc]); 365ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers Instruction::Code instr_code = instr->Opcode(); 366ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers is_static = (instr_code == Instruction::INVOKE_STATIC) || 367ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers (instr_code == Instruction::INVOKE_STATIC_RANGE); 368ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers DCHECK(is_static || (instr_code == Instruction::INVOKE_DIRECT) || 369ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers (instr_code == Instruction::INVOKE_DIRECT_RANGE)); 3701cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers } else { 371ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers is_static = type == Runtime::kStaticMethod; 372ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 373caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Place into local references incoming arguments from the caller's register arguments 37414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t cur_arg = 1; // skip method_idx in R0, first arg is in R1 375ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers if (!is_static) { 376ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); 377ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers cur_arg++; 37814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (args_in_regs < 3) { 37914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // If we thought we had fewer than 3 arguments in registers, account for the receiver 38014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs++; 38114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 382ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers AddLocalReference<jobject>(env, obj); 383ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 38414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t shorty_index = 1; // skip return value 38514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip 38614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // R0) 38714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) { 38814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers char c = shorty[shorty_index]; 38914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers shorty_index++; 390ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers if (c == 'L') { 391ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); 392ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers AddLocalReference<jobject>(env, obj); 393ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 394ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1); 395ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 396caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Place into local references incoming arguments from the caller's stack arguments 3976a4be3a6226cec645cf905dd352e44f7968a7fa4Brian Carlstrom cur_arg += 11; // skip LR, Method* and spills for R1 to R3 and callee saves 39814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (shorty_index < shorty_len) { 39914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers char c = shorty[shorty_index]; 40014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers shorty_index++; 401ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers if (c == 'L') { 40214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj = reinterpret_cast<Object*>(regs[cur_arg]); 403ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers AddLocalReference<jobject>(env, obj); 404ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 405ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1); 406ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 407ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Resolve method filling in dex cache 408ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers Method* called = linker->ResolveMethod(method_idx, *caller_sp, true); 409caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(!thread->IsExceptionPending())) { 410573db4a2077380d81fa74ee2309162530db87a98Ian Rogers if (LIKELY(called->IsDirect())) { 411573db4a2077380d81fa74ee2309162530db87a98Ian Rogers // Update CodeAndDirectMethod table 412573db4a2077380d81fa74ee2309162530db87a98Ian Rogers Method* caller = *caller_sp; 413573db4a2077380d81fa74ee2309162530db87a98Ian Rogers DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache(); 414573db4a2077380d81fa74ee2309162530db87a98Ian Rogers dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethod(method_idx, called); 415573db4a2077380d81fa74ee2309162530db87a98Ian Rogers // We got this far, ensure that the declaring class is initialized 416573db4a2077380d81fa74ee2309162530db87a98Ian Rogers linker->EnsureInitialized(called->GetDeclaringClass(), true); 417573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } else { 418573db4a2077380d81fa74ee2309162530db87a98Ian Rogers // Direct method has been made virtual 419573db4a2077380d81fa74ee2309162530db87a98Ian Rogers thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;", 420573db4a2077380d81fa74ee2309162530db87a98Ian Rogers "Expected direct method but found virtual: %s", 421573db4a2077380d81fa74ee2309162530db87a98Ian Rogers PrettyMethod(called, true).c_str()); 422573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } 423ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 424ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers void* code; 425caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(thread->IsExceptionPending())) { 426b2062cfb7266fc52b7f03f00d26f0883f04986aeBrian Carlstrom // Something went wrong in ResolveMethod or EnsureInitialized, 427b2062cfb7266fc52b7f03f00d26f0883f04986aeBrian Carlstrom // go into deliver exception with the pending exception in r0 428ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers code = reinterpret_cast<void*>(art_deliver_exception_from_code); 429b2062cfb7266fc52b7f03f00d26f0883f04986aeBrian Carlstrom regs[0] = reinterpret_cast<uintptr_t>(thread->GetException()); 430ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers thread->ClearException(); 431ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } else { 432ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Expect class to at least be initializing 433ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers CHECK(called->GetDeclaringClass()->IsInitializing()); 434ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers // Set up entry into main method 435b2062cfb7266fc52b7f03f00d26f0883f04986aeBrian Carlstrom regs[0] = reinterpret_cast<uintptr_t>(called); 436ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers code = const_cast<void*>(called->GetCode()); 437ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 438ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers return code; 439ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 440ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 441caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers// Fast path field resolution that can't throw exceptions 442caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogersstatic Field* FindFieldFast(uint32_t field_idx, const Method* referrer) { 443caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* resolved_field = referrer->GetDexCacheResolvedFields()->Get(field_idx); 444caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(resolved_field == NULL)) { 445caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return NULL; 446caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 447caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* fields_class = resolved_field->GetDeclaringClass(); 448caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Check class is initilaized or initializing 449caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(!fields_class->IsInitializing())) { 450caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return NULL; 451caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 452caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 453caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers} 454caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers 455caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers// Slow path field resolution and declaring class initialization 456ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan RogersField* FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static) { 457ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 458caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); 459caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(resolved_field != NULL)) { 460caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Class* fields_class = resolved_field->GetDeclaringClass(); 461ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers // If the class is already initializing, we must be inside <clinit>, or 462ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers // we'd still be waiting for the lock. 463caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (fields_class->IsInitializing()) { 464caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 465caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 466362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true)) { 467caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 468ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 469ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 470ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers DCHECK(Thread::Current()->IsExceptionPending()); // Throw exception and unwind 471ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return NULL; 472ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 473ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 474ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" Field* artFindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer, 475ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 476caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* resolved_field = FindFieldFast(field_idx, referrer); 477caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(resolved_field == NULL)) { 478caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 479caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers resolved_field = FindFieldFromCode(field_idx, referrer, false); 480caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 481caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return resolved_field; 482ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 483ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 484ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer, 485ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 486caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 487caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 4886d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 4896d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int32_t))) { 490caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return field->Get32(NULL); 491caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 492caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 493ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 494caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 495ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 4966d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 4976d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int32_t)) { 498ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 499ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted read of 32-bit primitive on field '%s'", 500ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 501ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 502ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return field->Get32(NULL); 503ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 504ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 505ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // Will throw exception by checking with Thread::Current 506ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 507ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 508ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer, 509ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 510caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 511caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 5126d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5136d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int64_t))) { 514caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return field->Get64(NULL); 515caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 516caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 517ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 518caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 519ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 5206d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5216d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int64_t)) { 522ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 523ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted read of 64-bit primitive on field '%s'", 524ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 525ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 526ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return field->Get64(NULL); 527ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 528ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 529ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // Will throw exception by checking with Thread::Current 530ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 531ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 532ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer, 533ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self, Method** sp) { 534caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 535caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 5366d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5376d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (LIKELY(!fh.IsPrimitiveType())) { 538caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return field->GetObj(NULL); 539caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 540caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 541ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 542caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 543ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 5446d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5456d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (fh.IsPrimitiveType()) { 546ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 547ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted read of reference on primitive field '%s'", 548ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 549ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 550ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return field->GetObj(NULL); 551ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 552ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 553ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return NULL; // Will throw exception by checking with Thread::Current 554ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 555ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 556ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" int artSet32StaticFromCode(uint32_t field_idx, const Method* referrer, 557ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers uint32_t new_value, Thread* self, Method** sp) { 558caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 559caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 5606d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5616d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int32_t))) { 562caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field->Set32(NULL, new_value); 563caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; // success 564caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 565caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 566ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 567caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 568ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 5696d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5706d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int32_t)) { 571ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 572ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted write of 32-bit primitive to field '%s'", 573ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 574ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 575ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers field->Set32(NULL, new_value); 576ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // success 577ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 578ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 579ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return -1; // failure 580ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 581ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 582ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer, 583ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers uint64_t new_value, Thread* self, Method** sp) { 584caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 585caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 5866d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5876d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int64_t))) { 588caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field->Set64(NULL, new_value); 589caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; // success 590caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 591caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 592ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 593caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 594caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 5956d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers FieldHelper fh(field); 5966d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (UNLIKELY(!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int64_t))) { 597ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 598ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted write of 64-bit primitive to field '%s'", 599ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 600ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 601ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers field->Set64(NULL, new_value); 602ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // success 603ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 604ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 605ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return -1; // failure 606ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 607ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 608ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" int artSetObjStaticFromCode(uint32_t field_idx, const Method* referrer, 609ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Object* new_value, Thread* self, Method** sp) { 610caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Field* field = FindFieldFast(field_idx, referrer); 611caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(field != NULL)) { 6126d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (LIKELY(!FieldHelper(field).IsPrimitiveType())) { 613caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field->SetObj(NULL, new_value); 614caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; // success 615caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 616caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 617ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 618caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers field = FindFieldFromCode(field_idx, referrer, true); 619ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers if (field != NULL) { 6206d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (FieldHelper(field).IsPrimitiveType()) { 621ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;", 622ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers "Attempted write of reference to primitive field '%s'", 623ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers PrettyField(field, true).c_str()); 624ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } else { 625ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers field->SetObj(NULL, new_value); 626ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return 0; // success 627ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 628ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers } 629ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return -1; // failure 630ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 631ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 6322d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it 6332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// cannot be resolved, throw an error. If it can, use it to create an instance. 634caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogersextern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method, 635caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Thread* self, Method** sp) { 6364f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 6372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 6384f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Runtime* runtime = Runtime::Current(); 639caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { 64033a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee klass = runtime->GetClassLinker()->ResolveType(type_idx, method); 6412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass == NULL) { 64233a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee DCHECK(self->IsExceptionPending()); 6432d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6442d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 64633a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) { 64733a129cb771f7e8850b085d6158e5c8bf1e1da32buzbee DCHECK(self->IsExceptionPending()); 6482d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6492d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6502d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return klass->AllocObject(); 6512d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 6522d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 65328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogersextern "C" Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, Method* method, 65428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers Thread* self, Method** sp) { 65528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 65628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 65728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers Runtime* runtime = Runtime::Current(); 65828ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (UNLIKELY(klass == NULL)) { 65928ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers klass = runtime->GetClassLinker()->ResolveType(type_idx, method); 66028ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (klass == NULL) { 66128ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers DCHECK(self->IsExceptionPending()); 66228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers return NULL; // Failure 66328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 66428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 66528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers Class* referrer = method->GetDeclaringClass(); 66628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (UNLIKELY(!referrer->CanAccess(klass))) { 66728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "illegal class access: '%s' -> '%s'", 6686d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(referrer).c_str(), 6696d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(klass).c_str()); 67028ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers return NULL; // Failure 67128ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 67228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) { 67328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers DCHECK(self->IsExceptionPending()); 67428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers return NULL; // Failure 67528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers } 67628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers return klass->AllocObject(); 677cc4540ece917ef4b5c81ee684e3294e47e49ff5bbuzbee} 678cc4540ece917ef4b5c81ee684e3294e47e49ff5bbuzbee 679ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan RogersArray* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, 680ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers Thread* self) { 681caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(component_count < 0)) { 682ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); 6832d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6842d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6852d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 686caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 6872d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 6882d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass == NULL) { // Error 6892d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(Thread::Current()->IsExceptionPending()); 6902d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 6912d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 6922d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 693caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) { 6942d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { 6955cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", 6962d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "Bad filled array request for type %s", 6976d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(klass).c_str()); 6982d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 6995cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;", 7002d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "Found type %s; filled-new-array not implemented for anything but \'int\'", 7016d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(klass).c_str()); 7022d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7032d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 7042d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 705caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers DCHECK(klass->IsArrayClass()) << PrettyClass(klass); 7062d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return Array::Alloc(klass, component_count); 7072d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7082d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7092d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 710ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers// Helper function to alloc array for OP_FILLED_NEW_ARRAY 711ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogersextern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, 712ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers int32_t component_count, Thread* self, Method** sp) { 713ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 714ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers return CheckAndAllocArrayFromCode(type_idx, method, component_count, self); 715ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers} 716ce9eca6de042f26e9eebc41c9bee8b4d14f753aaIan Rogers 7172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If 7182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// it cannot be resolved, throw an error. If it can, use it to create an array. 7194f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" Array* artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, 7204f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 7214f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 722caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(component_count < 0)) { 7235cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", 7242d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao component_count); 7252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 7262d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7272d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); 728caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 7292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); 7302d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (klass == NULL) { // Error 7312d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(Thread::Current()->IsExceptionPending()); 7322d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return NULL; // Failure 7332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao CHECK(klass->IsArrayClass()) << PrettyClass(klass); 7352d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return Array::Alloc(klass, component_count); 7372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 739caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers// Assignable test for code, won't throw. Null and equality tests already performed 740caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogersuint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class) { 741caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers DCHECK(klass != NULL); 742caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers DCHECK(ref_class != NULL); 743caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return klass->IsAssignableFrom(ref_class) ? 1 : 0; 744caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers} 745caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers 7462d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Check whether it is safe to cast one class to the other, throw exception and return -1 on failure 7474f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self, Method** sp) { 7482d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(a->IsClass()) << PrettyClass(a); 7492d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(b->IsClass()) << PrettyClass(b); 750caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(b->IsAssignableFrom(a))) { 7512d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; // Success 7522d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 753caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 7545cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;", 7552d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "%s cannot be cast to %s", 7566d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(a).c_str(), 7576d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(b).c_str()); 7582d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Failure 7592d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7602d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7612d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 7622d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Tests whether 'element' can be assigned into an array of type 'array_class'. 7632d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// Returns 0 on success and -1 if an exception is pending. 7644f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* array_class, 7654f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 7662d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(array_class != NULL); 7672d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // element can't be NULL as we catch this is screened in runtime_support 7682d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* element_class = element->GetClass(); 7692d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Class* component_type = array_class->GetComponentType(); 770caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(component_type->IsAssignableFrom(element_class))) { 7712d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; // Success 7722d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } else { 773caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 7745cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", 7752d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao "Cannot store an object of type %s in to an array of type %s", 7766d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(element_class).c_str(), 7776d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(array_class).c_str()); 7782d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Failure 7792d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 7802d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 7812d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 7824f0d07c783afef89703dce32c94440fc8621a29bIan RogersClass* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self) { 7834f0d07c783afef89703dce32c94440fc8621a29bIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 7844f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Class* klass = class_linker->ResolveType(type_idx, referrer); 785caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(klass == NULL)) { 7864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers CHECK(self->IsExceptionPending()); 7874f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 7884f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 789b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers DCHECK(referrer->GetDeclaringClass()->CanAccess(klass)); 790b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers // If we are the <clinit> of this class, just return our storage. 791b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers // 792b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished 793b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers // running. 7946d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (klass == referrer->GetDeclaringClass() && MethodHelper(referrer).IsClassInitializer()) { 795b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers return klass; 796b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers } 797b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers if (!class_linker->EnsureInitialized(klass, true)) { 798b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers CHECK(self->IsExceptionPending()); 799b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers return NULL; // Failure - Indicate to caller to deliver exception 800b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers } 801b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass); 802b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers return klass; 803b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers} 804b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers 805b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian RogersClass* InitializeStaticStorageAndVerifyAccess(uint32_t type_idx, const Method* referrer, 806b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers Thread* self) { 807b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 808b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers Class* klass = class_linker->ResolveType(type_idx, referrer); 809b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers if (UNLIKELY(klass == NULL)) { 810b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers CHECK(self->IsExceptionPending()); 811b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers return NULL; // Failure - Indicate to caller to deliver exception 812b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers } 813b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers // Perform access check 814b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers if (UNLIKELY(!referrer->GetDeclaringClass()->CanAccess(klass))) { 815b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", 816b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers "Class %s is inaccessible to method %s", 8176d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers PrettyDescriptor(klass).c_str(), 818b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers PrettyMethod(referrer, true).c_str()); 819b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers } 8204f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // If we are the <clinit> of this class, just return our storage. 8214f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // 8224f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished 8234f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // running. 8246d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (klass == referrer->GetDeclaringClass() && MethodHelper(referrer).IsClassInitializer()) { 8254f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return klass; 8264f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 8274f0d07c783afef89703dce32c94440fc8621a29bIan Rogers if (!class_linker->EnsureInitialized(klass, true)) { 8284f0d07c783afef89703dce32c94440fc8621a29bIan Rogers CHECK(self->IsExceptionPending()); 8294f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return NULL; // Failure - Indicate to caller to deliver exception 8304f0d07c783afef89703dce32c94440fc8621a29bIan Rogers } 8314f0d07c783afef89703dce32c94440fc8621a29bIan Rogers referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass); 8324f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return klass; 8332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 8342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 8354f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const Method* referrer, 8364f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 8374f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 8384f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return InitializeStaticStorage(type_idx, referrer, self); 8394f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 8404f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 84128ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogersextern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const Method* referrer, Thread* self, 84228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers Method** sp) { 84328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers // Called when method->dex_cache_resolved_types_[] misses 84428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 84528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers return InitializeStaticStorage(type_idx, referrer, self); 84628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers} 84728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers 848b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogersextern "C" Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, 849b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers const Method* referrer, Thread* self, 850b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers Method** sp) { 851b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers // Called when caller isn't guaranteed to have access to a type and the dex cache may be 852b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers // unpopulated 853b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 854b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers return InitializeStaticStorageAndVerifyAccess(type_idx, referrer, self); 855b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers} 856b093c6b27f8ea9bbe2d49c03ebe345203a121199Ian Rogers 85728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers// TODO: placeholder. Helper function to resolve virtual method 85828ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogersvoid ResolveMethodFromCode(Method* method, uint32_t method_idx) { 85928ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers /* 86028ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers * Slow-path handler on invoke virtual method path in which 86128ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers * base method is unresolved at compile-time. Doesn't need to 86228ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers * return anything - just either ensure that 86328ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers * method->dex_cache_resolved_methods_(method_idx) != NULL or 86428ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers * throw and unwind. The caller will restart call sequence 86528ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers * from the beginning. 86628ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers */ 86728ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers} 86828ad40dc3ec2f09b0ffd4f6d6787bf1b532ccd5dIan Rogers 869aded5f7ab991f3c1132851599d3bc60ff6707eedBrian CarlstromString* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) { 870aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 871aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return class_linker->ResolveString(string_idx, referrer); 872aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 873aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 874aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromextern "C" String* artResolveStringFromCode(Method* referrer, int32_t string_idx, 875aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom Thread* self, Method** sp) { 876aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 877aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return ResolveStringFromCode(referrer, string_idx); 878aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 879aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 8804f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, Method** sp) { 8814f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 8822d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(obj != NULL); // Assumed to have been checked before entry 8834f0d07c783afef89703dce32c94440fc8621a29bIan Rogers // MonitorExit may throw exception 8844f0d07c783afef89703dce32c94440fc8621a29bIan Rogers return obj->MonitorExit(self) ? 0 /* Success */ : -1 /* Failure */; 8854f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 8864f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 8874f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" void artLockObjectFromCode(Object* obj, Thread* thread, Method** sp) { 8884f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly); 8894f0d07c783afef89703dce32c94440fc8621a29bIan Rogers DCHECK(obj != NULL); // Assumed to have been checked before entry 8904f0d07c783afef89703dce32c94440fc8621a29bIan Rogers obj->MonitorEnter(thread); // May block 8912d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(thread->HoldsLock(obj)); 8922d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao // Only possible exception is NPE and is handled before entry 8932d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(!thread->IsExceptionPending()); 8942d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 8952d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 8964a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogersvoid CheckSuspendFromCode(Thread* thread) { 8974a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogers // Called when thread->suspend_count_ != 0 8984f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Runtime::Current()->GetThreadList()->FullSuspendCheck(thread); 8994f0d07c783afef89703dce32c94440fc8621a29bIan Rogers} 9004f0d07c783afef89703dce32c94440fc8621a29bIan Rogers 9014a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogersextern "C" void artTestSuspendFromCode(Thread* thread, Method** sp) { 9024a510d8750d50b77353d0a5a891d1b9b3a48ecd5Ian Rogers // Called when suspend count check value is 0 and thread->suspend_count_ != 0 9034f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly); 9042d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao Runtime::Current()->GetThreadList()->FullSuspendCheck(thread); 9052d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 9062d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 9072d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/* 9082d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Fill the array with predefined constant values, throwing exceptions if the array is null or 9092d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * not of sufficient length. 9102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 9112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * NOTE: When dealing with a raw dex file, the data to be copied uses 9122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * little-endian ordering. Require that oat2dex do any required swapping 9132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * so this routine can get by with a memcpy(). 9142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 9152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Format of the data: 9162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * ushort ident = 0x0300 magic value 9172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * ushort width width of each element in the table 9182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * uint size number of elements in the table 9192d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * ubyte data[size*width] table of data values (may contain a single-byte 9202d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * padding at the end) 9212d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 9224f0d07c783afef89703dce32c94440fc8621a29bIan Rogersextern "C" int artHandleFillArrayDataFromCode(Array* array, const uint16_t* table, 9234f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* self, Method** sp) { 9244f0d07c783afef89703dce32c94440fc8621a29bIan Rogers FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); 9252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK_EQ(table[0], 0x0300); 926caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(array == NULL)) { 9275cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;", 9285cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes "null array in fill array"); 9292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Error 9302d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 9312d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao DCHECK(array->IsArrayInstance() && !array->IsObjectArray()); 9322d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16); 933caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(static_cast<int32_t>(size) > array->GetLength())) { 9345cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", 9355cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes "failed array fill. length=%d; index=%d", array->GetLength(), size); 9362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return -1; // Error 9372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 9382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint16_t width = table[1]; 9392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint32_t size_in_bytes = size * width; 9402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao memcpy((char*)array + Array::DataOffset().Int32Value(), (char*)&table[4], size_in_bytes); 9412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; // Success 9422d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 9432d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 9442d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao// See comments in runtime_support_asm.S 9452d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoextern "C" uint64_t artFindInterfaceMethodInCacheFromCode(uint32_t method_idx, 946caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Object* this_object, 947caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Method* caller_method, 9484f0d07c783afef89703dce32c94440fc8621a29bIan Rogers Thread* thread, Method** sp) { 949caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Method* interface_method = caller_method->GetDexCacheResolvedMethods()->Get(method_idx); 950caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers Method* found_method = NULL; // The found method 951caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (LIKELY(interface_method != NULL && this_object != NULL)) { 952b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method, false); 953caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 954caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (UNLIKELY(found_method == NULL)) { 955caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs); 956caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (this_object == NULL) { 957caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers thread->ThrowNewExceptionF("Ljava/lang/NullPointerException;", 958caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers "null receiver during interface dispatch"); 959caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; 960caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 961caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (interface_method == NULL) { 962caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 963caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers interface_method = class_linker->ResolveMethod(method_idx, caller_method, false); 964caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (interface_method == NULL) { 965caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers // Could not resolve interface method. Throw error and unwind 966caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers CHECK(thread->IsExceptionPending()); 967caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; 968caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 969caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 970b04f69f90d2594092bec5b294bbe7329d295bd66Ian Rogers found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method, true); 971caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers if (found_method == NULL) { 972caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers CHECK(thread->IsExceptionPending()); 973caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers return 0; 974caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers } 9752d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao } 976caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers const void* code = found_method->GetCode(); 9772d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 978caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers uint32_t method_uint = reinterpret_cast<uint32_t>(found_method); 9792d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint64_t code_uint = reinterpret_cast<uint32_t>(code); 9802d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao uint64_t result = ((code_uint << 32) | method_uint); 9812d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return result; 9822d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 9832d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 984466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogersstatic void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) { 985466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jclass> jlr_UTE_class(env, 986466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers env->FindClass("java/lang/reflect/UndeclaredThrowableException")); 987466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (jlr_UTE_class.get() == NULL) { 988466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\""; 989466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 990466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>", 991466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers "(Ljava/lang/Throwable;)V"); 992466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers jthrowable jexception = AddLocalReference<jthrowable>(env, exception); 993466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jthrowable> jlr_UTE(env, 994466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor, 995466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers jexception))); 996466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers int rc = env->Throw(jlr_UTE.get()); 997466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (rc != JNI_OK) { 998466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\""; 999466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1000466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1001466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers CHECK(self->IsExceptionPending()); 1002466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers} 1003466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers 1004dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method 1005dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// which is responsible for recording callee save registers. We explicitly handlerize incoming 1006dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// reference arguments (so they survive GC) and create a boxed argument array. Finally we invoke 1007dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers// the invocation handler which is a field within the proxy object receiver. 1008dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogersextern "C" void artProxyInvokeHandler(Method* proxy_method, Object* receiver, 1009466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Thread* self, byte* stack_args) { 1010dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Register the top of the managed stack 1011466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Method** proxy_sp = reinterpret_cast<Method**>(stack_args - 12); 1012466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers DCHECK_EQ(*proxy_sp, proxy_method); 1013466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->SetTopOfStack(proxy_sp, 0); 1014dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // TODO: ARM specific 1015dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers DCHECK_EQ(proxy_method->GetFrameSizeInBytes(), 48u); 1016dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Start new JNI local reference state 1017dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers JNIEnvExt* env = self->GetJniEnv(); 1018dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers ScopedJniEnvLocalRefState env_state(env); 1019dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Create local ref. copies of proxy method and the receiver 1020dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject rcvr_jobj = AddLocalReference<jobject>(env, receiver); 1021dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject proxy_method_jobj = AddLocalReference<jobject>(env, proxy_method); 1022dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers 102314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Placing into local references incoming arguments from the caller's register arguments, 102414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // replacing original Object* with jobject 10256d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers MethodHelper proxy_mh(proxy_method); 10266d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers const size_t num_params = proxy_mh.NumArgs(); 102714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t args_in_regs = 0; 102814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers for (size_t i = 1; i < num_params; i++) { // skip receiver 10296d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers args_in_regs = args_in_regs + (proxy_mh.IsParamALongOrDouble(i) ? 2 : 1); 103014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (args_in_regs > 2) { 103114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args_in_regs = 2; 103214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers break; 103314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 103414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 103514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t cur_arg = 0; // current stack location to read 103614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers size_t param_index = 1; // skip receiver 103714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (cur_arg < args_in_regs && param_index < num_params) { 10386d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (proxy_mh.IsParamAReference(param_index)) { 103914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize)); 1040dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject jobj = AddLocalReference<jobject>(env, obj); 104114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj; 1042dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 10436d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1); 104414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 104514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 104614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Placing into local references incoming arguments from the caller's stack arguments 1047466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers cur_arg += 11; // skip callee saves, LR, Method* and out arg spills for R1 to R3 104814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (param_index < num_params) { 10496d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers if (proxy_mh.IsParamAReference(param_index)) { 105014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize)); 105114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers jobject jobj = AddLocalReference<jobject>(env, obj); 105214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj; 1053dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 10546d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1); 105514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 1056dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1057dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Set up arguments array and place in local IRT during boxing (which may allocate/GC) 1058dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jvalue args_jobj[3]; 1059dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers args_jobj[0].l = rcvr_jobj; 1060dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers args_jobj[1].l = proxy_method_jobj; 1061466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // Args array, if no arguments then NULL (don't include receiver in argument count) 1062466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args_jobj[2].l = NULL; 1063466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ObjectArray<Object>* args = NULL; 1064466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if ((num_params - 1) > 0) { 1065466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1); 1066362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes if (args == NULL) { 1067466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers CHECK(self->IsExceptionPending()); 1068466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers return; 1069466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1070466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args_jobj[2].l = AddLocalReference<jobjectArray>(env, args); 1071466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1072466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // Convert proxy method into expected interface method 1073466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Method* interface_method = proxy_method->FindOverriddenMethod(); 1074466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers CHECK(interface_method != NULL); 10756d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers CHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method); 1076466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers args_jobj[1].l = AddLocalReference<jobject>(env, interface_method); 1077dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Box arguments 107814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = 0; // reset stack location to read to start 107914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // reset index, will index into param type array which doesn't include the receiver 108014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index = 0; 10816d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes(); 108214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers CHECK(param_types != NULL); 108314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Check number of parameter types agrees with number from the Method - less 1 for the receiver. 108414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers CHECK_EQ(static_cast<size_t>(param_types->GetLength()), num_params - 1); 108514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers while (cur_arg < args_in_regs && param_index < (num_params - 1)) { 108614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Class* param_type = param_types->Get(param_index); 1087dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers Object* obj; 1088dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (!param_type->IsPrimitive()) { 108914b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize))); 1090dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } else { 109114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize)); 109214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (cur_arg == 1 && (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble())) { 109314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // long/double split over regs and stack, mask in high half from stack arguments 1094466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args + (13 * kPointerSize)); 1095caab8c4ef372db5c119bfac1911fa27b174a935cIan Rogers val.j = (val.j & 0xffffffffULL) | (high_half << 32); 109614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 10976b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom BoxPrimitive(env, param_type->GetPrimitiveType(), val); 1098dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (self->IsExceptionPending()) { 1099dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers return; 1100dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1101dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers obj = val.l; 1102dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 110314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args->Set(param_index, obj); 110414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1); 110514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 110614b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } 110714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers // Placing into local references incoming arguments from the caller's stack arguments 1108466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers cur_arg += 11; // skip callee saves, LR, Method* and out arg spills for R1 to R3 1109466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers while (param_index < (num_params - 1)) { 111014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Class* param_type = param_types->Get(param_index); 111114b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers Object* obj; 111214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (!param_type->IsPrimitive()) { 111314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize))); 111414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers } else { 111514b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize)); 11166b4ef025af12b158d117fc80fc79acf620f411a0Brian Carlstrom BoxPrimitive(env, param_type->GetPrimitiveType(), val); 111714b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers if (self->IsExceptionPending()) { 111814b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers return; 1119dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 112014b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers obj = val.l; 1121dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 112214b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers args->Set(param_index, obj); 112314b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1); 112414b1b249bdd21d674c9371dee34f8ae055f73ba2Ian Rogers param_index++; 1125dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1126dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Get the InvocationHandler method and the field that holds it within the Proxy object 1127dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers static jmethodID inv_hand_invoke_mid = NULL; 1128dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers static jfieldID proxy_inv_hand_fid = NULL; 1129dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (proxy_inv_hand_fid == NULL) { 1130466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy")); 1131dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;"); 1132466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler")); 1133dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke", 1134dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"); 1135dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1136466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy"))); 1137dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid); 1138dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Call InvocationHandler.invoke 1139dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj); 1140dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers // Place result in stack args 1141dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (!self->IsExceptionPending()) { 1142dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers Object* result_ref = self->DecodeJObject(result); 1143dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers if (result_ref != NULL) { 1144dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers JValue result_unboxed; 11456d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers UnboxPrimitive(env, result_ref, proxy_mh.GetReturnType(), result_unboxed); 1146dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers *reinterpret_cast<JValue*>(stack_args) = result_unboxed; 1147dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } else { 1148dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers *reinterpret_cast<jobject*>(stack_args) = NULL; 1149dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1150466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 1151466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // In the case of checked exceptions that aren't declared, the exception must be wrapped by 1152466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers // a UndeclaredThrowableException. 1153466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Throwable* exception = self->GetException(); 1154466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->ClearException(); 1155466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (!exception->IsCheckedException()) { 1156466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->SetException(exception); 1157466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 1158c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers SynthesizedProxyClass* proxy_class = 1159c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass()); 1160c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers int throws_index = -1; 1161c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers size_t num_virt_methods = proxy_class->NumVirtualMethods(); 1162c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers for (size_t i = 0; i < num_virt_methods; i++) { 1163c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers if (proxy_class->GetVirtualMethod(i) == proxy_method) { 1164c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers throws_index = i; 1165c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers break; 1166c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers } 1167c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers } 1168c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers CHECK_NE(throws_index, -1); 1169c2b4447ae9c0c1e77595620acac6508999df6698Ian Rogers ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); 1170466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Class* exception_class = exception->GetClass(); 1171466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers bool declares_exception = false; 1172466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) { 1173466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers Class* declared_exception = declared_exceptions->Get(i); 1174466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers declares_exception = declared_exception->IsAssignableFrom(exception_class); 1175466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1176466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers if (declares_exception) { 1177466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers self->SetException(exception); 1178466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } else { 1179466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers ThrowNewUndeclaredThrowableException(self, env, exception); 1180466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1181466bb25416b88fabd5d4387b7c7e5cc1ece78b8cIan Rogers } 1182dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers } 1183dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers} 1184dfcdf1a0d2d8d75b4c701317e4a092498a8d1e9eIan Rogers 1185e343b76af81a005ef64f5e75a555389fd9147dabjeffhaoextern "C" const void* artTraceMethodEntryFromCode(Method* method, Thread* self, uintptr_t lr) { 1186e343b76af81a005ef64f5e75a555389fd9147dabjeffhao LOG(INFO) << "Tracer - entering: " << PrettyMethod(method); 1187e343b76af81a005ef64f5e75a555389fd9147dabjeffhao TraceStackFrame trace_frame = TraceStackFrame(method, lr); 1188e343b76af81a005ef64f5e75a555389fd9147dabjeffhao self->PushTraceStackFrame(trace_frame); 1189e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 1190e343b76af81a005ef64f5e75a555389fd9147dabjeffhao return Trace::GetSavedCodeFromMap(method); 1191e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} 1192e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 1193e343b76af81a005ef64f5e75a555389fd9147dabjeffhaoextern "C" uintptr_t artTraceMethodExitFromCode() { 1194e343b76af81a005ef64f5e75a555389fd9147dabjeffhao TraceStackFrame trace_frame = Thread::Current()->PopTraceStackFrame(); 1195e343b76af81a005ef64f5e75a555389fd9147dabjeffhao Method* method = trace_frame.method_; 1196e343b76af81a005ef64f5e75a555389fd9147dabjeffhao uintptr_t lr = trace_frame.return_pc_; 1197e343b76af81a005ef64f5e75a555389fd9147dabjeffhao LOG(INFO) << "Tracer - exiting: " << PrettyMethod(method); 1198e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 1199e343b76af81a005ef64f5e75a555389fd9147dabjeffhao return lr; 1200e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} 1201e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 1202e343b76af81a005ef64f5e75a555389fd9147dabjeffhaouintptr_t artTraceMethodUnwindFromCode(Thread* self) { 1203e343b76af81a005ef64f5e75a555389fd9147dabjeffhao TraceStackFrame trace_frame = self->PopTraceStackFrame(); 1204e343b76af81a005ef64f5e75a555389fd9147dabjeffhao Method* method = trace_frame.method_; 1205e343b76af81a005ef64f5e75a555389fd9147dabjeffhao uintptr_t lr = trace_frame.return_pc_; 1206e343b76af81a005ef64f5e75a555389fd9147dabjeffhao LOG(INFO) << "Tracer - unwinding: " << PrettyMethod(method); 1207e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 1208e343b76af81a005ef64f5e75a555389fd9147dabjeffhao return lr; 1209e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} 1210e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 12112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/* 12122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Float/double conversion requires clamping to min and max of integer form. If 12132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * target doesn't support this normally, use these. 12142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 12152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoint64_t D2L(double d) { 12162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const double kMaxLong = (double)(int64_t)0x7fffffffffffffffULL; 12172d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const double kMinLong = (double)(int64_t)0x8000000000000000ULL; 12182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (d >= kMaxLong) 12192d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x7fffffffffffffffULL; 12202d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (d <= kMinLong) 12212d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x8000000000000000ULL; 12222d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (d != d) // NaN case 12232d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; 12242d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else 12252d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)d; 12262d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 12272d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 12282d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liaoint64_t F2L(float f) { 12292d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const float kMaxLong = (float)(int64_t)0x7fffffffffffffffULL; 12302d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao static const float kMinLong = (float)(int64_t)0x8000000000000000ULL; 12312d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao if (f >= kMaxLong) 12322d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x7fffffffffffffffULL; 12332d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (f <= kMinLong) 12342d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)0x8000000000000000ULL; 12352d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else if (f != f) // NaN case 12362d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return 0; 12372d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao else 12382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao return (int64_t)f; 12392d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} 12402d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 12412d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} // namespace art 1242