blob: 7b4c3ca9c33ae47f5dfb4568508c879206333eee [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
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070050namespace art {
Logan Chien8dbb7082013-01-25 20:31:17 +080051
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070052using ::art::mirror::AbstractMethod;
53
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();
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070063 AbstractMethod* method = cur_frame->GetMethod();
Jeff Hao11ffc2d2013-02-01 11:52:17 -080064 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
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700105} // namespace art
106
107extern "C" {
108
109using ::art::CatchHandlerIterator;
110using ::art::DexFile;
111using ::art::FindFieldFast;
112using ::art::FindMethodFast;
113using ::art::InstanceObjectRead;
114using ::art::InstanceObjectWrite;
115using ::art::InstancePrimitiveRead;
116using ::art::InstancePrimitiveWrite;
117using ::art::Instruction;
118using ::art::InvokeType;
119using ::art::JNIEnvExt;
120using ::art::JValue;
121using ::art::Locks;
122using ::art::MethodHelper;
123using ::art::PrettyClass;
124using ::art::PrettyMethod;
125using ::art::Primitive;
126using ::art::ResolveStringFromCode;
127using ::art::Runtime;
128using ::art::ScopedJniEnvLocalRefState;
129using ::art::ScopedObjectAccessUnchecked;
130using ::art::ShadowFrame;
131using ::art::ShadowFrameCopyVisitor;
132using ::art::StaticObjectRead;
133using ::art::StaticObjectWrite;
134using ::art::StaticPrimitiveRead;
135using ::art::StaticPrimitiveWrite;
136using ::art::Thread;
137using ::art::Thread;
138using ::art::ThrowArithmeticExceptionDivideByZero;
139using ::art::ThrowArrayIndexOutOfBoundsException;
140using ::art::ThrowArrayStoreException;
141using ::art::ThrowClassCastException;
142using ::art::ThrowLocation;
143using ::art::ThrowNoSuchMethodError;
144using ::art::ThrowNullPointerException;
145using ::art::ThrowNullPointerExceptionFromDexPC;
146using ::art::ThrowStackOverflowError;
147using ::art::kDirect;
148using ::art::kInterface;
149using ::art::kNative;
150using ::art::kStatic;
151using ::art::kSuper;
152using ::art::kVirtual;
153using ::art::mirror::AbstractMethod;
154using ::art::mirror::Array;
155using ::art::mirror::Class;
156using ::art::mirror::Field;
157using ::art::mirror::Object;
158using ::art::mirror::Throwable;
159
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800160//----------------------------------------------------------------------------
161// Thread
162//----------------------------------------------------------------------------
163
Logan Chien8dbb7082013-01-25 20:31:17 +0800164Thread* art_portable_get_current_thread_from_code() {
Ian Rogers948c5082013-01-23 14:25:30 -0800165#if defined(__arm__) || defined(__i386__)
166 LOG(FATAL) << "UNREACHABLE";
TDYa127d668a062012-04-13 12:36:57 -0700167#endif
Ian Rogers948c5082013-01-23 14:25:30 -0800168 return Thread::Current();
Logan Chienfc5bc672012-03-06 16:54:30 +0800169}
170
Logan Chien8dbb7082013-01-25 20:31:17 +0800171void* art_portable_set_current_thread_from_code(void* thread_object_addr) {
Ian Rogers948c5082013-01-23 14:25:30 -0800172 // Hijacked to set r9 on ARM.
173 LOG(FATAL) << "UNREACHABLE";
TDYa127c1478262012-06-20 20:22:27 -0700174 return NULL;
Logan Chienfc5bc672012-03-06 16:54:30 +0800175}
176
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700177void art_portable_lock_object_from_code(Object* obj, Thread* thread)
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700178 EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -0800179 DCHECK(obj != NULL); // Assumed to have been checked before entry
180 obj->MonitorEnter(thread); // May block
181 DCHECK(thread->HoldsLock(obj));
182 // Only possible exception is NPE and is handled before entry
183 DCHECK(!thread->IsExceptionPending());
Logan Chienfc5bc672012-03-06 16:54:30 +0800184}
185
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700186void art_portable_unlock_object_from_code(Object* obj, Thread* thread)
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700187 UNLOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -0800188 DCHECK(obj != NULL); // Assumed to have been checked before entry
189 // MonitorExit may throw exception
190 obj->MonitorExit(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800191}
192
Ian Rogers62d6c772013-02-27 08:32:07 -0800193void art_portable_test_suspend_from_code(Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700194 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800195 CheckSuspend(self);
196 if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) {
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800197 // Save out the shadow frame to the heap
Ian Rogers62d6c772013-02-27 08:32:07 -0800198 ShadowFrameCopyVisitor visitor(self);
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800199 visitor.WalkStack(true);
Ian Rogers62d6c772013-02-27 08:32:07 -0800200 self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy());
201 self->SetDeoptimizationReturnValue(JValue());
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700202 self->SetException(ThrowLocation(), reinterpret_cast<Throwable*>(-1));
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800203 }
Logan Chienfc5bc672012-03-06 16:54:30 +0800204}
205
Logan Chien8dbb7082013-01-25 20:31:17 +0800206ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread,
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700207 ShadowFrame* new_shadow_frame,
208 AbstractMethod* method,
209 uint32_t num_vregs) {
TDYa127de479be2012-05-31 08:03:26 -0700210 ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
211 new_shadow_frame->SetMethod(method);
Ian Rogers5438ad82012-10-15 17:22:44 -0700212 new_shadow_frame->SetNumberOfVRegs(num_vregs);
TDYa127de479be2012-05-31 08:03:26 -0700213 return old_frame;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800214}
215
Logan Chien8dbb7082013-01-25 20:31:17 +0800216void art_portable_pop_shadow_frame_from_code(void*) {
TDYa12783bb6622012-04-17 02:20:34 -0700217 LOG(FATAL) << "Implemented by IRBuilder.";
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800218}
219
Logan Chien8dbb7082013-01-25 20:31:17 +0800220void art_portable_mark_gc_card_from_code(void *, void*) {
TDYa12783bb6622012-04-17 02:20:34 -0700221 LOG(FATAL) << "Implemented by IRBuilder.";
222}
Logan Chienfc5bc672012-03-06 16:54:30 +0800223
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800224//----------------------------------------------------------------------------
225// Exception
226//----------------------------------------------------------------------------
227
Logan Chien8dbb7082013-01-25 20:31:17 +0800228bool art_portable_is_exception_pending_from_code() {
TDYa12783bb6622012-04-17 02:20:34 -0700229 LOG(FATAL) << "Implemented by IRBuilder.";
230 return false;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800231}
232
Logan Chien8dbb7082013-01-25 20:31:17 +0800233void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200234 ThrowArithmeticExceptionDivideByZero();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800235}
236
Logan Chien8dbb7082013-01-25 20:31:17 +0800237void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700238 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800239 ThrowArrayIndexOutOfBoundsException(index, length);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800240}
241
Logan Chien8dbb7082013-01-25 20:31:17 +0800242void art_portable_throw_no_such_method_from_code(int32_t method_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700243 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800244 ThrowNoSuchMethodError(method_idx);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800245}
246
Logan Chien8dbb7082013-01-25 20:31:17 +0800247void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700248 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800249 // TODO: remove dex_pc argument from caller.
250 UNUSED(dex_pc);
251 Thread* self = Thread::Current();
252 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
253 ThrowNullPointerExceptionFromDexPC(throw_location);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800254}
255
Logan Chien8dbb7082013-01-25 20:31:17 +0800256void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers948c5082013-01-23 14:25:30 -0800257 ThrowStackOverflowError(Thread::Current());
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800258}
259
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700260void art_portable_throw_exception_from_code(Throwable* exception)
Ian Rogers62d6c772013-02-27 08:32:07 -0800261 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
262 Thread* self = Thread::Current();
263 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
264 if (exception == NULL) {
265 ThrowNullPointerException(NULL, "throw with null exception");
266 } else {
267 self->SetException(throw_location, exception);
268 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800269}
270
Logan Chien8dbb7082013-01-25 20:31:17 +0800271void* art_portable_get_and_clear_exception(Thread* self)
TDYa127823433d2012-09-26 16:03:51 -0700272 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
273 DCHECK(self->IsExceptionPending());
Ian Rogers62d6c772013-02-27 08:32:07 -0800274 // TODO: make this inline.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700275 Throwable* exception = self->GetException(NULL);
TDYa127823433d2012-09-26 16:03:51 -0700276 self->ClearException();
277 return exception;
278}
279
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700280int32_t art_portable_find_catch_block_from_code(AbstractMethod* current_method,
281 uint32_t ti_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700282 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800283 Thread* self = Thread::Current(); // TODO: make an argument.
284 ThrowLocation throw_location;
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700285 Throwable* exception = self->GetException(&throw_location);
Ian Rogers62d6c772013-02-27 08:32:07 -0800286 // Check for special deoptimization exception.
287 if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800288 return -1;
289 }
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700290 Class* exception_type = exception->GetClass();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800291 MethodHelper mh(current_method);
292 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Logan Chien736df022012-04-27 16:25:57 +0800293 DCHECK_LT(ti_offset, code_item->tries_size_);
294 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
295
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800296 int iter_index = 0;
Ian Rogers62d6c772013-02-27 08:32:07 -0800297 int result = -1;
298 uint32_t catch_dex_pc = -1;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800299 // Iterate over the catch handlers associated with dex_pc
Logan Chien736df022012-04-27 16:25:57 +0800300 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800301 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
302 // Catch all case
303 if (iter_type_idx == DexFile::kDexNoIndex16) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800304 catch_dex_pc = it.GetHandlerAddress();
305 result = iter_index;
306 break;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800307 }
308 // Does this catch exception type apply?
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700309 Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
Ian Rogers62d6c772013-02-27 08:32:07 -0800310 if (UNLIKELY(iter_exception_type == NULL)) {
311 // TODO: check, the verifier (class linker?) should take care of resolving all exception
312 // classes early.
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800313 LOG(WARNING) << "Unresolved exception class when finding catch block: "
314 << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
315 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800316 catch_dex_pc = it.GetHandlerAddress();
317 result = iter_index;
318 break;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800319 }
320 ++iter_index;
321 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800322 if (result != -1) {
323 // Handler found.
324 Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self,
325 throw_location,
326 current_method,
327 catch_dex_pc,
328 exception);
329 }
330 return result;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800331}
332
Logan Chienfc5bc672012-03-06 16:54:30 +0800333
334//----------------------------------------------------------------------------
335// Object Space
336//----------------------------------------------------------------------------
337
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700338Object* art_portable_alloc_object_from_code(uint32_t type_idx, AbstractMethod* referrer, Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700339 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700340 return AllocObjectFromCode(type_idx, referrer, thread, false);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800341}
342
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700343Object* art_portable_alloc_object_from_code_with_access_check(uint32_t type_idx,
344 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800345 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700346 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700347 return AllocObjectFromCode(type_idx, referrer, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800348}
349
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700350Object* art_portable_alloc_array_from_code(uint32_t type_idx,
351 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800352 uint32_t length,
353 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700354 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700355 return AllocArrayFromCode(type_idx, referrer, length, self, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800356}
357
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700358Object* art_portable_alloc_array_from_code_with_access_check(uint32_t type_idx,
359 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800360 uint32_t length,
361 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700362 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700363 return AllocArrayFromCode(type_idx, referrer, length, self, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800364}
365
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700366Object* art_portable_check_and_alloc_array_from_code(uint32_t type_idx,
367 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800368 uint32_t length,
369 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700370 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700371 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800372}
373
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700374Object* art_portable_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
375 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800376 uint32_t length,
377 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700378 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700379 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800380}
381
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700382static AbstractMethod* FindMethodHelper(uint32_t method_idx,
383 Object* this_object,
384 AbstractMethod* caller_method,
385 bool access_check,
386 InvokeType type,
387 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700388 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700389 AbstractMethod* method = FindMethodFast(method_idx,
390 this_object,
391 caller_method,
392 access_check,
393 type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800394 if (UNLIKELY(method == NULL)) {
395 method = FindMethodFromCode(method_idx, this_object, caller_method,
TDYa127da83d972012-04-18 00:21:49 -0700396 thread, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800397 if (UNLIKELY(method == NULL)) {
TDYa127da83d972012-04-18 00:21:49 -0700398 CHECK(thread->IsExceptionPending());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800399 return 0; // failure
400 }
401 }
TDYa127da83d972012-04-18 00:21:49 -0700402 DCHECK(!thread->IsExceptionPending());
Jeff Haoaa4a7932013-05-13 11:28:27 -0700403 const void* code = method->GetEntryPointFromCompiledCode();
TDYa1273d71d802012-08-15 03:47:03 -0700404
405 // When we return, the caller will branch to this address, so it had better not be 0!
406 if (UNLIKELY(code == NULL)) {
407 MethodHelper mh(method);
408 LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
409 << " location: " << mh.GetDexFile().GetLocation();
410 }
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800411 return method;
412}
413
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700414Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx,
415 Object* this_object,
416 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800417 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700418 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700419 return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800420}
421
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700422Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx,
423 Object* this_object,
424 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800425 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700426 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700427 return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800428}
429
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700430Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
431 Object* this_object,
432 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800433 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700434 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700435 return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800436}
437
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700438Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx,
439 Object* this_object,
440 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800441 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700442 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700443 return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800444}
445
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700446Object* art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx,
447 Object* this_object,
448 AbstractMethod* referrer,
449 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700450 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700451 return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800452}
453
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700454Object* art_portable_find_interface_method_from_code(uint32_t method_idx,
455 Object* this_object,
456 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800457 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700458 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700459 return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800460}
461
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700462Object* art_portable_initialize_static_storage_from_code(uint32_t type_idx,
463 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800464 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700465 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700466 return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800467}
468
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700469Object* art_portable_initialize_type_from_code(uint32_t type_idx,
470 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800471 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700472 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700473 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800474}
475
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700476Object* art_portable_initialize_type_and_verify_access_from_code(uint32_t type_idx,
477 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800478 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700479 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800480 // Called when caller isn't guaranteed to have access to a type and the dex cache may be
481 // unpopulated
TDYa127706e9b62012-04-19 12:24:26 -0700482 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800483}
484
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700485Object* art_portable_resolve_string_from_code(AbstractMethod* referrer, uint32_t string_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700486 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800487 return ResolveStringFromCode(referrer, string_idx);
Logan Chienfc5bc672012-03-06 16:54:30 +0800488}
489
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700490int32_t art_portable_set32_static_from_code(uint32_t field_idx,
491 AbstractMethod* referrer,
492 int32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700493 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700494 Field* field = FindFieldFast(field_idx,
495 referrer,
496 StaticPrimitiveWrite,
497 sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800498 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700499 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800500 return 0;
501 }
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700502 field = FindFieldFromCode(field_idx,
503 referrer,
504 Thread::Current(),
505 StaticPrimitiveWrite,
506 sizeof(uint32_t),
507 true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800508 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700509 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800510 return 0;
511 }
512 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800513}
514
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700515int32_t art_portable_set64_static_from_code(uint32_t field_idx,
516 AbstractMethod* referrer,
517 int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700518 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700519 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800520 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700521 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800522 return 0;
523 }
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700524 field = FindFieldFromCode(field_idx,
525 referrer,
526 Thread::Current(),
527 StaticPrimitiveWrite,
528 sizeof(uint64_t),
529 true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800530 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700531 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800532 return 0;
533 }
534 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800535}
536
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700537int32_t art_portable_set_obj_static_from_code(uint32_t field_idx,
538 AbstractMethod* referrer,
539 Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700540 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700541 Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800542 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700543 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800544 return 0;
545 }
Ian Rogers948c5082013-01-23 14:25:30 -0800546 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700547 StaticObjectWrite, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800548 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700549 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800550 return 0;
551 }
552 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800553}
554
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700555int32_t art_portable_get32_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700556 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700557 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800558 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700559 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800560 }
Ian Rogers948c5082013-01-23 14:25:30 -0800561 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200562 StaticPrimitiveRead, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800563 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700564 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800565 }
566 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800567}
568
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700569int64_t art_portable_get64_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700570 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700571 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800572 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700573 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800574 }
Ian Rogers948c5082013-01-23 14:25:30 -0800575 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200576 StaticPrimitiveRead, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800577 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700578 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800579 }
580 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800581}
582
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700583Object* art_portable_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700584 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700585 Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800586 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700587 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800588 }
Ian Rogers948c5082013-01-23 14:25:30 -0800589 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700590 StaticObjectRead, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800591 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700592 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800593 }
594 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800595}
596
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700597int32_t art_portable_set32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
598 Object* obj, uint32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700599 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700600 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800601 if (LIKELY(field != NULL)) {
602 field->Set32(obj, new_value);
603 return 0;
604 }
Ian Rogers948c5082013-01-23 14:25:30 -0800605 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200606 InstancePrimitiveWrite, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800607 if (LIKELY(field != NULL)) {
608 field->Set32(obj, new_value);
609 return 0;
610 }
611 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800612}
613
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700614int32_t art_portable_set64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
615 Object* obj, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700616 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700617 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800618 if (LIKELY(field != NULL)) {
619 field->Set64(obj, new_value);
620 return 0;
621 }
Ian Rogers948c5082013-01-23 14:25:30 -0800622 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200623 InstancePrimitiveWrite, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800624 if (LIKELY(field != NULL)) {
625 field->Set64(obj, new_value);
626 return 0;
627 }
628 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800629}
630
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700631int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
632 Object* obj, Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700633 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700634 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800635 if (LIKELY(field != NULL)) {
636 field->SetObj(obj, new_value);
637 return 0;
638 }
Ian Rogers948c5082013-01-23 14:25:30 -0800639 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700640 InstanceObjectWrite, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800641 if (LIKELY(field != NULL)) {
642 field->SetObj(obj, new_value);
643 return 0;
644 }
645 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800646}
647
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700648int32_t art_portable_get32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700649 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700650 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800651 if (LIKELY(field != NULL)) {
652 return field->Get32(obj);
653 }
Ian Rogers948c5082013-01-23 14:25:30 -0800654 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200655 InstancePrimitiveRead, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800656 if (LIKELY(field != NULL)) {
657 return field->Get32(obj);
658 }
659 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800660}
661
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700662int64_t art_portable_get64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700663 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700664 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800665 if (LIKELY(field != NULL)) {
666 return field->Get64(obj);
667 }
Ian Rogers948c5082013-01-23 14:25:30 -0800668 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200669 InstancePrimitiveRead, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800670 if (LIKELY(field != NULL)) {
671 return field->Get64(obj);
672 }
673 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800674}
675
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700676Object* art_portable_get_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700677 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700678 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800679 if (LIKELY(field != NULL)) {
680 return field->GetObj(obj);
681 }
Ian Rogers948c5082013-01-23 14:25:30 -0800682 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700683 InstanceObjectRead, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800684 if (LIKELY(field != NULL)) {
685 return field->GetObj(obj);
686 }
687 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800688}
689
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700690void art_portable_fill_array_data_from_code(AbstractMethod* method, uint32_t dex_pc,
691 Array* array, uint32_t payload_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700692 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Logan Chien86f50672012-04-24 13:08:45 +0800693 // Test: Is array equal to null? (Guard NullPointerException)
694 if (UNLIKELY(array == NULL)) {
Logan Chien8dbb7082013-01-25 20:31:17 +0800695 art_portable_throw_null_pointer_exception_from_code(dex_pc);
Logan Chien86f50672012-04-24 13:08:45 +0800696 return;
697 }
698
699 // Find the payload from the CodeItem
700 MethodHelper mh(method);
701 const DexFile::CodeItem* code_item = mh.GetCodeItem();
702
703 DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
704
705 const Instruction::ArrayDataPayload* payload =
706 reinterpret_cast<const Instruction::ArrayDataPayload*>(
707 code_item->insns_ + payload_offset);
708
709 DCHECK_EQ(payload->ident,
710 static_cast<uint16_t>(Instruction::kArrayDataSignature));
711
712 // Test: Is array big enough?
713 uint32_t array_len = static_cast<uint32_t>(array->GetLength());
714 if (UNLIKELY(array_len < payload->element_count)) {
715 int32_t last_index = payload->element_count - 1;
Logan Chien8dbb7082013-01-25 20:31:17 +0800716 art_portable_throw_array_bounds_from_code(array_len, last_index);
Logan Chien86f50672012-04-24 13:08:45 +0800717 return;
718 }
719
720 // Copy the data
721 size_t size = payload->element_width * payload->element_count;
722 memcpy(array->GetRawData(payload->element_width), payload->data, size);
723}
724
725
726
Logan Chienfc5bc672012-03-06 16:54:30 +0800727//----------------------------------------------------------------------------
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700728// Type checking, in the nature of casting
Logan Chienfc5bc672012-03-06 16:54:30 +0800729//----------------------------------------------------------------------------
730
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700731int32_t art_portable_is_assignable_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700732 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1273de5ba32012-04-02 07:04:40 -0700733 DCHECK(dest_type != NULL);
734 DCHECK(src_type != NULL);
735 return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800736}
737
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700738void art_portable_check_cast_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700739 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700740 DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700741 DCHECK(src_type->IsClass()) << PrettyClass(src_type);
742 if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800743 ThrowClassCastException(dest_type, src_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700744 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800745}
746
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700747void art_portable_check_put_array_element_from_code(const Object* element,
748 const Object* array)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700749 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700750 if (element == NULL) {
751 return;
752 }
753 DCHECK(array != NULL);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700754 Class* array_class = array->GetClass();
TDYa1271b86d072012-04-05 17:38:56 -0700755 DCHECK(array_class != NULL);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700756 Class* component_type = array_class->GetComponentType();
757 Class* element_class = element->GetClass();
TDYa1271b86d072012-04-05 17:38:56 -0700758 if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800759 ThrowArrayStoreException(element_class, array_class);
TDYa1271b86d072012-04-05 17:38:56 -0700760 }
761 return;
762}
763
Logan Chien2771fb12012-03-06 16:28:35 +0800764//----------------------------------------------------------------------------
TDYa1273d71d802012-08-15 03:47:03 -0700765// JNI
766//----------------------------------------------------------------------------
767
768// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
Logan Chien8dbb7082013-01-25 20:31:17 +0800769uint32_t art_portable_jni_method_start(Thread* self)
TDYa1273d71d802012-08-15 03:47:03 -0700770 UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
771 JNIEnvExt* env = self->GetJniEnv();
772 uint32_t saved_local_ref_cookie = env->local_ref_cookie;
773 env->local_ref_cookie = env->locals.GetSegmentState();
774 self->TransitionFromRunnableToSuspended(kNative);
775 return saved_local_ref_cookie;
776}
777
Logan Chien8dbb7082013-01-25 20:31:17 +0800778uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700779 UNLOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700780 self->DecodeJObject(to_lock)->MonitorEnter(self);
Logan Chien8dbb7082013-01-25 20:31:17 +0800781 return art_portable_jni_method_start(self);
TDYa1273d71d802012-08-15 03:47:03 -0700782}
783
784static inline void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
785 JNIEnvExt* env = self->GetJniEnv();
786 env->locals.SetSegmentState(env->local_ref_cookie);
787 env->local_ref_cookie = saved_local_ref_cookie;
788}
789
Logan Chien8dbb7082013-01-25 20:31:17 +0800790void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700791 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700792 self->TransitionFromSuspendedToRunnable();
793 PopLocalReferences(saved_local_ref_cookie, self);
794}
795
796
Logan Chien8dbb7082013-01-25 20:31:17 +0800797void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie,
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700798 jobject locked,
799 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700800 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700801 self->TransitionFromSuspendedToRunnable();
802 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
803 PopLocalReferences(saved_local_ref_cookie, self);
804}
805
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700806Object* art_portable_jni_method_end_with_reference(jobject result,
807 uint32_t saved_local_ref_cookie,
Logan Chien8dbb7082013-01-25 20:31:17 +0800808 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700809 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700810 self->TransitionFromSuspendedToRunnable();
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700811 Object* o = self->DecodeJObject(result); // Must decode before pop.
TDYa1273d71d802012-08-15 03:47:03 -0700812 PopLocalReferences(saved_local_ref_cookie, self);
813 // Process result.
814 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
815 if (self->IsExceptionPending()) {
816 return NULL;
817 }
818 CheckReferenceResult(o, self);
819 }
820 return o;
821}
822
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700823Object* art_portable_jni_method_end_with_reference_synchronized(jobject result,
Logan Chien8dbb7082013-01-25 20:31:17 +0800824 uint32_t saved_local_ref_cookie,
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700825 jobject locked,
826 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700827 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700828 self->TransitionFromSuspendedToRunnable();
829 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700830 Object* o = self->DecodeJObject(result);
TDYa1273d71d802012-08-15 03:47:03 -0700831 PopLocalReferences(saved_local_ref_cookie, self);
832 // Process result.
833 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
834 if (self->IsExceptionPending()) {
835 return NULL;
836 }
837 CheckReferenceResult(o, self);
838 }
839 return o;
840}
841
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800842// Handler for invocation on proxy methods. Create a boxed argument array and invoke the invocation
843// handler which is a field within the proxy object receiver. The var args encode the arguments
844// with the last argument being a pointer to a JValue to store the result in.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700845void art_portable_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700846 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1275bb86012012-04-11 05:57:28 -0700847 va_list ap;
848 va_start(ap, proxy_method);
849
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700850 Object* receiver = va_arg(ap, Object*);
Ian Rogers50b35e22012-10-04 10:09:15 -0700851 Thread* self = va_arg(ap, Thread*);
TDYa1275bb86012012-04-11 05:57:28 -0700852 MethodHelper proxy_mh(proxy_method);
TDYa1275bb86012012-04-11 05:57:28 -0700853
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800854 // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
855 const char* old_cause =
856 self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
857 self->VerifyStack();
858
859 // Start new JNI local reference state.
Ian Rogers50b35e22012-10-04 10:09:15 -0700860 JNIEnvExt* env = self->GetJniEnv();
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700861 ScopedObjectAccessUnchecked soa(env);
TDYa1275bb86012012-04-11 05:57:28 -0700862 ScopedJniEnvLocalRefState env_state(env);
863
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800864 // Create local ref. copies of the receiver.
Ian Rogersc5e3d762012-08-14 16:33:47 -0700865 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
TDYa1275bb86012012-04-11 05:57:28 -0700866
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800867 // Convert proxy method into expected interface method.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700868 AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
TDYa1275bb86012012-04-11 05:57:28 -0700869 DCHECK(interface_method != NULL);
870 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800871 jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
TDYa1275bb86012012-04-11 05:57:28 -0700872
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700873 // Record arguments and turn Object* arguments into jobject to survive GC.
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800874 std::vector<jvalue> args;
875 const size_t num_params = proxy_mh.NumArgs();
876 for (size_t i = 1; i < num_params; ++i) {
877 jvalue val;
878 switch (proxy_mh.GetParamPrimitiveType(i)) {
879 case Primitive::kPrimNot:
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700880 val.l = soa.AddLocalReference<jobject>(va_arg(ap, Object*));
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700881 break;
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800882 case Primitive::kPrimBoolean: // Fall-through.
883 case Primitive::kPrimByte: // Fall-through.
884 case Primitive::kPrimChar: // Fall-through.
885 case Primitive::kPrimShort: // Fall-through.
886 case Primitive::kPrimInt: // Fall-through.
887 val.i = va_arg(ap, jint);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700888 break;
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800889 case Primitive::kPrimFloat:
Ian Rogersf10f9de2013-01-16 16:47:54 -0800890 // TODO: should this be jdouble? Floats aren't passed to var arg routines.
Ian Rogers87b185f2013-01-23 09:16:53 -0800891 val.i = va_arg(ap, jint);
TDYa1275bb86012012-04-11 05:57:28 -0700892 break;
Ian Rogersf10f9de2013-01-16 16:47:54 -0800893 case Primitive::kPrimDouble:
894 val.d = (va_arg(ap, jdouble));
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800895 break;
Ian Rogersf10f9de2013-01-16 16:47:54 -0800896 case Primitive::kPrimLong:
897 val.j = (va_arg(ap, jlong));
898 break;
899 case Primitive::kPrimVoid:
900 LOG(FATAL) << "UNREACHABLE";
901 val.j = 0;
TDYa1275bb86012012-04-11 05:57:28 -0700902 break;
903 }
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800904 args.push_back(val);
TDYa1275bb86012012-04-11 05:57:28 -0700905 }
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800906 self->EndAssertNoThreadSuspension(old_cause);
Ian Rogers87b185f2013-01-23 09:16:53 -0800907 JValue* result_location = NULL;
908 const char* shorty = proxy_mh.GetShorty();
909 if (shorty[0] != 'V') {
910 result_location = va_arg(ap, JValue*);
911 }
TDYa1275bb86012012-04-11 05:57:28 -0700912 va_end(ap);
Ian Rogers87b185f2013-01-23 09:16:53 -0800913 JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args);
914 if (result_location != NULL) {
915 *result_location = result;
916 }
TDYa1275bb86012012-04-11 05:57:28 -0700917}
918
Sebastien Hertz0d43d542013-02-27 19:02:16 +0100919//----------------------------------------------------------------------------
920// Memory barrier
921//----------------------------------------------------------------------------
922
923void art_portable_constructor_barrier() {
924 LOG(FATAL) << "Implemented by IRBuilder.";
925}
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700926
Logan Chien8dbb7082013-01-25 20:31:17 +0800927} // extern "C"