blob: e9726f8a7f1c357431c703d28b80fe0f26388370 [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_) {
Ian Rogersc5e3d762012-08-14 16:33:47 -070089 thread->FullSuspendCheck();
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();
Shih-wei Liaoa64f1572012-06-22 00:09:57 -0700144 NthCallerVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), 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();
TDYa1274165a832012-04-03 17:47:16 -0700153 if (Runtime::Current()->IsMethodTracingActive()) {
154 TraceMethodUnwindFromCode(thread);
155 }
Elliott Hughes6cf23882012-06-15 15:42:07 -0700156 thread->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute.
157 thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;", "stack size %s",
158 PrettySize(thread->GetStackSize()).c_str());
159 thread->ResetDefaultStackEnd(); // Return to default stack size.
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800160}
161
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700162void art_throw_exception_from_code(Object* exception)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700163 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700164 Thread* thread = art_get_current_thread_from_code();
TDYa127540a5b72012-04-03 18:56:08 -0700165 if (exception == NULL) {
166 thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
167 } else {
168 thread->SetException(static_cast<Throwable*>(exception));
169 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800170}
171
TDYa127823433d2012-09-26 16:03:51 -0700172void* art_get_and_clear_exception(Thread* self)
173 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
174 DCHECK(self->IsExceptionPending());
175 Throwable* exception = self->GetException();
176 self->ClearException();
177 return exception;
178}
179
Ian Rogers952a94a2012-09-21 22:42:29 -0700180int32_t art_find_catch_block_from_code(AbstractMethod* current_method,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700181 uint32_t ti_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700182 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127d668a062012-04-13 12:36:57 -0700183 Thread* thread = art_get_current_thread_from_code();
TDYa1272d702172012-04-01 15:15:13 -0700184 Class* exception_type = thread->GetException()->GetClass();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800185 MethodHelper mh(current_method);
186 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Logan Chien736df022012-04-27 16:25:57 +0800187 DCHECK_LT(ti_offset, code_item->tries_size_);
188 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
189
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800190 int iter_index = 0;
191 // Iterate over the catch handlers associated with dex_pc
Logan Chien736df022012-04-27 16:25:57 +0800192 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800193 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
194 // Catch all case
195 if (iter_type_idx == DexFile::kDexNoIndex16) {
196 return iter_index;
197 }
198 // Does this catch exception type apply?
199 Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
200 if (iter_exception_type == NULL) {
201 // The verifier should take care of resolving all exception classes early
202 LOG(WARNING) << "Unresolved exception class when finding catch block: "
203 << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
204 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
205 return iter_index;
206 }
207 ++iter_index;
208 }
209 // Handler not found
210 return -1;
211}
212
Logan Chienfc5bc672012-03-06 16:54:30 +0800213
214//----------------------------------------------------------------------------
215// Object Space
216//----------------------------------------------------------------------------
217
TDYa127da83d972012-04-18 00:21:49 -0700218Object* art_alloc_object_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700219 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700220 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700221 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700222 return AllocObjectFromCode(type_idx, referrer, thread, false);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800223}
224
TDYa127da83d972012-04-18 00:21:49 -0700225Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700226 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700227 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700228 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700229 return AllocObjectFromCode(type_idx, referrer, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800230}
231
TDYa127da83d972012-04-18 00:21:49 -0700232Object* art_alloc_array_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700233 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700234 uint32_t length,
Ian Rogers50b35e22012-10-04 10:09:15 -0700235 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700236 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700237 return AllocArrayFromCode(type_idx, referrer, length, self, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800238}
239
240Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700241 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700242 uint32_t length,
Ian Rogers50b35e22012-10-04 10:09:15 -0700243 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700244 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700245 return AllocArrayFromCode(type_idx, referrer, length, self, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800246}
247
248Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700249 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700250 uint32_t length,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700251 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700252 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700253 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800254}
255
256Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700257 AbstractMethod* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700258 uint32_t length,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700259 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700260 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700261 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800262}
263
Ian Rogers952a94a2012-09-21 22:42:29 -0700264static AbstractMethod* FindMethodHelper(uint32_t method_idx, Object* this_object,
265 AbstractMethod* caller_method, bool access_check,
266 InvokeType type, Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700267 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers952a94a2012-09-21 22:42:29 -0700268 AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800269 if (UNLIKELY(method == NULL)) {
270 method = FindMethodFromCode(method_idx, this_object, caller_method,
TDYa127da83d972012-04-18 00:21:49 -0700271 thread, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800272 if (UNLIKELY(method == NULL)) {
TDYa127da83d972012-04-18 00:21:49 -0700273 CHECK(thread->IsExceptionPending());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800274 return 0; // failure
275 }
276 }
TDYa127da83d972012-04-18 00:21:49 -0700277 DCHECK(!thread->IsExceptionPending());
TDYa1273d71d802012-08-15 03:47:03 -0700278 const void* code = method->GetCode();
279
280 // When we return, the caller will branch to this address, so it had better not be 0!
281 if (UNLIKELY(code == NULL)) {
282 MethodHelper mh(method);
283 LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
284 << " location: " << mh.GetDexFile().GetLocation();
285 }
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800286 return method;
287}
288
Logan Chien7e7fabc2012-04-10 18:59:11 +0800289Object* art_find_static_method_from_code_with_access_check(uint32_t method_idx,
290 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700291 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700292 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700293 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700294 return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800295}
296
Logan Chien7e7fabc2012-04-10 18:59:11 +0800297Object* art_find_direct_method_from_code_with_access_check(uint32_t method_idx,
298 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700299 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700300 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700301 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700302 return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800303}
304
305Object* art_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
306 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700307 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700308 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700309 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700310 return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800311}
312
Logan Chien7e7fabc2012-04-10 18:59:11 +0800313Object* art_find_super_method_from_code_with_access_check(uint32_t method_idx,
314 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700315 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700316 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700317 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700318 return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800319}
320
Logan Chien7e7fabc2012-04-10 18:59:11 +0800321Object*
322art_find_interface_method_from_code_with_access_check(uint32_t method_idx,
323 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700324 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700325 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700326 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700327 return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800328}
329
330Object* art_find_interface_method_from_code(uint32_t method_idx,
331 Object* this_object,
Ian Rogers952a94a2012-09-21 22:42:29 -0700332 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700333 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700334 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700335 return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800336}
337
TDYa127706e9b62012-04-19 12:24:26 -0700338Object* art_initialize_static_storage_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700339 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700340 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700341 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700342 return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800343}
344
TDYa127706e9b62012-04-19 12:24:26 -0700345Object* art_initialize_type_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700346 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700347 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700348 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700349 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800350}
351
TDYa127706e9b62012-04-19 12:24:26 -0700352Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx,
Ian Rogers952a94a2012-09-21 22:42:29 -0700353 AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700354 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700355 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800356 // Called when caller isn't guaranteed to have access to a type and the dex cache may be
357 // unpopulated
TDYa127706e9b62012-04-19 12:24:26 -0700358 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800359}
360
Ian Rogers952a94a2012-09-21 22:42:29 -0700361Object* art_resolve_string_from_code(AbstractMethod* referrer, uint32_t string_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700362 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800363 return ResolveStringFromCode(referrer, string_idx);
Logan Chienfc5bc672012-03-06 16:54:30 +0800364}
365
Ian Rogers952a94a2012-09-21 22:42:29 -0700366int32_t art_set32_static_from_code(uint32_t field_idx, AbstractMethod* referrer, int32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700367 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700368 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800369 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700370 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800371 return 0;
372 }
TDYa127d668a062012-04-13 12:36:57 -0700373 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700374 StaticPrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800375 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700376 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800377 return 0;
378 }
379 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800380}
381
Ian Rogers952a94a2012-09-21 22:42:29 -0700382int32_t art_set64_static_from_code(uint32_t field_idx, AbstractMethod* referrer, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700383 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700384 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800385 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700386 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800387 return 0;
388 }
TDYa127d668a062012-04-13 12:36:57 -0700389 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700390 StaticPrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800391 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700392 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800393 return 0;
394 }
395 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800396}
397
Ian Rogers952a94a2012-09-21 22:42:29 -0700398int32_t art_set_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700399 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700400 Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800401 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700402 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800403 return 0;
404 }
TDYa127d668a062012-04-13 12:36:57 -0700405 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700406 StaticObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800407 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700408 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800409 return 0;
410 }
411 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800412}
413
Ian Rogers952a94a2012-09-21 22:42:29 -0700414int32_t art_get32_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700415 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700416 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800417 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700418 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800419 }
TDYa127d668a062012-04-13 12:36:57 -0700420 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700421 StaticPrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800422 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700423 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800424 }
425 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800426}
427
Ian Rogers952a94a2012-09-21 22:42:29 -0700428int64_t art_get64_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700429 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700430 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800431 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700432 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800433 }
TDYa127d668a062012-04-13 12:36:57 -0700434 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700435 StaticPrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800436 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700437 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800438 }
439 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800440}
441
Ian Rogers952a94a2012-09-21 22:42:29 -0700442Object* art_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700443 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700444 Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800445 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700446 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800447 }
TDYa127d668a062012-04-13 12:36:57 -0700448 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700449 StaticObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800450 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700451 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800452 }
453 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800454}
455
Ian Rogers952a94a2012-09-21 22:42:29 -0700456int32_t art_set32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700457 Object* obj, uint32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700458 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700459 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800460 if (LIKELY(field != NULL)) {
461 field->Set32(obj, new_value);
462 return 0;
463 }
TDYa127d668a062012-04-13 12:36:57 -0700464 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700465 InstancePrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800466 if (LIKELY(field != NULL)) {
467 field->Set32(obj, new_value);
468 return 0;
469 }
470 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800471}
472
Ian Rogers952a94a2012-09-21 22:42:29 -0700473int32_t art_set64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700474 Object* obj, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700475 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700476 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800477 if (LIKELY(field != NULL)) {
478 field->Set64(obj, new_value);
479 return 0;
480 }
TDYa127d668a062012-04-13 12:36:57 -0700481 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700482 InstancePrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800483 if (LIKELY(field != NULL)) {
484 field->Set64(obj, new_value);
485 return 0;
486 }
487 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800488}
489
Ian Rogers952a94a2012-09-21 22:42:29 -0700490int32_t art_set_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700491 Object* obj, Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700492 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700493 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800494 if (LIKELY(field != NULL)) {
495 field->SetObj(obj, new_value);
496 return 0;
497 }
TDYa127d668a062012-04-13 12:36:57 -0700498 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700499 InstanceObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800500 if (LIKELY(field != NULL)) {
501 field->SetObj(obj, new_value);
502 return 0;
503 }
504 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800505}
506
Ian Rogers952a94a2012-09-21 22:42:29 -0700507int32_t art_get32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700508 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700509 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800510 if (LIKELY(field != NULL)) {
511 return field->Get32(obj);
512 }
TDYa127d668a062012-04-13 12:36:57 -0700513 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700514 InstancePrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800515 if (LIKELY(field != NULL)) {
516 return field->Get32(obj);
517 }
518 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800519}
520
Ian Rogers952a94a2012-09-21 22:42:29 -0700521int64_t art_get64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700522 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700523 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800524 if (LIKELY(field != NULL)) {
525 return field->Get64(obj);
526 }
TDYa127d668a062012-04-13 12:36:57 -0700527 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700528 InstancePrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800529 if (LIKELY(field != NULL)) {
530 return field->Get64(obj);
531 }
532 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800533}
534
Ian Rogers952a94a2012-09-21 22:42:29 -0700535Object* art_get_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700536 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700537 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800538 if (LIKELY(field != NULL)) {
539 return field->GetObj(obj);
540 }
TDYa127d668a062012-04-13 12:36:57 -0700541 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Ian Rogers08f753d2012-08-24 14:35:25 -0700542 InstanceObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800543 if (LIKELY(field != NULL)) {
544 return field->GetObj(obj);
545 }
546 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800547}
548
Ian Rogers952a94a2012-09-21 22:42:29 -0700549void art_fill_array_data_from_code(AbstractMethod* method, uint32_t dex_pc,
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700550 Array* array, uint32_t payload_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700551 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Logan Chien86f50672012-04-24 13:08:45 +0800552 // Test: Is array equal to null? (Guard NullPointerException)
553 if (UNLIKELY(array == NULL)) {
554 art_throw_null_pointer_exception_from_code(dex_pc);
555 return;
556 }
557
558 // Find the payload from the CodeItem
559 MethodHelper mh(method);
560 const DexFile::CodeItem* code_item = mh.GetCodeItem();
561
562 DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
563
564 const Instruction::ArrayDataPayload* payload =
565 reinterpret_cast<const Instruction::ArrayDataPayload*>(
566 code_item->insns_ + payload_offset);
567
568 DCHECK_EQ(payload->ident,
569 static_cast<uint16_t>(Instruction::kArrayDataSignature));
570
571 // Test: Is array big enough?
572 uint32_t array_len = static_cast<uint32_t>(array->GetLength());
573 if (UNLIKELY(array_len < payload->element_count)) {
574 int32_t last_index = payload->element_count - 1;
575 art_throw_array_bounds_from_code(array_len, last_index);
576 return;
577 }
578
579 // Copy the data
580 size_t size = payload->element_width * payload->element_count;
581 memcpy(array->GetRawData(payload->element_width), payload->data, size);
582}
583
584
585
Logan Chienfc5bc672012-03-06 16:54:30 +0800586//----------------------------------------------------------------------------
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700587// Type checking, in the nature of casting
Logan Chienfc5bc672012-03-06 16:54:30 +0800588//----------------------------------------------------------------------------
589
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700590int32_t art_is_assignable_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700591 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1273de5ba32012-04-02 07:04:40 -0700592 DCHECK(dest_type != NULL);
593 DCHECK(src_type != NULL);
594 return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800595}
596
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700597void art_check_cast_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700598 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700599 DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700600 DCHECK(src_type->IsClass()) << PrettyClass(src_type);
601 if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
TDYa127d668a062012-04-13 12:36:57 -0700602 Thread* thread = art_get_current_thread_from_code();
603 thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
604 "%s cannot be cast to %s",
TDYa1278e9b4492012-04-24 15:50:27 -0700605 PrettyDescriptor(src_type).c_str(),
606 PrettyDescriptor(dest_type).c_str());
TDYa1273de5ba32012-04-02 07:04:40 -0700607 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800608}
609
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700610void art_check_put_array_element_from_code(const Object* element, const Object* array)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700611 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700612 if (element == NULL) {
613 return;
614 }
615 DCHECK(array != NULL);
616 Class* array_class = array->GetClass();
617 DCHECK(array_class != NULL);
618 Class* component_type = array_class->GetComponentType();
619 Class* element_class = element->GetClass();
620 if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
TDYa127d668a062012-04-13 12:36:57 -0700621 Thread* thread = art_get_current_thread_from_code();
622 thread->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
623 "%s cannot be stored in an array of type %s",
624 PrettyDescriptor(element_class).c_str(),
625 PrettyDescriptor(array_class).c_str());
TDYa1271b86d072012-04-05 17:38:56 -0700626 }
627 return;
628}
629
Logan Chien2771fb12012-03-06 16:28:35 +0800630//----------------------------------------------------------------------------
TDYa1273d71d802012-08-15 03:47:03 -0700631// JNI
632//----------------------------------------------------------------------------
633
634// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
635uint32_t art_jni_method_start(Thread* self)
636 UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
637 JNIEnvExt* env = self->GetJniEnv();
638 uint32_t saved_local_ref_cookie = env->local_ref_cookie;
639 env->local_ref_cookie = env->locals.GetSegmentState();
640 self->TransitionFromRunnableToSuspended(kNative);
641 return saved_local_ref_cookie;
642}
643
644uint32_t art_jni_method_start_synchronized(jobject to_lock, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700645 UNLOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700646 self->DecodeJObject(to_lock)->MonitorEnter(self);
647 return art_jni_method_start(self);
648}
649
650static inline void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
651 JNIEnvExt* env = self->GetJniEnv();
652 env->locals.SetSegmentState(env->local_ref_cookie);
653 env->local_ref_cookie = saved_local_ref_cookie;
654}
655
656void art_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700657 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700658 self->TransitionFromSuspendedToRunnable();
659 PopLocalReferences(saved_local_ref_cookie, self);
660}
661
662
663void art_jni_method_end_synchronized(uint32_t saved_local_ref_cookie, jobject locked,
664 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700665 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700666 self->TransitionFromSuspendedToRunnable();
667 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
668 PopLocalReferences(saved_local_ref_cookie, self);
669}
670
671Object* art_jni_method_end_with_reference(jobject result, uint32_t saved_local_ref_cookie,
672 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700673 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700674 self->TransitionFromSuspendedToRunnable();
675 Object* o = self->DecodeJObject(result); // Must decode before pop.
676 PopLocalReferences(saved_local_ref_cookie, self);
677 // Process result.
678 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
679 if (self->IsExceptionPending()) {
680 return NULL;
681 }
682 CheckReferenceResult(o, self);
683 }
684 return o;
685}
686
687Object* art_jni_method_end_with_reference_synchronized(jobject result,
688 uint32_t saved_local_ref_cookie,
689 jobject locked, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700690 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700691 self->TransitionFromSuspendedToRunnable();
692 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
693 Object* o = self->DecodeJObject(result);
694 PopLocalReferences(saved_local_ref_cookie, self);
695 // Process result.
696 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
697 if (self->IsExceptionPending()) {
698 return NULL;
699 }
700 CheckReferenceResult(o, self);
701 }
702 return o;
703}
704
705//----------------------------------------------------------------------------
Logan Chien2771fb12012-03-06 16:28:35 +0800706// Runtime Support Function Lookup Callback
707//----------------------------------------------------------------------------
708
Logan Chien2d3bcbb2012-07-06 09:37:26 +0800709#define EXTERNAL_LINKAGE(NAME, RETURN_TYPE, ...) \
710extern "C" RETURN_TYPE NAME(__VA_ARGS__);
Logan Chien95dfa6a2012-06-01 16:08:02 +0800711COMPILER_RUNTIME_FUNC_LIST_NATIVE(EXTERNAL_LINKAGE)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800712#undef EXTERNAL_LINKAGE
713
Logan Chien12584172012-07-10 04:07:28 -0700714static void* art_find_compiler_runtime_func(const char* name) {
jeffhao41005dd2012-05-09 17:58:52 -0700715// 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 +0800716 static const char* const names[] = {
Logan Chien2d3bcbb2012-07-06 09:37:26 +0800717#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) #NAME ,
Logan Chien95dfa6a2012-06-01 16:08:02 +0800718 COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800719#undef DEFINE_ENTRY
720 };
721
722 static void* const funcs[] = {
Logan Chien2d3bcbb2012-07-06 09:37:26 +0800723#define DEFINE_ENTRY(NAME, RETURN_TYPE, ...) \
724 reinterpret_cast<void*>(static_cast<RETURN_TYPE (*)(__VA_ARGS__)>(NAME)) ,
Logan Chien95dfa6a2012-06-01 16:08:02 +0800725 COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800726#undef DEFINE_ENTRY
727 };
728
729 static const size_t num_entries = sizeof(names) / sizeof(const char* const);
730
Logan Chien64f884d2012-04-03 18:30:47 +0800731 const char* const* const names_begin = names;
732 const char* const* const names_end = names + num_entries;
Logan Chiend23c5ad2012-03-30 17:46:04 +0800733
Logan Chien64f884d2012-04-03 18:30:47 +0800734 const char* const* name_lbound_ptr =
Logan Chiena1beb1f2012-06-01 16:03:27 +0800735 std::lower_bound(names_begin, names_end, name,
736 CStringLessThanComparator());
Logan Chien64f884d2012-04-03 18:30:47 +0800737
738 if (name_lbound_ptr < names_end && strcmp(*name_lbound_ptr, name) == 0) {
739 return funcs[name_lbound_ptr - names_begin];
Logan Chiend23c5ad2012-03-30 17:46:04 +0800740 } else {
Logan Chien64f884d2012-04-03 18:30:47 +0800741 return NULL;
Logan Chiend23c5ad2012-03-30 17:46:04 +0800742 }
743}
744
TDYa1275bb86012012-04-11 05:57:28 -0700745// Handler for invocation on proxy methods. We create a boxed argument array. And we invoke
746// the invocation handler which is a field within the proxy object receiver.
Ian Rogers952a94a2012-09-21 22:42:29 -0700747void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700748 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1275bb86012012-04-11 05:57:28 -0700749 va_list ap;
750 va_start(ap, proxy_method);
751
752 Object* receiver = va_arg(ap, Object*);
Ian Rogers50b35e22012-10-04 10:09:15 -0700753 Thread* self = va_arg(ap, Thread*);
TDYa1275bb86012012-04-11 05:57:28 -0700754 MethodHelper proxy_mh(proxy_method);
755 const size_t num_params = proxy_mh.NumArgs();
756
757 // Start new JNI local reference state
Ian Rogers50b35e22012-10-04 10:09:15 -0700758 JNIEnvExt* env = self->GetJniEnv();
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700759 ScopedObjectAccessUnchecked soa(env);
TDYa1275bb86012012-04-11 05:57:28 -0700760 ScopedJniEnvLocalRefState env_state(env);
761
TDYa12754825032012-04-11 10:45:23 -0700762 // Create local ref. copies of the receiver
Ian Rogersc5e3d762012-08-14 16:33:47 -0700763 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
TDYa1275bb86012012-04-11 05:57:28 -0700764
765 // Convert proxy method into expected interface method
Ian Rogers952a94a2012-09-21 22:42:29 -0700766 AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
TDYa1275bb86012012-04-11 05:57:28 -0700767 DCHECK(interface_method != NULL);
768 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
769
770 // Set up arguments array and place in local IRT during boxing (which may allocate/GC)
771 jvalue args_jobj[3];
772 args_jobj[0].l = rcvr_jobj;
Ian Rogersc5e3d762012-08-14 16:33:47 -0700773 args_jobj[1].l = soa.AddLocalReference<jobject>(interface_method);
TDYa1275bb86012012-04-11 05:57:28 -0700774 // Args array, if no arguments then NULL (don't include receiver in argument count)
775 args_jobj[2].l = NULL;
776 ObjectArray<Object>* args = NULL;
777 if ((num_params - 1) > 0) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700778 args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(self, num_params - 1);
TDYa1275bb86012012-04-11 05:57:28 -0700779 if (args == NULL) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700780 CHECK(self->IsExceptionPending());
TDYa1275bb86012012-04-11 05:57:28 -0700781 return;
782 }
Ian Rogersc5e3d762012-08-14 16:33:47 -0700783 args_jobj[2].l = soa.AddLocalReference<jobjectArray>(args);
TDYa1275bb86012012-04-11 05:57:28 -0700784 }
785
786 // Get parameter types.
787 const char* shorty = proxy_mh.GetShorty();
Ian Rogers50b35e22012-10-04 10:09:15 -0700788 ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes(self);
TDYa1275bb86012012-04-11 05:57:28 -0700789 if (param_types == NULL) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700790 CHECK(self->IsExceptionPending());
TDYa1275bb86012012-04-11 05:57:28 -0700791 return;
792 }
793
794 // Box arguments.
795 for (size_t i = 0; i < (num_params - 1);++i) {
796 JValue val;
797 switch (shorty[i+1]) {
798 case 'Z':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700799 val.SetZ(va_arg(ap, jint));
800 break;
TDYa1275bb86012012-04-11 05:57:28 -0700801 case 'B':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700802 val.SetB(va_arg(ap, jint));
803 break;
TDYa1275bb86012012-04-11 05:57:28 -0700804 case 'C':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700805 val.SetC(va_arg(ap, jint));
806 break;
TDYa1275bb86012012-04-11 05:57:28 -0700807 case 'S':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700808 val.SetS(va_arg(ap, jint));
809 break;
TDYa1275bb86012012-04-11 05:57:28 -0700810 case 'I':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700811 val.SetI(va_arg(ap, jint));
812 break;
TDYa1275bb86012012-04-11 05:57:28 -0700813 case 'F':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700814 val.SetI(va_arg(ap, jint)); // TODO: is this right?
TDYa1275bb86012012-04-11 05:57:28 -0700815 break;
816 case 'L':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700817 val.SetL(va_arg(ap, Object*));
TDYa1275bb86012012-04-11 05:57:28 -0700818 break;
819 case 'D':
820 case 'J':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700821 val.SetJ(va_arg(ap, jlong)); // TODO: is this right for double?
TDYa1275bb86012012-04-11 05:57:28 -0700822 break;
823 }
824 Class* param_type = param_types->Get(i);
825 if (param_type->IsPrimitive()) {
826 BoxPrimitive(param_type->GetPrimitiveType(), val);
Ian Rogers50b35e22012-10-04 10:09:15 -0700827 if (self->IsExceptionPending()) {
TDYa1275bb86012012-04-11 05:57:28 -0700828 return;
829 }
830 }
Shih-wei Liao2272f7b2012-04-12 14:23:48 -0700831 args->Set(i, val.GetL());
TDYa1275bb86012012-04-11 05:57:28 -0700832 }
833
Elliott Hugheseac76672012-05-24 21:56:51 -0700834 DCHECK(env->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
TDYa1275bb86012012-04-11 05:57:28 -0700835
Elliott Hugheseac76672012-05-24 21:56:51 -0700836 jobject inv_hand = env->GetObjectField(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy_h);
TDYa1275bb86012012-04-11 05:57:28 -0700837 // Call InvocationHandler.invoke
Elliott Hugheseac76672012-05-24 21:56:51 -0700838 jobject result = env->CallObjectMethodA(inv_hand, WellKnownClasses::java_lang_reflect_InvocationHandler_invoke, args_jobj);
TDYa1275bb86012012-04-11 05:57:28 -0700839
840 // Place result in stack args
Ian Rogers50b35e22012-10-04 10:09:15 -0700841 if (!self->IsExceptionPending()) {
TDYa1275bb86012012-04-11 05:57:28 -0700842 if (shorty[0] == 'V') {
843 return;
844 }
Ian Rogers50b35e22012-10-04 10:09:15 -0700845 Object* result_ref = self->DecodeJObject(result);
TDYa1275bb86012012-04-11 05:57:28 -0700846 JValue* result_unboxed = va_arg(ap, JValue*);
847 if (result_ref == NULL) {
Shih-wei Liao2272f7b2012-04-12 14:23:48 -0700848 result_unboxed->SetL(NULL);
TDYa1275bb86012012-04-11 05:57:28 -0700849 } else {
Elliott Hughesaaa5edc2012-05-16 15:54:30 -0700850 bool unboxed_okay = UnboxPrimitiveForResult(result_ref, proxy_mh.GetReturnType(), *result_unboxed);
TDYa1275bb86012012-04-11 05:57:28 -0700851 if (!unboxed_okay) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700852 self->ClearException();
853 self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
TDYa1275bb86012012-04-11 05:57:28 -0700854 "Couldn't convert result of type %s to %s",
855 PrettyTypeOf(result_ref).c_str(),
856 PrettyDescriptor(proxy_mh.GetReturnType()).c_str());
857 return;
858 }
859 }
860 } else {
861 // In the case of checked exceptions that aren't declared, the exception must be wrapped by
862 // a UndeclaredThrowableException.
Ian Rogers50b35e22012-10-04 10:09:15 -0700863 Throwable* exception = self->GetException();
Elliott Hughesa4f94742012-05-29 16:28:38 -0700864 if (exception->IsCheckedException()) {
TDYa1275bb86012012-04-11 05:57:28 -0700865 SynthesizedProxyClass* proxy_class =
866 down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
867 int throws_index = -1;
868 size_t num_virt_methods = proxy_class->NumVirtualMethods();
869 for (size_t i = 0; i < num_virt_methods; i++) {
870 if (proxy_class->GetVirtualMethod(i) == proxy_method) {
871 throws_index = i;
872 break;
873 }
874 }
875 CHECK_NE(throws_index, -1);
876 ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
877 Class* exception_class = exception->GetClass();
878 bool declares_exception = false;
879 for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
880 Class* declared_exception = declared_exceptions->Get(i);
881 declares_exception = declared_exception->IsAssignableFrom(exception_class);
882 }
Elliott Hughesa4f94742012-05-29 16:28:38 -0700883 if (!declares_exception) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700884 self->ThrowNewWrappedException("Ljava/lang/reflect/UndeclaredThrowableException;", NULL);
TDYa1275bb86012012-04-11 05:57:28 -0700885 }
886 }
887 }
888
889 va_end(ap);
890}
891
Logan Chien12584172012-07-10 04:07:28 -0700892void* art_find_runtime_support_func(void* context, const char* name) {
Logan Chien2771fb12012-03-06 16:28:35 +0800893 struct func_entry_t {
Logan Chien12584172012-07-10 04:07:28 -0700894 const char* name;
Logan Chien2771fb12012-03-06 16:28:35 +0800895 size_t name_len;
896 void* addr;
897 };
898
899 static struct func_entry_t const tab[] = {
Logan Chienbc615a12012-03-06 17:03:48 +0800900#define DEFINE_ENTRY(ID, NAME) \
901 { #NAME, sizeof(#NAME) - 1, reinterpret_cast<void*>(NAME) },
Logan Chienbc615a12012-03-06 17:03:48 +0800902 RUNTIME_SUPPORT_FUNC_LIST(DEFINE_ENTRY)
Logan Chienbc615a12012-03-06 17:03:48 +0800903#undef DEFINE_ENTRY
Logan Chien2771fb12012-03-06 16:28:35 +0800904 };
905
906 static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
907
Logan Chiend23c5ad2012-03-30 17:46:04 +0800908 // Search the compiler runtime (such as __divdi3)
909 void* result = art_find_compiler_runtime_func(name);
910 if (result != NULL) {
911 return result;
912 }
913
Logan Chien2771fb12012-03-06 16:28:35 +0800914 // Note: Since our table is small, we are using trivial O(n) searching
Ian Rogers952a94a2012-09-21 22:42:29 -0700915 // function. For bigger table, it will be better to use a binary
Logan Chien2771fb12012-03-06 16:28:35 +0800916 // search or hash function.
917 size_t i;
918 size_t name_len = strlen(name);
919 for (i = 0; i < tab_size; ++i) {
920 if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
921 return tab[i].addr;
922 }
923 }
924
925 LOG(FATAL) << "Error: Can't find symbol " << name;
926 return 0;
927}
928
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800929} // namespace art