blob: d785affe88925db2f34e35d68734faa9df985c5b [file] [log] [blame]
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001/*
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 */
16
17#ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
18#define ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
19
20#include "interpreter.h"
21
22#include <math.h>
23
24#include "base/logging.h"
25#include "class_linker-inl.h"
26#include "common_throws.h"
27#include "dex_file-inl.h"
28#include "dex_instruction-inl.h"
29#include "dex_instruction.h"
30#include "entrypoints/entrypoint_utils.h"
31#include "gc/accounting/card_table-inl.h"
Mathieu Chartier0cd81352014-05-22 16:48:55 -070032#include "handle_scope-inl.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020033#include "nth_caller_visitor.h"
34#include "mirror/art_field-inl.h"
35#include "mirror/art_method.h"
36#include "mirror/art_method-inl.h"
37#include "mirror/class.h"
38#include "mirror/class-inl.h"
39#include "mirror/object-inl.h"
40#include "mirror/object_array-inl.h"
Douglas Leung4965c022014-06-11 11:41:11 -070041#include "mirror/string-inl.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020042#include "object_utils.h"
43#include "ScopedLocalRef.h"
44#include "scoped_thread_state_change.h"
45#include "thread.h"
46#include "well_known_classes.h"
47
48using ::art::mirror::ArtField;
49using ::art::mirror::ArtMethod;
50using ::art::mirror::Array;
51using ::art::mirror::BooleanArray;
52using ::art::mirror::ByteArray;
53using ::art::mirror::CharArray;
54using ::art::mirror::Class;
55using ::art::mirror::ClassLoader;
56using ::art::mirror::IntArray;
57using ::art::mirror::LongArray;
58using ::art::mirror::Object;
59using ::art::mirror::ObjectArray;
60using ::art::mirror::ShortArray;
61using ::art::mirror::String;
62using ::art::mirror::Throwable;
63
Sebastien Hertz82aeddb2014-05-20 20:09:45 +020064// b/14882674 Workaround stack overflow issue with clang
65#if defined(__clang__) && defined(__aarch64__)
66#define SOMETIMES_INLINE __attribute__((noinline))
67#define SOMETIMES_INLINE_KEYWORD
68#else
69#define SOMETIMES_INLINE ALWAYS_INLINE
70#define SOMETIMES_INLINE_KEYWORD inline
71#endif
72
Sebastien Hertz8ece0502013-08-07 11:26:41 +020073namespace art {
74namespace interpreter {
75
76// External references to both interpreter implementations.
77
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010078template<bool do_access_check, bool transaction_active>
Sebastien Hertz8ece0502013-08-07 11:26:41 +020079extern JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh,
80 const DexFile::CodeItem* code_item,
Sebastien Hertzc6714852013-09-30 16:42:32 +020081 ShadowFrame& shadow_frame, JValue result_register);
Sebastien Hertz8ece0502013-08-07 11:26:41 +020082
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010083template<bool do_access_check, bool transaction_active>
Sebastien Hertz8ece0502013-08-07 11:26:41 +020084extern JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh,
85 const DexFile::CodeItem* code_item,
Sebastien Hertzc6714852013-09-30 16:42:32 +020086 ShadowFrame& shadow_frame, JValue result_register);
Sebastien Hertz8ece0502013-08-07 11:26:41 +020087
Sebastien Hertzda843e12014-05-28 19:28:31 +020088// Workaround for b/14882674 where clang allocates stack for each ThrowLocation created by calls to
89// ShadowFrame::GetCurrentLocationForThrow(). Moving the call here prevents from doing such
90// allocation in the interpreter itself.
91static inline void ThrowNullPointerExceptionFromInterpreter(const ShadowFrame& shadow_frame)
92 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE;
93
94static inline void ThrowNullPointerExceptionFromInterpreter(
95 const ShadowFrame& shadow_frame) {
96 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
97}
98
Sebastien Hertz8ece0502013-08-07 11:26:41 +020099static inline void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
100 ref->MonitorEnter(self);
101}
102
103static inline void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
104 ref->MonitorExit(self);
105}
106
Mathieu Chartierb2c7ead2014-04-29 11:13:16 -0700107void AbortTransaction(Thread* self, const char* fmt, ...)
108 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
109
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100110void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count)
111 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
112
Sebastien Hertzc6714852013-09-30 16:42:32 +0200113// Invokes the given method. This is part of the invocation support and is used by DoInvoke and
114// DoInvokeVirtualQuick functions.
115// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200116template<bool is_range, bool do_assignability_check>
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100117bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertzc6714852013-09-30 16:42:32 +0200118 const Instruction* inst, uint16_t inst_data, JValue* result);
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200119
Sebastien Hertzc6714852013-09-30 16:42:32 +0200120// Handles invoke-XXX/range instructions.
121// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200122template<InvokeType type, bool is_range, bool do_access_check>
123static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
124 uint16_t inst_data, JValue* result) {
125 const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
126 const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700127 Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700128 mirror::ArtMethod* sf_method = shadow_frame.GetMethod();
129 ArtMethod* const method = FindMethodFromCode<type, do_access_check>(
130 method_idx, &receiver, &sf_method, self);
131 // The shadow frame should already be pushed, so we don't need to update it.
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200132 if (UNLIKELY(method == nullptr)) {
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200133 CHECK(self->IsExceptionPending());
134 result->SetJ(0);
135 return false;
136 } else if (UNLIKELY(method->IsAbstract())) {
137 ThrowAbstractMethodError(method);
138 result->SetJ(0);
139 return false;
140 } else {
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100141 return DoCall<is_range, do_access_check>(method, self, shadow_frame, inst, inst_data, result);
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200142 }
143}
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200144
Sebastien Hertzc6714852013-09-30 16:42:32 +0200145// Handles invoke-virtual-quick and invoke-virtual-quick-range instructions.
146// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200147template<bool is_range>
148static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
149 const Instruction* inst, uint16_t inst_data,
150 JValue* result) {
151 const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
152 Object* const receiver = shadow_frame.GetVRegReference(vregC);
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200153 if (UNLIKELY(receiver == nullptr)) {
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200154 // We lost the reference to the method index so we cannot get a more
155 // precised exception message.
156 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
157 return false;
158 }
159 const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
160 ArtMethod* const method = receiver->GetClass()->GetVTable()->GetWithoutChecks(vtable_idx);
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200161 if (UNLIKELY(method == nullptr)) {
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200162 CHECK(self->IsExceptionPending());
163 result->SetJ(0);
164 return false;
165 } else if (UNLIKELY(method->IsAbstract())) {
166 ThrowAbstractMethodError(method);
167 result->SetJ(0);
168 return false;
169 } else {
170 // No need to check since we've been quickened.
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100171 return DoCall<is_range, false>(method, self, shadow_frame, inst, inst_data, result);
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200172 }
173}
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200174
Sebastien Hertzc6714852013-09-30 16:42:32 +0200175// Handles iget-XXX and sget-XXX instructions.
176// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200177template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200178static SOMETIMES_INLINE_KEYWORD bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame,
179 const Instruction* inst, uint16_t inst_data) {
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200180 const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
181 const uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
182 ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
183 Primitive::FieldSize(field_type));
184 if (UNLIKELY(f == nullptr)) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200185 CHECK(self->IsExceptionPending());
186 return false;
187 }
188 Object* obj;
189 if (is_static) {
190 obj = f->GetDeclaringClass();
191 } else {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200192 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200193 if (UNLIKELY(obj == nullptr)) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200194 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
195 return false;
196 }
197 }
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200198 // Report this field access to instrumentation if needed.
199 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
200 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
201 Object* this_object = f->IsStatic() ? nullptr : obj;
202 instrumentation->FieldReadEvent(self, this_object, shadow_frame.GetMethod(),
203 shadow_frame.GetDexPC(), f);
204 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200205 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200206 switch (field_type) {
207 case Primitive::kPrimBoolean:
208 shadow_frame.SetVReg(vregA, f->GetBoolean(obj));
209 break;
210 case Primitive::kPrimByte:
211 shadow_frame.SetVReg(vregA, f->GetByte(obj));
212 break;
213 case Primitive::kPrimChar:
214 shadow_frame.SetVReg(vregA, f->GetChar(obj));
215 break;
216 case Primitive::kPrimShort:
217 shadow_frame.SetVReg(vregA, f->GetShort(obj));
218 break;
219 case Primitive::kPrimInt:
220 shadow_frame.SetVReg(vregA, f->GetInt(obj));
221 break;
222 case Primitive::kPrimLong:
223 shadow_frame.SetVRegLong(vregA, f->GetLong(obj));
224 break;
225 case Primitive::kPrimNot:
226 shadow_frame.SetVRegReference(vregA, f->GetObject(obj));
227 break;
228 default:
229 LOG(FATAL) << "Unreachable: " << field_type;
230 }
231 return true;
232}
233
Sebastien Hertzc6714852013-09-30 16:42:32 +0200234// Handles iget-quick, iget-wide-quick and iget-object-quick instructions.
235// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200236template<Primitive::Type field_type>
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200237static SOMETIMES_INLINE_KEYWORD bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200238 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200239 if (UNLIKELY(obj == nullptr)) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200240 // We lost the reference to the field index so we cannot get a more
241 // precised exception message.
242 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
243 return false;
244 }
245 MemberOffset field_offset(inst->VRegC_22c());
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200246 // Report this field access to instrumentation if needed. Since we only have the offset of
247 // the field from the base of the object, we need to look for it first.
248 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
249 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
250 ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
251 field_offset.Uint32Value());
252 DCHECK(f != nullptr);
253 DCHECK(!f->IsStatic());
254 instrumentation->FieldReadEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
255 shadow_frame.GetDexPC(), f);
256 }
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700257 // Note: iget-x-quick instructions are only for non-volatile fields.
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200258 const uint32_t vregA = inst->VRegA_22c(inst_data);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200259 switch (field_type) {
260 case Primitive::kPrimInt:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700261 shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetField32(field_offset)));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200262 break;
263 case Primitive::kPrimLong:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700264 shadow_frame.SetVRegLong(vregA, static_cast<int64_t>(obj->GetField64(field_offset)));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200265 break;
266 case Primitive::kPrimNot:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700267 shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object>(field_offset));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200268 break;
269 default:
270 LOG(FATAL) << "Unreachable: " << field_type;
271 }
272 return true;
273}
274
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200275template<Primitive::Type field_type>
276static inline JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
277 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
278 JValue field_value;
279 switch (field_type) {
280 case Primitive::kPrimBoolean:
281 field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
282 break;
283 case Primitive::kPrimByte:
284 field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
285 break;
286 case Primitive::kPrimChar:
287 field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
288 break;
289 case Primitive::kPrimShort:
290 field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
291 break;
292 case Primitive::kPrimInt:
293 field_value.SetI(shadow_frame.GetVReg(vreg));
294 break;
295 case Primitive::kPrimLong:
296 field_value.SetJ(shadow_frame.GetVRegLong(vreg));
297 break;
298 case Primitive::kPrimNot:
299 field_value.SetL(shadow_frame.GetVRegReference(vreg));
300 break;
301 default:
302 LOG(FATAL) << "Unreachable: " << field_type;
303 break;
304 }
305 return field_value;
306}
307
Sebastien Hertzc6714852013-09-30 16:42:32 +0200308// Handles iput-XXX and sput-XXX instructions.
309// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100310template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check, bool transaction_active>
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200311static SOMETIMES_INLINE_KEYWORD bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
312 const Instruction* inst, uint16_t inst_data) {
Jeff Haoa3faaf42013-09-03 19:07:00 -0700313 bool do_assignability_check = do_access_check;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200314 bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
315 uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200316 ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
317 Primitive::FieldSize(field_type));
318 if (UNLIKELY(f == nullptr)) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200319 CHECK(self->IsExceptionPending());
320 return false;
321 }
322 Object* obj;
323 if (is_static) {
324 obj = f->GetDeclaringClass();
325 } else {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200326 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200327 if (UNLIKELY(obj == nullptr)) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200328 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
329 f, false);
330 return false;
331 }
332 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200333 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200334 // Report this field access to instrumentation if needed. Since we only have the offset of
335 // the field from the base of the object, we need to look for it first.
336 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
337 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
338 JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
339 Object* this_object = f->IsStatic() ? nullptr : obj;
340 instrumentation->FieldWriteEvent(self, this_object, shadow_frame.GetMethod(),
341 shadow_frame.GetDexPC(), f, field_value);
342 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200343 switch (field_type) {
344 case Primitive::kPrimBoolean:
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100345 f->SetBoolean<transaction_active>(obj, shadow_frame.GetVReg(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200346 break;
347 case Primitive::kPrimByte:
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100348 f->SetByte<transaction_active>(obj, shadow_frame.GetVReg(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200349 break;
350 case Primitive::kPrimChar:
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100351 f->SetChar<transaction_active>(obj, shadow_frame.GetVReg(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200352 break;
353 case Primitive::kPrimShort:
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100354 f->SetShort<transaction_active>(obj, shadow_frame.GetVReg(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200355 break;
356 case Primitive::kPrimInt:
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100357 f->SetInt<transaction_active>(obj, shadow_frame.GetVReg(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200358 break;
359 case Primitive::kPrimLong:
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100360 f->SetLong<transaction_active>(obj, shadow_frame.GetVRegLong(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200361 break;
Jeff Haoa3faaf42013-09-03 19:07:00 -0700362 case Primitive::kPrimNot: {
363 Object* reg = shadow_frame.GetVRegReference(vregA);
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200364 if (do_assignability_check && reg != nullptr) {
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700365 // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
366 // object in the destructor.
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700367 Class* field_class;
368 {
369 StackHandleScope<3> hs(self);
370 HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
371 HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
372 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
373 FieldHelper fh(h_f);
374 field_class = fh.GetType();
375 }
Jeff Haoa3faaf42013-09-03 19:07:00 -0700376 if (!reg->VerifierInstanceOf(field_class)) {
377 // This should never happen.
378 self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
379 "Ljava/lang/VirtualMachineError;",
380 "Put '%s' that is not instance of field '%s' in '%s'",
Mathieu Chartierf8322842014-05-16 10:59:25 -0700381 reg->GetClass()->GetDescriptor().c_str(),
382 field_class->GetDescriptor().c_str(),
383 f->GetDeclaringClass()->GetDescriptor().c_str());
Jeff Haoa3faaf42013-09-03 19:07:00 -0700384 return false;
385 }
386 }
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100387 f->SetObj<transaction_active>(obj, reg);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200388 break;
Jeff Haoa3faaf42013-09-03 19:07:00 -0700389 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200390 default:
391 LOG(FATAL) << "Unreachable: " << field_type;
392 }
393 return true;
394}
395
Sebastien Hertzc6714852013-09-30 16:42:32 +0200396// Handles iput-quick, iput-wide-quick and iput-object-quick instructions.
397// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100398template<Primitive::Type field_type, bool transaction_active>
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700399static SOMETIMES_INLINE_KEYWORD bool DoIPutQuick(const ShadowFrame& shadow_frame,
400 const Instruction* inst, uint16_t inst_data) {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200401 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
Sebastien Hertzd4beb6b2013-10-02 17:07:20 +0200402 if (UNLIKELY(obj == nullptr)) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200403 // We lost the reference to the field index so we cannot get a more
404 // precised exception message.
405 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
406 return false;
407 }
408 MemberOffset field_offset(inst->VRegC_22c());
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200409 const uint32_t vregA = inst->VRegA_22c(inst_data);
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200410 // Report this field modification to instrumentation if needed. Since we only have the offset of
411 // the field from the base of the object, we need to look for it first.
412 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
413 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
414 ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
415 field_offset.Uint32Value());
416 DCHECK(f != nullptr);
417 DCHECK(!f->IsStatic());
418 JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
419 instrumentation->FieldWriteEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
420 shadow_frame.GetDexPC(), f, field_value);
421 }
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700422 // Note: iput-x-quick instructions are only for non-volatile fields.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200423 switch (field_type) {
424 case Primitive::kPrimInt:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700425 obj->SetField32<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200426 break;
427 case Primitive::kPrimLong:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700428 obj->SetField64<transaction_active>(field_offset, shadow_frame.GetVRegLong(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200429 break;
430 case Primitive::kPrimNot:
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700431 obj->SetFieldObject<transaction_active>(field_offset, shadow_frame.GetVRegReference(vregA));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200432 break;
433 default:
434 LOG(FATAL) << "Unreachable: " << field_type;
435 }
436 return true;
437}
438
Sebastien Hertzc6714852013-09-30 16:42:32 +0200439// Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
440// java.lang.String class is initialized.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200441static inline String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx)
442 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800443 CHECK(!kMovingMethods);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200444 Class* java_lang_string_class = String::GetJavaLangString();
445 if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
446 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700447 StackHandleScope<1> hs(self);
448 Handle<mirror::Class> h_class(hs.NewHandle(java_lang_string_class));
449 if (UNLIKELY(!class_linker->EnsureInitialized(h_class, true, true))) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200450 DCHECK(self->IsExceptionPending());
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800451 return nullptr;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200452 }
453 }
454 return mh.ResolveString(string_idx);
455}
456
Sebastien Hertzc6714852013-09-30 16:42:32 +0200457// Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions.
458// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200459static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
460 int32_t dividend, int32_t divisor)
461 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2e2deeb2013-09-23 11:58:57 -0700462 const int32_t kMinInt = std::numeric_limits<int32_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200463 if (UNLIKELY(divisor == 0)) {
464 ThrowArithmeticExceptionDivideByZero();
465 return false;
466 }
467 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
468 shadow_frame.SetVReg(result_reg, kMinInt);
469 } else {
470 shadow_frame.SetVReg(result_reg, dividend / divisor);
471 }
472 return true;
473}
474
Sebastien Hertzc6714852013-09-30 16:42:32 +0200475// Handles rem-int, rem-int/2addr, rem-int/li16 and rem-int/lit8 instructions.
476// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200477static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
478 int32_t dividend, int32_t divisor)
479 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2e2deeb2013-09-23 11:58:57 -0700480 const int32_t kMinInt = std::numeric_limits<int32_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200481 if (UNLIKELY(divisor == 0)) {
482 ThrowArithmeticExceptionDivideByZero();
483 return false;
484 }
485 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
486 shadow_frame.SetVReg(result_reg, 0);
487 } else {
488 shadow_frame.SetVReg(result_reg, dividend % divisor);
489 }
490 return true;
491}
492
Sebastien Hertzc6714852013-09-30 16:42:32 +0200493// Handles div-long and div-long-2addr instructions.
494// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200495static inline bool DoLongDivide(ShadowFrame& shadow_frame, size_t result_reg,
496 int64_t dividend, int64_t divisor)
497 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2e2deeb2013-09-23 11:58:57 -0700498 const int64_t kMinLong = std::numeric_limits<int64_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200499 if (UNLIKELY(divisor == 0)) {
500 ThrowArithmeticExceptionDivideByZero();
501 return false;
502 }
503 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
504 shadow_frame.SetVRegLong(result_reg, kMinLong);
505 } else {
506 shadow_frame.SetVRegLong(result_reg, dividend / divisor);
507 }
508 return true;
509}
510
Sebastien Hertzc6714852013-09-30 16:42:32 +0200511// Handles rem-long and rem-long-2addr instructions.
512// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200513static inline bool DoLongRemainder(ShadowFrame& shadow_frame, size_t result_reg,
514 int64_t dividend, int64_t divisor)
515 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers2e2deeb2013-09-23 11:58:57 -0700516 const int64_t kMinLong = std::numeric_limits<int64_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200517 if (UNLIKELY(divisor == 0)) {
518 ThrowArithmeticExceptionDivideByZero();
519 return false;
520 }
521 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
522 shadow_frame.SetVRegLong(result_reg, 0);
523 } else {
524 shadow_frame.SetVRegLong(result_reg, dividend % divisor);
525 }
526 return true;
527}
528
Sebastien Hertzc6714852013-09-30 16:42:32 +0200529// Handles filled-new-array and filled-new-array-range instructions.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200530// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100531template <bool is_range, bool do_access_check, bool transaction_active>
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200532bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
Sebastien Hertzc6714852013-09-30 16:42:32 +0200533 Thread* self, JValue* result);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200534
Sebastien Hertzc6714852013-09-30 16:42:32 +0200535// Handles packed-switch instruction.
536// Returns the branch offset to the next instruction to execute.
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200537static inline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
538 uint16_t inst_data)
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200539 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
540 DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH);
541 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200542 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200543 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
544 uint16_t size = switch_data[1];
545 DCHECK_GT(size, 0);
546 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
547 DCHECK(IsAligned<4>(keys));
548 int32_t first_key = keys[0];
549 const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
550 DCHECK(IsAligned<4>(targets));
551 int32_t index = test_val - first_key;
552 if (index >= 0 && index < size) {
553 return targets[index];
554 } else {
555 // No corresponding value: move forward by 3 (size of PACKED_SWITCH).
556 return 3;
557 }
558}
559
Sebastien Hertzc6714852013-09-30 16:42:32 +0200560// Handles sparse-switch instruction.
561// Returns the branch offset to the next instruction to execute.
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200562static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
563 uint16_t inst_data)
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200564 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
565 DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
566 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200567 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200568 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
569 uint16_t size = switch_data[1];
570 DCHECK_GT(size, 0);
571 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
572 DCHECK(IsAligned<4>(keys));
573 const int32_t* entries = keys + size;
574 DCHECK(IsAligned<4>(entries));
575 int lo = 0;
576 int hi = size - 1;
577 while (lo <= hi) {
578 int mid = (lo + hi) / 2;
579 int32_t foundVal = keys[mid];
580 if (test_val < foundVal) {
581 hi = mid - 1;
582 } else if (test_val > foundVal) {
583 lo = mid + 1;
584 } else {
585 return entries[mid];
586 }
587 }
588 // No corresponding value: move forward by 3 (size of SPARSE_SWITCH).
589 return 3;
590}
591
592static inline uint32_t FindNextInstructionFollowingException(Thread* self,
593 ShadowFrame& shadow_frame,
594 uint32_t dex_pc,
Sebastien Hertz947ff082013-09-17 14:10:13 +0200595 mirror::Object* this_object,
596 const instrumentation::Instrumentation* instrumentation)
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200597SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200598
599static inline uint32_t FindNextInstructionFollowingException(Thread* self,
600 ShadowFrame& shadow_frame,
601 uint32_t dex_pc,
Sebastien Hertz947ff082013-09-17 14:10:13 +0200602 mirror::Object* this_object,
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200603 const instrumentation::Instrumentation* instrumentation) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200604 self->VerifyStack();
605 ThrowLocation throw_location;
606 mirror::Throwable* exception = self->GetException(&throw_location);
Sebastien Hertz947ff082013-09-17 14:10:13 +0200607 bool clear_exception = false;
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700608 uint32_t found_dex_pc;
609 {
610 StackHandleScope<3> hs(self);
611 Handle<mirror::Class> exception_class(hs.NewHandle(exception->GetClass()));
612 Handle<mirror::ArtMethod> h_method(hs.NewHandle(shadow_frame.GetMethod()));
613 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(&this_object));
614 found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
615 &clear_exception);
616 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200617 if (found_dex_pc == DexFile::kDexNoIndex) {
Sebastien Hertz947ff082013-09-17 14:10:13 +0200618 instrumentation->MethodUnwindEvent(self, this_object,
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200619 shadow_frame.GetMethod(), dex_pc);
620 } else {
621 instrumentation->ExceptionCaughtEvent(self, throw_location,
622 shadow_frame.GetMethod(),
623 found_dex_pc, exception);
624 if (clear_exception) {
625 self->ClearException();
626 }
627 }
628 return found_dex_pc;
629}
630
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800631static inline void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh)
632 __attribute__((cold, noreturn))
633 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200634
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800635static inline void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700636 LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(mh.GetMethod()->GetDexFile());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200637 exit(0); // Unreachable, keep GCC happy.
638}
639
640static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
Jeff Haoa3faaf42013-09-03 19:07:00 -0700641 const uint32_t dex_pc, MethodHelper& mh)
642 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700643 constexpr bool kTracing = false;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200644 if (kTracing) {
645#define TRACE_LOG std::cerr
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700646 std::ostringstream oss;
647 oss << PrettyMethod(shadow_frame.GetMethod())
648 << StringPrintf("\n0x%x: ", dex_pc)
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700649 << inst->DumpString(mh.GetMethod()->GetDexFile()) << "\n";
Ian Rogersef7d42f2014-01-06 12:55:46 -0800650 for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200651 uint32_t raw_value = shadow_frame.GetVReg(i);
652 Object* ref_value = shadow_frame.GetVRegReference(i);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800653 oss << StringPrintf(" vreg%u=0x%08X", i, raw_value);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200654 if (ref_value != NULL) {
655 if (ref_value->GetClass()->IsStringClass() &&
656 ref_value->AsString()->GetCharArray() != NULL) {
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700657 oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200658 } else {
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700659 oss << "/" << PrettyTypeOf(ref_value);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200660 }
661 }
662 }
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700663 TRACE_LOG << oss.str() << "\n";
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200664#undef TRACE_LOG
665 }
666}
667
Sebastien Hertz1eda2262013-09-09 16:53:14 +0200668static inline bool IsBackwardBranch(int32_t branch_offset) {
669 return branch_offset <= 0;
670}
671
Sebastien Hertzc6714852013-09-30 16:42:32 +0200672// Explicitly instantiate all DoInvoke functions.
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100673#define EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, _is_range, _do_check) \
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200674 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE \
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100675 bool DoInvoke<_type, _is_range, _do_check>(Thread* self, ShadowFrame& shadow_frame, \
676 const Instruction* inst, uint16_t inst_data, \
677 JValue* result)
Sebastien Hertzc6714852013-09-30 16:42:32 +0200678
679#define EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(_type) \
680 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, false); \
681 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, true); \
682 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, false); \
683 EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, true);
684
685EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kStatic); // invoke-static/range.
686EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kDirect); // invoke-direct/range.
687EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kVirtual); // invoke-virtual/range.
688EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kSuper); // invoke-super/range.
689EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL(kInterface); // invoke-interface/range.
690#undef EXPLICIT_DO_INVOKE_ALL_TEMPLATE_DECL
691#undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL
692
693// Explicitly instantiate all DoFieldGet functions.
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100694#define EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, _do_check) \
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200695 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE \
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100696 bool DoFieldGet<_find_type, _field_type, _do_check>(Thread* self, ShadowFrame& shadow_frame, \
697 const Instruction* inst, uint16_t inst_data)
Sebastien Hertzc6714852013-09-30 16:42:32 +0200698
699#define EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(_find_type, _field_type) \
700 EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, false); \
701 EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, true);
702
703// iget-XXX
704EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimBoolean);
705EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimByte);
706EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimChar);
707EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimShort);
708EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimInt);
709EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimLong);
710EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstanceObjectRead, Primitive::kPrimNot);
711
712// sget-XXX
713EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimBoolean);
714EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimByte);
715EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimChar);
716EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimShort);
717EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimInt);
718EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimLong);
719EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticObjectRead, Primitive::kPrimNot);
720
721#undef EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL
722#undef EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL
723
724// Explicitly instantiate all DoFieldPut functions.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100725#define EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, _do_check, _transaction_active) \
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200726 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE \
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100727 bool DoFieldPut<_find_type, _field_type, _do_check, _transaction_active>(Thread* self, const ShadowFrame& shadow_frame, \
728 const Instruction* inst, uint16_t inst_data)
Sebastien Hertzc6714852013-09-30 16:42:32 +0200729
730#define EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(_find_type, _field_type) \
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100731 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, false, false); \
732 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, true, false); \
733 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, false, true); \
734 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, true, true);
Sebastien Hertzc6714852013-09-30 16:42:32 +0200735
736// iput-XXX
737EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimBoolean);
738EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimByte);
739EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimChar);
740EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimShort);
741EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimInt);
742EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimLong);
743EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstanceObjectWrite, Primitive::kPrimNot);
744
745// sput-XXX
746EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimBoolean);
747EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimByte);
748EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimChar);
749EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimShort);
750EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimInt);
751EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimLong);
752EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticObjectWrite, Primitive::kPrimNot);
753
754#undef EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL
755#undef EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL
756
757// Explicitly instantiate all DoInvokeVirtualQuick functions.
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100758#define EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(_is_range) \
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200759 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE \
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100760 bool DoInvokeVirtualQuick<_is_range>(Thread* self, ShadowFrame& shadow_frame, \
761 const Instruction* inst, uint16_t inst_data, \
762 JValue* result)
Sebastien Hertzc6714852013-09-30 16:42:32 +0200763
764EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(false); // invoke-virtual-quick.
765EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(true); // invoke-virtual-quick-range.
766#undef EXPLICIT_INSTANTIATION_DO_INVOKE_VIRTUAL_QUICK
767
768// Explicitly instantiate all DoIGetQuick functions.
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100769#define EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(_field_type) \
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200770 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE \
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100771 bool DoIGetQuick<_field_type>(ShadowFrame& shadow_frame, const Instruction* inst, \
772 uint16_t inst_data)
Sebastien Hertzc6714852013-09-30 16:42:32 +0200773
774EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimInt); // iget-quick.
775EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimLong); // iget-wide-quick.
776EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimNot); // iget-object-quick.
777#undef EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL
778
779// Explicitly instantiate all DoIPutQuick functions.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100780#define EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, _transaction_active) \
Sebastien Hertz82aeddb2014-05-20 20:09:45 +0200781 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) SOMETIMES_INLINE \
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100782 bool DoIPutQuick<_field_type, _transaction_active>(const ShadowFrame& shadow_frame, \
783 const Instruction* inst, \
784 uint16_t inst_data)
Sebastien Hertzc6714852013-09-30 16:42:32 +0200785
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100786#define EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(_field_type) \
787 EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, false); \
788 EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, true);
789
790EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimInt); // iget-quick.
791EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimLong); // iget-wide-quick.
792EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimNot); // iget-object-quick.
793#undef EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL
Sebastien Hertzc6714852013-09-30 16:42:32 +0200794#undef EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL
795
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200796} // namespace interpreter
797} // namespace art
798
799#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_