blob: 93785a60f4eb91ed943b834b80b85c39e235a33a [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
17#include "class_linker.h"
Logan Chien95dfa6a2012-06-01 16:08:02 +080018#include "compiler_runtime_func_list.h"
Logan Chien86f50672012-04-24 13:08:45 +080019#include "dex_file.h"
20#include "dex_instruction.h"
TDYa1273f9137d2012-04-08 15:59:19 -070021#include "nth_caller_visitor.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080022#include "object.h"
23#include "object_utils.h"
TDYa1275bb86012012-04-11 05:57:28 -070024#include "reflection.h"
Shih-wei Liaob1ab7df2012-03-29 13:53:46 -070025#include "runtime_support.h"
Logan Chien95dfa6a2012-06-01 16:08:02 +080026#include "runtime_support_func_list.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080027#include "runtime_support_llvm.h"
TDYa1275bb86012012-04-11 05:57:28 -070028#include "ScopedLocalRef.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080029#include "thread.h"
Shih-wei Liao66adbb72012-03-07 01:31:50 -080030#include "thread_list.h"
Logan Chiena1beb1f2012-06-01 16:03:27 +080031#include "utils_llvm.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070032#include "verifier/method_verifier.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070033#include "well_known_classes.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080034
Logan Chiend23c5ad2012-03-30 17:46:04 +080035#include <algorithm>
TDYa1275bb86012012-04-11 05:57:28 -070036#include <cstdarg>
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080037#include <stdint.h>
38
TDYa127d668a062012-04-13 12:36:57 -070039#include "asm_support.h"
40
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080041namespace art {
42
43//----------------------------------------------------------------------------
44// Thread
45//----------------------------------------------------------------------------
46
TDYa12783bb6622012-04-17 02:20:34 -070047// This is used by other runtime support functions, NOT FROM CODE. The REAL GetCurrentThread is
48// implemented by IRBuilder. (So, ARM can't return R9 in this function.)
49// TODO: Maybe remove these which are implemented by IRBuilder after refactor runtime support.
Logan Chienfc5bc672012-03-06 16:54:30 +080050Thread* art_get_current_thread_from_code() {
TDYa127d668a062012-04-13 12:36:57 -070051#if defined(__i386__)
52 Thread* ptr;
Elliott Hughes7834cbd2012-05-14 18:25:16 -070053 __asm__ __volatile__("movl %%fs:(%1), %0"
TDYa127d668a062012-04-13 12:36:57 -070054 : "=r"(ptr) // output
55 : "r"(THREAD_SELF_OFFSET) // input
56 :); // clobber
57 return ptr;
58#else
Logan Chienfc5bc672012-03-06 16:54:30 +080059 return Thread::Current();
TDYa127d668a062012-04-13 12:36:57 -070060#endif
Logan Chienfc5bc672012-03-06 16:54:30 +080061}
62
TDYa127c1478262012-06-20 20:22:27 -070063void* art_set_current_thread_from_code(void* thread_object_addr) {
TDYa127b08ed122012-06-05 23:51:19 -070064 // Nothing to be done.
TDYa127c1478262012-06-20 20:22:27 -070065 return NULL;
Logan Chienfc5bc672012-03-06 16:54:30 +080066}
67
TDYa127706e9b62012-04-19 12:24:26 -070068void art_lock_object_from_code(Object* obj, Thread* thread) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -080069 DCHECK(obj != NULL); // Assumed to have been checked before entry
70 obj->MonitorEnter(thread); // May block
71 DCHECK(thread->HoldsLock(obj));
72 // Only possible exception is NPE and is handled before entry
73 DCHECK(!thread->IsExceptionPending());
Logan Chienfc5bc672012-03-06 16:54:30 +080074}
75
TDYa127706e9b62012-04-19 12:24:26 -070076void art_unlock_object_from_code(Object* obj, Thread* thread) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -080077 DCHECK(obj != NULL); // Assumed to have been checked before entry
78 // MonitorExit may throw exception
79 obj->MonitorExit(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +080080}
81
TDYa127706e9b62012-04-19 12:24:26 -070082void art_test_suspend_from_code(Thread* thread) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -080083 Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +080084}
85
TDYa127de479be2012-05-31 08:03:26 -070086ShadowFrame* art_push_shadow_frame_from_code(Thread* thread, ShadowFrame* new_shadow_frame,
87 Method* method, uint32_t size) {
88 ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
89 new_shadow_frame->SetMethod(method);
90 new_shadow_frame->SetNumberOfReferences(size);
91 return old_frame;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080092}
93
TDYa1270de52be2012-05-27 20:49:31 -070094void art_pop_shadow_frame_from_code(void*) {
TDYa12783bb6622012-04-17 02:20:34 -070095 LOG(FATAL) << "Implemented by IRBuilder.";
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080096}
97
TDYa12783bb6622012-04-17 02:20:34 -070098void art_mark_gc_card_from_code(void *, void*) {
99 LOG(FATAL) << "Implemented by IRBuilder.";
100}
Logan Chienfc5bc672012-03-06 16:54:30 +0800101
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800102//----------------------------------------------------------------------------
103// Exception
104//----------------------------------------------------------------------------
105
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800106bool art_is_exception_pending_from_code() {
TDYa12783bb6622012-04-17 02:20:34 -0700107 LOG(FATAL) << "Implemented by IRBuilder.";
108 return false;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800109}
110
111void art_throw_div_zero_from_code() {
TDYa127d668a062012-04-13 12:36:57 -0700112 Thread* thread = art_get_current_thread_from_code();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800113 thread->ThrowNewException("Ljava/lang/ArithmeticException;",
114 "divide by zero");
115}
116
Shih-wei Liao77065fb2012-06-21 11:32:19 -0700117void art_throw_array_bounds_from_code(int32_t index, int32_t length) {
TDYa127d668a062012-04-13 12:36:57 -0700118 Thread* thread = art_get_current_thread_from_code();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800119 thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
120 "length=%d; index=%d", length, index);
121}
122
123void art_throw_no_such_method_from_code(int32_t method_idx) {
TDYa127d668a062012-04-13 12:36:57 -0700124 Thread* thread = art_get_current_thread_from_code();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800125 // We need the calling method as context for the method_idx
Ian Rogers0399dde2012-06-06 17:09:28 -0700126 Method* method = thread->GetCurrentMethod();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800127 thread->ThrowNewException("Ljava/lang/NoSuchMethodError;",
128 MethodNameFromIndex(method,
129 method_idx,
130 verifier::VERIFY_ERROR_REF_METHOD,
131 false).c_str());
132}
133
TDYa1273f9137d2012-04-08 15:59:19 -0700134void art_throw_null_pointer_exception_from_code(uint32_t dex_pc) {
TDYa127d668a062012-04-13 12:36:57 -0700135 Thread* thread = art_get_current_thread_from_code();
Shih-wei Liaoa64f1572012-06-22 00:09:57 -0700136 NthCallerVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), 0);
Ian Rogers0399dde2012-06-06 17:09:28 -0700137 visitor.WalkStack();
TDYa1273f9137d2012-04-08 15:59:19 -0700138 Method* throw_method = visitor.caller;
139 ThrowNullPointerExceptionFromDexPC(thread, throw_method, dex_pc);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800140}
141
TDYa1274165a832012-04-03 17:47:16 -0700142void art_throw_stack_overflow_from_code() {
TDYa127d668a062012-04-13 12:36:57 -0700143 Thread* thread = art_get_current_thread_from_code();
TDYa1274165a832012-04-03 17:47:16 -0700144 if (Runtime::Current()->IsMethodTracingActive()) {
145 TraceMethodUnwindFromCode(thread);
146 }
Elliott Hughes6cf23882012-06-15 15:42:07 -0700147 thread->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute.
148 thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;", "stack size %s",
149 PrettySize(thread->GetStackSize()).c_str());
150 thread->ResetDefaultStackEnd(); // Return to default stack size.
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800151}
152
153void art_throw_exception_from_code(Object* exception) {
TDYa127d668a062012-04-13 12:36:57 -0700154 Thread* thread = art_get_current_thread_from_code();
TDYa127540a5b72012-04-03 18:56:08 -0700155 if (exception == NULL) {
156 thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
157 } else {
158 thread->SetException(static_cast<Throwable*>(exception));
159 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800160}
161
Logan Chien9e5f5c12012-04-10 13:51:45 +0800162void art_throw_verification_error_from_code(Method* current_method,
163 int32_t kind,
164 int32_t ref) {
TDYa127d668a062012-04-13 12:36:57 -0700165 ThrowVerificationError(art_get_current_thread_from_code(), current_method, kind, ref);
Logan Chien9e5f5c12012-04-10 13:51:45 +0800166}
167
Logan Chien736df022012-04-27 16:25:57 +0800168int32_t art_find_catch_block_from_code(Method* current_method,
169 uint32_t ti_offset) {
TDYa127d668a062012-04-13 12:36:57 -0700170 Thread* thread = art_get_current_thread_from_code();
TDYa1272d702172012-04-01 15:15:13 -0700171 Class* exception_type = thread->GetException()->GetClass();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800172 MethodHelper mh(current_method);
173 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Logan Chien736df022012-04-27 16:25:57 +0800174 DCHECK_LT(ti_offset, code_item->tries_size_);
175 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
176
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800177 int iter_index = 0;
178 // Iterate over the catch handlers associated with dex_pc
Logan Chien736df022012-04-27 16:25:57 +0800179 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800180 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
181 // Catch all case
182 if (iter_type_idx == DexFile::kDexNoIndex16) {
183 return iter_index;
184 }
185 // Does this catch exception type apply?
186 Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
187 if (iter_exception_type == NULL) {
188 // The verifier should take care of resolving all exception classes early
189 LOG(WARNING) << "Unresolved exception class when finding catch block: "
190 << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
191 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
192 return iter_index;
193 }
194 ++iter_index;
195 }
196 // Handler not found
197 return -1;
198}
199
Logan Chienfc5bc672012-03-06 16:54:30 +0800200
201//----------------------------------------------------------------------------
202// Object Space
203//----------------------------------------------------------------------------
204
TDYa127da83d972012-04-18 00:21:49 -0700205Object* art_alloc_object_from_code(uint32_t type_idx,
206 Method* referrer,
207 Thread* thread) {
208 return AllocObjectFromCode(type_idx, referrer, thread, false);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800209}
210
TDYa127da83d972012-04-18 00:21:49 -0700211Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx,
212 Method* referrer,
213 Thread* thread) {
214 return AllocObjectFromCode(type_idx, referrer, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800215}
216
TDYa127da83d972012-04-18 00:21:49 -0700217Object* art_alloc_array_from_code(uint32_t type_idx,
218 Method* referrer,
219 uint32_t length,
220 Thread* thread) {
221 return AllocArrayFromCode(type_idx, referrer, length, thread, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800222}
223
224Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800225 Method* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700226 uint32_t length,
227 Thread* thread) {
228 return AllocArrayFromCode(type_idx, referrer, length, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800229}
230
231Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800232 Method* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700233 uint32_t length,
234 Thread* thread) {
235 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800236}
237
238Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800239 Method* referrer,
TDYa127da83d972012-04-18 00:21:49 -0700240 uint32_t length,
241 Thread* thread) {
242 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800243}
244
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800245static Method* FindMethodHelper(uint32_t method_idx, Object* this_object, Method* caller_method,
TDYa127da83d972012-04-18 00:21:49 -0700246 bool access_check, InvokeType type, Thread* thread) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800247 Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
248 if (UNLIKELY(method == NULL)) {
249 method = FindMethodFromCode(method_idx, this_object, caller_method,
TDYa127da83d972012-04-18 00:21:49 -0700250 thread, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800251 if (UNLIKELY(method == NULL)) {
TDYa127da83d972012-04-18 00:21:49 -0700252 CHECK(thread->IsExceptionPending());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800253 return 0; // failure
254 }
255 }
TDYa127da83d972012-04-18 00:21:49 -0700256 DCHECK(!thread->IsExceptionPending());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800257 return method;
258}
259
Logan Chien7e7fabc2012-04-10 18:59:11 +0800260Object* art_find_static_method_from_code_with_access_check(uint32_t method_idx,
261 Object* this_object,
TDYa127da83d972012-04-18 00:21:49 -0700262 Method* referrer,
263 Thread* thread) {
264 return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800265}
266
Logan Chien7e7fabc2012-04-10 18:59:11 +0800267Object* art_find_direct_method_from_code_with_access_check(uint32_t method_idx,
268 Object* this_object,
TDYa127da83d972012-04-18 00:21:49 -0700269 Method* referrer,
270 Thread* thread) {
271 return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800272}
273
274Object* art_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
275 Object* this_object,
TDYa127da83d972012-04-18 00:21:49 -0700276 Method* referrer,
277 Thread* thread) {
278 return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800279}
280
Logan Chien7e7fabc2012-04-10 18:59:11 +0800281Object* art_find_super_method_from_code_with_access_check(uint32_t method_idx,
282 Object* this_object,
TDYa127da83d972012-04-18 00:21:49 -0700283 Method* referrer,
284 Thread* thread) {
285 return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800286}
287
Logan Chien7e7fabc2012-04-10 18:59:11 +0800288Object*
289art_find_interface_method_from_code_with_access_check(uint32_t method_idx,
290 Object* this_object,
TDYa127da83d972012-04-18 00:21:49 -0700291 Method* referrer,
292 Thread* thread) {
293 return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800294}
295
296Object* art_find_interface_method_from_code(uint32_t method_idx,
297 Object* this_object,
TDYa127da83d972012-04-18 00:21:49 -0700298 Method* referrer,
299 Thread* thread) {
300 return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800301}
302
TDYa127706e9b62012-04-19 12:24:26 -0700303Object* art_initialize_static_storage_from_code(uint32_t type_idx,
304 Method* referrer,
305 Thread* thread) {
306 return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800307}
308
TDYa127706e9b62012-04-19 12:24:26 -0700309Object* art_initialize_type_from_code(uint32_t type_idx,
310 Method* referrer,
311 Thread* thread) {
312 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800313}
314
TDYa127706e9b62012-04-19 12:24:26 -0700315Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx,
316 Method* referrer,
317 Thread* thread) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800318 // Called when caller isn't guaranteed to have access to a type and the dex cache may be
319 // unpopulated
TDYa127706e9b62012-04-19 12:24:26 -0700320 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800321}
322
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800323Object* art_resolve_string_from_code(Method* referrer, uint32_t string_idx) {
324 return ResolveStringFromCode(referrer, string_idx);
Logan Chienfc5bc672012-03-06 16:54:30 +0800325}
326
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800327int32_t art_set32_static_from_code(uint32_t field_idx, Method* referrer, int32_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800328 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint32_t));
329 if (LIKELY(field != NULL)) {
330 field->Set32(NULL, new_value);
331 return 0;
332 }
TDYa127d668a062012-04-13 12:36:57 -0700333 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800334 true, true, true, sizeof(uint32_t));
335 if (LIKELY(field != NULL)) {
336 field->Set32(NULL, new_value);
337 return 0;
338 }
339 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800340}
341
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800342int32_t art_set64_static_from_code(uint32_t field_idx, Method* referrer, int64_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800343 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint64_t));
344 if (LIKELY(field != NULL)) {
345 field->Set64(NULL, new_value);
346 return 0;
347 }
TDYa127d668a062012-04-13 12:36:57 -0700348 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800349 true, true, true, sizeof(uint64_t));
350 if (LIKELY(field != NULL)) {
351 field->Set64(NULL, new_value);
352 return 0;
353 }
354 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800355}
356
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800357int32_t art_set_obj_static_from_code(uint32_t field_idx, Method* referrer, Object* new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800358 Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
359 if (LIKELY(field != NULL)) {
360 field->SetObj(NULL, new_value);
361 return 0;
362 }
TDYa127d668a062012-04-13 12:36:57 -0700363 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800364 true, false, true, sizeof(Object*));
365 if (LIKELY(field != NULL)) {
366 field->SetObj(NULL, new_value);
367 return 0;
368 }
369 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800370}
371
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800372int32_t art_get32_static_from_code(uint32_t field_idx, Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800373 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint32_t));
374 if (LIKELY(field != NULL)) {
375 return field->Get32(NULL);
376 }
TDYa127d668a062012-04-13 12:36:57 -0700377 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800378 true, true, false, sizeof(uint32_t));
379 if (LIKELY(field != NULL)) {
380 return field->Get32(NULL);
381 }
382 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800383}
384
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800385int64_t art_get64_static_from_code(uint32_t field_idx, Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800386 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint64_t));
387 if (LIKELY(field != NULL)) {
388 return field->Get64(NULL);
389 }
TDYa127d668a062012-04-13 12:36:57 -0700390 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800391 true, true, false, sizeof(uint64_t));
392 if (LIKELY(field != NULL)) {
393 return field->Get64(NULL);
394 }
395 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800396}
397
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800398Object* art_get_obj_static_from_code(uint32_t field_idx, Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800399 Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
400 if (LIKELY(field != NULL)) {
401 return field->GetObj(NULL);
402 }
TDYa127d668a062012-04-13 12:36:57 -0700403 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800404 true, false, false, sizeof(Object*));
405 if (LIKELY(field != NULL)) {
406 return field->GetObj(NULL);
407 }
408 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800409}
410
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800411int32_t art_set32_instance_from_code(uint32_t field_idx, Method* referrer,
412 Object* obj, uint32_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800413 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint32_t));
414 if (LIKELY(field != NULL)) {
415 field->Set32(obj, new_value);
416 return 0;
417 }
TDYa127d668a062012-04-13 12:36:57 -0700418 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800419 false, true, true, sizeof(uint32_t));
420 if (LIKELY(field != NULL)) {
421 field->Set32(obj, new_value);
422 return 0;
423 }
424 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800425}
426
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800427int32_t art_set64_instance_from_code(uint32_t field_idx, Method* referrer,
428 Object* obj, int64_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800429 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint64_t));
430 if (LIKELY(field != NULL)) {
431 field->Set64(obj, new_value);
432 return 0;
433 }
TDYa127d668a062012-04-13 12:36:57 -0700434 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800435 false, true, true, sizeof(uint64_t));
436 if (LIKELY(field != NULL)) {
437 field->Set64(obj, new_value);
438 return 0;
439 }
440 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800441}
442
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800443int32_t art_set_obj_instance_from_code(uint32_t field_idx, Method* referrer,
444 Object* obj, Object* new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800445 Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
446 if (LIKELY(field != NULL)) {
447 field->SetObj(obj, new_value);
448 return 0;
449 }
TDYa127d668a062012-04-13 12:36:57 -0700450 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800451 false, false, true, sizeof(Object*));
452 if (LIKELY(field != NULL)) {
453 field->SetObj(obj, new_value);
454 return 0;
455 }
456 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800457}
458
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800459int32_t art_get32_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800460 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint32_t));
461 if (LIKELY(field != NULL)) {
462 return field->Get32(obj);
463 }
TDYa127d668a062012-04-13 12:36:57 -0700464 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800465 false, true, false, sizeof(uint32_t));
466 if (LIKELY(field != NULL)) {
467 return field->Get32(obj);
468 }
469 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800470}
471
472int64_t art_get64_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800473 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint64_t));
474 if (LIKELY(field != NULL)) {
475 return field->Get64(obj);
476 }
TDYa127d668a062012-04-13 12:36:57 -0700477 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800478 false, true, false, sizeof(uint64_t));
479 if (LIKELY(field != NULL)) {
480 return field->Get64(obj);
481 }
482 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800483}
484
485Object* art_get_obj_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800486 Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
487 if (LIKELY(field != NULL)) {
488 return field->GetObj(obj);
489 }
TDYa127d668a062012-04-13 12:36:57 -0700490 field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800491 false, false, false, sizeof(Object*));
492 if (LIKELY(field != NULL)) {
493 return field->GetObj(obj);
494 }
495 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800496}
497
Ian Rogersc553b952012-06-18 23:39:11 -0700498Object* art_decode_jobject_in_thread(Thread* self, jobject java_object) {
499 if (self->IsExceptionPending()) {
TDYa12728f1a142012-03-15 21:51:52 -0700500 return NULL;
501 }
Ian Rogersc553b952012-06-18 23:39:11 -0700502 Object* o = self->DecodeJObject(java_object);
503 if (o == NULL || !self->GetJniEnv()->check_jni) {
504 return o;
505 }
506
507 if (o == kInvalidIndirectRefObject) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700508 JniAbortF(NULL, "invalid reference returned from %s",
509 PrettyMethod(self->GetCurrentMethod()).c_str());
Ian Rogersc553b952012-06-18 23:39:11 -0700510 }
511
512 // Make sure that the result is an instance of the type this
513 // method was expected to return.
514 Method* m = self->GetCurrentMethod();
515 MethodHelper mh(m);
516 Class* return_type = mh.GetReturnType();
517
518 if (!o->InstanceOf(return_type)) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700519 JniAbortF(NULL, "attempt to return an instance of %s from %s",
520 PrettyTypeOf(o).c_str(), PrettyMethod(m).c_str());
Ian Rogersc553b952012-06-18 23:39:11 -0700521 }
522
523 return o;
TDYa12728f1a142012-03-15 21:51:52 -0700524}
Logan Chienfc5bc672012-03-06 16:54:30 +0800525
Logan Chien86f50672012-04-24 13:08:45 +0800526void art_fill_array_data_from_code(Method* method, uint32_t dex_pc,
527 Array* array, uint32_t payload_offset) {
528 // Test: Is array equal to null? (Guard NullPointerException)
529 if (UNLIKELY(array == NULL)) {
530 art_throw_null_pointer_exception_from_code(dex_pc);
531 return;
532 }
533
534 // Find the payload from the CodeItem
535 MethodHelper mh(method);
536 const DexFile::CodeItem* code_item = mh.GetCodeItem();
537
538 DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
539
540 const Instruction::ArrayDataPayload* payload =
541 reinterpret_cast<const Instruction::ArrayDataPayload*>(
542 code_item->insns_ + payload_offset);
543
544 DCHECK_EQ(payload->ident,
545 static_cast<uint16_t>(Instruction::kArrayDataSignature));
546
547 // Test: Is array big enough?
548 uint32_t array_len = static_cast<uint32_t>(array->GetLength());
549 if (UNLIKELY(array_len < payload->element_count)) {
550 int32_t last_index = payload->element_count - 1;
551 art_throw_array_bounds_from_code(array_len, last_index);
552 return;
553 }
554
555 // Copy the data
556 size_t size = payload->element_width * payload->element_count;
557 memcpy(array->GetRawData(payload->element_width), payload->data, size);
558}
559
560
561
Logan Chienfc5bc672012-03-06 16:54:30 +0800562//----------------------------------------------------------------------------
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700563// Type checking, in the nature of casting
Logan Chienfc5bc672012-03-06 16:54:30 +0800564//----------------------------------------------------------------------------
565
TDYa1273de5ba32012-04-02 07:04:40 -0700566int32_t art_is_assignable_from_code(const Class* dest_type, const Class* src_type) {
567 DCHECK(dest_type != NULL);
568 DCHECK(src_type != NULL);
569 return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800570}
571
TDYa1273de5ba32012-04-02 07:04:40 -0700572void art_check_cast_from_code(const Class* dest_type, const Class* src_type) {
TDYa1271b86d072012-04-05 17:38:56 -0700573 DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700574 DCHECK(src_type->IsClass()) << PrettyClass(src_type);
575 if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
TDYa127d668a062012-04-13 12:36:57 -0700576 Thread* thread = art_get_current_thread_from_code();
577 thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
578 "%s cannot be cast to %s",
TDYa1278e9b4492012-04-24 15:50:27 -0700579 PrettyDescriptor(src_type).c_str(),
580 PrettyDescriptor(dest_type).c_str());
TDYa1273de5ba32012-04-02 07:04:40 -0700581 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800582}
583
TDYa1271b86d072012-04-05 17:38:56 -0700584void art_check_put_array_element_from_code(const Object* element, const Object* array) {
585 if (element == NULL) {
586 return;
587 }
588 DCHECK(array != NULL);
589 Class* array_class = array->GetClass();
590 DCHECK(array_class != NULL);
591 Class* component_type = array_class->GetComponentType();
592 Class* element_class = element->GetClass();
593 if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
TDYa127d668a062012-04-13 12:36:57 -0700594 Thread* thread = art_get_current_thread_from_code();
595 thread->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
596 "%s cannot be stored in an array of type %s",
597 PrettyDescriptor(element_class).c_str(),
598 PrettyDescriptor(array_class).c_str());
TDYa1271b86d072012-04-05 17:38:56 -0700599 }
600 return;
601}
602
Logan Chien2771fb12012-03-06 16:28:35 +0800603//----------------------------------------------------------------------------
604// Runtime Support Function Lookup Callback
605//----------------------------------------------------------------------------
606
Logan Chiend23c5ad2012-03-30 17:46:04 +0800607#define EXTERNAL_LINKAGE(NAME) \
608extern "C" void NAME(...);
Logan Chien95dfa6a2012-06-01 16:08:02 +0800609COMPILER_RUNTIME_FUNC_LIST_NATIVE(EXTERNAL_LINKAGE)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800610#undef EXTERNAL_LINKAGE
611
612static void* art_find_compiler_runtime_func(char const* name) {
jeffhao41005dd2012-05-09 17:58:52 -0700613// 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 +0800614 static const char* const names[] = {
615#define DEFINE_ENTRY(NAME) #NAME ,
Logan Chien95dfa6a2012-06-01 16:08:02 +0800616 COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800617#undef DEFINE_ENTRY
618 };
619
620 static void* const funcs[] = {
621#define DEFINE_ENTRY(NAME) reinterpret_cast<void*>(NAME) ,
Logan Chien95dfa6a2012-06-01 16:08:02 +0800622 COMPILER_RUNTIME_FUNC_LIST_NATIVE(DEFINE_ENTRY)
Logan Chiend23c5ad2012-03-30 17:46:04 +0800623#undef DEFINE_ENTRY
624 };
625
626 static const size_t num_entries = sizeof(names) / sizeof(const char* const);
627
Logan Chien64f884d2012-04-03 18:30:47 +0800628 const char* const* const names_begin = names;
629 const char* const* const names_end = names + num_entries;
Logan Chiend23c5ad2012-03-30 17:46:04 +0800630
Logan Chien64f884d2012-04-03 18:30:47 +0800631 const char* const* name_lbound_ptr =
Logan Chiena1beb1f2012-06-01 16:03:27 +0800632 std::lower_bound(names_begin, names_end, name,
633 CStringLessThanComparator());
Logan Chien64f884d2012-04-03 18:30:47 +0800634
635 if (name_lbound_ptr < names_end && strcmp(*name_lbound_ptr, name) == 0) {
636 return funcs[name_lbound_ptr - names_begin];
Logan Chiend23c5ad2012-03-30 17:46:04 +0800637 } else {
Logan Chien64f884d2012-04-03 18:30:47 +0800638 return NULL;
Logan Chiend23c5ad2012-03-30 17:46:04 +0800639 }
640}
641
TDYa12705fe3b62012-04-21 00:28:54 -0700642// TODO: This runtime support function is the temporary solution for the link issue.
TDYa1270b686e52012-04-09 22:43:35 -0700643// It calls to this function before invoking any function, and this function will check:
TDYa12705fe3b62012-04-21 00:28:54 -0700644// 1. The code address is 0. -> Link the code by ELFLoader
645// That will solved by in-place linking at image loading.
TDYa1270b686e52012-04-09 22:43:35 -0700646const void* art_fix_stub_from_code(Method* called) {
TDYa1270b686e52012-04-09 22:43:35 -0700647 const void* code = called->GetCode();
TDYa12705fe3b62012-04-21 00:28:54 -0700648 // 1. The code address is 0. -> Link the code by ELFLoader
649 if (UNLIKELY(code == NULL)) {
650 Runtime::Current()->GetClassLinker()->LinkOatCodeFor(called);
TDYa1270b686e52012-04-09 22:43:35 -0700651 return called->GetCode();
TDYa12785321912012-04-01 15:24:56 -0700652 }
TDYa1270b686e52012-04-09 22:43:35 -0700653
654 return code;
TDYa12785321912012-04-01 15:24:56 -0700655}
656
TDYa1275bb86012012-04-11 05:57:28 -0700657// Handler for invocation on proxy methods. We create a boxed argument array. And we invoke
658// the invocation handler which is a field within the proxy object receiver.
659void art_proxy_invoke_handler_from_code(Method* proxy_method, ...) {
660 va_list ap;
661 va_start(ap, proxy_method);
662
663 Object* receiver = va_arg(ap, Object*);
TDYa127eead4ac2012-06-03 07:15:25 -0700664 Thread* thread = va_arg(ap, Thread*);
TDYa1275bb86012012-04-11 05:57:28 -0700665 MethodHelper proxy_mh(proxy_method);
666 const size_t num_params = proxy_mh.NumArgs();
667
668 // Start new JNI local reference state
669 JNIEnvExt* env = thread->GetJniEnv();
670 ScopedJniEnvLocalRefState env_state(env);
671
TDYa12754825032012-04-11 10:45:23 -0700672 // Create local ref. copies of the receiver
TDYa1275bb86012012-04-11 05:57:28 -0700673 jobject rcvr_jobj = AddLocalReference<jobject>(env, receiver);
674
675 // Convert proxy method into expected interface method
676 Method* interface_method = proxy_method->FindOverriddenMethod();
677 DCHECK(interface_method != NULL);
678 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
679
680 // Set up arguments array and place in local IRT during boxing (which may allocate/GC)
681 jvalue args_jobj[3];
682 args_jobj[0].l = rcvr_jobj;
683 args_jobj[1].l = AddLocalReference<jobject>(env, interface_method);
684 // Args array, if no arguments then NULL (don't include receiver in argument count)
685 args_jobj[2].l = NULL;
686 ObjectArray<Object>* args = NULL;
687 if ((num_params - 1) > 0) {
688 args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1);
689 if (args == NULL) {
690 CHECK(thread->IsExceptionPending());
691 return;
692 }
693 args_jobj[2].l = AddLocalReference<jobjectArray>(env, args);
694 }
695
696 // Get parameter types.
697 const char* shorty = proxy_mh.GetShorty();
698 ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
699 if (param_types == NULL) {
700 CHECK(thread->IsExceptionPending());
701 return;
702 }
703
704 // Box arguments.
705 for (size_t i = 0; i < (num_params - 1);++i) {
706 JValue val;
707 switch (shorty[i+1]) {
708 case 'Z':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700709 val.SetZ(va_arg(ap, jint));
710 break;
TDYa1275bb86012012-04-11 05:57:28 -0700711 case 'B':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700712 val.SetB(va_arg(ap, jint));
713 break;
TDYa1275bb86012012-04-11 05:57:28 -0700714 case 'C':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700715 val.SetC(va_arg(ap, jint));
716 break;
TDYa1275bb86012012-04-11 05:57:28 -0700717 case 'S':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700718 val.SetS(va_arg(ap, jint));
719 break;
TDYa1275bb86012012-04-11 05:57:28 -0700720 case 'I':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700721 val.SetI(va_arg(ap, jint));
722 break;
TDYa1275bb86012012-04-11 05:57:28 -0700723 case 'F':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700724 val.SetI(va_arg(ap, jint)); // TODO: is this right?
TDYa1275bb86012012-04-11 05:57:28 -0700725 break;
726 case 'L':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700727 val.SetL(va_arg(ap, Object*));
TDYa1275bb86012012-04-11 05:57:28 -0700728 break;
729 case 'D':
730 case 'J':
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700731 val.SetJ(va_arg(ap, jlong)); // TODO: is this right for double?
TDYa1275bb86012012-04-11 05:57:28 -0700732 break;
733 }
734 Class* param_type = param_types->Get(i);
735 if (param_type->IsPrimitive()) {
736 BoxPrimitive(param_type->GetPrimitiveType(), val);
737 if (thread->IsExceptionPending()) {
738 return;
739 }
740 }
Shih-wei Liao2272f7b2012-04-12 14:23:48 -0700741 args->Set(i, val.GetL());
TDYa1275bb86012012-04-11 05:57:28 -0700742 }
743
Elliott Hugheseac76672012-05-24 21:56:51 -0700744 DCHECK(env->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
TDYa1275bb86012012-04-11 05:57:28 -0700745
Elliott Hugheseac76672012-05-24 21:56:51 -0700746 jobject inv_hand = env->GetObjectField(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy_h);
TDYa1275bb86012012-04-11 05:57:28 -0700747 // Call InvocationHandler.invoke
Elliott Hugheseac76672012-05-24 21:56:51 -0700748 jobject result = env->CallObjectMethodA(inv_hand, WellKnownClasses::java_lang_reflect_InvocationHandler_invoke, args_jobj);
TDYa1275bb86012012-04-11 05:57:28 -0700749
750 // Place result in stack args
751 if (!thread->IsExceptionPending()) {
752 if (shorty[0] == 'V') {
753 return;
754 }
755 Object* result_ref = thread->DecodeJObject(result);
756 JValue* result_unboxed = va_arg(ap, JValue*);
757 if (result_ref == NULL) {
Shih-wei Liao2272f7b2012-04-12 14:23:48 -0700758 result_unboxed->SetL(NULL);
TDYa1275bb86012012-04-11 05:57:28 -0700759 } else {
Elliott Hughesaaa5edc2012-05-16 15:54:30 -0700760 bool unboxed_okay = UnboxPrimitiveForResult(result_ref, proxy_mh.GetReturnType(), *result_unboxed);
TDYa1275bb86012012-04-11 05:57:28 -0700761 if (!unboxed_okay) {
762 thread->ClearException();
763 thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
764 "Couldn't convert result of type %s to %s",
765 PrettyTypeOf(result_ref).c_str(),
766 PrettyDescriptor(proxy_mh.GetReturnType()).c_str());
767 return;
768 }
769 }
770 } else {
771 // In the case of checked exceptions that aren't declared, the exception must be wrapped by
772 // a UndeclaredThrowableException.
773 Throwable* exception = thread->GetException();
Elliott Hughesa4f94742012-05-29 16:28:38 -0700774 if (exception->IsCheckedException()) {
TDYa1275bb86012012-04-11 05:57:28 -0700775 SynthesizedProxyClass* proxy_class =
776 down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
777 int throws_index = -1;
778 size_t num_virt_methods = proxy_class->NumVirtualMethods();
779 for (size_t i = 0; i < num_virt_methods; i++) {
780 if (proxy_class->GetVirtualMethod(i) == proxy_method) {
781 throws_index = i;
782 break;
783 }
784 }
785 CHECK_NE(throws_index, -1);
786 ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
787 Class* exception_class = exception->GetClass();
788 bool declares_exception = false;
789 for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
790 Class* declared_exception = declared_exceptions->Get(i);
791 declares_exception = declared_exception->IsAssignableFrom(exception_class);
792 }
Elliott Hughesa4f94742012-05-29 16:28:38 -0700793 if (!declares_exception) {
Shih-wei Liao4b644ec2012-05-29 17:16:31 -0700794 thread->ThrowNewWrappedException("Ljava/lang/reflect/UndeclaredThrowableException;", NULL);
TDYa1275bb86012012-04-11 05:57:28 -0700795 }
796 }
797 }
798
799 va_end(ap);
800}
801
Logan Chien2771fb12012-03-06 16:28:35 +0800802void* art_find_runtime_support_func(void* context, char const* name) {
803 struct func_entry_t {
804 char const* name;
805 size_t name_len;
806 void* addr;
807 };
808
809 static struct func_entry_t const tab[] = {
Logan Chienbc615a12012-03-06 17:03:48 +0800810#define DEFINE_ENTRY(ID, NAME) \
811 { #NAME, sizeof(#NAME) - 1, reinterpret_cast<void*>(NAME) },
Logan Chienbc615a12012-03-06 17:03:48 +0800812 RUNTIME_SUPPORT_FUNC_LIST(DEFINE_ENTRY)
Logan Chienbc615a12012-03-06 17:03:48 +0800813#undef DEFINE_ENTRY
Logan Chien2771fb12012-03-06 16:28:35 +0800814 };
815
816 static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
817
Logan Chiend23c5ad2012-03-30 17:46:04 +0800818 // Search the compiler runtime (such as __divdi3)
819 void* result = art_find_compiler_runtime_func(name);
820 if (result != NULL) {
821 return result;
822 }
823
Logan Chien2771fb12012-03-06 16:28:35 +0800824 // Note: Since our table is small, we are using trivial O(n) searching
825 // function. For bigger table, it will be better to use binary
826 // search or hash function.
827 size_t i;
828 size_t name_len = strlen(name);
829 for (i = 0; i < tab_size; ++i) {
830 if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
831 return tab[i].addr;
832 }
833 }
834
835 LOG(FATAL) << "Error: Can't find symbol " << name;
836 return 0;
837}
838
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800839} // namespace art