blob: 3cdd532493d39ac2d42c9664013bfd90982bf69c [file] [log] [blame]
Elliott Hughes0f3c5532012-03-30 14:51:51 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080016
Logan Chien2a5885c2012-07-10 07:47:16 -070017#include "runtime_support_llvm.h"
18
19#include "ScopedLocalRef.h"
20#include "asm_support.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080021#include "class_linker.h"
Logan Chien95dfa6a2012-06-01 16:08:02 +080022#include "compiler_runtime_func_list.h"
Logan Chien86f50672012-04-24 13:08:45 +080023#include "dex_file.h"
24#include "dex_instruction.h"
TDYa1273f9137d2012-04-08 15:59:19 -070025#include "nth_caller_visitor.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080026#include "object.h"
27#include "object_utils.h"
TDYa1275bb86012012-04-11 05:57:28 -070028#include "reflection.h"
Shih-wei Liaob1ab7df2012-03-29 13:53:46 -070029#include "runtime_support.h"
Logan Chien95dfa6a2012-06-01 16:08:02 +080030#include "runtime_support_func_list.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070031#include "scoped_thread_state_change.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080032#include "thread.h"
Shih-wei Liao66adbb72012-03-07 01:31:50 -080033#include "thread_list.h"
Logan Chiena1beb1f2012-06-01 16:03:27 +080034#include "utils_llvm.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070035#include "verifier/method_verifier.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070036#include "well_known_classes.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080037
Logan Chiend23c5ad2012-03-30 17:46:04 +080038#include <algorithm>
Logan Chien2d3bcbb2012-07-06 09:37:26 +080039#include <math.h>
40#include <stdarg.h>
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080041#include <stdint.h>
Logan Chien2d3bcbb2012-07-06 09:37:26 +080042#include <stdlib.h>
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080043
44namespace art {
45
46//----------------------------------------------------------------------------
47// Thread
48//----------------------------------------------------------------------------
49
TDYa12783bb6622012-04-17 02:20:34 -070050// This is used by other runtime support functions, NOT FROM CODE. The REAL GetCurrentThread is
51// implemented by IRBuilder. (So, ARM can't return R9 in this function.)
52// TODO: Maybe remove these which are implemented by IRBuilder after refactor runtime support.
Logan Chienfc5bc672012-03-06 16:54:30 +080053Thread* art_get_current_thread_from_code() {
TDYa127d668a062012-04-13 12:36:57 -070054#if defined(__i386__)
55 Thread* ptr;
Elliott Hughes7834cbd2012-05-14 18:25:16 -070056 __asm__ __volatile__("movl %%fs:(%1), %0"
TDYa127d668a062012-04-13 12:36:57 -070057 : "=r"(ptr) // output
58 : "r"(THREAD_SELF_OFFSET) // input
59 :); // clobber
60 return ptr;
61#else
Logan Chienfc5bc672012-03-06 16:54:30 +080062 return Thread::Current();
TDYa127d668a062012-04-13 12:36:57 -070063#endif
Logan Chienfc5bc672012-03-06 16:54:30 +080064}
65
TDYa127c1478262012-06-20 20:22:27 -070066void* art_set_current_thread_from_code(void* thread_object_addr) {
TDYa127b08ed122012-06-05 23:51:19 -070067 // Nothing to be done.
TDYa127c1478262012-06-20 20:22:27 -070068 return NULL;
Logan Chienfc5bc672012-03-06 16:54:30 +080069}
70
Shih-wei Liaocd05a622012-08-15 00:02:05 -070071void art_lock_object_from_code(Object* obj, Thread* thread)
72 EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -080073 DCHECK(obj != NULL); // Assumed to have been checked before entry
74 obj->MonitorEnter(thread); // May block
75 DCHECK(thread->HoldsLock(obj));
76 // Only possible exception is NPE and is handled before entry
77 DCHECK(!thread->IsExceptionPending());
Logan Chienfc5bc672012-03-06 16:54:30 +080078}
79
Shih-wei Liaocd05a622012-08-15 00:02:05 -070080void art_unlock_object_from_code(Object* obj, Thread* thread)
81 UNLOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -080082 DCHECK(obj != NULL); // Assumed to have been checked before entry
83 // MonitorExit may throw exception
84 obj->MonitorExit(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +080085}
86
Shih-wei Liaocd05a622012-08-15 00:02:05 -070087void art_test_suspend_from_code(Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -070088 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhao373c52f2012-11-20 16:11:52 -080089 CheckSuspend(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +080090}
91
TDYa127de479be2012-05-31 08:03:26 -070092ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame,
Ian Rogers5438ad82012-10-15 17:22:44 -070093 AbstractMethod* method, uint16_t num_refs,
94 uint16_t num_vregs) {
TDYa127de479be2012-05-31 08:03:26 -070095 ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
96 new_shadow_frame->SetMethod(method);
Ian Rogers5438ad82012-10-15 17:22:44 -070097 new_shadow_frame->SetNumberOfReferences(num_refs);
98 new_shadow_frame->SetNumberOfVRegs(num_vregs);
TDYa127de479be2012-05-31 08:03:26 -070099 return old_frame;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800100}
101
TDYa1270de52be2012-05-27 20:49:31 -0700102void art_pop_shadow_frame_from_code(void*) {
TDYa12783bb6622012-04-17 02:20:34 -0700103 LOG(FATAL) << "Implemented by IRBuilder.";
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800104}
105
TDYa12783bb6622012-04-17 02:20:34 -0700106void art_mark_gc_card_from_code(void *, void*) {
107 LOG(FATAL) << "Implemented by IRBuilder.";
108}
Logan Chienfc5bc672012-03-06 16:54:30 +0800109
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800110//----------------------------------------------------------------------------
111// Exception
112//----------------------------------------------------------------------------
113
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800114bool art_is_exception_pending_from_code() {
TDYa12783bb6622012-04-17 02:20:34 -0700115 LOG(FATAL) << "Implemented by IRBuilder.";
116 return false;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800117}
118
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700119void art_throw_div_zero_from_code()
Ian Rogersb726dcb2012-09-05 08:57:23 -0700120 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700121 Thread* thread = art_get_current_thread_from_code();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800122 thread->ThrowNewException("Ljava/lang/ArithmeticException;",
123 "divide by zero");
124}
125
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700126void art_throw_array_bounds_from_code(int32_t index, int32_t length)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700127 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700128 Thread* thread = art_get_current_thread_from_code();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800129 thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
130 "length=%d; index=%d", length, index);
131}
132
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700133void art_throw_no_such_method_from_code(int32_t method_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700134 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700135 Thread* thread = art_get_current_thread_from_code();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800136 // We need the calling method as context for the method_idx
Ian Rogers952a94a2012-09-21 22:42:29 -0700137 AbstractMethod* method = thread->GetCurrentMethod();
Ian Rogers87e552d2012-08-31 15:54:48 -0700138 ThrowNoSuchMethodError(method_idx, method);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800139}
140
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700141void art_throw_null_pointer_exception_from_code(uint32_t dex_pc)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700142 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700143 Thread* thread = art_get_current_thread_from_code();
jeffhao725a9572012-11-13 18:20:12 -0800144 NthCallerVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), 0);
Ian Rogers0399dde2012-06-06 17:09:28 -0700145 visitor.WalkStack();
Ian Rogers952a94a2012-09-21 22:42:29 -0700146 AbstractMethod* throw_method = visitor.caller;
Ian Rogers87e552d2012-08-31 15:54:48 -0700147 ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800148}
149
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700150void art_throw_stack_overflow_from_code()
Ian Rogersb726dcb2012-09-05 08:57:23 -0700151 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700152 Thread* thread = art_get_current_thread_from_code();
jeffhaod7521322012-11-21 15:38:24 -0800153 ThrowStackOverflowError(thread);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800154}
155
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700156void art_throw_exception_from_code(Object* exception)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700157 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700158 Thread* thread = art_get_current_thread_from_code();
jeffhaoce945c42012-11-26 17:19:20 -0800159 thread->DeliverException(static_cast<Throwable*>(exception));
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800160}
161
TDYa127823433d2012-09-26 16:03:51 -0700162void* art_get_and_clear_exception(Thread* self)
163 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
164 DCHECK(self->IsExceptionPending());
165 Throwable* exception = self->GetException();
166 self->ClearException();
167 return exception;
168}
169
Ian Rogers952a94a2012-09-21 22:42:29 -0700170int32_t art_find_catch_block_from_code(AbstractMethod* current_method,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700171 uint32_t ti_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700172 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700173 Thread* thread = art_get_current_thread_from_code();
TDYa1272d702172012-04-01 15:15:13 -0700174 Class* exception_type = thread->GetException()->GetClass();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800175 MethodHelper mh(current_method);
176 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Logan Chien736df022012-04-27 16:25:57 +0800177 DCHECK_LT(ti_offset, code_item->tries_size_);
178 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
179
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800180 int iter_index = 0;
181 // Iterate over the catch handlers associated with dex_pc
Logan Chien736df022012-04-27 16:25:57 +0800182 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800183 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
184 // Catch all case
185 if (iter_type_idx == DexFile::kDexNoIndex16) {
186 return iter_index;
187 }
188 // Does this catch exception type apply?
189 Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
190 if (iter_exception_type == NULL) {
191 // The verifier should take care of resolving all exception classes early
192 LOG(WARNING) << "Unresolved exception class when finding catch block: "
193 << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
194 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
195 return iter_index;
196 }
197 ++iter_index;
198 }
199 // Handler not found
200 return -1;
201}
202
Logan Chienfc5bc672012-03-06 16:54:30 +0800203
204//----------------------------------------------------------------------------
205// Object Space
206//----------------------------------------------------------------------------
207
TDYa127da83d972012-04-18 00:21:49 -0700208Object* art_alloc_object_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700209 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700210 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700211 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700212 return AllocObjectFromCode(type_idx, referrer, thread, false);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800213}
214
TDYa127da83d972012-04-18 00:21:49 -0700215Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700216 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700217 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700218 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700219 return AllocObjectFromCode(type_idx, referrer, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800220}
221
TDYa127da83d972012-04-18 00:21:49 -0700222Object* art_alloc_array_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700223 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700224 uint32_t length,
Ian Rogers50b35e22012-10-04 10:09:15 -0700225 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700226 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700227 return AllocArrayFromCode(type_idx, referrer, length, self, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800228}
229
230Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700231 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700232 uint32_t length,
Ian Rogers50b35e22012-10-04 10:09:15 -0700233 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700234 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700235 return AllocArrayFromCode(type_idx, referrer, length, self, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800236}
237
238Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700239 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700240 uint32_t length,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700241 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700242 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700243 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800244}
245
246Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700247 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700248 uint32_t length,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700249 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700250 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700251 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800252}
253
Ian Rogers952a94a2012-09-21 22:42:29 -0700254static AbstractMethod* FindMethodHelper(uint32_t method_idx, Object* this_object,
255 AbstractMethod* caller_method, bool access_check,
256 InvokeType type, Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700257 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers952a94a2012-09-21 22:42:29 -0700258 AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800259 if (UNLIKELY(method == NULL)) {
260 method = FindMethodFromCode(method_idx, this_object, caller_method,
TDYa127da83d972012-04-18 00:21:49 -0700261 thread, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800262 if (UNLIKELY(method == NULL)) {
TDYa127da83d972012-04-18 00:21:49 -0700263 CHECK(thread->IsExceptionPending());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800264 return 0; // failure
265 }
266 }
TDYa127da83d972012-04-18 00:21:49 -0700267 DCHECK(!thread->IsExceptionPending());
TDYa1273d71d802012-08-15 03:47:03 -0700268 const void* code = method->GetCode();
269
270 // When we return, the caller will branch to this address, so it had better not be 0!
271 if (UNLIKELY(code == NULL)) {
272 MethodHelper mh(method);
273 LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
274 << " location: " << mh.GetDexFile().GetLocation();
275 }
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800276 return method;
277}
278
Logan Chien7e7fabc2012-04-10 18:59:11 +0800279Object* art_find_static_method_from_code_with_access_check(uint32_t method_idx,
280 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700281 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700282 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700283 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700284 return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800285}
286
Logan Chien7e7fabc2012-04-10 18:59:11 +0800287Object* art_find_direct_method_from_code_with_access_check(uint32_t method_idx,
288 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700289 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700290 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700291 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700292 return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800293}
294
295Object* art_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
296 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700297 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700298 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700299 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700300 return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800301}
302
Logan Chien7e7fabc2012-04-10 18:59:11 +0800303Object* art_find_super_method_from_code_with_access_check(uint32_t method_idx,
304 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700305 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700306 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700307 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700308 return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800309}
310
Logan Chien7e7fabc2012-04-10 18:59:11 +0800311Object*
312art_find_interface_method_from_code_with_access_check(uint32_t method_idx,
313 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700314 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700315 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700316 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700317 return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800318}
319
320Object* art_find_interface_method_from_code(uint32_t method_idx,
321 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700322 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700323 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700324 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700325 return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800326}
327
TDYa127706e9b62012-04-19 12:24:26 -0700328Object* art_initialize_static_storage_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700329 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700330 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700331 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700332 return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800333}
334
TDYa127706e9b62012-04-19 12:24:26 -0700335Object* art_initialize_type_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700336 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700337 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700338 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700339 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800340}
341
TDYa127706e9b62012-04-19 12:24:26 -0700342Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700343 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700344 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700345 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800346 // Called when caller isn't guaranteed to have access to a type and the dex cache may be
347 // unpopulated
TDYa127706e9b62012-04-19 12:24:26 -0700348 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800349}
350
Ian Rogers952a94a2012-09-21 22:42:29 -0700351Object* art_resolve_string_from_code(AbstractMethod* referrer, uint32_t string_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700352 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800353 return ResolveStringFromCode(referrer, string_idx);
Logan Chienfc5bc672012-03-06 16:54:30 +0800354}
355
Ian Rogers952a94a2012-09-21 22:42:29 -0700356int32_t art_set32_static_from_code(uint32_t field_idx, AbstractMethod* referrer, int32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700357 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700358 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800359 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700360 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800361 return 0;
362 }
TDYa127d668a062012-04-13 12:36:57 -0700363 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700364 StaticPrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800365 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700366 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800367 return 0;
368 }
369 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800370}
371
Ian Rogers952a94a2012-09-21 22:42:29 -0700372int32_t art_set64_static_from_code(uint32_t field_idx, AbstractMethod* referrer, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700373 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700374 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800375 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700376 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800377 return 0;
378 }
TDYa127d668a062012-04-13 12:36:57 -0700379 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700380 StaticPrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800381 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700382 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800383 return 0;
384 }
385 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800386}
387
Ian Rogers952a94a2012-09-21 22:42:29 -0700388int32_t art_set_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700389 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700390 Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800391 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700392 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800393 return 0;
394 }
TDYa127d668a062012-04-13 12:36:57 -0700395 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700396 StaticObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800397 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700398 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800399 return 0;
400 }
401 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800402}
403
Ian Rogers952a94a2012-09-21 22:42:29 -0700404int32_t art_get32_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700405 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700406 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800407 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700408 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800409 }
TDYa127d668a062012-04-13 12:36:57 -0700410 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700411 StaticPrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800412 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700413 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800414 }
415 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800416}
417
Ian Rogers952a94a2012-09-21 22:42:29 -0700418int64_t art_get64_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700419 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700420 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800421 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700422 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800423 }
TDYa127d668a062012-04-13 12:36:57 -0700424 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700425 StaticPrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800426 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700427 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800428 }
429 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800430}
431
Ian Rogers952a94a2012-09-21 22:42:29 -0700432Object* art_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700433 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700434 Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800435 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700436 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800437 }
TDYa127d668a062012-04-13 12:36:57 -0700438 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700439 StaticObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800440 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700441 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800442 }
443 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800444}
445
Ian Rogers952a94a2012-09-21 22:42:29 -0700446int32_t art_set32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700447 Object* obj, uint32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700448 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700449 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800450 if (LIKELY(field != NULL)) {
451 field->Set32(obj, new_value);
452 return 0;
453 }
TDYa127d668a062012-04-13 12:36:57 -0700454 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700455 InstancePrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800456 if (LIKELY(field != NULL)) {
457 field->Set32(obj, new_value);
458 return 0;
459 }
460 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800461}
462
Ian Rogers952a94a2012-09-21 22:42:29 -0700463int32_t art_set64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700464 Object* obj, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700465 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700466 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800467 if (LIKELY(field != NULL)) {
468 field->Set64(obj, new_value);
469 return 0;
470 }
TDYa127d668a062012-04-13 12:36:57 -0700471 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700472 InstancePrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800473 if (LIKELY(field != NULL)) {
474 field->Set64(obj, new_value);
475 return 0;
476 }
477 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800478}
479
Ian Rogers952a94a2012-09-21 22:42:29 -0700480int32_t art_set_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700481 Object* obj, Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700482 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700483 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800484 if (LIKELY(field != NULL)) {
485 field->SetObj(obj, new_value);
486 return 0;
487 }
TDYa127d668a062012-04-13 12:36:57 -0700488 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700489 InstanceObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800490 if (LIKELY(field != NULL)) {
491 field->SetObj(obj, new_value);
492 return 0;
493 }
494 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800495}
496
Ian Rogers952a94a2012-09-21 22:42:29 -0700497int32_t art_get32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700498 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700499 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800500 if (LIKELY(field != NULL)) {
501 return field->Get32(obj);
502 }
TDYa127d668a062012-04-13 12:36:57 -0700503 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700504 InstancePrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800505 if (LIKELY(field != NULL)) {
506 return field->Get32(obj);
507 }
508 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800509}
510
Ian Rogers952a94a2012-09-21 22:42:29 -0700511int64_t art_get64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700512 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700513 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800514 if (LIKELY(field != NULL)) {
515 return field->Get64(obj);
516 }
TDYa127d668a062012-04-13 12:36:57 -0700517 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700518 InstancePrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800519 if (LIKELY(field != NULL)) {
520 return field->Get64(obj);
521 }
522 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800523}
524
Ian Rogers952a94a2012-09-21 22:42:29 -0700525Object* art_get_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700526 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700527 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800528 if (LIKELY(field != NULL)) {
529 return field->GetObj(obj);
530 }
TDYa127d668a062012-04-13 12:36:57 -0700531 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700532 InstanceObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800533 if (LIKELY(field != NULL)) {
534 return field->GetObj(obj);
535 }
536 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800537}
538
Ian Rogers952a94a2012-09-21 22:42:29 -0700539void art_fill_array_data_from_code(AbstractMethod* method, uint32_t dex_pc,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700540 Array* array, uint32_t payload_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700541 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Logan Chien86f50672012-04-24 13:08:45 +0800542 // Test: Is array equal to null? (Guard NullPointerException)
543 if (UNLIKELY(array == NULL)) {
544 art_throw_null_pointer_exception_from_code(dex_pc);
545 return;
546 }
547
548 // Find the payload from the CodeItem
549 MethodHelper mh(method);
550 const DexFile::CodeItem* code_item = mh.GetCodeItem();
551
552 DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
553
554 const Instruction::ArrayDataPayload* payload =
555 reinterpret_cast<const Instruction::ArrayDataPayload*>(
556 code_item->insns_ + payload_offset);
557
558 DCHECK_EQ(payload->ident,
559 static_cast<uint16_t>(Instruction::kArrayDataSignature));
560
561 // Test: Is array big enough?
562 uint32_t array_len = static_cast<uint32_t>(array->GetLength());
563 if (UNLIKELY(array_len < payload->element_count)) {
564 int32_t last_index = payload->element_count - 1;
565 art_throw_array_bounds_from_code(array_len, last_index);
566 return;
567 }
568
569 // Copy the data
570 size_t size = payload->element_width * payload->element_count;
571 memcpy(array->GetRawData(payload->element_width), payload->data, size);
572}
573
574
575
Logan Chienfc5bc672012-03-06 16:54:30 +0800576//----------------------------------------------------------------------------
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700577// Type checking, in the nature of casting
Logan Chienfc5bc672012-03-06 16:54:30 +0800578//----------------------------------------------------------------------------
579
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700580int32_t art_is_assignable_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700581 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1273de5ba32012-04-02 07:04:40 -0700582 DCHECK(dest_type != NULL);
583 DCHECK(src_type != NULL);
584 return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800585}
586
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700587void art_check_cast_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700588 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700589 DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700590 DCHECK(src_type->IsClass()) << PrettyClass(src_type);
591 if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
TDYa127d668a062012-04-13 12:36:57 -0700592 Thread* thread = art_get_current_thread_from_code();
593 thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
594 "%s cannot be cast to %s",
TDYa1278e9b4492012-04-24 15:50:27 -0700595 PrettyDescriptor(src_type).c_str(),
596 PrettyDescriptor(dest_type).c_str());
TDYa1273de5ba32012-04-02 07:04:40 -0700597 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800598}
599
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700600void art_check_put_array_element_from_code(const Object* element, const Object* array)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700601 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700602 if (element == NULL) {
603 return;
604 }
605 DCHECK(array != NULL);
606 Class* array_class = array->GetClass();
607 DCHECK(array_class != NULL);
608 Class* component_type = array_class->GetComponentType();
609 Class* element_class = element->GetClass();
610 if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
TDYa127d668a062012-04-13 12:36:57 -0700611 Thread* thread = art_get_current_thread_from_code();
612 thread->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
613 "%s cannot be stored in an array of type %s",
614 PrettyDescriptor(element_class).c_str(),
615 PrettyDescriptor(array_class).c_str());
TDYa1271b86d072012-04-05 17:38:56 -0700616 }
617 return;
618}
619
Logan Chien2771fb12012-03-06 16:28:35 +0800620//----------------------------------------------------------------------------
TDYa1273d71d802012-08-15 03:47:03 -0700621// JNI
622//----------------------------------------------------------------------------
623
624// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
625uint32_t art_jni_method_start(Thread* self)
626 UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
627 JNIEnvExt* env = self->GetJniEnv();
628 uint32_t saved_local_ref_cookie = env->local_ref_cookie;
629 env->local_ref_cookie = env->locals.GetSegmentState();
630 self->TransitionFromRunnableToSuspended(kNative);
631 return saved_local_ref_cookie;
632}
633
634uint32_t art_jni_method_start_synchronized(jobject to_lock, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700635 UNLOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700636 self->DecodeJObject(to_lock)->MonitorEnter(self);
637 return art_jni_method_start(self);
638}
639
640static inline void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
641 JNIEnvExt* env = self->GetJniEnv();
642 env->locals.SetSegmentState(env->local_ref_cookie);
643 env->local_ref_cookie = saved_local_ref_cookie;
644}
645
646void art_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700647 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700648 self->TransitionFromSuspendedToRunnable();
649 PopLocalReferences(saved_local_ref_cookie, self);
650}
651
652
653void art_jni_method_end_synchronized(uint32_t saved_local_ref_cookie, jobject locked,
654 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700655 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700656 self->TransitionFromSuspendedToRunnable();
657 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
658 PopLocalReferences(saved_local_ref_cookie, self);
659}
660
661Object* art_jni_method_end_with_reference(jobject result, uint32_t saved_local_ref_cookie,
662 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700663 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700664 self->TransitionFromSuspendedToRunnable();
665 Object* o = self->DecodeJObject(result); // Must decode before pop.
666 PopLocalReferences(saved_local_ref_cookie, self);
667 // Process result.
668 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
669 if (self->IsExceptionPending()) {
670 return NULL;
671 }
672 CheckReferenceResult(o, self);
673 }
674 return o;
675}
676
677Object* art_jni_method_end_with_reference_synchronized(jobject result,
678 uint32_t saved_local_ref_cookie,
679 jobject locked, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700680 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700681 self->TransitionFromSuspendedToRunnable();
682 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
683 Object* o = self->DecodeJObject(result);
684 PopLocalReferences(saved_local_ref_cookie, self);
685 // Process result.
686 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
687 if (self->IsExceptionPending()) {
688 return NULL;
689 }
690 CheckReferenceResult(o, self);
691 }
692 return o;
693}
694
695//----------------------------------------------------------------------------
Logan Chien2771fb12012-03-06 16:28:35 +0800696// Runtime Support Function Lookup Callback
697//----------------------------------------------------------------------------
698
Logan Chien2d3bcbb2012-07-06 09:37:26 +0800699#define EXTERNAL_LINKAGE(NAME, RETURN_TYPE, ...) \
700extern "C" RETURN_TYPE NAME(__VA_ARGS__);
Logan Chien95dfa6a2012-06-01 16:08:02 +0800701COMPILER_RUNTIME_FUNC_LIST_NATIVE(EXTERNAL_LINKAGE)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800702#undef EXTERNAL_LINKAGE
703
Logan Chien12584172012-07-10 04:07:28 -0700704static void* art_find_compiler_runtime_func(const char* name) {
jeffhao41005dd2012-05-09 17:58:52 -0700705// TODO: If target support some math func, use the target's version. (e.g. art_d2i -> __aeabi_d2iz)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800706 static const char* const names[] = {
Logan Chien2d3bcbb2012-07-06 09:37:26 +0800707#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) #NAME ,
Logan Chien95dfa6a2012-06-01 16:08:02 +0800708 COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800709#undef DEFINE_ENTRY
710 };
711
712 static void* const funcs[] = {
Logan Chien2d3bcbb2012-07-06 09:37:26 +0800713#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) \
714 reinterpret_cast<void*>(static_cast<RETURN_TYPE (*)(__VA_ARGS__)>(NAME)) ,
Logan Chien95dfa6a2012-06-01 16:08:02 +0800715 COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800716#undef DEFINE_ENTRY
717 };
718
719 static const size_t num_entries = sizeof(names) / sizeof(const char* const);
720
Logan Chien64f884d2012-04-03 18:30:47 +0800721 const char* const* const names_begin = names;
722 const char* const* const names_end = names + num_entries;
Logan Chiend23c5ad2012-03-30 17:46:04 +0800723
Logan Chien64f884d2012-04-03 18:30:47 +0800724 const char* const* name_lbound_ptr =
Logan Chiena1beb1f2012-06-01 16:03:27 +0800725 std::lower_bound(names_begin, names_end, name,
726 CStringLessThanComparator());
Logan Chien64f884d2012-04-03 18:30:47 +0800727
728 if (name_lbound_ptr < names_end && strcmp(*name_lbound_ptr, name) == 0) {
729 return funcs[name_lbound_ptr - names_begin];
Logan Chiend23c5ad2012-03-30 17:46:04 +0800730 } else {
Logan Chien64f884d2012-04-03 18:30:47 +0800731 return NULL;
Logan Chiend23c5ad2012-03-30 17:46:04 +0800732 }
733}
734
TDYa1275bb86012012-04-11 05:57:28 -0700735// Handler for invocation on proxy methods. We create a boxed argument array. And we invoke
736// the invocation handler which is a field within the proxy object receiver.
Ian Rogers952a94a2012-09-21 22:42:29 -0700737void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700738 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1275bb86012012-04-11 05:57:28 -0700739 va_list ap;
740 va_start(ap, proxy_method);
741
742 Object* receiver = va_arg(ap, Object*);
Ian Rogers50b35e22012-10-04 10:09:15 -0700743 Thread* self = va_arg(ap, Thread*);
TDYa1275bb86012012-04-11 05:57:28 -0700744 MethodHelper proxy_mh(proxy_method);
745 const size_t num_params = proxy_mh.NumArgs();
746
747 // Start new JNI local reference state
Ian Rogers50b35e22012-10-04 10:09:15 -0700748 JNIEnvExt* env = self->GetJniEnv();
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700749 ScopedObjectAccessUnchecked soa(env);
TDYa1275bb86012012-04-11 05:57:28 -0700750 ScopedJniEnvLocalRefState env_state(env);
751
TDYa12754825032012-04-11 10:45:23 -0700752 // Create local ref. copies of the receiver
Ian Rogersc5e3d762012-08-14 16:33:47 -0700753 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
TDYa1275bb86012012-04-11 05:57:28 -0700754
755 // Convert proxy method into expected interface method
Ian Rogers952a94a2012-09-21 22:42:29 -0700756 AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
TDYa1275bb86012012-04-11 05:57:28 -0700757 DCHECK(interface_method != NULL);
758 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
759
760 // Set up arguments array and place in local IRT during boxing (which may allocate/GC)
761 jvalue args_jobj[3];
762 args_jobj[0].l = rcvr_jobj;
Ian Rogersc5e3d762012-08-14 16:33:47 -0700763 args_jobj[1].l = soa.AddLocalReference<jobject>(interface_method);
TDYa1275bb86012012-04-11 05:57:28 -0700764 // Args array, if no arguments then NULL (don't include receiver in argument count)
765 args_jobj[2].l = NULL;
766 ObjectArray<Object>* args = NULL;
767 if ((num_params - 1) > 0) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700768 args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(self, num_params - 1);
TDYa1275bb86012012-04-11 05:57:28 -0700769 if (args == NULL) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700770 CHECK(self->IsExceptionPending());
TDYa1275bb86012012-04-11 05:57:28 -0700771 return;
772 }
Ian Rogersc5e3d762012-08-14 16:33:47 -0700773 args_jobj[2].l = soa.AddLocalReference<jobjectArray>(args);
TDYa1275bb86012012-04-11 05:57:28 -0700774 }
775
776 // Get parameter types.
777 const char* shorty = proxy_mh.GetShorty();
Ian Rogers50b35e22012-10-04 10:09:15 -0700778 ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes(self);
TDYa1275bb86012012-04-11 05:57:28 -0700779 if (param_types == NULL) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700780 CHECK(self->IsExceptionPending());
TDYa1275bb86012012-04-11 05:57:28 -0700781 return;
782 }
783
784 // Box arguments.
785 for (size_t i = 0; i < (num_params - 1);++i) {
786 JValue val;
787 switch (shorty[i+1]) {
788 case 'Z':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700789 val.SetZ(va_arg(ap, jint));
790 break;
TDYa1275bb86012012-04-11 05:57:28 -0700791 case 'B':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700792 val.SetB(va_arg(ap, jint));
793 break;
TDYa1275bb86012012-04-11 05:57:28 -0700794 case 'C':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700795 val.SetC(va_arg(ap, jint));
796 break;
TDYa1275bb86012012-04-11 05:57:28 -0700797 case 'S':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700798 val.SetS(va_arg(ap, jint));
799 break;
TDYa1275bb86012012-04-11 05:57:28 -0700800 case 'I':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700801 val.SetI(va_arg(ap, jint));
802 break;
TDYa1275bb86012012-04-11 05:57:28 -0700803 case 'F':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700804 val.SetI(va_arg(ap, jint)); // TODO: is this right?
TDYa1275bb86012012-04-11 05:57:28 -0700805 break;
806 case 'L':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700807 val.SetL(va_arg(ap, Object*));
TDYa1275bb86012012-04-11 05:57:28 -0700808 break;
809 case 'D':
810 case 'J':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700811 val.SetJ(va_arg(ap, jlong)); // TODO: is this right for double?
TDYa1275bb86012012-04-11 05:57:28 -0700812 break;
813 }
814 Class* param_type = param_types->Get(i);
815 if (param_type->IsPrimitive()) {
816 BoxPrimitive(param_type->GetPrimitiveType(), val);
Ian Rogers50b35e22012-10-04 10:09:15 -0700817 if (self->IsExceptionPending()) {
TDYa1275bb86012012-04-11 05:57:28 -0700818 return;
819 }
820 }
Shih-wei Liao2272f7b2012-04-12 14:23:48 -0700821 args->Set(i, val.GetL());
TDYa1275bb86012012-04-11 05:57:28 -0700822 }
823
Elliott Hugheseac76672012-05-24 21:56:51 -0700824 DCHECK(env->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
TDYa1275bb86012012-04-11 05:57:28 -0700825
Elliott Hugheseac76672012-05-24 21:56:51 -0700826 jobject inv_hand = env->GetObjectField(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy_h);
TDYa1275bb86012012-04-11 05:57:28 -0700827 // Call InvocationHandler.invoke
Elliott Hugheseac76672012-05-24 21:56:51 -0700828 jobject result = env->CallObjectMethodA(inv_hand, WellKnownClasses::java_lang_reflect_InvocationHandler_invoke, args_jobj);
TDYa1275bb86012012-04-11 05:57:28 -0700829
830 // Place result in stack args
Ian Rogers50b35e22012-10-04 10:09:15 -0700831 if (!self->IsExceptionPending()) {
TDYa1275bb86012012-04-11 05:57:28 -0700832 if (shorty[0] == 'V') {
833 return;
834 }
Ian Rogers50b35e22012-10-04 10:09:15 -0700835 Object* result_ref = self->DecodeJObject(result);
TDYa1275bb86012012-04-11 05:57:28 -0700836 JValue* result_unboxed = va_arg(ap, JValue*);
837 if (result_ref == NULL) {
Shih-wei Liao2272f7b2012-04-12 14:23:48 -0700838 result_unboxed->SetL(NULL);
TDYa1275bb86012012-04-11 05:57:28 -0700839 } else {
Elliott Hughesaaa5edc2012-05-16 15:54:30 -0700840 bool unboxed_okay = UnboxPrimitiveForResult(result_ref, proxy_mh.GetReturnType(), *result_unboxed);
TDYa1275bb86012012-04-11 05:57:28 -0700841 if (!unboxed_okay) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700842 self->ClearException();
843 self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
TDYa1275bb86012012-04-11 05:57:28 -0700844 "Couldn't convert result of type %s to %s",
845 PrettyTypeOf(result_ref).c_str(),
846 PrettyDescriptor(proxy_mh.GetReturnType()).c_str());
847 return;
848 }
849 }
850 } else {
851 // In the case of checked exceptions that aren't declared, the exception must be wrapped by
852 // a UndeclaredThrowableException.
Ian Rogers50b35e22012-10-04 10:09:15 -0700853 Throwable* exception = self->GetException();
Elliott Hughesa4f94742012-05-29 16:28:38 -0700854 if (exception->IsCheckedException()) {
TDYa1275bb86012012-04-11 05:57:28 -0700855 SynthesizedProxyClass* proxy_class =
856 down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
857 int throws_index = -1;
858 size_t num_virt_methods = proxy_class->NumVirtualMethods();
859 for (size_t i = 0; i < num_virt_methods; i++) {
860 if (proxy_class->GetVirtualMethod(i) == proxy_method) {
861 throws_index = i;
862 break;
863 }
864 }
865 CHECK_NE(throws_index, -1);
866 ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
867 Class* exception_class = exception->GetClass();
868 bool declares_exception = false;
869 for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
870 Class* declared_exception = declared_exceptions->Get(i);
871 declares_exception = declared_exception->IsAssignableFrom(exception_class);
872 }
Elliott Hughesa4f94742012-05-29 16:28:38 -0700873 if (!declares_exception) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700874 self->ThrowNewWrappedException("Ljava/lang/reflect/UndeclaredThrowableException;", NULL);
TDYa1275bb86012012-04-11 05:57:28 -0700875 }
876 }
877 }
878
879 va_end(ap);
880}
881
Logan Chien12584172012-07-10 04:07:28 -0700882void* art_find_runtime_support_func(void* context, const char* name) {
Logan Chien2771fb12012-03-06 16:28:35 +0800883 struct func_entry_t {
Logan Chien12584172012-07-10 04:07:28 -0700884 const char* name;
Logan Chien2771fb12012-03-06 16:28:35 +0800885 size_t name_len;
886 void* addr;
887 };
888
889 static struct func_entry_t const tab[] = {
Logan Chienbc615a12012-03-06 17:03:48 +0800890#define DEFINE_ENTRY(ID, NAME) \
891 { #NAME, sizeof(#NAME) - 1, reinterpret_cast<void*>(NAME) },
Logan Chienbc615a12012-03-06 17:03:48 +0800892 RUNTIME_SUPPORT_FUNC_LIST(DEFINE_ENTRY)
Logan Chienbc615a12012-03-06 17:03:48 +0800893#undef DEFINE_ENTRY
Logan Chien2771fb12012-03-06 16:28:35 +0800894 };
895
896 static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
897
Logan Chiend23c5ad2012-03-30 17:46:04 +0800898 // Search the compiler runtime (such as __divdi3)
899 void* result = art_find_compiler_runtime_func(name);
900 if (result != NULL) {
901 return result;
902 }
903
Logan Chien2771fb12012-03-06 16:28:35 +0800904 // Note: Since our table is small, we are using trivial O(n) searching
Ian Rogers952a94a2012-09-21 22:42:29 -0700905 // function. For bigger table, it will be better to use a binary
Logan Chien2771fb12012-03-06 16:28:35 +0800906 // search or hash function.
907 size_t i;
908 size_t name_len = strlen(name);
909 for (i = 0; i < tab_size; ++i) {
910 if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
911 return tab[i].addr;
912 }
913 }
914
915 LOG(FATAL) << "Error: Can't find symbol " << name;
916 return 0;
917}
918
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800919} // namespace art