blob: 59b8efbfb34fb32c54bc42d89c10da7021bc99aa [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"
18#include "dex_verifier.h"
19#include "object.h"
20#include "object_utils.h"
Shih-wei Liaob1ab7df2012-03-29 13:53:46 -070021#include "runtime_support.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080022#include "runtime_support_llvm.h"
Logan Chienf7ad17e2012-03-15 03:10:03 +080023#include "shadow_frame.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080024#include "thread.h"
Shih-wei Liao66adbb72012-03-07 01:31:50 -080025#include "thread_list.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080026
Logan Chiend23c5ad2012-03-30 17:46:04 +080027#include <algorithm>
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080028#include <stdint.h>
29
30namespace art {
31
32//----------------------------------------------------------------------------
33// Thread
34//----------------------------------------------------------------------------
35
Logan Chienfc5bc672012-03-06 16:54:30 +080036Thread* art_get_current_thread_from_code() {
37 return Thread::Current();
38}
39
40void art_set_current_thread_from_code(void* thread_object_addr) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -080041 // TODO: LLVM IR generating something like "r9 = thread_object_addr"
Logan Chienfc5bc672012-03-06 16:54:30 +080042 UNIMPLEMENTED(WARNING);
43}
44
Shih-wei Liao66adbb72012-03-07 01:31:50 -080045void art_lock_object_from_code(Object* obj) {
46 Thread* thread = Thread::Current();
47 DCHECK(obj != NULL); // Assumed to have been checked before entry
48 obj->MonitorEnter(thread); // May block
49 DCHECK(thread->HoldsLock(obj));
50 // Only possible exception is NPE and is handled before entry
51 DCHECK(!thread->IsExceptionPending());
Logan Chienfc5bc672012-03-06 16:54:30 +080052}
53
Shih-wei Liao66adbb72012-03-07 01:31:50 -080054void art_unlock_object_from_code(Object* obj) {
55 Thread* thread = Thread::Current();
56 DCHECK(obj != NULL); // Assumed to have been checked before entry
57 // MonitorExit may throw exception
58 obj->MonitorExit(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +080059}
60
61void art_test_suspend_from_code() {
Shih-wei Liao66adbb72012-03-07 01:31:50 -080062 Thread* thread = Thread::Current();
63 Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +080064}
65
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080066void art_push_shadow_frame_from_code(void* new_shadow_frame) {
67 Thread* thread = Thread::Current();
Logan Chienf7ad17e2012-03-15 03:10:03 +080068 thread->PushShadowFrame(static_cast<ShadowFrame*>(new_shadow_frame));
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080069}
70
71void art_pop_shadow_frame_from_code() {
72 Thread* thread = Thread::Current();
Logan Chienf7ad17e2012-03-15 03:10:03 +080073 thread->PopShadowFrame();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080074}
75
76
Logan Chienfc5bc672012-03-06 16:54:30 +080077
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080078//----------------------------------------------------------------------------
79// Exception
80//----------------------------------------------------------------------------
81
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080082bool art_is_exception_pending_from_code() {
83 return Thread::Current()->IsExceptionPending();
84}
85
86void art_throw_div_zero_from_code() {
87 Thread* thread = Thread::Current();
88 thread->ThrowNewException("Ljava/lang/ArithmeticException;",
89 "divide by zero");
90}
91
92void art_throw_array_bounds_from_code(int32_t length, int32_t index) {
93 Thread* thread = Thread::Current();
94 thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
95 "length=%d; index=%d", length, index);
96}
97
98void art_throw_no_such_method_from_code(int32_t method_idx) {
99 Thread* thread = Thread::Current();
100 // We need the calling method as context for the method_idx
101 Frame frame = thread->GetTopOfStack();
102 frame.Next();
103 Method* method = frame.GetMethod();
104 thread->ThrowNewException("Ljava/lang/NoSuchMethodError;",
105 MethodNameFromIndex(method,
106 method_idx,
107 verifier::VERIFY_ERROR_REF_METHOD,
108 false).c_str());
109}
110
111void art_throw_null_pointer_exception_from_code() {
112 Thread* thread = Thread::Current();
113 thread->ThrowNewException("Ljava/lang/NullPointerException;", NULL);
114}
115
116void art_throw_stack_overflow_from_code(void*) {
117 Thread* thread = Thread::Current();
118 thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;",
119 "stack size %zdkb; default stack size: %zdkb",
120 thread->GetStackSize() / KB,
121 Runtime::Current()->GetDefaultStackSize() / KB);
122}
123
124void art_throw_exception_from_code(Object* exception) {
125 Thread* thread = Thread::Current();
126 thread->SetException(static_cast<Throwable*>(exception));
127}
128
TDYa1272d702172012-04-01 15:15:13 -0700129int32_t art_find_catch_block_from_code(Method* current_method, int32_t dex_pc) {
130 Thread* thread = Thread::Current();
131 Class* exception_type = thread->GetException()->GetClass();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800132 MethodHelper mh(current_method);
133 const DexFile::CodeItem* code_item = mh.GetCodeItem();
134 int iter_index = 0;
135 // Iterate over the catch handlers associated with dex_pc
136 for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
137 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
138 // Catch all case
139 if (iter_type_idx == DexFile::kDexNoIndex16) {
140 return iter_index;
141 }
142 // Does this catch exception type apply?
143 Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
144 if (iter_exception_type == NULL) {
145 // The verifier should take care of resolving all exception classes early
146 LOG(WARNING) << "Unresolved exception class when finding catch block: "
147 << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
148 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
149 return iter_index;
150 }
151 ++iter_index;
152 }
153 // Handler not found
154 return -1;
155}
156
Logan Chienfc5bc672012-03-06 16:54:30 +0800157
158//----------------------------------------------------------------------------
159// Object Space
160//----------------------------------------------------------------------------
161
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800162Object* art_alloc_object_from_code(uint32_t type_idx, Method* referrer) {
163 return AllocObjectFromCode(type_idx, referrer, Thread::Current(), false);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800164}
165
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800166Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx, Method* referrer) {
167 return AllocObjectFromCode(type_idx, referrer, Thread::Current(), true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800168}
169
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800170Object* art_alloc_array_from_code(uint32_t type_idx, Method* referrer, uint32_t length) {
171 return AllocArrayFromCode(type_idx, referrer, length, Thread::Current(), false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800172}
173
174Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800175 Method* referrer,
Logan Chienfc5bc672012-03-06 16:54:30 +0800176 uint32_t length) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800177 return AllocArrayFromCode(type_idx, referrer, length, Thread::Current(), true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800178}
179
180Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800181 Method* referrer,
Logan Chienfc5bc672012-03-06 16:54:30 +0800182 uint32_t length) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800183 return CheckAndAllocArrayFromCode(type_idx, referrer, length, Thread::Current(), false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800184}
185
186Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800187 Method* referrer,
Logan Chienfc5bc672012-03-06 16:54:30 +0800188 uint32_t length) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800189 return CheckAndAllocArrayFromCode(type_idx, referrer, length, Thread::Current(), true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800190}
191
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800192static Method* FindMethodHelper(uint32_t method_idx, Object* this_object, Method* caller_method,
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700193 bool access_check, InvokeType type) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800194 Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
195 if (UNLIKELY(method == NULL)) {
196 method = FindMethodFromCode(method_idx, this_object, caller_method,
197 Thread::Current(), access_check, type);
198 if (UNLIKELY(method == NULL)) {
199 CHECK(Thread::Current()->IsExceptionPending());
200 return 0; // failure
201 }
202 }
203 DCHECK(!Thread::Current()->IsExceptionPending());
204 return method;
205}
206
Logan Chienfc5bc672012-03-06 16:54:30 +0800207Object* art_find_interface_method_from_code(uint32_t method_idx,
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800208 Object* this_object,
209 Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800210 return FindMethodHelper(method_idx, this_object, referrer, true, kInterface);
Logan Chienfc5bc672012-03-06 16:54:30 +0800211}
212
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800213Object* art_find_virtual_method_from_code(uint32_t method_idx,
214 Object* this_object,
215 Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800216 return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual);
Logan Chienfc5bc672012-03-06 16:54:30 +0800217}
218
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800219Object* art_find_super_method_from_code(uint32_t method_idx,
220 Object* this_object,
221 Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800222 return FindMethodHelper(method_idx, this_object, referrer, true, kSuper);
Logan Chienfc5bc672012-03-06 16:54:30 +0800223}
224
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800225Object* art_initialize_static_storage_from_code(uint32_t type_idx, Method* referrer) {
226 return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), true, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800227}
228
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800229Object* art_initialize_type_from_code(uint32_t type_idx, Method* referrer) {
230 return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), false, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800231}
232
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800233Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx, Method* referrer) {
234 // Called when caller isn't guaranteed to have access to a type and the dex cache may be
235 // unpopulated
236 return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), false, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800237}
238
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800239Object* art_resolve_string_from_code(Method* referrer, uint32_t string_idx) {
240 return ResolveStringFromCode(referrer, string_idx);
Logan Chienfc5bc672012-03-06 16:54:30 +0800241}
242
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800243int32_t art_set32_static_from_code(uint32_t field_idx, Method* referrer, int32_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800244 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint32_t));
245 if (LIKELY(field != NULL)) {
246 field->Set32(NULL, new_value);
247 return 0;
248 }
249 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
250 true, true, true, sizeof(uint32_t));
251 if (LIKELY(field != NULL)) {
252 field->Set32(NULL, new_value);
253 return 0;
254 }
255 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800256}
257
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800258int32_t art_set64_static_from_code(uint32_t field_idx, Method* referrer, int64_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800259 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint64_t));
260 if (LIKELY(field != NULL)) {
261 field->Set64(NULL, new_value);
262 return 0;
263 }
264 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
265 true, true, true, sizeof(uint64_t));
266 if (LIKELY(field != NULL)) {
267 field->Set64(NULL, new_value);
268 return 0;
269 }
270 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800271}
272
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800273int32_t art_set_obj_static_from_code(uint32_t field_idx, Method* referrer, Object* new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800274 Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
275 if (LIKELY(field != NULL)) {
276 field->SetObj(NULL, new_value);
277 return 0;
278 }
279 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
280 true, false, true, sizeof(Object*));
281 if (LIKELY(field != NULL)) {
282 field->SetObj(NULL, new_value);
283 return 0;
284 }
285 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800286}
287
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800288int32_t art_get32_static_from_code(uint32_t field_idx, Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800289 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint32_t));
290 if (LIKELY(field != NULL)) {
291 return field->Get32(NULL);
292 }
293 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
294 true, true, false, sizeof(uint32_t));
295 if (LIKELY(field != NULL)) {
296 return field->Get32(NULL);
297 }
298 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800299}
300
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800301int64_t art_get64_static_from_code(uint32_t field_idx, Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800302 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint64_t));
303 if (LIKELY(field != NULL)) {
304 return field->Get64(NULL);
305 }
306 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
307 true, true, false, sizeof(uint64_t));
308 if (LIKELY(field != NULL)) {
309 return field->Get64(NULL);
310 }
311 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800312}
313
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800314Object* art_get_obj_static_from_code(uint32_t field_idx, Method* referrer) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800315 Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
316 if (LIKELY(field != NULL)) {
317 return field->GetObj(NULL);
318 }
319 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
320 true, false, false, sizeof(Object*));
321 if (LIKELY(field != NULL)) {
322 return field->GetObj(NULL);
323 }
324 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800325}
326
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800327int32_t art_set32_instance_from_code(uint32_t field_idx, Method* referrer,
328 Object* obj, uint32_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800329 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint32_t));
330 if (LIKELY(field != NULL)) {
331 field->Set32(obj, new_value);
332 return 0;
333 }
334 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
335 false, true, true, sizeof(uint32_t));
336 if (LIKELY(field != NULL)) {
337 field->Set32(obj, new_value);
338 return 0;
339 }
340 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800341}
342
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800343int32_t art_set64_instance_from_code(uint32_t field_idx, Method* referrer,
344 Object* obj, int64_t new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800345 Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(uint64_t));
346 if (LIKELY(field != NULL)) {
347 field->Set64(obj, new_value);
348 return 0;
349 }
350 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
351 false, true, true, sizeof(uint64_t));
352 if (LIKELY(field != NULL)) {
353 field->Set64(obj, new_value);
354 return 0;
355 }
356 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800357}
358
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800359int32_t art_set_obj_instance_from_code(uint32_t field_idx, Method* referrer,
360 Object* obj, Object* new_value) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800361 Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
362 if (LIKELY(field != NULL)) {
363 field->SetObj(obj, new_value);
364 return 0;
365 }
366 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
367 false, false, true, sizeof(Object*));
368 if (LIKELY(field != NULL)) {
369 field->SetObj(obj, new_value);
370 return 0;
371 }
372 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800373}
374
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800375int32_t art_get32_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800376 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint32_t));
377 if (LIKELY(field != NULL)) {
378 return field->Get32(obj);
379 }
380 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
381 false, true, false, sizeof(uint32_t));
382 if (LIKELY(field != NULL)) {
383 return field->Get32(obj);
384 }
385 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800386}
387
388int64_t art_get64_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800389 Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(uint64_t));
390 if (LIKELY(field != NULL)) {
391 return field->Get64(obj);
392 }
393 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
394 false, true, false, sizeof(uint64_t));
395 if (LIKELY(field != NULL)) {
396 return field->Get64(obj);
397 }
398 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800399}
400
401Object* art_get_obj_instance_from_code(uint32_t field_idx, Method* referrer, Object* obj) {
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800402 Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
403 if (LIKELY(field != NULL)) {
404 return field->GetObj(obj);
405 }
406 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
407 false, false, false, sizeof(Object*));
408 if (LIKELY(field != NULL)) {
409 return field->GetObj(obj);
410 }
411 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800412}
413
TDYa12728f1a142012-03-15 21:51:52 -0700414Object* art_decode_jobject_in_thread(Thread* thread, jobject obj) {
415 if (thread->IsExceptionPending()) {
416 return NULL;
417 }
418 return thread->DecodeJObject(obj);
419}
Logan Chienfc5bc672012-03-06 16:54:30 +0800420
421//----------------------------------------------------------------------------
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700422// Type checking, in the nature of casting
Logan Chienfc5bc672012-03-06 16:54:30 +0800423//----------------------------------------------------------------------------
424
TDYa1273de5ba32012-04-02 07:04:40 -0700425int32_t art_is_assignable_from_code(const Class* dest_type, const Class* src_type) {
426 DCHECK(dest_type != NULL);
427 DCHECK(src_type != NULL);
428 return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800429}
430
TDYa1273de5ba32012-04-02 07:04:40 -0700431void art_check_cast_from_code(const Class* dest_type, const Class* src_type) {
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700432DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700433 DCHECK(src_type->IsClass()) << PrettyClass(src_type);
434 if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
435 Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
436 "%s cannot be cast to %s",
437 PrettyDescriptor(dest_type).c_str(),
438 PrettyDescriptor(src_type).c_str());
439 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800440}
441
Logan Chien2771fb12012-03-06 16:28:35 +0800442//----------------------------------------------------------------------------
443// Runtime Support Function Lookup Callback
444//----------------------------------------------------------------------------
445
Logan Chiend23c5ad2012-03-30 17:46:04 +0800446class CStringComparator {
447 public:
448 bool operator()(const char* lhs, const char* rhs) const {
449 return (strcmp(lhs, rhs) <= 0);
450 }
451};
452
453#define EXTERNAL_LINKAGE(NAME) \
454extern "C" void NAME(...);
455
456#include "compiler_runtime_func_list.h"
457COMPILER_RUNTIME_FUNC_LIST(EXTERNAL_LINKAGE)
458#undef COMPILER_RUNTIME_FUNC_LIST
459#undef EXTERNAL_LINKAGE
460
461static void* art_find_compiler_runtime_func(char const* name) {
462 static const char* const names[] = {
463#define DEFINE_ENTRY(NAME) #NAME ,
464#include "compiler_runtime_func_list.h"
465 COMPILER_RUNTIME_FUNC_LIST(DEFINE_ENTRY)
466#undef COMPILER_RUNTIME_FUNC_LIST
467#undef DEFINE_ENTRY
468 };
469
470 static void* const funcs[] = {
471#define DEFINE_ENTRY(NAME) reinterpret_cast<void*>(NAME) ,
472#include "compiler_runtime_func_list.h"
473 COMPILER_RUNTIME_FUNC_LIST(DEFINE_ENTRY)
474#undef COMPILER_RUNTIME_FUNC_LIST
475#undef DEFINE_ENTRY
476 };
477
478 static const size_t num_entries = sizeof(names) / sizeof(const char* const);
479
480 const char* const* matched_name_ptr =
481 std::lower_bound(names, names + num_entries, name, CStringComparator());
482
483 if (matched_name_ptr == names + num_entries) {
484 return NULL;
485 } else {
486 return funcs[matched_name_ptr - names];
487 }
488}
489
Logan Chien2771fb12012-03-06 16:28:35 +0800490void* art_find_runtime_support_func(void* context, char const* name) {
491 struct func_entry_t {
492 char const* name;
493 size_t name_len;
494 void* addr;
495 };
496
497 static struct func_entry_t const tab[] = {
Logan Chienbc615a12012-03-06 17:03:48 +0800498#define DEFINE_ENTRY(ID, NAME) \
499 { #NAME, sizeof(#NAME) - 1, reinterpret_cast<void*>(NAME) },
Logan Chien2771fb12012-03-06 16:28:35 +0800500
Logan Chienbc615a12012-03-06 17:03:48 +0800501#include "runtime_support_func_list.h"
502 RUNTIME_SUPPORT_FUNC_LIST(DEFINE_ENTRY)
503#undef RUNTIME_SUPPORT_FUNC_LIST
504#undef DEFINE_ENTRY
Logan Chien2771fb12012-03-06 16:28:35 +0800505 };
506
507 static size_t const tab_size = sizeof(tab) / sizeof(struct func_entry_t);
508
Logan Chiend23c5ad2012-03-30 17:46:04 +0800509 // Search the compiler runtime (such as __divdi3)
510 void* result = art_find_compiler_runtime_func(name);
511 if (result != NULL) {
512 return result;
513 }
514
Logan Chien2771fb12012-03-06 16:28:35 +0800515 // Note: Since our table is small, we are using trivial O(n) searching
516 // function. For bigger table, it will be better to use binary
517 // search or hash function.
518 size_t i;
519 size_t name_len = strlen(name);
520 for (i = 0; i < tab_size; ++i) {
521 if (name_len == tab[i].name_len && strcmp(name, tab[i].name) == 0) {
522 return tab[i].addr;
523 }
524 }
525
526 LOG(FATAL) << "Error: Can't find symbol " << name;
527 return 0;
528}
529
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800530} // namespace art