blob: cbdefe8a0365e6c3e6099fc551a1dcf59cbe04d9 [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"
Ian Rogers98573f92013-01-30 17:26:32 -080022#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070023#include "dex_file-inl.h"
Logan Chien86f50672012-04-24 13:08:45 +080024#include "dex_instruction.h"
Ian Rogers98573f92013-01-30 17:26:32 -080025#include "mirror/abstract_method-inl.h"
26#include "mirror/class-inl.h"
Ian Rogers39ebcb82013-05-30 16:57:23 -070027#include "mirror/dex_cache-inl.h"
Ian Rogers98573f92013-01-30 17:26:32 -080028#include "mirror/field-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029#include "mirror/object.h"
Ian Rogers98573f92013-01-30 17:26:32 -080030#include "mirror/object-inl.h"
31#include "mirror/object_array-inl.h"
TDYa1273f9137d2012-04-08 15:59:19 -070032#include "nth_caller_visitor.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080033#include "object_utils.h"
TDYa1275bb86012012-04-11 05:57:28 -070034#include "reflection.h"
Shih-wei Liaob1ab7df2012-03-29 13:53:46 -070035#include "runtime_support.h"
Brian Carlstrom51c24672013-07-11 16:00:56 -070036#include "runtime_support_llvm_func_list.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070037#include "scoped_thread_state_change.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080038#include "thread.h"
Shih-wei Liao66adbb72012-03-07 01:31:50 -080039#include "thread_list.h"
Jeff Hao11ffc2d2013-02-01 11:52:17 -080040#include "verifier/dex_gc_map.h"
Ian Rogers776ac1f2012-04-13 23:36:36 -070041#include "verifier/method_verifier.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070042#include "well_known_classes.h"
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080043
Logan Chiend23c5ad2012-03-30 17:46:04 +080044#include <algorithm>
Logan Chien2d3bcbb2012-07-06 09:37:26 +080045#include <math.h>
46#include <stdarg.h>
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080047#include <stdint.h>
Logan Chien2d3bcbb2012-07-06 09:37:26 +080048#include <stdlib.h>
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080049
Logan Chien8dbb7082013-01-25 20:31:17 +080050using namespace art;
51
52extern "C" {
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -080053
Jeff Hao11ffc2d2013-02-01 11:52:17 -080054class ShadowFrameCopyVisitor : public StackVisitor {
55 public:
56 explicit ShadowFrameCopyVisitor(Thread* self) : StackVisitor(self, NULL), prev_frame_(NULL),
57 top_frame_(NULL) {}
58
59 bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
60 if (IsShadowFrame()) {
61 ShadowFrame* cur_frame = GetCurrentShadowFrame();
62 size_t num_regs = cur_frame->NumberOfVRegs();
63 mirror::AbstractMethod* method = cur_frame->GetMethod();
64 uint32_t dex_pc = cur_frame->GetDexPC();
65 ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, method, dex_pc);
66
67 const uint8_t* gc_map = method->GetNativeGcMap();
68 uint32_t gc_map_length = static_cast<uint32_t>((gc_map[0] << 24) |
69 (gc_map[1] << 16) |
70 (gc_map[2] << 8) |
71 (gc_map[3] << 0));
72 verifier::DexPcToReferenceMap dex_gc_map(gc_map + 4, gc_map_length);
73 const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
74 for (size_t reg = 0; reg < num_regs; ++reg) {
75 if (TestBitmap(reg, reg_bitmap)) {
76 new_frame->SetVRegReference(reg, cur_frame->GetVRegReference(reg));
77 } else {
78 new_frame->SetVReg(reg, cur_frame->GetVReg(reg));
79 }
80 }
81
82 if (prev_frame_ != NULL) {
83 prev_frame_->SetLink(new_frame);
84 } else {
85 top_frame_ = new_frame;
86 }
87 prev_frame_ = new_frame;
88 }
89 return true;
90 }
91
92 ShadowFrame* GetShadowFrameCopy() {
93 return top_frame_;
94 }
95
96 private:
97 static bool TestBitmap(int reg, const uint8_t* reg_vector) {
98 return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
99 }
100
101 ShadowFrame* prev_frame_;
102 ShadowFrame* top_frame_;
103};
104
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800105//----------------------------------------------------------------------------
106// Thread
107//----------------------------------------------------------------------------
108
Logan Chien8dbb7082013-01-25 20:31:17 +0800109Thread* art_portable_get_current_thread_from_code() {
Ian Rogers948c5082013-01-23 14:25:30 -0800110#if defined(__arm__) || defined(__i386__)
111 LOG(FATAL) << "UNREACHABLE";
TDYa127d668a062012-04-13 12:36:57 -0700112#endif
Ian Rogers948c5082013-01-23 14:25:30 -0800113 return Thread::Current();
Logan Chienfc5bc672012-03-06 16:54:30 +0800114}
115
Logan Chien8dbb7082013-01-25 20:31:17 +0800116void* art_portable_set_current_thread_from_code(void* thread_object_addr) {
Ian Rogers948c5082013-01-23 14:25:30 -0800117 // Hijacked to set r9 on ARM.
118 LOG(FATAL) << "UNREACHABLE";
TDYa127c1478262012-06-20 20:22:27 -0700119 return NULL;
Logan Chienfc5bc672012-03-06 16:54:30 +0800120}
121
Logan Chien8dbb7082013-01-25 20:31:17 +0800122void art_portable_lock_object_from_code(mirror::Object* obj, Thread* thread)
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700123 EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -0800124 DCHECK(obj != NULL); // Assumed to have been checked before entry
125 obj->MonitorEnter(thread); // May block
126 DCHECK(thread->HoldsLock(obj));
127 // Only possible exception is NPE and is handled before entry
128 DCHECK(!thread->IsExceptionPending());
Logan Chienfc5bc672012-03-06 16:54:30 +0800129}
130
Logan Chien8dbb7082013-01-25 20:31:17 +0800131void art_portable_unlock_object_from_code(mirror::Object* obj, Thread* thread)
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700132 UNLOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -0800133 DCHECK(obj != NULL); // Assumed to have been checked before entry
134 // MonitorExit may throw exception
135 obj->MonitorExit(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800136}
137
Ian Rogers62d6c772013-02-27 08:32:07 -0800138void art_portable_test_suspend_from_code(Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700139 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800140 CheckSuspend(self);
141 if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) {
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800142 // Save out the shadow frame to the heap
Ian Rogers62d6c772013-02-27 08:32:07 -0800143 ShadowFrameCopyVisitor visitor(self);
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800144 visitor.WalkStack(true);
Ian Rogers62d6c772013-02-27 08:32:07 -0800145 self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy());
146 self->SetDeoptimizationReturnValue(JValue());
147 self->SetException(ThrowLocation(), reinterpret_cast<mirror::Throwable*>(-1));
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800148 }
Logan Chienfc5bc672012-03-06 16:54:30 +0800149}
150
Logan Chien8dbb7082013-01-25 20:31:17 +0800151ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread,
152 ShadowFrame* new_shadow_frame,
153 mirror::AbstractMethod* method,
154 uint32_t num_vregs) {
TDYa127de479be2012-05-31 08:03:26 -0700155 ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
156 new_shadow_frame->SetMethod(method);
Ian Rogers5438ad82012-10-15 17:22:44 -0700157 new_shadow_frame->SetNumberOfVRegs(num_vregs);
TDYa127de479be2012-05-31 08:03:26 -0700158 return old_frame;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800159}
160
Logan Chien8dbb7082013-01-25 20:31:17 +0800161void art_portable_pop_shadow_frame_from_code(void*) {
TDYa12783bb6622012-04-17 02:20:34 -0700162 LOG(FATAL) << "Implemented by IRBuilder.";
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800163}
164
Logan Chien8dbb7082013-01-25 20:31:17 +0800165void art_portable_mark_gc_card_from_code(void *, void*) {
TDYa12783bb6622012-04-17 02:20:34 -0700166 LOG(FATAL) << "Implemented by IRBuilder.";
167}
Logan Chienfc5bc672012-03-06 16:54:30 +0800168
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800169//----------------------------------------------------------------------------
170// Exception
171//----------------------------------------------------------------------------
172
Logan Chien8dbb7082013-01-25 20:31:17 +0800173bool art_portable_is_exception_pending_from_code() {
TDYa12783bb6622012-04-17 02:20:34 -0700174 LOG(FATAL) << "Implemented by IRBuilder.";
175 return false;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800176}
177
Logan Chien8dbb7082013-01-25 20:31:17 +0800178void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200179 ThrowArithmeticExceptionDivideByZero();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800180}
181
Logan Chien8dbb7082013-01-25 20:31:17 +0800182void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700183 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800184 ThrowArrayIndexOutOfBoundsException(index, length);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800185}
186
Logan Chien8dbb7082013-01-25 20:31:17 +0800187void art_portable_throw_no_such_method_from_code(int32_t method_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700188 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800189 ThrowNoSuchMethodError(method_idx);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800190}
191
Logan Chien8dbb7082013-01-25 20:31:17 +0800192void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700193 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800194 // TODO: remove dex_pc argument from caller.
195 UNUSED(dex_pc);
196 Thread* self = Thread::Current();
197 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
198 ThrowNullPointerExceptionFromDexPC(throw_location);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800199}
200
Logan Chien8dbb7082013-01-25 20:31:17 +0800201void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers948c5082013-01-23 14:25:30 -0800202 ThrowStackOverflowError(Thread::Current());
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800203}
204
Ian Rogers62d6c772013-02-27 08:32:07 -0800205void art_portable_throw_exception_from_code(mirror::Throwable* exception)
206 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
207 Thread* self = Thread::Current();
208 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
209 if (exception == NULL) {
210 ThrowNullPointerException(NULL, "throw with null exception");
211 } else {
212 self->SetException(throw_location, exception);
213 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800214}
215
Logan Chien8dbb7082013-01-25 20:31:17 +0800216void* art_portable_get_and_clear_exception(Thread* self)
TDYa127823433d2012-09-26 16:03:51 -0700217 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
218 DCHECK(self->IsExceptionPending());
Ian Rogers62d6c772013-02-27 08:32:07 -0800219 // TODO: make this inline.
220 mirror::Throwable* exception = self->GetException(NULL);
TDYa127823433d2012-09-26 16:03:51 -0700221 self->ClearException();
222 return exception;
223}
224
Logan Chien8dbb7082013-01-25 20:31:17 +0800225int32_t art_portable_find_catch_block_from_code(mirror::AbstractMethod* current_method, uint32_t ti_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700226 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800227 Thread* self = Thread::Current(); // TODO: make an argument.
228 ThrowLocation throw_location;
229 mirror::Throwable* exception = self->GetException(&throw_location);
230 // Check for special deoptimization exception.
231 if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800232 return -1;
233 }
234 mirror::Class* exception_type = exception->GetClass();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800235 MethodHelper mh(current_method);
236 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Logan Chien736df022012-04-27 16:25:57 +0800237 DCHECK_LT(ti_offset, code_item->tries_size_);
238 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
239
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800240 int iter_index = 0;
Ian Rogers62d6c772013-02-27 08:32:07 -0800241 int result = -1;
242 uint32_t catch_dex_pc = -1;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800243 // Iterate over the catch handlers associated with dex_pc
Logan Chien736df022012-04-27 16:25:57 +0800244 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800245 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
246 // Catch all case
247 if (iter_type_idx == DexFile::kDexNoIndex16) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800248 catch_dex_pc = it.GetHandlerAddress();
249 result = iter_index;
250 break;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800251 }
252 // Does this catch exception type apply?
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800253 mirror::Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
Ian Rogers62d6c772013-02-27 08:32:07 -0800254 if (UNLIKELY(iter_exception_type == NULL)) {
255 // TODO: check, the verifier (class linker?) should take care of resolving all exception
256 // classes early.
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800257 LOG(WARNING) << "Unresolved exception class when finding catch block: "
258 << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
259 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800260 catch_dex_pc = it.GetHandlerAddress();
261 result = iter_index;
262 break;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800263 }
264 ++iter_index;
265 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800266 if (result != -1) {
267 // Handler found.
268 Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self,
269 throw_location,
270 current_method,
271 catch_dex_pc,
272 exception);
273 }
274 return result;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800275}
276
Logan Chienfc5bc672012-03-06 16:54:30 +0800277
278//----------------------------------------------------------------------------
279// Object Space
280//----------------------------------------------------------------------------
281
Logan Chien8dbb7082013-01-25 20:31:17 +0800282mirror::Object* art_portable_alloc_object_from_code(uint32_t type_idx,
283 mirror::AbstractMethod* referrer,
284 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700285 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700286 return AllocObjectFromCode(type_idx, referrer, thread, false);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800287}
288
Logan Chien8dbb7082013-01-25 20:31:17 +0800289mirror::Object* art_portable_alloc_object_from_code_with_access_check(uint32_t type_idx,
290 mirror::AbstractMethod* referrer,
291 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700292 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700293 return AllocObjectFromCode(type_idx, referrer, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800294}
295
Logan Chien8dbb7082013-01-25 20:31:17 +0800296mirror::Object* art_portable_alloc_array_from_code(uint32_t type_idx,
297 mirror::AbstractMethod* referrer,
298 uint32_t length,
299 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700300 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700301 return AllocArrayFromCode(type_idx, referrer, length, self, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800302}
303
Logan Chien8dbb7082013-01-25 20:31:17 +0800304mirror::Object* art_portable_alloc_array_from_code_with_access_check(uint32_t type_idx,
305 mirror::AbstractMethod* referrer,
306 uint32_t length,
307 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700308 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700309 return AllocArrayFromCode(type_idx, referrer, length, self, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800310}
311
Logan Chien8dbb7082013-01-25 20:31:17 +0800312mirror::Object* art_portable_check_and_alloc_array_from_code(uint32_t type_idx,
313 mirror::AbstractMethod* referrer,
314 uint32_t length,
315 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700316 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700317 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800318}
319
Logan Chien8dbb7082013-01-25 20:31:17 +0800320mirror::Object* art_portable_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
321 mirror::AbstractMethod* referrer,
322 uint32_t length,
323 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700324 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700325 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800326}
327
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800328static mirror::AbstractMethod* FindMethodHelper(uint32_t method_idx, mirror::Object* this_object,
329 mirror::AbstractMethod* caller_method, bool access_check,
Ian Rogers952a94a2012-09-21 22:42:29 -0700330 InvokeType type, Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700331 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800332 mirror::AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800333 if (UNLIKELY(method == NULL)) {
334 method = FindMethodFromCode(method_idx, this_object, caller_method,
TDYa127da83d972012-04-18 00:21:49 -0700335 thread, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800336 if (UNLIKELY(method == NULL)) {
TDYa127da83d972012-04-18 00:21:49 -0700337 CHECK(thread->IsExceptionPending());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800338 return 0; // failure
339 }
340 }
TDYa127da83d972012-04-18 00:21:49 -0700341 DCHECK(!thread->IsExceptionPending());
Jeff Haoaa4a7932013-05-13 11:28:27 -0700342 const void* code = method->GetEntryPointFromCompiledCode();
TDYa1273d71d802012-08-15 03:47:03 -0700343
344 // When we return, the caller will branch to this address, so it had better not be 0!
345 if (UNLIKELY(code == NULL)) {
346 MethodHelper mh(method);
347 LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
348 << " location: " << mh.GetDexFile().GetLocation();
349 }
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800350 return method;
351}
352
Logan Chien8dbb7082013-01-25 20:31:17 +0800353mirror::Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx,
354 mirror::Object* this_object,
355 mirror::AbstractMethod* referrer,
356 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700357 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700358 return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800359}
360
Logan Chien8dbb7082013-01-25 20:31:17 +0800361mirror::Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx,
362 mirror::Object* this_object,
363 mirror::AbstractMethod* referrer,
364 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700365 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700366 return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800367}
368
Logan Chien8dbb7082013-01-25 20:31:17 +0800369mirror::Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
370 mirror::Object* this_object,
371 mirror::AbstractMethod* referrer,
372 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700373 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700374 return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800375}
376
Logan Chien8dbb7082013-01-25 20:31:17 +0800377mirror::Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx,
378 mirror::Object* this_object,
379 mirror::AbstractMethod* referrer,
380 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700381 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700382 return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800383}
384
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800385mirror::Object*
Logan Chien8dbb7082013-01-25 20:31:17 +0800386art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx,
387 mirror::Object* this_object,
388 mirror::AbstractMethod* referrer,
389 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700390 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700391 return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800392}
393
Logan Chien8dbb7082013-01-25 20:31:17 +0800394mirror::Object* art_portable_find_interface_method_from_code(uint32_t method_idx,
395 mirror::Object* this_object,
396 mirror::AbstractMethod* referrer,
397 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700398 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700399 return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800400}
401
Logan Chien8dbb7082013-01-25 20:31:17 +0800402mirror::Object* art_portable_initialize_static_storage_from_code(uint32_t type_idx,
403 mirror::AbstractMethod* referrer,
404 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700405 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700406 return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800407}
408
Logan Chien8dbb7082013-01-25 20:31:17 +0800409mirror::Object* art_portable_initialize_type_from_code(uint32_t type_idx,
410 mirror::AbstractMethod* referrer,
411 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700412 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700413 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800414}
415
Logan Chien8dbb7082013-01-25 20:31:17 +0800416mirror::Object* art_portable_initialize_type_and_verify_access_from_code(uint32_t type_idx,
417 mirror::AbstractMethod* referrer,
418 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700419 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800420 // Called when caller isn't guaranteed to have access to a type and the dex cache may be
421 // unpopulated
TDYa127706e9b62012-04-19 12:24:26 -0700422 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800423}
424
Logan Chien8dbb7082013-01-25 20:31:17 +0800425mirror::Object* art_portable_resolve_string_from_code(mirror::AbstractMethod* referrer, uint32_t string_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700426 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800427 return ResolveStringFromCode(referrer, string_idx);
Logan Chienfc5bc672012-03-06 16:54:30 +0800428}
429
Logan Chien8dbb7082013-01-25 20:31:17 +0800430int32_t art_portable_set32_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, int32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700431 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800432 mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800433 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700434 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800435 return 0;
436 }
Ian Rogers948c5082013-01-23 14:25:30 -0800437 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200438 StaticPrimitiveWrite, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800439 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700440 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800441 return 0;
442 }
443 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800444}
445
Logan Chien8dbb7082013-01-25 20:31:17 +0800446int32_t art_portable_set64_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700447 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800448 mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800449 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700450 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800451 return 0;
452 }
Ian Rogers948c5082013-01-23 14:25:30 -0800453 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200454 StaticPrimitiveWrite, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800455 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700456 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800457 return 0;
458 }
459 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800460}
461
Logan Chien8dbb7082013-01-25 20:31:17 +0800462int32_t art_portable_set_obj_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700463 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800464 mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(mirror::Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800465 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700466 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800467 return 0;
468 }
Ian Rogers948c5082013-01-23 14:25:30 -0800469 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200470 StaticObjectWrite, sizeof(mirror::Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800471 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700472 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800473 return 0;
474 }
475 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800476}
477
Logan Chien8dbb7082013-01-25 20:31:17 +0800478int32_t art_portable_get32_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700479 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800480 mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800481 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700482 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800483 }
Ian Rogers948c5082013-01-23 14:25:30 -0800484 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200485 StaticPrimitiveRead, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800486 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700487 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800488 }
489 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800490}
491
Logan Chien8dbb7082013-01-25 20:31:17 +0800492int64_t art_portable_get64_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700493 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800494 mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800495 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700496 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800497 }
Ian Rogers948c5082013-01-23 14:25:30 -0800498 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200499 StaticPrimitiveRead, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800500 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700501 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800502 }
503 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800504}
505
Logan Chien8dbb7082013-01-25 20:31:17 +0800506mirror::Object* art_portable_get_obj_static_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700507 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800508 mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(mirror::Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800509 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700510 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800511 }
Ian Rogers948c5082013-01-23 14:25:30 -0800512 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200513 StaticObjectRead, sizeof(mirror::Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800514 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700515 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800516 }
517 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800518}
519
Logan Chien8dbb7082013-01-25 20:31:17 +0800520int32_t art_portable_set32_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800521 mirror::Object* obj, uint32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700522 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800523 mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800524 if (LIKELY(field != NULL)) {
525 field->Set32(obj, new_value);
526 return 0;
527 }
Ian Rogers948c5082013-01-23 14:25:30 -0800528 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200529 InstancePrimitiveWrite, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800530 if (LIKELY(field != NULL)) {
531 field->Set32(obj, new_value);
532 return 0;
533 }
534 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800535}
536
Logan Chien8dbb7082013-01-25 20:31:17 +0800537int32_t art_portable_set64_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer,
538 mirror::Object* obj, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700539 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800540 mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800541 if (LIKELY(field != NULL)) {
542 field->Set64(obj, new_value);
543 return 0;
544 }
Ian Rogers948c5082013-01-23 14:25:30 -0800545 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200546 InstancePrimitiveWrite, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800547 if (LIKELY(field != NULL)) {
548 field->Set64(obj, new_value);
549 return 0;
550 }
551 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800552}
553
Logan Chien8dbb7082013-01-25 20:31:17 +0800554int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer,
555 mirror::Object* obj, mirror::Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700556 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800557 mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(mirror::Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800558 if (LIKELY(field != NULL)) {
559 field->SetObj(obj, new_value);
560 return 0;
561 }
Ian Rogers948c5082013-01-23 14:25:30 -0800562 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200563 InstanceObjectWrite, sizeof(mirror::Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800564 if (LIKELY(field != NULL)) {
565 field->SetObj(obj, new_value);
566 return 0;
567 }
568 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800569}
570
Logan Chien8dbb7082013-01-25 20:31:17 +0800571int32_t art_portable_get32_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700572 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800573 mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800574 if (LIKELY(field != NULL)) {
575 return field->Get32(obj);
576 }
Ian Rogers948c5082013-01-23 14:25:30 -0800577 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200578 InstancePrimitiveRead, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800579 if (LIKELY(field != NULL)) {
580 return field->Get32(obj);
581 }
582 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800583}
584
Logan Chien8dbb7082013-01-25 20:31:17 +0800585int64_t art_portable_get64_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700586 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800587 mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800588 if (LIKELY(field != NULL)) {
589 return field->Get64(obj);
590 }
Ian Rogers948c5082013-01-23 14:25:30 -0800591 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200592 InstancePrimitiveRead, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800593 if (LIKELY(field != NULL)) {
594 return field->Get64(obj);
595 }
596 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800597}
598
Logan Chien8dbb7082013-01-25 20:31:17 +0800599mirror::Object* art_portable_get_obj_instance_from_code(uint32_t field_idx, mirror::AbstractMethod* referrer, mirror::Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700600 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800601 mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(mirror::Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800602 if (LIKELY(field != NULL)) {
603 return field->GetObj(obj);
604 }
Ian Rogers948c5082013-01-23 14:25:30 -0800605 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200606 InstanceObjectRead, sizeof(mirror::Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800607 if (LIKELY(field != NULL)) {
608 return field->GetObj(obj);
609 }
610 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800611}
612
Logan Chien8dbb7082013-01-25 20:31:17 +0800613void art_portable_fill_array_data_from_code(mirror::AbstractMethod* method, uint32_t dex_pc,
614 mirror::Array* array, uint32_t payload_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700615 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Logan Chien86f50672012-04-24 13:08:45 +0800616 // Test: Is array equal to null? (Guard NullPointerException)
617 if (UNLIKELY(array == NULL)) {
Logan Chien8dbb7082013-01-25 20:31:17 +0800618 art_portable_throw_null_pointer_exception_from_code(dex_pc);
Logan Chien86f50672012-04-24 13:08:45 +0800619 return;
620 }
621
622 // Find the payload from the CodeItem
623 MethodHelper mh(method);
624 const DexFile::CodeItem* code_item = mh.GetCodeItem();
625
626 DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
627
628 const Instruction::ArrayDataPayload* payload =
629 reinterpret_cast<const Instruction::ArrayDataPayload*>(
630 code_item->insns_ + payload_offset);
631
632 DCHECK_EQ(payload->ident,
633 static_cast<uint16_t>(Instruction::kArrayDataSignature));
634
635 // Test: Is array big enough?
636 uint32_t array_len = static_cast<uint32_t>(array->GetLength());
637 if (UNLIKELY(array_len < payload->element_count)) {
638 int32_t last_index = payload->element_count - 1;
Logan Chien8dbb7082013-01-25 20:31:17 +0800639 art_portable_throw_array_bounds_from_code(array_len, last_index);
Logan Chien86f50672012-04-24 13:08:45 +0800640 return;
641 }
642
643 // Copy the data
644 size_t size = payload->element_width * payload->element_count;
645 memcpy(array->GetRawData(payload->element_width), payload->data, size);
646}
647
648
649
Logan Chienfc5bc672012-03-06 16:54:30 +0800650//----------------------------------------------------------------------------
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700651// Type checking, in the nature of casting
Logan Chienfc5bc672012-03-06 16:54:30 +0800652//----------------------------------------------------------------------------
653
Logan Chien8dbb7082013-01-25 20:31:17 +0800654int32_t art_portable_is_assignable_from_code(const mirror::Class* dest_type, const mirror::Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700655 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1273de5ba32012-04-02 07:04:40 -0700656 DCHECK(dest_type != NULL);
657 DCHECK(src_type != NULL);
658 return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800659}
660
Logan Chien8dbb7082013-01-25 20:31:17 +0800661void art_portable_check_cast_from_code(const mirror::Class* dest_type, const mirror::Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700662 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700663 DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700664 DCHECK(src_type->IsClass()) << PrettyClass(src_type);
665 if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800666 ThrowClassCastException(dest_type, src_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700667 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800668}
669
Ian Rogers62d6c772013-02-27 08:32:07 -0800670void art_portable_check_put_array_element_from_code(const mirror::Object* element,
671 const mirror::Object* array)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700672 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700673 if (element == NULL) {
674 return;
675 }
676 DCHECK(array != NULL);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800677 mirror::Class* array_class = array->GetClass();
TDYa1271b86d072012-04-05 17:38:56 -0700678 DCHECK(array_class != NULL);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800679 mirror::Class* component_type = array_class->GetComponentType();
680 mirror::Class* element_class = element->GetClass();
TDYa1271b86d072012-04-05 17:38:56 -0700681 if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800682 ThrowArrayStoreException(element_class, array_class);
TDYa1271b86d072012-04-05 17:38:56 -0700683 }
684 return;
685}
686
Logan Chien2771fb12012-03-06 16:28:35 +0800687//----------------------------------------------------------------------------
TDYa1273d71d802012-08-15 03:47:03 -0700688// JNI
689//----------------------------------------------------------------------------
690
691// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
Logan Chien8dbb7082013-01-25 20:31:17 +0800692uint32_t art_portable_jni_method_start(Thread* self)
TDYa1273d71d802012-08-15 03:47:03 -0700693 UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
694 JNIEnvExt* env = self->GetJniEnv();
695 uint32_t saved_local_ref_cookie = env->local_ref_cookie;
696 env->local_ref_cookie = env->locals.GetSegmentState();
697 self->TransitionFromRunnableToSuspended(kNative);
698 return saved_local_ref_cookie;
699}
700
Logan Chien8dbb7082013-01-25 20:31:17 +0800701uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700702 UNLOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700703 self->DecodeJObject(to_lock)->MonitorEnter(self);
Logan Chien8dbb7082013-01-25 20:31:17 +0800704 return art_portable_jni_method_start(self);
TDYa1273d71d802012-08-15 03:47:03 -0700705}
706
707static inline void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
708 JNIEnvExt* env = self->GetJniEnv();
709 env->locals.SetSegmentState(env->local_ref_cookie);
710 env->local_ref_cookie = saved_local_ref_cookie;
711}
712
Logan Chien8dbb7082013-01-25 20:31:17 +0800713void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700714 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700715 self->TransitionFromSuspendedToRunnable();
716 PopLocalReferences(saved_local_ref_cookie, self);
717}
718
719
Logan Chien8dbb7082013-01-25 20:31:17 +0800720void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie,
721 jobject locked,
722 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700723 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700724 self->TransitionFromSuspendedToRunnable();
725 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
726 PopLocalReferences(saved_local_ref_cookie, self);
727}
728
Logan Chien8dbb7082013-01-25 20:31:17 +0800729mirror::Object* art_portable_jni_method_end_with_reference(jobject result, uint32_t saved_local_ref_cookie,
730 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700731 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700732 self->TransitionFromSuspendedToRunnable();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800733 mirror::Object* o = self->DecodeJObject(result); // Must decode before pop.
TDYa1273d71d802012-08-15 03:47:03 -0700734 PopLocalReferences(saved_local_ref_cookie, self);
735 // Process result.
736 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
737 if (self->IsExceptionPending()) {
738 return NULL;
739 }
740 CheckReferenceResult(o, self);
741 }
742 return o;
743}
744
Logan Chien8dbb7082013-01-25 20:31:17 +0800745mirror::Object* art_portable_jni_method_end_with_reference_synchronized(jobject result,
746 uint32_t saved_local_ref_cookie,
747 jobject locked, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700748 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700749 self->TransitionFromSuspendedToRunnable();
750 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800751 mirror::Object* o = self->DecodeJObject(result);
TDYa1273d71d802012-08-15 03:47:03 -0700752 PopLocalReferences(saved_local_ref_cookie, self);
753 // Process result.
754 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
755 if (self->IsExceptionPending()) {
756 return NULL;
757 }
758 CheckReferenceResult(o, self);
759 }
760 return o;
761}
762
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800763// Handler for invocation on proxy methods. Create a boxed argument array and invoke the invocation
764// handler which is a field within the proxy object receiver. The var args encode the arguments
765// with the last argument being a pointer to a JValue to store the result in.
Logan Chien8dbb7082013-01-25 20:31:17 +0800766void art_portable_proxy_invoke_handler_from_code(mirror::AbstractMethod* proxy_method, ...)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700767 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1275bb86012012-04-11 05:57:28 -0700768 va_list ap;
769 va_start(ap, proxy_method);
770
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800771 mirror::Object* receiver = va_arg(ap, mirror::Object*);
Ian Rogers50b35e22012-10-04 10:09:15 -0700772 Thread* self = va_arg(ap, Thread*);
TDYa1275bb86012012-04-11 05:57:28 -0700773 MethodHelper proxy_mh(proxy_method);
TDYa1275bb86012012-04-11 05:57:28 -0700774
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800775 // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
776 const char* old_cause =
777 self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
778 self->VerifyStack();
779
780 // Start new JNI local reference state.
Ian Rogers50b35e22012-10-04 10:09:15 -0700781 JNIEnvExt* env = self->GetJniEnv();
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700782 ScopedObjectAccessUnchecked soa(env);
TDYa1275bb86012012-04-11 05:57:28 -0700783 ScopedJniEnvLocalRefState env_state(env);
784
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800785 // Create local ref. copies of the receiver.
Ian Rogersc5e3d762012-08-14 16:33:47 -0700786 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
TDYa1275bb86012012-04-11 05:57:28 -0700787
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800788 // Convert proxy method into expected interface method.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800789 mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
TDYa1275bb86012012-04-11 05:57:28 -0700790 DCHECK(interface_method != NULL);
791 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800792 jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
TDYa1275bb86012012-04-11 05:57:28 -0700793
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800794 // Record arguments and turn mirror::Object* arguments into jobject to survive GC.
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800795 std::vector<jvalue> args;
796 const size_t num_params = proxy_mh.NumArgs();
797 for (size_t i = 1; i < num_params; ++i) {
798 jvalue val;
799 switch (proxy_mh.GetParamPrimitiveType(i)) {
800 case Primitive::kPrimNot:
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800801 val.l = soa.AddLocalReference<jobject>(va_arg(ap, mirror::Object*));
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700802 break;
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800803 case Primitive::kPrimBoolean: // Fall-through.
804 case Primitive::kPrimByte: // Fall-through.
805 case Primitive::kPrimChar: // Fall-through.
806 case Primitive::kPrimShort: // Fall-through.
807 case Primitive::kPrimInt: // Fall-through.
808 val.i = va_arg(ap, jint);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700809 break;
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800810 case Primitive::kPrimFloat:
Ian Rogersf10f9de2013-01-16 16:47:54 -0800811 // TODO: should this be jdouble? Floats aren't passed to var arg routines.
Ian Rogers87b185f2013-01-23 09:16:53 -0800812 val.i = va_arg(ap, jint);
TDYa1275bb86012012-04-11 05:57:28 -0700813 break;
Ian Rogersf10f9de2013-01-16 16:47:54 -0800814 case Primitive::kPrimDouble:
815 val.d = (va_arg(ap, jdouble));
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800816 break;
Ian Rogersf10f9de2013-01-16 16:47:54 -0800817 case Primitive::kPrimLong:
818 val.j = (va_arg(ap, jlong));
819 break;
820 case Primitive::kPrimVoid:
821 LOG(FATAL) << "UNREACHABLE";
822 val.j = 0;
TDYa1275bb86012012-04-11 05:57:28 -0700823 break;
824 }
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800825 args.push_back(val);
TDYa1275bb86012012-04-11 05:57:28 -0700826 }
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800827 self->EndAssertNoThreadSuspension(old_cause);
Ian Rogers87b185f2013-01-23 09:16:53 -0800828 JValue* result_location = NULL;
829 const char* shorty = proxy_mh.GetShorty();
830 if (shorty[0] != 'V') {
831 result_location = va_arg(ap, JValue*);
832 }
TDYa1275bb86012012-04-11 05:57:28 -0700833 va_end(ap);
Ian Rogers87b185f2013-01-23 09:16:53 -0800834 JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args);
835 if (result_location != NULL) {
836 *result_location = result;
837 }
TDYa1275bb86012012-04-11 05:57:28 -0700838}
839
Sebastien Hertz0d43d542013-02-27 19:02:16 +0100840//----------------------------------------------------------------------------
841// Memory barrier
842//----------------------------------------------------------------------------
843
844void art_portable_constructor_barrier() {
845 LOG(FATAL) << "Implemented by IRBuilder.";
846}
847
Logan Chien8dbb7082013-01-25 20:31:17 +0800848} // extern "C"