blob: 9d83f9e49ee5f46c73684c7e685dc9b1ccfe9bb0 [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" {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700108using ::art::CatchHandlerIterator;
109using ::art::DexFile;
110using ::art::FindFieldFast;
111using ::art::FindMethodFast;
112using ::art::InstanceObjectRead;
113using ::art::InstanceObjectWrite;
114using ::art::InstancePrimitiveRead;
115using ::art::InstancePrimitiveWrite;
116using ::art::Instruction;
117using ::art::InvokeType;
118using ::art::JNIEnvExt;
119using ::art::JValue;
120using ::art::Locks;
121using ::art::MethodHelper;
122using ::art::PrettyClass;
123using ::art::PrettyMethod;
124using ::art::Primitive;
125using ::art::ResolveStringFromCode;
126using ::art::Runtime;
127using ::art::ScopedJniEnvLocalRefState;
128using ::art::ScopedObjectAccessUnchecked;
129using ::art::ShadowFrame;
130using ::art::ShadowFrameCopyVisitor;
131using ::art::StaticObjectRead;
132using ::art::StaticObjectWrite;
133using ::art::StaticPrimitiveRead;
134using ::art::StaticPrimitiveWrite;
135using ::art::Thread;
136using ::art::Thread;
137using ::art::ThrowArithmeticExceptionDivideByZero;
138using ::art::ThrowArrayIndexOutOfBoundsException;
139using ::art::ThrowArrayStoreException;
140using ::art::ThrowClassCastException;
141using ::art::ThrowLocation;
142using ::art::ThrowNoSuchMethodError;
143using ::art::ThrowNullPointerException;
144using ::art::ThrowNullPointerExceptionFromDexPC;
145using ::art::ThrowStackOverflowError;
146using ::art::kDirect;
147using ::art::kInterface;
148using ::art::kNative;
149using ::art::kStatic;
150using ::art::kSuper;
151using ::art::kVirtual;
152using ::art::mirror::AbstractMethod;
153using ::art::mirror::Array;
154using ::art::mirror::Class;
155using ::art::mirror::Field;
156using ::art::mirror::Object;
157using ::art::mirror::Throwable;
158
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800159//----------------------------------------------------------------------------
160// Thread
161//----------------------------------------------------------------------------
162
Logan Chien8dbb7082013-01-25 20:31:17 +0800163Thread* art_portable_get_current_thread_from_code() {
Ian Rogers948c5082013-01-23 14:25:30 -0800164#if defined(__arm__) || defined(__i386__)
165 LOG(FATAL) << "UNREACHABLE";
TDYa127d668a062012-04-13 12:36:57 -0700166#endif
Ian Rogers948c5082013-01-23 14:25:30 -0800167 return Thread::Current();
Logan Chienfc5bc672012-03-06 16:54:30 +0800168}
169
Logan Chien8dbb7082013-01-25 20:31:17 +0800170void* art_portable_set_current_thread_from_code(void* thread_object_addr) {
Ian Rogers948c5082013-01-23 14:25:30 -0800171 // Hijacked to set r9 on ARM.
172 LOG(FATAL) << "UNREACHABLE";
TDYa127c1478262012-06-20 20:22:27 -0700173 return NULL;
Logan Chienfc5bc672012-03-06 16:54:30 +0800174}
175
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700176void art_portable_lock_object_from_code(Object* obj, Thread* thread)
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700177 EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -0800178 DCHECK(obj != NULL); // Assumed to have been checked before entry
179 obj->MonitorEnter(thread); // May block
180 DCHECK(thread->HoldsLock(obj));
181 // Only possible exception is NPE and is handled before entry
182 DCHECK(!thread->IsExceptionPending());
Logan Chienfc5bc672012-03-06 16:54:30 +0800183}
184
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700185void art_portable_unlock_object_from_code(Object* obj, Thread* thread)
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700186 UNLOCK_FUNCTION(monitor_lock_) {
Shih-wei Liao66adbb72012-03-07 01:31:50 -0800187 DCHECK(obj != NULL); // Assumed to have been checked before entry
188 // MonitorExit may throw exception
189 obj->MonitorExit(thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800190}
191
Ian Rogers62d6c772013-02-27 08:32:07 -0800192void art_portable_test_suspend_from_code(Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700193 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800194 CheckSuspend(self);
195 if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) {
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800196 // Save out the shadow frame to the heap
Ian Rogers62d6c772013-02-27 08:32:07 -0800197 ShadowFrameCopyVisitor visitor(self);
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800198 visitor.WalkStack(true);
Ian Rogers62d6c772013-02-27 08:32:07 -0800199 self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy());
200 self->SetDeoptimizationReturnValue(JValue());
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700201 self->SetException(ThrowLocation(), reinterpret_cast<Throwable*>(-1));
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800202 }
Logan Chienfc5bc672012-03-06 16:54:30 +0800203}
204
Logan Chien8dbb7082013-01-25 20:31:17 +0800205ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread,
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700206 ShadowFrame* new_shadow_frame,
207 AbstractMethod* method,
208 uint32_t num_vregs) {
TDYa127de479be2012-05-31 08:03:26 -0700209 ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
210 new_shadow_frame->SetMethod(method);
Ian Rogers5438ad82012-10-15 17:22:44 -0700211 new_shadow_frame->SetNumberOfVRegs(num_vregs);
TDYa127de479be2012-05-31 08:03:26 -0700212 return old_frame;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800213}
214
Logan Chien8dbb7082013-01-25 20:31:17 +0800215void art_portable_pop_shadow_frame_from_code(void*) {
TDYa12783bb6622012-04-17 02:20:34 -0700216 LOG(FATAL) << "Implemented by IRBuilder.";
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800217}
218
Logan Chien8dbb7082013-01-25 20:31:17 +0800219void art_portable_mark_gc_card_from_code(void *, void*) {
TDYa12783bb6622012-04-17 02:20:34 -0700220 LOG(FATAL) << "Implemented by IRBuilder.";
221}
Logan Chienfc5bc672012-03-06 16:54:30 +0800222
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800223//----------------------------------------------------------------------------
224// Exception
225//----------------------------------------------------------------------------
226
Logan Chien8dbb7082013-01-25 20:31:17 +0800227bool art_portable_is_exception_pending_from_code() {
TDYa12783bb6622012-04-17 02:20:34 -0700228 LOG(FATAL) << "Implemented by IRBuilder.";
229 return false;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800230}
231
Logan Chien8dbb7082013-01-25 20:31:17 +0800232void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200233 ThrowArithmeticExceptionDivideByZero();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800234}
235
Logan Chien8dbb7082013-01-25 20:31:17 +0800236void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700237 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800238 ThrowArrayIndexOutOfBoundsException(index, length);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800239}
240
Logan Chien8dbb7082013-01-25 20:31:17 +0800241void art_portable_throw_no_such_method_from_code(int32_t method_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700242 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800243 ThrowNoSuchMethodError(method_idx);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800244}
245
Logan Chien8dbb7082013-01-25 20:31:17 +0800246void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700247 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800248 // TODO: remove dex_pc argument from caller.
249 UNUSED(dex_pc);
250 Thread* self = Thread::Current();
251 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
252 ThrowNullPointerExceptionFromDexPC(throw_location);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800253}
254
Logan Chien8dbb7082013-01-25 20:31:17 +0800255void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers948c5082013-01-23 14:25:30 -0800256 ThrowStackOverflowError(Thread::Current());
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800257}
258
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700259void art_portable_throw_exception_from_code(Throwable* exception)
Ian Rogers62d6c772013-02-27 08:32:07 -0800260 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
261 Thread* self = Thread::Current();
262 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
263 if (exception == NULL) {
264 ThrowNullPointerException(NULL, "throw with null exception");
265 } else {
266 self->SetException(throw_location, exception);
267 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800268}
269
Logan Chien8dbb7082013-01-25 20:31:17 +0800270void* art_portable_get_and_clear_exception(Thread* self)
TDYa127823433d2012-09-26 16:03:51 -0700271 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
272 DCHECK(self->IsExceptionPending());
Ian Rogers62d6c772013-02-27 08:32:07 -0800273 // TODO: make this inline.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700274 Throwable* exception = self->GetException(NULL);
TDYa127823433d2012-09-26 16:03:51 -0700275 self->ClearException();
276 return exception;
277}
278
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700279int32_t art_portable_find_catch_block_from_code(AbstractMethod* current_method,
280 uint32_t ti_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700281 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800282 Thread* self = Thread::Current(); // TODO: make an argument.
283 ThrowLocation throw_location;
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700284 Throwable* exception = self->GetException(&throw_location);
Ian Rogers62d6c772013-02-27 08:32:07 -0800285 // Check for special deoptimization exception.
286 if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800287 return -1;
288 }
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700289 Class* exception_type = exception->GetClass();
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800290 MethodHelper mh(current_method);
291 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Logan Chien736df022012-04-27 16:25:57 +0800292 DCHECK_LT(ti_offset, code_item->tries_size_);
293 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
294
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800295 int iter_index = 0;
Ian Rogers62d6c772013-02-27 08:32:07 -0800296 int result = -1;
297 uint32_t catch_dex_pc = -1;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800298 // Iterate over the catch handlers associated with dex_pc
Logan Chien736df022012-04-27 16:25:57 +0800299 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800300 uint16_t iter_type_idx = it.GetHandlerTypeIndex();
301 // Catch all case
302 if (iter_type_idx == DexFile::kDexNoIndex16) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800303 catch_dex_pc = it.GetHandlerAddress();
304 result = iter_index;
305 break;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800306 }
307 // Does this catch exception type apply?
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700308 Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
Ian Rogers62d6c772013-02-27 08:32:07 -0800309 if (UNLIKELY(iter_exception_type == NULL)) {
310 // TODO: check, the verifier (class linker?) should take care of resolving all exception
311 // classes early.
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800312 LOG(WARNING) << "Unresolved exception class when finding catch block: "
313 << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
314 } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800315 catch_dex_pc = it.GetHandlerAddress();
316 result = iter_index;
317 break;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800318 }
319 ++iter_index;
320 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800321 if (result != -1) {
322 // Handler found.
323 Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self,
324 throw_location,
325 current_method,
326 catch_dex_pc,
327 exception);
328 }
329 return result;
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800330}
331
Logan Chienfc5bc672012-03-06 16:54:30 +0800332
333//----------------------------------------------------------------------------
334// Object Space
335//----------------------------------------------------------------------------
336
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700337Object* art_portable_alloc_object_from_code(uint32_t type_idx, AbstractMethod* referrer, Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700338 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700339 return AllocObjectFromCode(type_idx, referrer, thread, false);
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800340}
341
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700342Object* art_portable_alloc_object_from_code_with_access_check(uint32_t type_idx,
343 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800344 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700345 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700346 return AllocObjectFromCode(type_idx, referrer, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800347}
348
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700349Object* art_portable_alloc_array_from_code(uint32_t type_idx,
350 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800351 uint32_t length,
352 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700353 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700354 return AllocArrayFromCode(type_idx, referrer, length, self, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800355}
356
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700357Object* art_portable_alloc_array_from_code_with_access_check(uint32_t type_idx,
358 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800359 uint32_t length,
360 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700361 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700362 return AllocArrayFromCode(type_idx, referrer, length, self, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800363}
364
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700365Object* art_portable_check_and_alloc_array_from_code(uint32_t type_idx,
366 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800367 uint32_t length,
368 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700369 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700370 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800371}
372
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700373Object* art_portable_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
374 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800375 uint32_t length,
376 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700377 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700378 return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800379}
380
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700381static AbstractMethod* FindMethodHelper(uint32_t method_idx,
382 Object* this_object,
383 AbstractMethod* caller_method,
384 bool access_check,
385 InvokeType type,
386 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700387 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700388 AbstractMethod* method = FindMethodFast(method_idx,
389 this_object,
390 caller_method,
391 access_check,
392 type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800393 if (UNLIKELY(method == NULL)) {
394 method = FindMethodFromCode(method_idx, this_object, caller_method,
TDYa127da83d972012-04-18 00:21:49 -0700395 thread, access_check, type);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800396 if (UNLIKELY(method == NULL)) {
TDYa127da83d972012-04-18 00:21:49 -0700397 CHECK(thread->IsExceptionPending());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800398 return 0; // failure
399 }
400 }
TDYa127da83d972012-04-18 00:21:49 -0700401 DCHECK(!thread->IsExceptionPending());
Jeff Haoaa4a7932013-05-13 11:28:27 -0700402 const void* code = method->GetEntryPointFromCompiledCode();
TDYa1273d71d802012-08-15 03:47:03 -0700403
404 // When we return, the caller will branch to this address, so it had better not be 0!
405 if (UNLIKELY(code == NULL)) {
406 MethodHelper mh(method);
407 LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
408 << " location: " << mh.GetDexFile().GetLocation();
409 }
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800410 return method;
411}
412
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700413Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx,
414 Object* this_object,
415 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800416 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700417 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700418 return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800419}
420
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700421Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx,
422 Object* this_object,
423 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800424 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700425 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700426 return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800427}
428
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700429Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
430 Object* this_object,
431 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800432 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700433 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700434 return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800435}
436
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700437Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx,
438 Object* this_object,
439 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800440 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700441 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700442 return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
Logan Chienfc5bc672012-03-06 16:54:30 +0800443}
444
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700445Object* art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx,
446 Object* this_object,
447 AbstractMethod* referrer,
448 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700449 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700450 return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800451}
452
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700453Object* art_portable_find_interface_method_from_code(uint32_t method_idx,
454 Object* this_object,
455 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800456 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700457 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127da83d972012-04-18 00:21:49 -0700458 return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
Logan Chien7e7fabc2012-04-10 18:59:11 +0800459}
460
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700461Object* art_portable_initialize_static_storage_from_code(uint32_t type_idx,
462 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800463 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700464 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700465 return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800466}
467
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700468Object* art_portable_initialize_type_from_code(uint32_t type_idx,
469 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800470 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700471 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa127706e9b62012-04-19 12:24:26 -0700472 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
Logan Chienfc5bc672012-03-06 16:54:30 +0800473}
474
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700475Object* art_portable_initialize_type_and_verify_access_from_code(uint32_t type_idx,
476 AbstractMethod* referrer,
Logan Chien8dbb7082013-01-25 20:31:17 +0800477 Thread* thread)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700478 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800479 // Called when caller isn't guaranteed to have access to a type and the dex cache may be
480 // unpopulated
TDYa127706e9b62012-04-19 12:24:26 -0700481 return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
Logan Chienfc5bc672012-03-06 16:54:30 +0800482}
483
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700484Object* art_portable_resolve_string_from_code(AbstractMethod* referrer, uint32_t string_idx)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700485 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800486 return ResolveStringFromCode(referrer, string_idx);
Logan Chienfc5bc672012-03-06 16:54:30 +0800487}
488
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700489int32_t art_portable_set32_static_from_code(uint32_t field_idx,
490 AbstractMethod* referrer,
491 int32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700492 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700493 Field* field = FindFieldFast(field_idx,
494 referrer,
495 StaticPrimitiveWrite,
496 sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800497 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700498 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800499 return 0;
500 }
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700501 field = FindFieldFromCode(field_idx,
502 referrer,
503 Thread::Current(),
504 StaticPrimitiveWrite,
505 sizeof(uint32_t),
506 true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800507 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700508 field->Set32(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800509 return 0;
510 }
511 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800512}
513
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700514int32_t art_portable_set64_static_from_code(uint32_t field_idx,
515 AbstractMethod* referrer,
516 int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700517 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700518 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800519 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700520 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800521 return 0;
522 }
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700523 field = FindFieldFromCode(field_idx,
524 referrer,
525 Thread::Current(),
526 StaticPrimitiveWrite,
527 sizeof(uint64_t),
528 true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800529 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700530 field->Set64(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800531 return 0;
532 }
533 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800534}
535
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700536int32_t art_portable_set_obj_static_from_code(uint32_t field_idx,
537 AbstractMethod* referrer,
538 Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700539 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700540 Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800541 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700542 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800543 return 0;
544 }
Ian Rogers948c5082013-01-23 14:25:30 -0800545 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700546 StaticObjectWrite, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800547 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700548 field->SetObj(field->GetDeclaringClass(), new_value);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800549 return 0;
550 }
551 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800552}
553
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700554int32_t art_portable_get32_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700555 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700556 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800557 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700558 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800559 }
Ian Rogers948c5082013-01-23 14:25:30 -0800560 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200561 StaticPrimitiveRead, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800562 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700563 return field->Get32(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800564 }
565 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800566}
567
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700568int64_t art_portable_get64_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700569 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700570 Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800571 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700572 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800573 }
Ian Rogers948c5082013-01-23 14:25:30 -0800574 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200575 StaticPrimitiveRead, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800576 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700577 return field->Get64(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800578 }
579 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800580}
581
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700582Object* art_portable_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700583 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700584 Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800585 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700586 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800587 }
Ian Rogers948c5082013-01-23 14:25:30 -0800588 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700589 StaticObjectRead, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800590 if (LIKELY(field != NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700591 return field->GetObj(field->GetDeclaringClass());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800592 }
593 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800594}
595
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700596int32_t art_portable_set32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
597 Object* obj, uint32_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700598 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700599 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800600 if (LIKELY(field != NULL)) {
601 field->Set32(obj, new_value);
602 return 0;
603 }
Ian Rogers948c5082013-01-23 14:25:30 -0800604 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200605 InstancePrimitiveWrite, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800606 if (LIKELY(field != NULL)) {
607 field->Set32(obj, new_value);
608 return 0;
609 }
610 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800611}
612
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700613int32_t art_portable_set64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
614 Object* obj, int64_t new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700615 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700616 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800617 if (LIKELY(field != NULL)) {
618 field->Set64(obj, new_value);
619 return 0;
620 }
Ian Rogers948c5082013-01-23 14:25:30 -0800621 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200622 InstancePrimitiveWrite, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800623 if (LIKELY(field != NULL)) {
624 field->Set64(obj, new_value);
625 return 0;
626 }
627 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800628}
629
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700630int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
631 Object* obj, Object* new_value)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700632 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700633 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800634 if (LIKELY(field != NULL)) {
635 field->SetObj(obj, new_value);
636 return 0;
637 }
Ian Rogers948c5082013-01-23 14:25:30 -0800638 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700639 InstanceObjectWrite, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800640 if (LIKELY(field != NULL)) {
641 field->SetObj(obj, new_value);
642 return 0;
643 }
644 return -1;
Logan Chienfc5bc672012-03-06 16:54:30 +0800645}
646
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700647int32_t art_portable_get32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700648 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700649 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800650 if (LIKELY(field != NULL)) {
651 return field->Get32(obj);
652 }
Ian Rogers948c5082013-01-23 14:25:30 -0800653 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200654 InstancePrimitiveRead, sizeof(uint32_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800655 if (LIKELY(field != NULL)) {
656 return field->Get32(obj);
657 }
658 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800659}
660
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700661int64_t art_portable_get64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700662 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700663 Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800664 if (LIKELY(field != NULL)) {
665 return field->Get64(obj);
666 }
Ian Rogers948c5082013-01-23 14:25:30 -0800667 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200668 InstancePrimitiveRead, sizeof(uint64_t), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800669 if (LIKELY(field != NULL)) {
670 return field->Get64(obj);
671 }
672 return 0;
Shih-wei Liao399ed3f2012-03-08 01:27:04 -0800673}
674
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700675Object* art_portable_get_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700676 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700677 Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*));
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800678 if (LIKELY(field != NULL)) {
679 return field->GetObj(obj);
680 }
Ian Rogers948c5082013-01-23 14:25:30 -0800681 field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700682 InstanceObjectRead, sizeof(Object*), true);
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -0800683 if (LIKELY(field != NULL)) {
684 return field->GetObj(obj);
685 }
686 return 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800687}
688
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700689void art_portable_fill_array_data_from_code(AbstractMethod* method, uint32_t dex_pc,
690 Array* array, uint32_t payload_offset)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700691 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Logan Chien86f50672012-04-24 13:08:45 +0800692 // Test: Is array equal to null? (Guard NullPointerException)
693 if (UNLIKELY(array == NULL)) {
Logan Chien8dbb7082013-01-25 20:31:17 +0800694 art_portable_throw_null_pointer_exception_from_code(dex_pc);
Logan Chien86f50672012-04-24 13:08:45 +0800695 return;
696 }
697
698 // Find the payload from the CodeItem
699 MethodHelper mh(method);
700 const DexFile::CodeItem* code_item = mh.GetCodeItem();
701
702 DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
703
704 const Instruction::ArrayDataPayload* payload =
705 reinterpret_cast<const Instruction::ArrayDataPayload*>(
706 code_item->insns_ + payload_offset);
707
708 DCHECK_EQ(payload->ident,
709 static_cast<uint16_t>(Instruction::kArrayDataSignature));
710
711 // Test: Is array big enough?
712 uint32_t array_len = static_cast<uint32_t>(array->GetLength());
713 if (UNLIKELY(array_len < payload->element_count)) {
714 int32_t last_index = payload->element_count - 1;
Logan Chien8dbb7082013-01-25 20:31:17 +0800715 art_portable_throw_array_bounds_from_code(array_len, last_index);
Logan Chien86f50672012-04-24 13:08:45 +0800716 return;
717 }
718
719 // Copy the data
720 size_t size = payload->element_width * payload->element_count;
721 memcpy(array->GetRawData(payload->element_width), payload->data, size);
722}
723
724
725
Logan Chienfc5bc672012-03-06 16:54:30 +0800726//----------------------------------------------------------------------------
Shih-wei Liao9e0e54d2012-04-02 19:22:28 -0700727// Type checking, in the nature of casting
Logan Chienfc5bc672012-03-06 16:54:30 +0800728//----------------------------------------------------------------------------
729
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700730int32_t art_portable_is_assignable_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700731 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1273de5ba32012-04-02 07:04:40 -0700732 DCHECK(dest_type != NULL);
733 DCHECK(src_type != NULL);
734 return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
Logan Chienfc5bc672012-03-06 16:54:30 +0800735}
736
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700737void art_portable_check_cast_from_code(const Class* dest_type, const Class* src_type)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700738 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700739 DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700740 DCHECK(src_type->IsClass()) << PrettyClass(src_type);
741 if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800742 ThrowClassCastException(dest_type, src_type);
TDYa1273de5ba32012-04-02 07:04:40 -0700743 }
Shih-wei Liaoa8a9c342012-03-03 22:35:16 -0800744}
745
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700746void art_portable_check_put_array_element_from_code(const Object* element,
747 const Object* array)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700748 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1271b86d072012-04-05 17:38:56 -0700749 if (element == NULL) {
750 return;
751 }
752 DCHECK(array != NULL);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700753 Class* array_class = array->GetClass();
TDYa1271b86d072012-04-05 17:38:56 -0700754 DCHECK(array_class != NULL);
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700755 Class* component_type = array_class->GetComponentType();
756 Class* element_class = element->GetClass();
TDYa1271b86d072012-04-05 17:38:56 -0700757 if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800758 ThrowArrayStoreException(element_class, array_class);
TDYa1271b86d072012-04-05 17:38:56 -0700759 }
760 return;
761}
762
Logan Chien2771fb12012-03-06 16:28:35 +0800763//----------------------------------------------------------------------------
TDYa1273d71d802012-08-15 03:47:03 -0700764// JNI
765//----------------------------------------------------------------------------
766
767// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
Logan Chien8dbb7082013-01-25 20:31:17 +0800768uint32_t art_portable_jni_method_start(Thread* self)
TDYa1273d71d802012-08-15 03:47:03 -0700769 UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
770 JNIEnvExt* env = self->GetJniEnv();
771 uint32_t saved_local_ref_cookie = env->local_ref_cookie;
772 env->local_ref_cookie = env->locals.GetSegmentState();
773 self->TransitionFromRunnableToSuspended(kNative);
774 return saved_local_ref_cookie;
775}
776
Logan Chien8dbb7082013-01-25 20:31:17 +0800777uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700778 UNLOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700779 self->DecodeJObject(to_lock)->MonitorEnter(self);
Logan Chien8dbb7082013-01-25 20:31:17 +0800780 return art_portable_jni_method_start(self);
TDYa1273d71d802012-08-15 03:47:03 -0700781}
782
783static inline void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
784 JNIEnvExt* env = self->GetJniEnv();
785 env->locals.SetSegmentState(env->local_ref_cookie);
786 env->local_ref_cookie = saved_local_ref_cookie;
787}
788
Logan Chien8dbb7082013-01-25 20:31:17 +0800789void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700790 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700791 self->TransitionFromSuspendedToRunnable();
792 PopLocalReferences(saved_local_ref_cookie, self);
793}
794
795
Logan Chien8dbb7082013-01-25 20:31:17 +0800796void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie,
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700797 jobject locked,
798 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700799 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700800 self->TransitionFromSuspendedToRunnable();
801 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
802 PopLocalReferences(saved_local_ref_cookie, self);
803}
804
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700805Object* art_portable_jni_method_end_with_reference(jobject result,
806 uint32_t saved_local_ref_cookie,
Logan Chien8dbb7082013-01-25 20:31:17 +0800807 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700808 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700809 self->TransitionFromSuspendedToRunnable();
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700810 Object* o = self->DecodeJObject(result); // Must decode before pop.
TDYa1273d71d802012-08-15 03:47:03 -0700811 PopLocalReferences(saved_local_ref_cookie, self);
812 // Process result.
813 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
814 if (self->IsExceptionPending()) {
815 return NULL;
816 }
817 CheckReferenceResult(o, self);
818 }
819 return o;
820}
821
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700822Object* art_portable_jni_method_end_with_reference_synchronized(jobject result,
Logan Chien8dbb7082013-01-25 20:31:17 +0800823 uint32_t saved_local_ref_cookie,
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700824 jobject locked,
825 Thread* self)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700826 SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
TDYa1273d71d802012-08-15 03:47:03 -0700827 self->TransitionFromSuspendedToRunnable();
828 UnlockJniSynchronizedMethod(locked, self); // Must decode before pop.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700829 Object* o = self->DecodeJObject(result);
TDYa1273d71d802012-08-15 03:47:03 -0700830 PopLocalReferences(saved_local_ref_cookie, self);
831 // Process result.
832 if (UNLIKELY(self->GetJniEnv()->check_jni)) {
833 if (self->IsExceptionPending()) {
834 return NULL;
835 }
836 CheckReferenceResult(o, self);
837 }
838 return o;
839}
840
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800841// Handler for invocation on proxy methods. Create a boxed argument array and invoke the invocation
842// handler which is a field within the proxy object receiver. The var args encode the arguments
843// with the last argument being a pointer to a JValue to store the result in.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700844void art_portable_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700845 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
TDYa1275bb86012012-04-11 05:57:28 -0700846 va_list ap;
847 va_start(ap, proxy_method);
848
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700849 Object* receiver = va_arg(ap, Object*);
Ian Rogers50b35e22012-10-04 10:09:15 -0700850 Thread* self = va_arg(ap, Thread*);
TDYa1275bb86012012-04-11 05:57:28 -0700851 MethodHelper proxy_mh(proxy_method);
TDYa1275bb86012012-04-11 05:57:28 -0700852
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800853 // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
854 const char* old_cause =
855 self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
856 self->VerifyStack();
857
858 // Start new JNI local reference state.
Ian Rogers50b35e22012-10-04 10:09:15 -0700859 JNIEnvExt* env = self->GetJniEnv();
Shih-wei Liaocd05a622012-08-15 00:02:05 -0700860 ScopedObjectAccessUnchecked soa(env);
TDYa1275bb86012012-04-11 05:57:28 -0700861 ScopedJniEnvLocalRefState env_state(env);
862
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800863 // Create local ref. copies of the receiver.
Ian Rogersc5e3d762012-08-14 16:33:47 -0700864 jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
TDYa1275bb86012012-04-11 05:57:28 -0700865
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800866 // Convert proxy method into expected interface method.
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700867 AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
TDYa1275bb86012012-04-11 05:57:28 -0700868 DCHECK(interface_method != NULL);
869 DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800870 jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
TDYa1275bb86012012-04-11 05:57:28 -0700871
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700872 // Record arguments and turn Object* arguments into jobject to survive GC.
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800873 std::vector<jvalue> args;
874 const size_t num_params = proxy_mh.NumArgs();
875 for (size_t i = 1; i < num_params; ++i) {
876 jvalue val;
877 switch (proxy_mh.GetParamPrimitiveType(i)) {
878 case Primitive::kPrimNot:
Brian Carlstrom3e3d5912013-07-18 00:19:45 -0700879 val.l = soa.AddLocalReference<jobject>(va_arg(ap, Object*));
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700880 break;
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800881 case Primitive::kPrimBoolean: // Fall-through.
882 case Primitive::kPrimByte: // Fall-through.
883 case Primitive::kPrimChar: // Fall-through.
884 case Primitive::kPrimShort: // Fall-through.
885 case Primitive::kPrimInt: // Fall-through.
886 val.i = va_arg(ap, jint);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700887 break;
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800888 case Primitive::kPrimFloat:
Ian Rogersf10f9de2013-01-16 16:47:54 -0800889 // TODO: should this be jdouble? Floats aren't passed to var arg routines.
Ian Rogers87b185f2013-01-23 09:16:53 -0800890 val.i = va_arg(ap, jint);
TDYa1275bb86012012-04-11 05:57:28 -0700891 break;
Ian Rogersf10f9de2013-01-16 16:47:54 -0800892 case Primitive::kPrimDouble:
893 val.d = (va_arg(ap, jdouble));
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800894 break;
Ian Rogersf10f9de2013-01-16 16:47:54 -0800895 case Primitive::kPrimLong:
896 val.j = (va_arg(ap, jlong));
897 break;
898 case Primitive::kPrimVoid:
899 LOG(FATAL) << "UNREACHABLE";
900 val.j = 0;
TDYa1275bb86012012-04-11 05:57:28 -0700901 break;
902 }
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800903 args.push_back(val);
TDYa1275bb86012012-04-11 05:57:28 -0700904 }
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800905 self->EndAssertNoThreadSuspension(old_cause);
Ian Rogers87b185f2013-01-23 09:16:53 -0800906 JValue* result_location = NULL;
907 const char* shorty = proxy_mh.GetShorty();
908 if (shorty[0] != 'V') {
909 result_location = va_arg(ap, JValue*);
910 }
TDYa1275bb86012012-04-11 05:57:28 -0700911 va_end(ap);
Ian Rogers87b185f2013-01-23 09:16:53 -0800912 JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args);
913 if (result_location != NULL) {
914 *result_location = result;
915 }
TDYa1275bb86012012-04-11 05:57:28 -0700916}
917
Sebastien Hertz0d43d542013-02-27 19:02:16 +0100918//----------------------------------------------------------------------------
919// Memory barrier
920//----------------------------------------------------------------------------
921
922void art_portable_constructor_barrier() {
923 LOG(FATAL) << "Implemented by IRBuilder.";
924}
Logan Chien8dbb7082013-01-25 20:31:17 +0800925} // extern "C"