blob: 59f0ac2e38aab10ed2b532f60c2c4bdc8b62f648 [file] [log] [blame]
Ian Rogers2fa6b2e2012-10-17 00:10:17 -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 */
16
17#include "interpreter.h"
18
19#include <math.h>
20
Elliott Hughes07ed66b2012-12-12 18:34:25 -080021#include "base/logging.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080022#include "class_linker-inl.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070023#include "common_throws.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070024#include "dex_file-inl.h"
Sebastien Hertz807a2562013-04-15 09:33:39 +020025#include "dex_instruction-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070026#include "dex_instruction.h"
Ian Rogers7655f292013-07-29 11:07:13 -070027#include "entrypoints/entrypoint_utils.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070028#include "gc/accounting/card_table-inl.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070029#include "invoke_arg_array_builder.h"
Ian Rogers64b6d142012-10-29 16:34:15 -070030#include "nth_caller_visitor.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070031#include "mirror/art_field-inl.h"
32#include "mirror/art_method.h"
33#include "mirror/art_method-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/class.h"
35#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036#include "mirror/object-inl.h"
37#include "mirror/object_array-inl.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070038#include "object_utils.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070039#include "ScopedLocalRef.h"
40#include "scoped_thread_state_change.h"
41#include "thread.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070042#include "well_known_classes.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070043
Brian Carlstromea46f952013-07-30 01:26:50 -070044using ::art::mirror::ArtField;
45using ::art::mirror::ArtMethod;
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070046using ::art::mirror::Array;
47using ::art::mirror::BooleanArray;
48using ::art::mirror::ByteArray;
49using ::art::mirror::CharArray;
50using ::art::mirror::Class;
51using ::art::mirror::ClassLoader;
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070052using ::art::mirror::IntArray;
53using ::art::mirror::LongArray;
54using ::art::mirror::Object;
55using ::art::mirror::ObjectArray;
56using ::art::mirror::ShortArray;
57using ::art::mirror::String;
58using ::art::mirror::Throwable;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080059
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070060namespace art {
Jeff Hao16743632013-05-08 10:59:04 -070061
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070062namespace interpreter {
63
jeffhao87a6edd2012-11-20 18:05:18 -080064static const int32_t kMaxInt = std::numeric_limits<int32_t>::max();
65static const int32_t kMinInt = std::numeric_limits<int32_t>::min();
66static const int64_t kMaxLong = std::numeric_limits<int64_t>::max();
67static const int64_t kMinLong = std::numeric_limits<int64_t>::min();
68
Jeff Hao790ad902013-05-22 15:02:08 -070069static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
70 const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
71 JValue* result, size_t arg_offset)
Ian Rogers64b6d142012-10-29 16:34:15 -070072 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
73 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
74 // problems in core libraries.
Jeff Hao790ad902013-05-22 15:02:08 -070075 std::string name(PrettyMethod(shadow_frame->GetMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -070076 if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") {
Jeff Hao16743632013-05-08 10:59:04 -070077 std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
Brian Carlstrom7934ac22013-07-26 10:54:15 -070078 ClassLoader* class_loader = NULL; // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
Ian Rogers64b6d142012-10-29 16:34:15 -070079 Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(),
80 class_loader);
81 CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
82 << PrettyDescriptor(descriptor);
83 result->SetL(found);
84 } else if (name == "java.lang.Object java.lang.Class.newInstance()") {
Jeff Hao16743632013-05-08 10:59:04 -070085 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
Brian Carlstromea46f952013-07-30 01:26:50 -070086 ArtMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");
Ian Rogers64b6d142012-10-29 16:34:15 -070087 CHECK(c != NULL);
Brian Carlstromea46f952013-07-30 01:26:50 -070088 SirtRef<Object> obj(self, klass->AllocObject(self));
89 CHECK(obj.get() != NULL);
90 EnterInterpreterFromInvoke(self, c, obj.get(), NULL, NULL);
91 result->SetL(obj.get());
Ian Rogers64b6d142012-10-29 16:34:15 -070092 } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") {
93 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
94 // going the reflective Dex way.
Jeff Hao16743632013-05-08 10:59:04 -070095 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
96 String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
Brian Carlstromea46f952013-07-30 01:26:50 -070097 ArtField* found = NULL;
Ian Rogers64b6d142012-10-29 16:34:15 -070098 FieldHelper fh;
Brian Carlstromea46f952013-07-30 01:26:50 -070099 ObjectArray<ArtField>* fields = klass->GetIFields();
Ian Rogers64b6d142012-10-29 16:34:15 -0700100 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700101 ArtField* f = fields->Get(i);
Ian Rogers64b6d142012-10-29 16:34:15 -0700102 fh.ChangeField(f);
103 if (name->Equals(fh.GetName())) {
104 found = f;
105 }
106 }
107 if (found == NULL) {
108 fields = klass->GetSFields();
109 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700110 ArtField* f = fields->Get(i);
Ian Rogers64b6d142012-10-29 16:34:15 -0700111 fh.ChangeField(f);
112 if (name->Equals(fh.GetName())) {
113 found = f;
114 }
115 }
116 }
117 CHECK(found != NULL)
118 << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
119 << name->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
120 // TODO: getDeclaredField calls GetType once the field is found to ensure a
121 // NoClassDefFoundError is thrown if the field's type cannot be resolved.
Brian Carlstromea46f952013-07-30 01:26:50 -0700122 Class* jlr_Field = self->DecodeJObject(WellKnownClasses::java_lang_reflect_Field)->AsClass();
123 SirtRef<Object> field(self, jlr_Field->AllocObject(self));
124 CHECK(field.get() != NULL);
125 ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V");
126 uint32_t args[1];
127 args[0] = reinterpret_cast<uint32_t>(found);
128 EnterInterpreterFromInvoke(self, c, field.get(), args, NULL);
129 result->SetL(field.get());
Ian Rogers64b6d142012-10-29 16:34:15 -0700130 } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") {
131 // Special case array copying without initializing System.
Jeff Hao16743632013-05-08 10:59:04 -0700132 Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType();
133 jint srcPos = shadow_frame->GetVReg(arg_offset + 1);
134 jint dstPos = shadow_frame->GetVReg(arg_offset + 3);
135 jint length = shadow_frame->GetVReg(arg_offset + 4);
Ian Rogers64b6d142012-10-29 16:34:15 -0700136 if (!ctype->IsPrimitive()) {
Jeff Hao16743632013-05-08 10:59:04 -0700137 ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>();
138 ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>();
Ian Rogers64b6d142012-10-29 16:34:15 -0700139 for (jint i = 0; i < length; ++i) {
140 dst->Set(dstPos + i, src->Get(srcPos + i));
141 }
142 } else if (ctype->IsPrimitiveChar()) {
Jeff Hao16743632013-05-08 10:59:04 -0700143 CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray();
144 CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray();
Ian Rogers64b6d142012-10-29 16:34:15 -0700145 for (jint i = 0; i < length; ++i) {
146 dst->Set(dstPos + i, src->Get(srcPos + i));
147 }
148 } else if (ctype->IsPrimitiveInt()) {
Jeff Hao16743632013-05-08 10:59:04 -0700149 IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray();
150 IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray();
Ian Rogers64b6d142012-10-29 16:34:15 -0700151 for (jint i = 0; i < length; ++i) {
152 dst->Set(dstPos + i, src->Get(srcPos + i));
153 }
154 } else {
155 UNIMPLEMENTED(FATAL) << "System.arraycopy of unexpected type: " << PrettyDescriptor(ctype);
156 }
157 } else {
158 // Not special, continue with regular interpreter execution.
Ian Rogers848871b2013-08-05 10:56:33 -0700159 artInterpreterToInterpreterBridge(self, mh, code_item, shadow_frame, result);
Ian Rogers64b6d142012-10-29 16:34:15 -0700160 }
161}
162
163// Hand select a number of methods to be run in a not yet started runtime without using JNI.
Brian Carlstromea46f952013-07-30 01:26:50 -0700164static void UnstartedRuntimeJni(Thread* self, ArtMethod* method,
Jeff Hao5d917302013-02-27 17:57:33 -0800165 Object* receiver, uint32_t* args, JValue* result)
Ian Rogers64b6d142012-10-29 16:34:15 -0700166 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
167 std::string name(PrettyMethod(method));
168 if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") {
169 result->SetL(NULL);
170 } else if (name == "java.lang.Class dalvik.system.VMStack.getStackClass2()") {
Ian Rogers7a22fa62013-01-23 12:16:16 -0800171 NthCallerVisitor visitor(self, 3);
Ian Rogers64b6d142012-10-29 16:34:15 -0700172 visitor.WalkStack();
173 result->SetL(visitor.caller->GetDeclaringClass());
174 } else if (name == "double java.lang.Math.log(double)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800175 JValue value;
176 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
177 result->SetD(log(value.GetD()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700178 } else if (name == "java.lang.String java.lang.Class.getNameNative()") {
179 result->SetL(receiver->AsClass()->ComputeName());
180 } else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800181 result->SetI(args[0]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700182 } else if (name == "float java.lang.Float.intBitsToFloat(int)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800183 result->SetI(args[0]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700184 } else if (name == "double java.lang.Math.exp(double)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800185 JValue value;
186 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
187 result->SetD(exp(value.GetD()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700188 } else if (name == "java.lang.Object java.lang.Object.internalClone()") {
189 result->SetL(receiver->Clone(self));
190 } else if (name == "void java.lang.Object.notifyAll()") {
Ian Rogers05f30572013-02-20 12:13:11 -0800191 receiver->NotifyAll(self);
Ian Rogers64b6d142012-10-29 16:34:15 -0700192 } else if (name == "int java.lang.String.compareTo(java.lang.String)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800193 String* rhs = reinterpret_cast<Object*>(args[0])->AsString();
Ian Rogers64b6d142012-10-29 16:34:15 -0700194 CHECK(rhs != NULL);
195 result->SetI(receiver->AsString()->CompareTo(rhs));
196 } else if (name == "java.lang.String java.lang.String.intern()") {
197 result->SetL(receiver->AsString()->Intern());
198 } else if (name == "int java.lang.String.fastIndexOf(int, int)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800199 result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700200 } else if (name == "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") {
Jeff Hao5d917302013-02-27 17:57:33 -0800201 result->SetL(Array::CreateMultiArray(self, reinterpret_cast<Object*>(args[0])->AsClass(), reinterpret_cast<Object*>(args[1])->AsIntArray()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700202 } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") {
203 ScopedObjectAccessUnchecked soa(self);
204 result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace(soa)));
205 } else if (name == "boolean java.nio.ByteOrder.isLittleEndian()") {
206 result->SetJ(JNI_TRUE);
207 } else if (name == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800208 Object* obj = reinterpret_cast<Object*>(args[0]);
209 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
210 jint expectedValue = args[3];
211 jint newValue = args[4];
Ian Rogers64b6d142012-10-29 16:34:15 -0700212 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
213 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
214 // Note: android_atomic_release_cas() returns 0 on success, not failure.
215 int r = android_atomic_release_cas(expectedValue, newValue, address);
216 result->SetZ(r == 0);
217 } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800218 Object* obj = reinterpret_cast<Object*>(args[0]);
219 Object* newValue = reinterpret_cast<Object*>(args[3]);
220 obj->SetFieldObject(MemberOffset((static_cast<uint64_t>(args[2]) << 32) | args[1]), newValue, false);
Ian Rogers64b6d142012-10-29 16:34:15 -0700221 } else {
222 LOG(FATAL) << "Attempt to invoke native method in non-started runtime: " << name;
223 }
224}
225
Brian Carlstromea46f952013-07-30 01:26:50 -0700226static void InterpreterJni(Thread* self, ArtMethod* method, StringPiece shorty,
Jeff Hao5d917302013-02-27 17:57:33 -0800227 Object* receiver, uint32_t* args, JValue* result)
Ian Rogers64b6d142012-10-29 16:34:15 -0700228 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
229 // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
230 // it should be removed and JNI compiled stubs used instead.
231 ScopedObjectAccessUnchecked soa(self);
232 if (method->IsStatic()) {
233 if (shorty == "L") {
234 typedef jobject (fnptr)(JNIEnv*, jclass);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700235 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700236 ScopedLocalRef<jclass> klass(soa.Env(),
237 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
Ian Rogers556d6372012-11-20 12:19:36 -0800238 jobject jresult;
239 {
240 ScopedThreadStateChange tsc(self, kNative);
241 jresult = fn(soa.Env(), klass.get());
242 }
243 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700244 } else if (shorty == "V") {
245 typedef void (fnptr)(JNIEnv*, jclass);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700246 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700247 ScopedLocalRef<jclass> klass(soa.Env(),
248 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
249 ScopedThreadStateChange tsc(self, kNative);
250 fn(soa.Env(), klass.get());
251 } else if (shorty == "Z") {
252 typedef jboolean (fnptr)(JNIEnv*, jclass);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700253 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700254 ScopedLocalRef<jclass> klass(soa.Env(),
255 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
256 ScopedThreadStateChange tsc(self, kNative);
257 result->SetZ(fn(soa.Env(), klass.get()));
258 } else if (shorty == "BI") {
259 typedef jbyte (fnptr)(JNIEnv*, jclass, jint);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700260 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700261 ScopedLocalRef<jclass> klass(soa.Env(),
262 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
263 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800264 result->SetB(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700265 } else if (shorty == "II") {
266 typedef jint (fnptr)(JNIEnv*, jclass, jint);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700267 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700268 ScopedLocalRef<jclass> klass(soa.Env(),
269 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
270 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800271 result->SetI(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700272 } else if (shorty == "LL") {
273 typedef jobject (fnptr)(JNIEnv*, jclass, jobject);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700274 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700275 ScopedLocalRef<jclass> klass(soa.Env(),
276 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
277 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800278 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -0800279 jobject jresult;
280 {
281 ScopedThreadStateChange tsc(self, kNative);
282 jresult = fn(soa.Env(), klass.get(), arg0.get());
283 }
284 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700285 } else if (shorty == "IIZ") {
286 typedef jint (fnptr)(JNIEnv*, jclass, jint, jboolean);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700287 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700288 ScopedLocalRef<jclass> klass(soa.Env(),
289 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
290 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800291 result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700292 } else if (shorty == "ILI") {
293 typedef jint (fnptr)(JNIEnv*, jclass, jobject, jint);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700294 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700295 ScopedLocalRef<jclass> klass(soa.Env(),
296 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
297 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800298 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700299 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800300 result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700301 } else if (shorty == "SIZ") {
302 typedef jshort (fnptr)(JNIEnv*, jclass, jint, jboolean);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700303 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700304 ScopedLocalRef<jclass> klass(soa.Env(),
305 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
306 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800307 result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700308 } else if (shorty == "VIZ") {
309 typedef void (fnptr)(JNIEnv*, jclass, jint, jboolean);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700310 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700311 ScopedLocalRef<jclass> klass(soa.Env(),
312 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
313 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800314 fn(soa.Env(), klass.get(), args[0], args[1]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700315 } else if (shorty == "ZLL") {
316 typedef jboolean (fnptr)(JNIEnv*, jclass, jobject, jobject);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700317 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700318 ScopedLocalRef<jclass> klass(soa.Env(),
319 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
320 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800321 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700322 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800323 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700324 ScopedThreadStateChange tsc(self, kNative);
325 result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
326 } else if (shorty == "ZILL") {
327 typedef jboolean (fnptr)(JNIEnv*, jclass, jint, jobject, jobject);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700328 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700329 ScopedLocalRef<jclass> klass(soa.Env(),
330 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
331 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800332 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700333 ScopedLocalRef<jobject> arg2(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800334 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700335 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800336 result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700337 } else if (shorty == "VILII") {
338 typedef void (fnptr)(JNIEnv*, jclass, jint, jobject, jint, jint);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700339 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700340 ScopedLocalRef<jclass> klass(soa.Env(),
341 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
342 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800343 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700344 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800345 fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700346 } else if (shorty == "VLILII") {
347 typedef void (fnptr)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700348 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700349 ScopedLocalRef<jclass> klass(soa.Env(),
350 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
351 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800352 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700353 ScopedLocalRef<jobject> arg2(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800354 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700355 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800356 fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700357 } else {
358 LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
359 << " shorty: " << shorty;
360 }
361 } else {
362 if (shorty == "L") {
363 typedef jobject (fnptr)(JNIEnv*, jobject);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700364 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700365 ScopedLocalRef<jobject> rcvr(soa.Env(),
366 soa.AddLocalReference<jobject>(receiver));
Ian Rogers556d6372012-11-20 12:19:36 -0800367 jobject jresult;
368 {
369 ScopedThreadStateChange tsc(self, kNative);
370 jresult = fn(soa.Env(), rcvr.get());
371 }
372 result->SetL(soa.Decode<Object*>(jresult));
Jeff Hao3dd9f762013-07-08 13:09:25 -0700373 } else if (shorty == "V") {
374 typedef void (fnptr)(JNIEnv*, jobject);
375 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
376 ScopedLocalRef<jobject> rcvr(soa.Env(),
377 soa.AddLocalReference<jobject>(receiver));
378 ScopedThreadStateChange tsc(self, kNative);
379 fn(soa.Env(), rcvr.get());
Ian Rogers64b6d142012-10-29 16:34:15 -0700380 } else if (shorty == "LL") {
381 typedef jobject (fnptr)(JNIEnv*, jobject, jobject);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700382 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700383 ScopedLocalRef<jobject> rcvr(soa.Env(),
384 soa.AddLocalReference<jobject>(receiver));
385 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800386 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -0800387 jobject jresult;
388 {
389 ScopedThreadStateChange tsc(self, kNative);
390 jresult = fn(soa.Env(), rcvr.get(), arg0.get());
Ian Rogers556d6372012-11-20 12:19:36 -0800391 }
392 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700393 ScopedThreadStateChange tsc(self, kNative);
Ian Rogers64b6d142012-10-29 16:34:15 -0700394 } else if (shorty == "III") {
395 typedef jint (fnptr)(JNIEnv*, jobject, jint, jint);
Ian Rogersd8274bc2013-05-15 15:54:45 -0700396 const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
Ian Rogers64b6d142012-10-29 16:34:15 -0700397 ScopedLocalRef<jobject> rcvr(soa.Env(),
398 soa.AddLocalReference<jobject>(receiver));
399 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800400 result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700401 } else {
402 LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
403 << " shorty: " << shorty;
404 }
405 }
406}
407
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700408static void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
409 ref->MonitorEnter(self);
410}
411
412static void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
413 ref->MonitorExit(self);
414}
415
Ian Rogersba3ce9a2013-05-17 18:50:09 -0700416// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
417// specialization.
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200418template<InvokeType type, bool is_range, bool do_access_check>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200419static bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
Ian Rogersba3ce9a2013-05-17 18:50:09 -0700420 const Instruction* inst, JValue* result) NO_THREAD_SAFETY_ANALYSIS;
421
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200422template<InvokeType type, bool is_range, bool do_access_check>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200423static bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
Ian Rogersba3ce9a2013-05-17 18:50:09 -0700424 const Instruction* inst, JValue* result) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200425 uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
Jeff Hao790ad902013-05-22 15:02:08 -0700426 uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
427 Object* receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
Brian Carlstromea46f952013-07-30 01:26:50 -0700428 ArtMethod* method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
429 do_access_check, type);
Jeff Hao790ad902013-05-22 15:02:08 -0700430 if (UNLIKELY(method == NULL)) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700431 CHECK(self->IsExceptionPending());
432 result->SetJ(0);
Sebastien Hertz1521e952013-07-23 10:02:11 +0200433 return false;
434 } else if (UNLIKELY(method->IsAbstract())) {
435 ThrowAbstractMethodError(method);
436 result->SetJ(0);
437 return false;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700438 }
Jeff Hao16743632013-05-08 10:59:04 -0700439
Jeff Hao790ad902013-05-22 15:02:08 -0700440 MethodHelper mh(method);
441 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Jeff Hao16743632013-05-08 10:59:04 -0700442 uint16_t num_regs;
443 uint16_t num_ins;
Jeff Hao790ad902013-05-22 15:02:08 -0700444 if (LIKELY(code_item != NULL)) {
Jeff Hao16743632013-05-08 10:59:04 -0700445 num_regs = code_item->registers_size_;
446 num_ins = code_item->ins_size_;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700447 } else {
Jeff Hao790ad902013-05-22 15:02:08 -0700448 DCHECK(method->IsNative() || method->IsProxyMethod());
Brian Carlstromea46f952013-07-30 01:26:50 -0700449 num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
Jeff Hao790ad902013-05-22 15:02:08 -0700450 if (!method->IsStatic()) {
Jeff Hao16743632013-05-08 10:59:04 -0700451 num_regs++;
452 num_ins++;
Jeff Hao5d917302013-02-27 17:57:33 -0800453 }
Jeff Hao16743632013-05-08 10:59:04 -0700454 }
455
Jeff Hao66135192013-05-14 11:02:41 -0700456 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
Jeff Hao790ad902013-05-22 15:02:08 -0700457 ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
Jeff Hao16743632013-05-08 10:59:04 -0700458 size_t cur_reg = num_regs - num_ins;
459 if (receiver != NULL) {
460 new_shadow_frame->SetVRegReference(cur_reg, receiver);
461 ++cur_reg;
462 }
463
464 size_t arg_offset = (receiver == NULL) ? 0 : 1;
Jeff Hao790ad902013-05-22 15:02:08 -0700465 const char* shorty = mh.GetShorty();
Sebastien Hertz807a2562013-04-15 09:33:39 +0200466 uint32_t arg[5];
467 if (!is_range) {
468 inst->GetArgs(arg);
469 }
Jeff Hao16743632013-05-08 10:59:04 -0700470 for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
Jeff Hao790ad902013-05-22 15:02:08 -0700471 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
Sebastien Hertz807a2562013-04-15 09:33:39 +0200472 size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
Jeff Hao16743632013-05-08 10:59:04 -0700473 switch (shorty[shorty_pos + 1]) {
474 case 'L': {
475 Object* o = shadow_frame.GetVRegReference(arg_pos);
476 new_shadow_frame->SetVRegReference(cur_reg, o);
477 break;
478 }
479 case 'J': case 'D': {
480 uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
481 static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
482 new_shadow_frame->SetVRegLong(cur_reg, wide_value);
483 cur_reg++;
484 arg_offset++;
485 break;
486 }
487 default:
488 new_shadow_frame->SetVReg(cur_reg, shadow_frame.GetVReg(arg_pos));
489 break;
490 }
491 }
492
Jeff Hao66135192013-05-14 11:02:41 -0700493 if (LIKELY(Runtime::Current()->IsStarted())) {
Jeff Hao790ad902013-05-22 15:02:08 -0700494 (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
Jeff Hao16743632013-05-08 10:59:04 -0700495 } else {
Jeff Hao790ad902013-05-22 15:02:08 -0700496 UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, num_regs - num_ins);
Ian Rogers64b6d142012-10-29 16:34:15 -0700497 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200498 return !self->IsExceptionPending();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700499}
500
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200501// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
502// specialization.
503template<bool is_range>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200504static bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200505 const Instruction* inst, JValue* result)
506 NO_THREAD_SAFETY_ANALYSIS;
507
508template<bool is_range>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200509static bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200510 const Instruction* inst, JValue* result) {
511 uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
512 Object* receiver = shadow_frame.GetVRegReference(vregC);
513 if (UNLIKELY(receiver == NULL)) {
514 // We lost the reference to the method index so we cannot get a more
515 // precised exception message.
516 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Sebastien Hertz1521e952013-07-23 10:02:11 +0200517 return false;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200518 }
519 uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
Sebastien Hertz1521e952013-07-23 10:02:11 +0200520 // TODO: use ObjectArray<T>::GetWithoutChecks ?
Brian Carlstromea46f952013-07-30 01:26:50 -0700521 ArtMethod* method = receiver->GetClass()->GetVTable()->Get(vtable_idx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200522 if (UNLIKELY(method == NULL)) {
523 CHECK(self->IsExceptionPending());
524 result->SetJ(0);
Sebastien Hertz1521e952013-07-23 10:02:11 +0200525 return false;
526 } else if (UNLIKELY(method->IsAbstract())) {
527 ThrowAbstractMethodError(method);
528 result->SetJ(0);
529 return false;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200530 }
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200531
Sebastien Hertz1521e952013-07-23 10:02:11 +0200532 MethodHelper mh(method);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200533 const DexFile::CodeItem* code_item = mh.GetCodeItem();
534 uint16_t num_regs;
535 uint16_t num_ins;
536 if (code_item != NULL) {
537 num_regs = code_item->registers_size_;
538 num_ins = code_item->ins_size_;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200539 } else {
540 DCHECK(method->IsNative() || method->IsProxyMethod());
Brian Carlstromea46f952013-07-30 01:26:50 -0700541 num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200542 if (!method->IsStatic()) {
543 num_regs++;
544 num_ins++;
545 }
546 }
547
548 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
549 ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame,
550 method, 0, memory));
551 size_t cur_reg = num_regs - num_ins;
552 if (receiver != NULL) {
553 new_shadow_frame->SetVRegReference(cur_reg, receiver);
554 ++cur_reg;
555 }
556
557 size_t arg_offset = (receiver == NULL) ? 0 : 1;
558 const char* shorty = mh.GetShorty();
559 uint32_t arg[5];
560 if (!is_range) {
561 inst->GetArgs(arg);
562 }
563 for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
564 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
565 size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
566 switch (shorty[shorty_pos + 1]) {
567 case 'L': {
568 Object* o = shadow_frame.GetVRegReference(arg_pos);
569 new_shadow_frame->SetVRegReference(cur_reg, o);
570 break;
571 }
572 case 'J': case 'D': {
573 uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
574 static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
575 new_shadow_frame->SetVRegLong(cur_reg, wide_value);
576 cur_reg++;
577 arg_offset++;
578 break;
579 }
580 default:
581 new_shadow_frame->SetVReg(cur_reg, shadow_frame.GetVReg(arg_pos));
582 break;
583 }
584 }
585
586 if (LIKELY(Runtime::Current()->IsStarted())) {
587 (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
588 } else {
589 UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, num_regs - num_ins);
590 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200591 return !self->IsExceptionPending();
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200592}
593
Sebastien Hertzc8a3ff82013-05-22 11:26:35 +0200594// We use template functions to optimize compiler inlining process. Otherwise,
595// some parts of the code (like a switch statement) which depend on a constant
596// parameter would not be inlined while it should be. These constant parameters
597// are now part of the template arguments.
598// Note these template functions are static and inlined so they should not be
599// part of the final object file.
Ian Rogersba3ce9a2013-05-17 18:50:09 -0700600// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
601// specialization.
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200602template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200603static bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertzc8a3ff82013-05-22 11:26:35 +0200604 const Instruction* inst)
Ian Rogersba3ce9a2013-05-17 18:50:09 -0700605 NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
Ian Rogersfa46d3e2013-05-15 00:16:04 -0700606
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200607template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200608static inline bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertzc8a3ff82013-05-22 11:26:35 +0200609 const Instruction* inst) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700610 bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200611 uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
Brian Carlstromea46f952013-07-30 01:26:50 -0700612 ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
613 find_type, Primitive::FieldSize(field_type),
614 do_access_check);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200615 if (UNLIKELY(f == NULL)) {
616 CHECK(self->IsExceptionPending());
Sebastien Hertz1521e952013-07-23 10:02:11 +0200617 return false;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200618 }
619 Object* obj;
620 if (is_static) {
621 obj = f->GetDeclaringClass();
622 } else {
623 obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
624 if (UNLIKELY(obj == NULL)) {
625 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
Sebastien Hertz1521e952013-07-23 10:02:11 +0200626 return false;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700627 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200628 }
629 uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c();
630 switch (field_type) {
631 case Primitive::kPrimBoolean:
632 shadow_frame.SetVReg(vregA, f->GetBoolean(obj));
633 break;
634 case Primitive::kPrimByte:
635 shadow_frame.SetVReg(vregA, f->GetByte(obj));
636 break;
637 case Primitive::kPrimChar:
638 shadow_frame.SetVReg(vregA, f->GetChar(obj));
639 break;
640 case Primitive::kPrimShort:
641 shadow_frame.SetVReg(vregA, f->GetShort(obj));
642 break;
643 case Primitive::kPrimInt:
644 shadow_frame.SetVReg(vregA, f->GetInt(obj));
645 break;
646 case Primitive::kPrimLong:
647 shadow_frame.SetVRegLong(vregA, f->GetLong(obj));
648 break;
649 case Primitive::kPrimNot:
650 shadow_frame.SetVRegReference(vregA, f->GetObject(obj));
651 break;
652 default:
653 LOG(FATAL) << "Unreachable: " << field_type;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700654 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200655 return true;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700656}
657
Ian Rogersba3ce9a2013-05-17 18:50:09 -0700658// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
659// specialization.
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200660template<Primitive::Type field_type>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200661static bool DoIGetQuick(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200662 const Instruction* inst)
663 NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
664
665template<Primitive::Type field_type>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200666static inline bool DoIGetQuick(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200667 const Instruction* inst) {
668 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
669 if (UNLIKELY(obj == NULL)) {
670 // We lost the reference to the field index so we cannot get a more
671 // precised exception message.
672 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Sebastien Hertz1521e952013-07-23 10:02:11 +0200673 return false;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200674 }
675 MemberOffset field_offset(inst->VRegC_22c());
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700676 const bool is_volatile = false; // iget-x-quick only on non volatile fields.
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200677 const uint32_t vregA = inst->VRegA_22c();
678 switch (field_type) {
679 case Primitive::kPrimInt:
680 shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetField32(field_offset, is_volatile)));
681 break;
682 case Primitive::kPrimLong:
683 shadow_frame.SetVRegLong(vregA, static_cast<int64_t>(obj->GetField64(field_offset, is_volatile)));
684 break;
685 case Primitive::kPrimNot:
686 shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object*>(field_offset, is_volatile));
687 break;
688 default:
689 LOG(FATAL) << "Unreachable: " << field_type;
690 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200691 return true;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200692}
693
694// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
695// specialization.
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200696template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200697static bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
Sebastien Hertzc8a3ff82013-05-22 11:26:35 +0200698 const Instruction* inst)
Ian Rogersba3ce9a2013-05-17 18:50:09 -0700699 NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
Ian Rogersfa46d3e2013-05-15 00:16:04 -0700700
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200701template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200702static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
Sebastien Hertzc8a3ff82013-05-22 11:26:35 +0200703 const Instruction* inst) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700704 bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200705 uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
Brian Carlstromea46f952013-07-30 01:26:50 -0700706 ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
707 find_type, Primitive::FieldSize(field_type),
708 do_access_check);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200709 if (UNLIKELY(f == NULL)) {
710 CHECK(self->IsExceptionPending());
Sebastien Hertz1521e952013-07-23 10:02:11 +0200711 return false;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200712 }
713 Object* obj;
714 if (is_static) {
715 obj = f->GetDeclaringClass();
716 } else {
717 obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
718 if (UNLIKELY(obj == NULL)) {
719 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
720 f, false);
Sebastien Hertz1521e952013-07-23 10:02:11 +0200721 return false;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700722 }
723 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200724 uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c();
725 switch (field_type) {
726 case Primitive::kPrimBoolean:
727 f->SetBoolean(obj, shadow_frame.GetVReg(vregA));
728 break;
729 case Primitive::kPrimByte:
730 f->SetByte(obj, shadow_frame.GetVReg(vregA));
731 break;
732 case Primitive::kPrimChar:
733 f->SetChar(obj, shadow_frame.GetVReg(vregA));
734 break;
735 case Primitive::kPrimShort:
736 f->SetShort(obj, shadow_frame.GetVReg(vregA));
737 break;
738 case Primitive::kPrimInt:
739 f->SetInt(obj, shadow_frame.GetVReg(vregA));
740 break;
741 case Primitive::kPrimLong:
742 f->SetLong(obj, shadow_frame.GetVRegLong(vregA));
743 break;
744 case Primitive::kPrimNot:
745 f->SetObj(obj, shadow_frame.GetVRegReference(vregA));
746 break;
747 default:
748 LOG(FATAL) << "Unreachable: " << field_type;
749 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200750 return true;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200751}
752
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200753// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
754// specialization.
755template<Primitive::Type field_type>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200756static bool DoIPutQuick(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200757 const Instruction* inst)
758 NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
759
760template<Primitive::Type field_type>
Sebastien Hertz1521e952013-07-23 10:02:11 +0200761static inline bool DoIPutQuick(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200762 const Instruction* inst) {
763 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
764 if (UNLIKELY(obj == NULL)) {
765 // We lost the reference to the field index so we cannot get a more
766 // precised exception message.
767 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Sebastien Hertz1521e952013-07-23 10:02:11 +0200768 return false;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200769 }
770 MemberOffset field_offset(inst->VRegC_22c());
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700771 const bool is_volatile = false; // iput-x-quick only on non volatile fields.
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200772 const uint32_t vregA = inst->VRegA_22c();
773 switch (field_type) {
774 case Primitive::kPrimInt:
775 obj->SetField32(field_offset, shadow_frame.GetVReg(vregA), is_volatile);
776 break;
777 case Primitive::kPrimLong:
778 obj->SetField64(field_offset, shadow_frame.GetVRegLong(vregA), is_volatile);
779 break;
780 case Primitive::kPrimNot:
781 obj->SetFieldObject(field_offset, shadow_frame.GetVRegReference(vregA), is_volatile);
782 break;
783 default:
784 LOG(FATAL) << "Unreachable: " << field_type;
785 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200786 return true;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200787}
788
Ian Rogers33e95662013-05-20 20:29:14 -0700789static inline String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx)
790 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200791 Class* java_lang_string_class = String::GetJavaLangString();
792 if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
793 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
794 if (UNLIKELY(!class_linker->EnsureInitialized(java_lang_string_class,
795 true, true))) {
796 DCHECK(self->IsExceptionPending());
797 return NULL;
798 }
799 }
800 return mh.ResolveString(string_idx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700801}
802
Sebastien Hertz1521e952013-07-23 10:02:11 +0200803static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200804 int32_t dividend, int32_t divisor)
805 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800806 if (UNLIKELY(divisor == 0)) {
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200807 ThrowArithmeticExceptionDivideByZero();
Sebastien Hertz1521e952013-07-23 10:02:11 +0200808 return false;
809 }
810 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
jeffhaod91398c2012-11-20 17:17:33 -0800811 shadow_frame.SetVReg(result_reg, kMinInt);
812 } else {
813 shadow_frame.SetVReg(result_reg, dividend / divisor);
814 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200815 return true;
jeffhaod91398c2012-11-20 17:17:33 -0800816}
817
Sebastien Hertz1521e952013-07-23 10:02:11 +0200818static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200819 int32_t dividend, int32_t divisor)
820 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800821 if (UNLIKELY(divisor == 0)) {
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200822 ThrowArithmeticExceptionDivideByZero();
Sebastien Hertz1521e952013-07-23 10:02:11 +0200823 return false;
824 }
825 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
jeffhaod91398c2012-11-20 17:17:33 -0800826 shadow_frame.SetVReg(result_reg, 0);
827 } else {
828 shadow_frame.SetVReg(result_reg, dividend % divisor);
829 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200830 return true;
jeffhaod91398c2012-11-20 17:17:33 -0800831}
832
Sebastien Hertz1521e952013-07-23 10:02:11 +0200833static inline bool DoLongDivide(ShadowFrame& shadow_frame, size_t result_reg,
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200834 int64_t dividend, int64_t divisor)
835 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800836 if (UNLIKELY(divisor == 0)) {
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200837 ThrowArithmeticExceptionDivideByZero();
Sebastien Hertz1521e952013-07-23 10:02:11 +0200838 return false;
839 }
840 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
jeffhaod91398c2012-11-20 17:17:33 -0800841 shadow_frame.SetVRegLong(result_reg, kMinLong);
842 } else {
843 shadow_frame.SetVRegLong(result_reg, dividend / divisor);
844 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200845 return true;
jeffhaod91398c2012-11-20 17:17:33 -0800846}
847
Sebastien Hertz1521e952013-07-23 10:02:11 +0200848static inline bool DoLongRemainder(ShadowFrame& shadow_frame, size_t result_reg,
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200849 int64_t dividend, int64_t divisor)
850 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800851 if (UNLIKELY(divisor == 0)) {
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200852 ThrowArithmeticExceptionDivideByZero();
Sebastien Hertz1521e952013-07-23 10:02:11 +0200853 return false;
854 }
855 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
jeffhaod91398c2012-11-20 17:17:33 -0800856 shadow_frame.SetVRegLong(result_reg, 0);
857 } else {
858 shadow_frame.SetVRegLong(result_reg, dividend % divisor);
859 }
Sebastien Hertz1521e952013-07-23 10:02:11 +0200860 return true;
jeffhaod91398c2012-11-20 17:17:33 -0800861}
862
Sebastien Hertz24bbb102013-06-28 09:57:10 +0200863// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
864// specialization.
865// Returns true on success, otherwise throws an exception and returns false.
866template <bool is_range, bool do_access_check>
867static bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
868 Thread* self, JValue* result)
869 NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
870
871template <bool is_range, bool do_access_check>
872static inline bool DoFilledNewArray(const Instruction* inst,
873 const ShadowFrame& shadow_frame,
874 Thread* self, JValue* result) {
875 DCHECK(inst->Opcode() == Instruction::FILLED_NEW_ARRAY ||
876 inst->Opcode() == Instruction::FILLED_NEW_ARRAY_RANGE);
877 const int32_t length = is_range ? inst->VRegA_3rc() : inst->VRegA_35c();
878 if (!is_range) {
879 // Checks FILLED_NEW_ARRAY's length does not exceed 5 arguments.
880 CHECK_LE(length, 5);
881 }
882 if (UNLIKELY(length < 0)) {
883 ThrowNegativeArraySizeException(length);
884 return false;
885 }
886 uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
887 Class* arrayClass = ResolveVerifyAndClinit(type_idx, shadow_frame.GetMethod(),
888 self, false, do_access_check);
889 if (UNLIKELY(arrayClass == NULL)) {
890 DCHECK(self->IsExceptionPending());
891 return false;
892 }
893 CHECK(arrayClass->IsArrayClass());
894 Class* componentClass = arrayClass->GetComponentType();
895 if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
896 if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
897 ThrowRuntimeException("Bad filled array request for type %s",
898 PrettyDescriptor(componentClass).c_str());
899 } else {
900 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
901 "Ljava/lang/InternalError;",
902 "Found type %s; filled-new-array not implemented for anything but \'int\'",
903 PrettyDescriptor(componentClass).c_str());
904 }
905 return false;
906 }
907 Object* newArray = Array::Alloc(self, arrayClass, length);
908 if (UNLIKELY(newArray == NULL)) {
909 DCHECK(self->IsExceptionPending());
910 return false;
911 }
912 if (is_range) {
913 uint32_t vregC = inst->VRegC_3rc();
914 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
915 for (int32_t i = 0; i < length; ++i) {
916 if (is_primitive_int_component) {
917 newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(vregC + i));
918 } else {
919 newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(vregC + i));
920 }
921 }
922 } else {
923 uint32_t arg[5];
924 inst->GetArgs(arg);
925 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
926 for (int32_t i = 0; i < length; ++i) {
927 if (is_primitive_int_component) {
928 newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(arg[i]));
929 } else {
930 newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(arg[i]));
931 }
932 }
933 }
934
935 result->SetL(newArray);
936 return true;
937}
938
Sebastien Hertz2cb33b82013-06-28 10:01:18 +0200939static inline const Instruction* DoSparseSwitch(const Instruction* inst,
940 const ShadowFrame& shadow_frame)
941 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
942 DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
943 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
944 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
945 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
946 uint16_t size = switch_data[1];
947 DCHECK_GT(size, 0);
948 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
949 DCHECK(IsAligned<4>(keys));
950 const int32_t* entries = keys + size;
951 DCHECK(IsAligned<4>(entries));
952 int lo = 0;
953 int hi = size - 1;
954 while (lo <= hi) {
955 int mid = (lo + hi) / 2;
956 int32_t foundVal = keys[mid];
957 if (test_val < foundVal) {
958 hi = mid - 1;
959 } else if (test_val > foundVal) {
960 lo = mid + 1;
961 } else {
962 return inst->RelativeAt(entries[mid]);
963 }
964 }
965 return inst->Next_3xx();
966}
967
Ian Rogersfa46d3e2013-05-15 00:16:04 -0700968static inline const Instruction* FindNextInstructionFollowingException(Thread* self,
969 ShadowFrame& shadow_frame,
970 uint32_t dex_pc,
971 const uint16_t* insns,
972 SirtRef<Object>& this_object_ref,
973 instrumentation::Instrumentation* instrumentation)
974 ALWAYS_INLINE;
975
976static inline const Instruction* FindNextInstructionFollowingException(Thread* self,
977 ShadowFrame& shadow_frame,
978 uint32_t dex_pc,
979 const uint16_t* insns,
980 SirtRef<Object>& this_object_ref,
Ian Rogers33e95662013-05-20 20:29:14 -0700981 instrumentation::Instrumentation* instrumentation)
982 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Jeff Hao9cec2472013-05-14 18:17:06 -0700983 self->VerifyStack();
984 ThrowLocation throw_location;
985 mirror::Throwable* exception = self->GetException(&throw_location);
Ian Rogersc449aa82013-07-29 14:35:46 -0700986 bool clear_exception;
987 uint32_t found_dex_pc = shadow_frame.GetMethod()->FindCatchBlock(exception->GetClass(), dex_pc,
988 &clear_exception);
Jeff Hao9cec2472013-05-14 18:17:06 -0700989 if (found_dex_pc == DexFile::kDexNoIndex) {
990 instrumentation->MethodUnwindEvent(self, this_object_ref.get(),
991 shadow_frame.GetMethod(), dex_pc);
992 return NULL;
993 } else {
994 instrumentation->ExceptionCaughtEvent(self, throw_location,
995 shadow_frame.GetMethod(),
996 found_dex_pc, exception);
Ian Rogersc449aa82013-07-29 14:35:46 -0700997 if (clear_exception) {
998 self->ClearException();
999 }
Jeff Hao9cec2472013-05-14 18:17:06 -07001000 return Instruction::At(insns + found_dex_pc);
1001 }
1002}
1003
1004#define HANDLE_PENDING_EXCEPTION() \
1005 CHECK(self->IsExceptionPending()); \
Ian Rogersd8274bc2013-05-15 15:54:45 -07001006 inst = FindNextInstructionFollowingException(self, shadow_frame, inst->GetDexPc(insns), insns, \
Jeff Hao9cec2472013-05-14 18:17:06 -07001007 this_object_ref, instrumentation); \
1008 if (inst == NULL) { \
1009 return JValue(); /* Handled in caller. */ \
1010 }
1011
Sebastien Hertz1521e952013-07-23 10:02:11 +02001012#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
1013 if (UNLIKELY(is_exception_pending)) { \
1014 HANDLE_PENDING_EXCEPTION(); \
Jeff Hao9cec2472013-05-14 18:17:06 -07001015 } else { \
Brian Carlstromdf629502013-07-17 22:39:56 -07001016 inst = inst->next_function(); \
Jeff Hao9cec2472013-05-14 18:17:06 -07001017 }
1018
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001019static void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh)
Brian Carlstromdf629502013-07-17 22:39:56 -07001020 __attribute__((cold, noreturn, noinline));
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001021
Ian Rogers33e95662013-05-20 20:29:14 -07001022static void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh)
1023 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001024 LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(&mh.GetDexFile());
1025 exit(0); // Unreachable, keep GCC happy.
1026}
1027
Ian Rogersd8274bc2013-05-15 15:54:45 -07001028// Code to run before each dex instruction.
1029#define PREAMBLE()
1030
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02001031// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
1032// specialization.
1033template<bool do_access_check>
1034static JValue ExecuteImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
Ian Rogers306057f2012-11-26 12:45:53 -08001035 ShadowFrame& shadow_frame, JValue result_register)
Brian Carlstromdf629502013-07-17 22:39:56 -07001036 NO_THREAD_SAFETY_ANALYSIS __attribute__((hot));
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001037
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02001038template<bool do_access_check>
1039static JValue ExecuteImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001040 ShadowFrame& shadow_frame, JValue result_register) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001041 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
1042 LOG(FATAL) << "Invalid shadow frame for interpreter use";
1043 return JValue();
1044 }
1045 self->VerifyStack();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001046 instrumentation::Instrumentation* const instrumentation = Runtime::Current()->GetInstrumentation();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001047
1048 // As the 'this' object won't change during the execution of current code, we
1049 // want to cache it in local variables. Nevertheless, in order to let the
1050 // garbage collector access it, we store it into sirt references.
Jeff Haoe701f482013-05-24 11:50:49 -07001051 SirtRef<Object> this_object_ref(self, shadow_frame.GetThisObject(code_item->ins_size_));
Sebastien Hertz807a2562013-04-15 09:33:39 +02001052
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001053 uint32_t dex_pc = shadow_frame.GetDexPC();
1054 if (LIKELY(dex_pc == 0)) { // We are entering the method as opposed to deoptimizing..
Sebastien Hertz74109f62013-06-07 17:40:09 +02001055 if (UNLIKELY(instrumentation->HasMethodEntryListeners())) {
1056 instrumentation->MethodEnterEvent(self, this_object_ref.get(),
1057 shadow_frame.GetMethod(), 0);
1058 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001059 }
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001060 const uint16_t* const insns = code_item->insns_;
1061 const Instruction* inst = Instruction::At(insns + dex_pc);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001062 while (true) {
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001063 dex_pc = inst->GetDexPc(insns);
1064 shadow_frame.SetDexPC(dex_pc);
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001065 if (UNLIKELY(self->TestAllFlags())) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001066 CheckSuspend(self);
1067 }
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001068 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
Sebastien Hertz74109f62013-06-07 17:40:09 +02001069 instrumentation->DexPcMovedEvent(self, this_object_ref.get(),
1070 shadow_frame.GetMethod(), dex_pc);
1071 }
Ian Rogers64b6d142012-10-29 16:34:15 -07001072 const bool kTracing = false;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001073 if (kTracing) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001074#define TRACE_LOG std::cerr
1075 TRACE_LOG << PrettyMethod(shadow_frame.GetMethod())
Sebastien Hertz807a2562013-04-15 09:33:39 +02001076 << StringPrintf("\n0x%x: ", dex_pc)
Ian Rogers62d6c772013-02-27 08:32:07 -08001077 << inst->DumpString(&mh.GetDexFile()) << "\n";
TDYa127ce4cc0d2012-11-18 16:59:53 -08001078 for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001079 uint32_t raw_value = shadow_frame.GetVReg(i);
1080 Object* ref_value = shadow_frame.GetVRegReference(i);
1081 TRACE_LOG << StringPrintf(" vreg%d=0x%08X", i, raw_value);
1082 if (ref_value != NULL) {
1083 if (ref_value->GetClass()->IsStringClass() &&
1084 ref_value->AsString()->GetCharArray() != NULL) {
1085 TRACE_LOG << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001086 } else {
Ian Rogers62d6c772013-02-27 08:32:07 -08001087 TRACE_LOG << "/" << PrettyTypeOf(ref_value);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001088 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001089 }
1090 }
Ian Rogers62d6c772013-02-27 08:32:07 -08001091 TRACE_LOG << "\n";
1092#undef TRACE_LOG
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001093 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001094 switch (inst->Opcode()) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001095 case Instruction::NOP:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001096 PREAMBLE();
Jeff Hao9cec2472013-05-14 18:17:06 -07001097 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001098 break;
1099 case Instruction::MOVE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001100 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001101 shadow_frame.SetVReg(inst->VRegA_12x(),
1102 shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001103 inst = inst->Next_1xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001104 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001105 case Instruction::MOVE_FROM16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001106 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001107 shadow_frame.SetVReg(inst->VRegA_22x(),
1108 shadow_frame.GetVReg(inst->VRegB_22x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001109 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001110 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001111 case Instruction::MOVE_16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001112 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001113 shadow_frame.SetVReg(inst->VRegA_32x(),
1114 shadow_frame.GetVReg(inst->VRegB_32x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001115 inst = inst->Next_3xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001116 break;
1117 case Instruction::MOVE_WIDE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001118 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001119 shadow_frame.SetVRegLong(inst->VRegA_12x(),
1120 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001121 inst = inst->Next_1xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001122 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001123 case Instruction::MOVE_WIDE_FROM16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001124 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001125 shadow_frame.SetVRegLong(inst->VRegA_22x(),
1126 shadow_frame.GetVRegLong(inst->VRegB_22x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001127 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001128 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001129 case Instruction::MOVE_WIDE_16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001130 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001131 shadow_frame.SetVRegLong(inst->VRegA_32x(),
1132 shadow_frame.GetVRegLong(inst->VRegB_32x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001133 inst = inst->Next_3xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001134 break;
1135 case Instruction::MOVE_OBJECT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001136 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001137 shadow_frame.SetVRegReference(inst->VRegA_12x(),
1138 shadow_frame.GetVRegReference(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001139 inst = inst->Next_1xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001140 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001141 case Instruction::MOVE_OBJECT_FROM16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001142 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001143 shadow_frame.SetVRegReference(inst->VRegA_22x(),
1144 shadow_frame.GetVRegReference(inst->VRegB_22x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001145 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001146 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001147 case Instruction::MOVE_OBJECT_16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001148 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001149 shadow_frame.SetVRegReference(inst->VRegA_32x(),
1150 shadow_frame.GetVRegReference(inst->VRegB_32x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07001151 inst = inst->Next_3xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001152 break;
1153 case Instruction::MOVE_RESULT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001154 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001155 shadow_frame.SetVReg(inst->VRegA_11x(), result_register.GetI());
Jeff Hao9cec2472013-05-14 18:17:06 -07001156 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001157 break;
1158 case Instruction::MOVE_RESULT_WIDE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001159 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001160 shadow_frame.SetVRegLong(inst->VRegA_11x(), result_register.GetJ());
Jeff Hao9cec2472013-05-14 18:17:06 -07001161 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001162 break;
1163 case Instruction::MOVE_RESULT_OBJECT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001164 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001165 shadow_frame.SetVRegReference(inst->VRegA_11x(), result_register.GetL());
Jeff Hao9cec2472013-05-14 18:17:06 -07001166 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001167 break;
1168 case Instruction::MOVE_EXCEPTION: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001169 PREAMBLE();
Ian Rogers62d6c772013-02-27 08:32:07 -08001170 Throwable* exception = self->GetException(NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001171 self->ClearException();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001172 shadow_frame.SetVRegReference(inst->VRegA_11x(), exception);
Jeff Hao9cec2472013-05-14 18:17:06 -07001173 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001174 break;
1175 }
1176 case Instruction::RETURN_VOID: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001177 PREAMBLE();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001178 JValue result;
Sebastien Hertz74109f62013-06-07 17:40:09 +02001179 if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
1180 instrumentation->MethodExitEvent(self, this_object_ref.get(),
1181 shadow_frame.GetMethod(), inst->GetDexPc(insns),
1182 result);
1183 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001184 return result;
1185 }
Sebastien Hertzcc10e0e2013-06-28 14:24:48 +02001186 case Instruction::RETURN_VOID_BARRIER: {
1187 PREAMBLE();
1188 ANDROID_MEMBAR_STORE();
1189 JValue result;
1190 if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
1191 instrumentation->MethodExitEvent(self, this_object_ref.get(),
1192 shadow_frame.GetMethod(), inst->GetDexPc(insns),
1193 result);
1194 }
1195 return result;
1196 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001197 case Instruction::RETURN: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001198 PREAMBLE();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001199 JValue result;
1200 result.SetJ(0);
Sebastien Hertz807a2562013-04-15 09:33:39 +02001201 result.SetI(shadow_frame.GetVReg(inst->VRegA_11x()));
Sebastien Hertz74109f62013-06-07 17:40:09 +02001202 if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
1203 instrumentation->MethodExitEvent(self, this_object_ref.get(),
1204 shadow_frame.GetMethod(), inst->GetDexPc(insns),
1205 result);
1206 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001207 return result;
1208 }
1209 case Instruction::RETURN_WIDE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001210 PREAMBLE();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001211 JValue result;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001212 result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x()));
Sebastien Hertz74109f62013-06-07 17:40:09 +02001213 if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
1214 instrumentation->MethodExitEvent(self, this_object_ref.get(),
1215 shadow_frame.GetMethod(), inst->GetDexPc(insns),
1216 result);
1217 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001218 return result;
1219 }
1220 case Instruction::RETURN_OBJECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001221 PREAMBLE();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001222 JValue result;
1223 result.SetJ(0);
Sebastien Hertz807a2562013-04-15 09:33:39 +02001224 result.SetL(shadow_frame.GetVRegReference(inst->VRegA_11x()));
Sebastien Hertz74109f62013-06-07 17:40:09 +02001225 if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
1226 instrumentation->MethodExitEvent(self, this_object_ref.get(),
1227 shadow_frame.GetMethod(), inst->GetDexPc(insns),
1228 result);
1229 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001230 return result;
1231 }
1232 case Instruction::CONST_4: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001233 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001234 uint4_t dst = inst->VRegA_11n();
1235 int4_t val = inst->VRegB_11n();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001236 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001237 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001238 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001239 }
Jeff Hao9cec2472013-05-14 18:17:06 -07001240 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001241 break;
1242 }
1243 case Instruction::CONST_16: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001244 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001245 uint8_t dst = inst->VRegA_21s();
1246 int16_t val = inst->VRegB_21s();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001247 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001248 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001249 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001250 }
Jeff Hao9cec2472013-05-14 18:17:06 -07001251 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001252 break;
1253 }
1254 case Instruction::CONST: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001255 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001256 uint8_t dst = inst->VRegA_31i();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001257 int32_t val = inst->VRegB_31i();
1258 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001259 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001260 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001261 }
Jeff Hao9cec2472013-05-14 18:17:06 -07001262 inst = inst->Next_3xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001263 break;
1264 }
1265 case Instruction::CONST_HIGH16: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001266 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02001267 uint8_t dst = inst->VRegA_21h();
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02001268 int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
Sebastien Hertz807a2562013-04-15 09:33:39 +02001269 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001270 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001271 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001272 }
Jeff Hao9cec2472013-05-14 18:17:06 -07001273 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001274 break;
1275 }
Ian Rogers64b6d142012-10-29 16:34:15 -07001276 case Instruction::CONST_WIDE_16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001277 PREAMBLE();
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02001278 shadow_frame.SetVRegLong(inst->VRegA_21s(), inst->VRegB_21s());
Jeff Hao9cec2472013-05-14 18:17:06 -07001279 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001280 break;
Ian Rogers64b6d142012-10-29 16:34:15 -07001281 case Instruction::CONST_WIDE_32:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001282 PREAMBLE();
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02001283 shadow_frame.SetVRegLong(inst->VRegA_31i(), inst->VRegB_31i());
Jeff Hao9cec2472013-05-14 18:17:06 -07001284 inst = inst->Next_3xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001285 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001286 case Instruction::CONST_WIDE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07001287 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001288 shadow_frame.SetVRegLong(inst->VRegA_51l(), inst->VRegB_51l());
Jeff Hao9cec2472013-05-14 18:17:06 -07001289 inst = inst->Next_51l();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001290 break;
1291 case Instruction::CONST_WIDE_HIGH16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001292 shadow_frame.SetVRegLong(inst->VRegA_21h(),
1293 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
Jeff Hao9cec2472013-05-14 18:17:06 -07001294 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001295 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001296 case Instruction::CONST_STRING: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001297 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001298 String* s = ResolveString(self, mh, inst->VRegB_21c());
1299 if (UNLIKELY(s == NULL)) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001300 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001301 } else {
Brian Carlstromdf629502013-07-17 22:39:56 -07001302 shadow_frame.SetVRegReference(inst->VRegA_21c(), s);
Jeff Hao9cec2472013-05-14 18:17:06 -07001303 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001304 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001305 break;
1306 }
1307 case Instruction::CONST_STRING_JUMBO: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001308 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001309 String* s = ResolveString(self, mh, inst->VRegB_31c());
1310 if (UNLIKELY(s == NULL)) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001311 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001312 } else {
Brian Carlstromdf629502013-07-17 22:39:56 -07001313 shadow_frame.SetVRegReference(inst->VRegA_31c(), s);
Jeff Hao9cec2472013-05-14 18:17:06 -07001314 inst = inst->Next_3xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001315 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001316 break;
1317 }
jeffhao0a9bb732012-11-26 12:28:49 -08001318 case Instruction::CONST_CLASS: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001319 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001320 Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02001321 self, false, do_access_check);
Sebastien Hertz807a2562013-04-15 09:33:39 +02001322 if (UNLIKELY(c == NULL)) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001323 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001324 } else {
1325 shadow_frame.SetVRegReference(inst->VRegA_21c(), c);
Jeff Hao9cec2472013-05-14 18:17:06 -07001326 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001327 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001328 break;
jeffhao0a9bb732012-11-26 12:28:49 -08001329 }
jeffhao87a6edd2012-11-20 18:05:18 -08001330 case Instruction::MONITOR_ENTER: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001331 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001332 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x());
jeffhao87a6edd2012-11-20 18:05:18 -08001333 if (UNLIKELY(obj == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001334 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Sebastien Hertze15e7fa2013-05-17 14:20:05 +02001335 HANDLE_PENDING_EXCEPTION();
jeffhao87a6edd2012-11-20 18:05:18 -08001336 } else {
1337 DoMonitorEnter(self, obj);
Sebastien Hertz1521e952013-07-23 10:02:11 +02001338 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
jeffhao87a6edd2012-11-20 18:05:18 -08001339 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001340 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001341 }
1342 case Instruction::MONITOR_EXIT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001343 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001344 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x());
jeffhao87a6edd2012-11-20 18:05:18 -08001345 if (UNLIKELY(obj == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001346 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Sebastien Hertze15e7fa2013-05-17 14:20:05 +02001347 HANDLE_PENDING_EXCEPTION();
jeffhao87a6edd2012-11-20 18:05:18 -08001348 } else {
1349 DoMonitorExit(self, obj);
Sebastien Hertz1521e952013-07-23 10:02:11 +02001350 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
jeffhao87a6edd2012-11-20 18:05:18 -08001351 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001352 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001353 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001354 case Instruction::CHECK_CAST: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001355 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001356 Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02001357 self, false, do_access_check);
jeffhao87a6edd2012-11-20 18:05:18 -08001358 if (UNLIKELY(c == NULL)) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001359 HANDLE_PENDING_EXCEPTION();
jeffhao87a6edd2012-11-20 18:05:18 -08001360 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001361 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_21c());
jeffhao87a6edd2012-11-20 18:05:18 -08001362 if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001363 ThrowClassCastException(c, obj->GetClass());
Jeff Hao9cec2472013-05-14 18:17:06 -07001364 HANDLE_PENDING_EXCEPTION();
1365 } else {
1366 inst = inst->Next_2xx();
jeffhao87a6edd2012-11-20 18:05:18 -08001367 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001368 }
1369 break;
1370 }
1371 case Instruction::INSTANCE_OF: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001372 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001373 Class* c = ResolveVerifyAndClinit(inst->VRegC_22c(), shadow_frame.GetMethod(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02001374 self, false, do_access_check);
jeffhao87a6edd2012-11-20 18:05:18 -08001375 if (UNLIKELY(c == NULL)) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001376 HANDLE_PENDING_EXCEPTION();
jeffhao87a6edd2012-11-20 18:05:18 -08001377 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001378 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
1379 shadow_frame.SetVReg(inst->VRegA_22c(), (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
Jeff Hao9cec2472013-05-14 18:17:06 -07001380 inst = inst->Next_2xx();
jeffhao87a6edd2012-11-20 18:05:18 -08001381 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001382 break;
1383 }
1384 case Instruction::ARRAY_LENGTH: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001385 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001386 Object* array = shadow_frame.GetVRegReference(inst->VRegB_12x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001387 if (UNLIKELY(array == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001388 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001389 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02001390 } else {
1391 shadow_frame.SetVReg(inst->VRegA_12x(), array->AsArray()->GetLength());
1392 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001393 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001394 break;
1395 }
1396 case Instruction::NEW_INSTANCE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001397 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001398 Object* obj = AllocObjectFromCode(inst->VRegB_21c(), shadow_frame.GetMethod(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02001399 self, do_access_check);
Sebastien Hertz807a2562013-04-15 09:33:39 +02001400 if (UNLIKELY(obj == NULL)) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001401 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001402 } else {
1403 shadow_frame.SetVRegReference(inst->VRegA_21c(), obj);
Jeff Hao9cec2472013-05-14 18:17:06 -07001404 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001405 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001406 break;
1407 }
1408 case Instruction::NEW_ARRAY: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001409 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001410 int32_t length = shadow_frame.GetVReg(inst->VRegB_22c());
1411 Object* obj = AllocArrayFromCode(inst->VRegC_22c(), shadow_frame.GetMethod(),
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02001412 length, self, do_access_check);
Sebastien Hertz807a2562013-04-15 09:33:39 +02001413 if (UNLIKELY(obj == NULL)) {
Jeff Hao9cec2472013-05-14 18:17:06 -07001414 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001415 } else {
1416 shadow_frame.SetVRegReference(inst->VRegA_22c(), obj);
Jeff Hao9cec2472013-05-14 18:17:06 -07001417 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001418 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001419 break;
1420 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001421 case Instruction::FILLED_NEW_ARRAY: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001422 PREAMBLE();
Sebastien Hertz24bbb102013-06-28 09:57:10 +02001423 bool success = DoFilledNewArray<false, do_access_check>(inst, shadow_frame,
1424 self, &result_register);
Sebastien Hertz1521e952013-07-23 10:02:11 +02001425 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001426 break;
Ian Rogers64b6d142012-10-29 16:34:15 -07001427 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001428 case Instruction::FILLED_NEW_ARRAY_RANGE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001429 PREAMBLE();
Sebastien Hertz24bbb102013-06-28 09:57:10 +02001430 bool success = DoFilledNewArray<true, do_access_check>(inst, shadow_frame,
1431 self, &result_register);
Sebastien Hertz1521e952013-07-23 10:02:11 +02001432 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001433 break;
1434 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001435 case Instruction::FILL_ARRAY_DATA: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001436 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001437 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_31t());
1438 if (UNLIKELY(obj == NULL)) {
1439 ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
Jeff Hao9cec2472013-05-14 18:17:06 -07001440 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001441 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001442 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001443 Array* array = obj->AsArray();
1444 DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02001445 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001446 const Instruction::ArrayDataPayload* payload =
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02001447 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
Sebastien Hertz807a2562013-04-15 09:33:39 +02001448 if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
1449 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
1450 "Ljava/lang/ArrayIndexOutOfBoundsException;",
1451 "failed FILL_ARRAY_DATA; length=%d, index=%d",
1452 array->GetLength(), payload->element_count);
Jeff Hao9cec2472013-05-14 18:17:06 -07001453 HANDLE_PENDING_EXCEPTION();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001454 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001455 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001456 uint32_t size_in_bytes = payload->element_count * payload->element_width;
1457 memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
Jeff Hao9cec2472013-05-14 18:17:06 -07001458 inst = inst->Next_3xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001459 break;
1460 }
1461 case Instruction::THROW: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001462 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001463 Object* exception = shadow_frame.GetVRegReference(inst->VRegA_11x());
1464 if (UNLIKELY(exception == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001465 ThrowNullPointerException(NULL, "throw with null exception");
1466 } else {
1467 self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
1468 }
Jeff Hao9cec2472013-05-14 18:17:06 -07001469 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001470 break;
1471 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001472 case Instruction::GOTO: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001473 PREAMBLE();
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001474 inst = inst->RelativeAt(inst->VRegA_10t());
Sebastien Hertz807a2562013-04-15 09:33:39 +02001475 break;
1476 }
1477 case Instruction::GOTO_16: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001478 PREAMBLE();
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001479 inst = inst->RelativeAt(inst->VRegA_20t());
Sebastien Hertz807a2562013-04-15 09:33:39 +02001480 break;
1481 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001482 case Instruction::GOTO_32: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001483 PREAMBLE();
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001484 inst = inst->RelativeAt(inst->VRegA_30t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001485 break;
1486 }
Ian Rogers556d6372012-11-20 12:19:36 -08001487 case Instruction::PACKED_SWITCH: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001488 PREAMBLE();
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001489 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001490 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
Ian Rogersd8274bc2013-05-15 15:54:45 -07001491 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
Ian Rogers556d6372012-11-20 12:19:36 -08001492 uint16_t size = switch_data[1];
Ian Rogersd8274bc2013-05-15 15:54:45 -07001493 DCHECK_GT(size, 0);
Ian Rogers556d6372012-11-20 12:19:36 -08001494 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
Sebastien Hertz443dcc32013-06-07 17:06:05 +02001495 DCHECK(IsAligned<4>(keys));
Ian Rogers556d6372012-11-20 12:19:36 -08001496 int32_t first_key = keys[0];
1497 const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
Ian Rogersd8274bc2013-05-15 15:54:45 -07001498 DCHECK(IsAligned<4>(targets));
Ian Rogers556d6372012-11-20 12:19:36 -08001499 int32_t index = test_val - first_key;
1500 if (index >= 0 && index < size) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001501 inst = inst->RelativeAt(targets[index]);
Jeff Hao9cec2472013-05-14 18:17:06 -07001502 } else {
1503 inst = inst->Next_3xx();
Ian Rogers556d6372012-11-20 12:19:36 -08001504 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001505 break;
Ian Rogers556d6372012-11-20 12:19:36 -08001506 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001507 case Instruction::SPARSE_SWITCH: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001508 PREAMBLE();
Sebastien Hertz2cb33b82013-06-28 10:01:18 +02001509 inst = DoSparseSwitch(inst, shadow_frame);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001510 break;
1511 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001512 case Instruction::CMPL_FLOAT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001513 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001514 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
1515 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
1516 int32_t result;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001517 if (val1 > val2) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001518 result = 1;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001519 } else if (val1 == val2) {
1520 result = 0;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001521 } else {
1522 result = -1;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001523 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001524 shadow_frame.SetVReg(inst->VRegA_23x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07001525 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001526 break;
1527 }
1528 case Instruction::CMPG_FLOAT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001529 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001530 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
1531 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
1532 int32_t result;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001533 if (val1 < val2) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001534 result = -1;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001535 } else if (val1 == val2) {
1536 result = 0;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001537 } else {
1538 result = 1;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001539 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001540 shadow_frame.SetVReg(inst->VRegA_23x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07001541 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001542 break;
1543 }
1544 case Instruction::CMPL_DOUBLE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001545 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001546 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
1547 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
1548 int32_t result;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001549 if (val1 > val2) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001550 result = 1;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001551 } else if (val1 == val2) {
1552 result = 0;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001553 } else {
1554 result = -1;
1555 }
1556 shadow_frame.SetVReg(inst->VRegA_23x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07001557 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001558 break;
1559 }
1560
1561 case Instruction::CMPG_DOUBLE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001562 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001563 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
1564 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
1565 int32_t result;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001566 if (val1 < val2) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001567 result = -1;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07001568 } else if (val1 == val2) {
1569 result = 0;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001570 } else {
1571 result = 1;
1572 }
1573 shadow_frame.SetVReg(inst->VRegA_23x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07001574 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001575 break;
1576 }
1577 case Instruction::CMP_LONG: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001578 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001579 int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
1580 int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
1581 int32_t result;
1582 if (val1 > val2) {
1583 result = 1;
1584 } else if (val1 == val2) {
1585 result = 0;
1586 } else {
1587 result = -1;
1588 }
1589 shadow_frame.SetVReg(inst->VRegA_23x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07001590 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001591 break;
1592 }
1593 case Instruction::IF_EQ: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001594 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001595 if (shadow_frame.GetVReg(inst->VRegA_22t()) == shadow_frame.GetVReg(inst->VRegB_22t())) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001596 inst = inst->RelativeAt(inst->VRegC_22t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001597 } else {
1598 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001599 }
1600 break;
1601 }
1602 case Instruction::IF_NE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001603 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001604 if (shadow_frame.GetVReg(inst->VRegA_22t()) != shadow_frame.GetVReg(inst->VRegB_22t())) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001605 inst = inst->RelativeAt(inst->VRegC_22t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001606 } else {
1607 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001608 }
1609 break;
1610 }
1611 case Instruction::IF_LT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001612 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001613 if (shadow_frame.GetVReg(inst->VRegA_22t()) < shadow_frame.GetVReg(inst->VRegB_22t())) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001614 inst = inst->RelativeAt(inst->VRegC_22t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001615 } else {
1616 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001617 }
1618 break;
1619 }
1620 case Instruction::IF_GE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001621 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001622 if (shadow_frame.GetVReg(inst->VRegA_22t()) >= shadow_frame.GetVReg(inst->VRegB_22t())) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001623 inst = inst->RelativeAt(inst->VRegC_22t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001624 } else {
1625 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001626 }
1627 break;
1628 }
1629 case Instruction::IF_GT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001630 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001631 if (shadow_frame.GetVReg(inst->VRegA_22t()) > shadow_frame.GetVReg(inst->VRegB_22t())) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001632 inst = inst->RelativeAt(inst->VRegC_22t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001633 } else {
1634 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001635 }
1636 break;
1637 }
1638 case Instruction::IF_LE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001639 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001640 if (shadow_frame.GetVReg(inst->VRegA_22t()) <= shadow_frame.GetVReg(inst->VRegB_22t())) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001641 inst = inst->RelativeAt(inst->VRegC_22t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001642 } else {
1643 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001644 }
1645 break;
1646 }
1647 case Instruction::IF_EQZ: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001648 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001649 if (shadow_frame.GetVReg(inst->VRegA_21t()) == 0) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001650 inst = inst->RelativeAt(inst->VRegB_21t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001651 } else {
1652 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001653 }
1654 break;
1655 }
1656 case Instruction::IF_NEZ: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001657 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001658 if (shadow_frame.GetVReg(inst->VRegA_21t()) != 0) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001659 inst = inst->RelativeAt(inst->VRegB_21t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001660 } else {
1661 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001662 }
1663 break;
1664 }
1665 case Instruction::IF_LTZ: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001666 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001667 if (shadow_frame.GetVReg(inst->VRegA_21t()) < 0) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001668 inst = inst->RelativeAt(inst->VRegB_21t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001669 } else {
1670 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001671 }
1672 break;
1673 }
1674 case Instruction::IF_GEZ: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001675 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001676 if (shadow_frame.GetVReg(inst->VRegA_21t()) >= 0) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001677 inst = inst->RelativeAt(inst->VRegB_21t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001678 } else {
1679 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001680 }
1681 break;
1682 }
1683 case Instruction::IF_GTZ: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001684 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001685 if (shadow_frame.GetVReg(inst->VRegA_21t()) > 0) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001686 inst = inst->RelativeAt(inst->VRegB_21t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001687 } else {
1688 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001689 }
1690 break;
1691 }
1692 case Instruction::IF_LEZ: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001693 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001694 if (shadow_frame.GetVReg(inst->VRegA_21t()) <= 0) {
Sebastien Hertz92c607f2013-06-04 16:18:52 +02001695 inst = inst->RelativeAt(inst->VRegB_21t());
Jeff Hao9cec2472013-05-14 18:17:06 -07001696 } else {
1697 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001698 }
1699 break;
1700 }
1701 case Instruction::AGET_BOOLEAN: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001702 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001703 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001704 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001705 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001706 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001707 break;
1708 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001709 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001710 BooleanArray* array = a->AsBooleanArray();
1711 if (LIKELY(array->IsValidIndex(index))) {
1712 shadow_frame.SetVReg(inst->VRegA_23x(), array->GetData()[index]);
1713 inst = inst->Next_2xx();
1714 } else {
1715 HANDLE_PENDING_EXCEPTION();
1716 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001717 break;
1718 }
1719 case Instruction::AGET_BYTE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001720 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001721 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001722 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001723 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001724 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001725 break;
1726 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001727 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001728 ByteArray* array = a->AsByteArray();
1729 if (LIKELY(array->IsValidIndex(index))) {
1730 shadow_frame.SetVReg(inst->VRegA_23x(), array->GetData()[index]);
1731 inst = inst->Next_2xx();
1732 } else {
1733 HANDLE_PENDING_EXCEPTION();
1734 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001735 break;
1736 }
1737 case Instruction::AGET_CHAR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001738 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001739 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001740 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001741 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001742 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001743 break;
1744 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001745 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001746 CharArray* array = a->AsCharArray();
1747 if (LIKELY(array->IsValidIndex(index))) {
1748 shadow_frame.SetVReg(inst->VRegA_23x(), array->GetData()[index]);
1749 inst = inst->Next_2xx();
1750 } else {
1751 HANDLE_PENDING_EXCEPTION();
1752 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001753 break;
1754 }
1755 case Instruction::AGET_SHORT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001756 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001757 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001758 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001759 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001760 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001761 break;
1762 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001763 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001764 ShortArray* array = a->AsShortArray();
1765 if (LIKELY(array->IsValidIndex(index))) {
1766 shadow_frame.SetVReg(inst->VRegA_23x(), array->GetData()[index]);
1767 inst = inst->Next_2xx();
1768 } else {
1769 HANDLE_PENDING_EXCEPTION();
1770 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001771 break;
1772 }
1773 case Instruction::AGET: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001774 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001775 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001776 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001777 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001778 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001779 break;
1780 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001781 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001782 IntArray* array = a->AsIntArray();
1783 if (LIKELY(array->IsValidIndex(index))) {
1784 shadow_frame.SetVReg(inst->VRegA_23x(), array->GetData()[index]);
1785 inst = inst->Next_2xx();
1786 } else {
1787 HANDLE_PENDING_EXCEPTION();
1788 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001789 break;
1790 }
1791 case Instruction::AGET_WIDE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001792 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001793 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001794 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001795 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001796 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001797 break;
1798 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001799 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001800 LongArray* array = a->AsLongArray();
1801 if (LIKELY(array->IsValidIndex(index))) {
1802 shadow_frame.SetVRegLong(inst->VRegA_23x(), array->GetData()[index]);
1803 inst = inst->Next_2xx();
1804 } else {
1805 HANDLE_PENDING_EXCEPTION();
1806 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001807 break;
1808 }
1809 case Instruction::AGET_OBJECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001810 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001811 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001812 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001813 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001814 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001815 break;
1816 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001817 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001818 ObjectArray<Object>* array = a->AsObjectArray<Object>();
1819 if (LIKELY(array->IsValidIndex(index))) {
1820 shadow_frame.SetVRegReference(inst->VRegA_23x(), array->GetWithoutChecks(index));
1821 inst = inst->Next_2xx();
1822 } else {
1823 HANDLE_PENDING_EXCEPTION();
1824 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001825 break;
1826 }
1827 case Instruction::APUT_BOOLEAN: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001828 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001829 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001830 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001831 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001832 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001833 break;
1834 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001835 uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1836 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001837 BooleanArray* array = a->AsBooleanArray();
1838 if (LIKELY(array->IsValidIndex(index))) {
1839 array->GetData()[index] = val;
1840 inst = inst->Next_2xx();
1841 } else {
1842 HANDLE_PENDING_EXCEPTION();
1843 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001844 break;
1845 }
1846 case Instruction::APUT_BYTE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001847 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001848 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001849 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001850 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001851 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001852 break;
1853 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001854 int8_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1855 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001856 ByteArray* array = a->AsByteArray();
1857 if (LIKELY(array->IsValidIndex(index))) {
1858 array->GetData()[index] = val;
1859 inst = inst->Next_2xx();
1860 } else {
1861 HANDLE_PENDING_EXCEPTION();
1862 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001863 break;
1864 }
1865 case Instruction::APUT_CHAR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001866 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001867 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001868 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001869 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001870 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001871 break;
1872 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001873 uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1874 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001875 CharArray* array = a->AsCharArray();
1876 if (LIKELY(array->IsValidIndex(index))) {
1877 array->GetData()[index] = val;
1878 inst = inst->Next_2xx();
1879 } else {
1880 HANDLE_PENDING_EXCEPTION();
1881 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001882 break;
1883 }
1884 case Instruction::APUT_SHORT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001885 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001886 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001887 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001888 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001889 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001890 break;
1891 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001892 int16_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1893 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001894 ShortArray* array = a->AsShortArray();
1895 if (LIKELY(array->IsValidIndex(index))) {
1896 array->GetData()[index] = val;
1897 inst = inst->Next_2xx();
1898 } else {
1899 HANDLE_PENDING_EXCEPTION();
1900 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001901 break;
1902 }
1903 case Instruction::APUT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001904 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001905 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001906 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001907 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001908 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001909 break;
1910 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001911 int32_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1912 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001913 IntArray* array = a->AsIntArray();
1914 if (LIKELY(array->IsValidIndex(index))) {
1915 array->GetData()[index] = val;
1916 inst = inst->Next_2xx();
1917 } else {
1918 HANDLE_PENDING_EXCEPTION();
1919 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001920 break;
1921 }
1922 case Instruction::APUT_WIDE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001923 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001924 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001925 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001926 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001927 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001928 break;
1929 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001930 int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x());
1931 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Jeff Hao9cec2472013-05-14 18:17:06 -07001932 LongArray* array = a->AsLongArray();
1933 if (LIKELY(array->IsValidIndex(index))) {
1934 array->GetData()[index] = val;
1935 inst = inst->Next_2xx();
1936 } else {
1937 HANDLE_PENDING_EXCEPTION();
1938 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001939 break;
1940 }
1941 case Instruction::APUT_OBJECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001942 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02001943 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001944 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001945 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Jeff Hao9cec2472013-05-14 18:17:06 -07001946 HANDLE_PENDING_EXCEPTION();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001947 break;
1948 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001949 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
Sebastien Hertz6bdd8f42013-05-17 14:44:01 +02001950 Object* val = shadow_frame.GetVRegReference(inst->VRegA_23x());
1951 ObjectArray<Object>* array = a->AsObjectArray<Object>();
1952 if (LIKELY(array->IsValidIndex(index) && array->CheckAssignable(val))) {
1953 array->SetWithoutChecks(index, val);
1954 inst = inst->Next_2xx();
1955 } else {
1956 HANDLE_PENDING_EXCEPTION();
1957 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001958 break;
1959 }
Sebastien Hertz1521e952013-07-23 10:02:11 +02001960 case Instruction::IGET_BOOLEAN: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001961 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02001962 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(self, shadow_frame, inst);
1963 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001964 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02001965 }
1966 case Instruction::IGET_BYTE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001967 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02001968 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(self, shadow_frame, inst);
1969 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001970 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02001971 }
1972 case Instruction::IGET_CHAR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001973 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02001974 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(self, shadow_frame, inst);
1975 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001976 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02001977 }
1978 case Instruction::IGET_SHORT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001979 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02001980 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(self, shadow_frame, inst);
1981 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001982 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02001983 }
1984 case Instruction::IGET: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001985 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02001986 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(self, shadow_frame, inst);
1987 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001988 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02001989 }
1990 case Instruction::IGET_WIDE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001991 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02001992 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(self, shadow_frame, inst);
1993 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001994 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02001995 }
1996 case Instruction::IGET_OBJECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07001997 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02001998 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(self, shadow_frame, inst);
1999 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002000 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002001 }
2002 case Instruction::IGET_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002003 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002004 bool success = DoIGetQuick<Primitive::kPrimInt>(self, shadow_frame, inst);
2005 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002006 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002007 }
2008 case Instruction::IGET_WIDE_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002009 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002010 bool success = DoIGetQuick<Primitive::kPrimLong>(self, shadow_frame, inst);
2011 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002012 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002013 }
2014 case Instruction::IGET_OBJECT_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002015 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002016 bool success = DoIGetQuick<Primitive::kPrimNot>(self, shadow_frame, inst);
2017 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002018 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002019 }
2020 case Instruction::SGET_BOOLEAN: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002021 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002022 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check>(self, shadow_frame, inst);
2023 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002024 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002025 }
2026 case Instruction::SGET_BYTE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002027 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002028 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check>(self, shadow_frame, inst);
2029 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002030 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002031 }
2032 case Instruction::SGET_CHAR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002033 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002034 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check>(self, shadow_frame, inst);
2035 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002036 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002037 }
2038 case Instruction::SGET_SHORT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002039 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002040 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check>(self, shadow_frame, inst);
2041 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002042 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002043 }
2044 case Instruction::SGET: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002045 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002046 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check>(self, shadow_frame, inst);
2047 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002048 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002049 }
2050 case Instruction::SGET_WIDE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002051 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002052 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check>(self, shadow_frame, inst);
2053 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002054 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002055 }
2056 case Instruction::SGET_OBJECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002057 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002058 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check>(self, shadow_frame, inst);
2059 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002060 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002061 }
2062 case Instruction::IPUT_BOOLEAN: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002063 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002064 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check>(self, shadow_frame, inst);
2065 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002066 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002067 }
2068 case Instruction::IPUT_BYTE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002069 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002070 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check>(self, shadow_frame, inst);
2071 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002072 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002073 }
2074 case Instruction::IPUT_CHAR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002075 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002076 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check>(self, shadow_frame, inst);
2077 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002078 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002079 }
2080 case Instruction::IPUT_SHORT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002081 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002082 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check>(self, shadow_frame, inst);
2083 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002084 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002085 }
2086 case Instruction::IPUT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002087 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002088 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check>(self, shadow_frame, inst);
2089 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002090 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002091 }
2092 case Instruction::IPUT_WIDE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002093 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002094 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check>(self, shadow_frame, inst);
2095 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002096 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002097 }
2098 case Instruction::IPUT_OBJECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002099 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002100 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check>(self, shadow_frame, inst);
2101 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002102 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002103 }
2104 case Instruction::IPUT_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002105 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002106 bool success = DoIPutQuick<Primitive::kPrimInt>(self, shadow_frame, inst);
2107 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002108 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002109 }
2110 case Instruction::IPUT_WIDE_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002111 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002112 bool success = DoIPutQuick<Primitive::kPrimLong>(self, shadow_frame, inst);
2113 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002114 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002115 }
2116 case Instruction::IPUT_OBJECT_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002117 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002118 bool success = DoIPutQuick<Primitive::kPrimNot>(self, shadow_frame, inst);
2119 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002120 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002121 }
2122 case Instruction::SPUT_BOOLEAN: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002123 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002124 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check>(self, shadow_frame, inst);
2125 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002126 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002127 }
2128 case Instruction::SPUT_BYTE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002129 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002130 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check>(self, shadow_frame, inst);
2131 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002132 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002133 }
2134 case Instruction::SPUT_CHAR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002135 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002136 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check>(self, shadow_frame, inst);
2137 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002138 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002139 }
2140 case Instruction::SPUT_SHORT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002141 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002142 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check>(self, shadow_frame, inst);
2143 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002144 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002145 }
2146 case Instruction::SPUT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002147 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002148 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check>(self, shadow_frame, inst);
2149 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002150 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002151 }
2152 case Instruction::SPUT_WIDE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002153 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002154 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check>(self, shadow_frame, inst);
2155 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002156 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002157 }
2158 case Instruction::SPUT_OBJECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002159 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002160 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check>(self, shadow_frame, inst);
2161 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002162 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002163 }
2164 case Instruction::INVOKE_VIRTUAL: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002165 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002166 bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, &result_register);
2167 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002168 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002169 }
2170 case Instruction::INVOKE_VIRTUAL_RANGE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002171 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002172 bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, &result_register);
2173 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002174 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002175 }
2176 case Instruction::INVOKE_SUPER: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002177 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002178 bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, &result_register);
2179 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002180 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002181 }
2182 case Instruction::INVOKE_SUPER_RANGE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002183 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002184 bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, &result_register);
2185 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002186 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002187 }
2188 case Instruction::INVOKE_DIRECT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002189 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002190 bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, &result_register);
2191 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002192 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002193 }
2194 case Instruction::INVOKE_DIRECT_RANGE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002195 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002196 bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, &result_register);
2197 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002198 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002199 }
2200 case Instruction::INVOKE_INTERFACE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002201 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002202 bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, &result_register);
2203 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002204 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002205 }
2206 case Instruction::INVOKE_INTERFACE_RANGE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002207 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002208 bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, &result_register);
2209 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002210 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002211 }
2212 case Instruction::INVOKE_STATIC: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002213 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002214 bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, &result_register);
2215 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002216 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002217 }
2218 case Instruction::INVOKE_STATIC_RANGE: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002219 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002220 bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, &result_register);
2221 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002222 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002223 }
2224 case Instruction::INVOKE_VIRTUAL_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002225 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002226 bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, &result_register);
2227 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002228 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002229 }
2230 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002231 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002232 bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, &result_register);
2233 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02002234 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002235 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002236 case Instruction::NEG_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002237 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002238 shadow_frame.SetVReg(inst->VRegA_12x(), -shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002239 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002240 break;
2241 case Instruction::NOT_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002242 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002243 shadow_frame.SetVReg(inst->VRegA_12x(), ~shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002244 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002245 break;
2246 case Instruction::NEG_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002247 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002248 shadow_frame.SetVRegLong(inst->VRegA_12x(), -shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002249 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002250 break;
2251 case Instruction::NOT_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002252 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002253 shadow_frame.SetVRegLong(inst->VRegA_12x(), ~shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002254 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002255 break;
2256 case Instruction::NEG_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002257 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002258 shadow_frame.SetVRegFloat(inst->VRegA_12x(), -shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002259 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002260 break;
2261 case Instruction::NEG_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002262 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002263 shadow_frame.SetVRegDouble(inst->VRegA_12x(), -shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002264 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002265 break;
2266 case Instruction::INT_TO_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002267 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002268 shadow_frame.SetVRegLong(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002269 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002270 break;
2271 case Instruction::INT_TO_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002272 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002273 shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002274 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002275 break;
2276 case Instruction::INT_TO_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002277 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002278 shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002279 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002280 break;
2281 case Instruction::LONG_TO_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002282 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002283 shadow_frame.SetVReg(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002284 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002285 break;
2286 case Instruction::LONG_TO_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002287 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002288 shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002289 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002290 break;
2291 case Instruction::LONG_TO_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002292 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002293 shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002294 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002295 break;
jeffhao87a6edd2012-11-20 18:05:18 -08002296 case Instruction::FLOAT_TO_INT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002297 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002298 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002299 int32_t result;
jeffhao87a6edd2012-11-20 18:05:18 -08002300 if (val != val) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002301 result = 0;
jeffhao87a6edd2012-11-20 18:05:18 -08002302 } else if (val > static_cast<float>(kMaxInt)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002303 result = kMaxInt;
jeffhao87a6edd2012-11-20 18:05:18 -08002304 } else if (val < static_cast<float>(kMinInt)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002305 result = kMinInt;
jeffhao87a6edd2012-11-20 18:05:18 -08002306 } else {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002307 result = val;
jeffhao87a6edd2012-11-20 18:05:18 -08002308 }
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002309 shadow_frame.SetVReg(inst->VRegA_12x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07002310 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002311 break;
jeffhao87a6edd2012-11-20 18:05:18 -08002312 }
2313 case Instruction::FLOAT_TO_LONG: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002314 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002315 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002316 int64_t result;
jeffhao87a6edd2012-11-20 18:05:18 -08002317 if (val != val) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002318 result = 0;
jeffhao87a6edd2012-11-20 18:05:18 -08002319 } else if (val > static_cast<float>(kMaxLong)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002320 result = kMaxLong;
jeffhao87a6edd2012-11-20 18:05:18 -08002321 } else if (val < static_cast<float>(kMinLong)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002322 result = kMinLong;
jeffhao87a6edd2012-11-20 18:05:18 -08002323 } else {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002324 result = val;
jeffhao87a6edd2012-11-20 18:05:18 -08002325 }
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002326 shadow_frame.SetVRegLong(inst->VRegA_12x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07002327 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002328 break;
jeffhao87a6edd2012-11-20 18:05:18 -08002329 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002330 case Instruction::FLOAT_TO_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002331 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002332 shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002333 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002334 break;
jeffhao87a6edd2012-11-20 18:05:18 -08002335 case Instruction::DOUBLE_TO_INT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002336 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002337 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002338 int32_t result;
jeffhao87a6edd2012-11-20 18:05:18 -08002339 if (val != val) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002340 result = 0;
jeffhao87a6edd2012-11-20 18:05:18 -08002341 } else if (val > static_cast<double>(kMaxInt)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002342 result = kMaxInt;
jeffhao87a6edd2012-11-20 18:05:18 -08002343 } else if (val < static_cast<double>(kMinInt)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002344 result = kMinInt;
jeffhao87a6edd2012-11-20 18:05:18 -08002345 } else {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002346 result = val;
jeffhao87a6edd2012-11-20 18:05:18 -08002347 }
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002348 shadow_frame.SetVReg(inst->VRegA_12x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07002349 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002350 break;
jeffhao87a6edd2012-11-20 18:05:18 -08002351 }
2352 case Instruction::DOUBLE_TO_LONG: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002353 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002354 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002355 int64_t result;
jeffhao87a6edd2012-11-20 18:05:18 -08002356 if (val != val) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002357 result = 0;
jeffhao87a6edd2012-11-20 18:05:18 -08002358 } else if (val > static_cast<double>(kMaxLong)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002359 result = kMaxLong;
jeffhao87a6edd2012-11-20 18:05:18 -08002360 } else if (val < static_cast<double>(kMinLong)) {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002361 result = kMinLong;
jeffhao87a6edd2012-11-20 18:05:18 -08002362 } else {
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002363 result = val;
jeffhao87a6edd2012-11-20 18:05:18 -08002364 }
Sebastien Hertz13e2d1f2013-06-28 09:50:36 +02002365 shadow_frame.SetVRegLong(inst->VRegA_12x(), result);
Jeff Hao9cec2472013-05-14 18:17:06 -07002366 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002367 break;
jeffhao87a6edd2012-11-20 18:05:18 -08002368 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002369 case Instruction::DOUBLE_TO_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002370 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002371 shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002372 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002373 break;
2374 case Instruction::INT_TO_BYTE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002375 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002376 shadow_frame.SetVReg(inst->VRegA_12x(),
2377 static_cast<int8_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
Jeff Hao9cec2472013-05-14 18:17:06 -07002378 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002379 break;
2380 case Instruction::INT_TO_CHAR:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002381 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002382 shadow_frame.SetVReg(inst->VRegA_12x(),
2383 static_cast<uint16_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
Jeff Hao9cec2472013-05-14 18:17:06 -07002384 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002385 break;
2386 case Instruction::INT_TO_SHORT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002387 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002388 shadow_frame.SetVReg(inst->VRegA_12x(),
2389 static_cast<int16_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
Jeff Hao9cec2472013-05-14 18:17:06 -07002390 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002391 break;
2392 case Instruction::ADD_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002393 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002394 shadow_frame.SetVReg(inst->VRegA_23x(),
2395 shadow_frame.GetVReg(inst->VRegB_23x()) +
2396 shadow_frame.GetVReg(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002397 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002398 break;
2399 case Instruction::SUB_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002400 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002401 shadow_frame.SetVReg(inst->VRegA_23x(),
2402 shadow_frame.GetVReg(inst->VRegB_23x()) -
2403 shadow_frame.GetVReg(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002404 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002405 break;
2406 case Instruction::MUL_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002407 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002408 shadow_frame.SetVReg(inst->VRegA_23x(),
2409 shadow_frame.GetVReg(inst->VRegB_23x()) *
2410 shadow_frame.GetVReg(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002411 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002412 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002413 case Instruction::DIV_INT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002414 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002415 bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(),
2416 shadow_frame.GetVReg(inst->VRegB_23x()),
2417 shadow_frame.GetVReg(inst->VRegC_23x()));
2418 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz807a2562013-04-15 09:33:39 +02002419 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002420 }
2421 case Instruction::REM_INT: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002422 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002423 bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(),
2424 shadow_frame.GetVReg(inst->VRegB_23x()),
2425 shadow_frame.GetVReg(inst->VRegC_23x()));
2426 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002427 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002428 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002429 case Instruction::SHL_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002430 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002431 shadow_frame.SetVReg(inst->VRegA_23x(),
2432 shadow_frame.GetVReg(inst->VRegB_23x()) <<
2433 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002434 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002435 break;
2436 case Instruction::SHR_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002437 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002438 shadow_frame.SetVReg(inst->VRegA_23x(),
2439 shadow_frame.GetVReg(inst->VRegB_23x()) >>
2440 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002441 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002442 break;
2443 case Instruction::USHR_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002444 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002445 shadow_frame.SetVReg(inst->VRegA_23x(),
2446 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
2447 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002448 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002449 break;
2450 case Instruction::AND_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002451 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002452 shadow_frame.SetVReg(inst->VRegA_23x(),
2453 shadow_frame.GetVReg(inst->VRegB_23x()) &
2454 shadow_frame.GetVReg(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002455 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002456 break;
2457 case Instruction::OR_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002458 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002459 shadow_frame.SetVReg(inst->VRegA_23x(),
2460 shadow_frame.GetVReg(inst->VRegB_23x()) |
2461 shadow_frame.GetVReg(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002462 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002463 break;
2464 case Instruction::XOR_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002465 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002466 shadow_frame.SetVReg(inst->VRegA_23x(),
2467 shadow_frame.GetVReg(inst->VRegB_23x()) ^
2468 shadow_frame.GetVReg(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002469 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002470 break;
2471 case Instruction::ADD_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002472 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002473 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2474 shadow_frame.GetVRegLong(inst->VRegB_23x()) +
2475 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002476 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002477 break;
2478 case Instruction::SUB_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002479 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002480 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2481 shadow_frame.GetVRegLong(inst->VRegB_23x()) -
2482 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002483 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002484 break;
2485 case Instruction::MUL_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002486 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002487 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2488 shadow_frame.GetVRegLong(inst->VRegB_23x()) *
2489 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002490 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002491 break;
2492 case Instruction::DIV_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002493 PREAMBLE();
Sebastien Hertz0a3b8632013-06-26 11:16:01 +02002494 DoLongDivide(shadow_frame, inst->VRegA_23x(),
Sebastien Hertz807a2562013-04-15 09:33:39 +02002495 shadow_frame.GetVRegLong(inst->VRegB_23x()),
2496 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Sebastien Hertz1521e952013-07-23 10:02:11 +02002497 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002498 break;
2499 case Instruction::REM_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002500 PREAMBLE();
Sebastien Hertz0a3b8632013-06-26 11:16:01 +02002501 DoLongRemainder(shadow_frame, inst->VRegA_23x(),
Sebastien Hertz807a2562013-04-15 09:33:39 +02002502 shadow_frame.GetVRegLong(inst->VRegB_23x()),
2503 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Sebastien Hertz1521e952013-07-23 10:02:11 +02002504 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002505 break;
2506 case Instruction::AND_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002507 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002508 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2509 shadow_frame.GetVRegLong(inst->VRegB_23x()) &
2510 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002511 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002512 break;
2513 case Instruction::OR_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002514 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002515 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2516 shadow_frame.GetVRegLong(inst->VRegB_23x()) |
2517 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002518 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002519 break;
2520 case Instruction::XOR_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002521 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002522 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2523 shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
2524 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002525 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002526 break;
2527 case Instruction::SHL_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002528 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002529 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2530 shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
2531 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002532 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002533 break;
2534 case Instruction::SHR_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002535 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002536 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2537 shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
2538 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002539 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002540 break;
2541 case Instruction::USHR_LONG:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002542 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002543 shadow_frame.SetVRegLong(inst->VRegA_23x(),
2544 static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
2545 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002546 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002547 break;
2548 case Instruction::ADD_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002549 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002550 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
2551 shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
2552 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002553 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002554 break;
2555 case Instruction::SUB_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002556 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002557 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
2558 shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
2559 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002560 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002561 break;
2562 case Instruction::MUL_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002563 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002564 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
2565 shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
2566 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002567 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002568 break;
2569 case Instruction::DIV_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002570 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002571 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
2572 shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
2573 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002574 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002575 break;
2576 case Instruction::REM_FLOAT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002577 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002578 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
2579 fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
2580 shadow_frame.GetVRegFloat(inst->VRegC_23x())));
Jeff Hao9cec2472013-05-14 18:17:06 -07002581 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002582 break;
2583 case Instruction::ADD_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002584 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002585 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
2586 shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
2587 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002588 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002589 break;
2590 case Instruction::SUB_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002591 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002592 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
2593 shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
2594 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002595 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002596 break;
2597 case Instruction::MUL_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002598 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002599 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
2600 shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
2601 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002602 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002603 break;
2604 case Instruction::DIV_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002605 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002606 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
2607 shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
2608 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002609 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002610 break;
2611 case Instruction::REM_DOUBLE:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002612 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002613 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
2614 fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
2615 shadow_frame.GetVRegDouble(inst->VRegC_23x())));
Jeff Hao9cec2472013-05-14 18:17:06 -07002616 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002617 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002618 case Instruction::ADD_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002619 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002620 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002621 shadow_frame.SetVReg(vregA,
2622 shadow_frame.GetVReg(vregA) +
2623 shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002624 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002625 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002626 }
2627 case Instruction::SUB_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002628 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002629 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002630 shadow_frame.SetVReg(vregA,
2631 shadow_frame.GetVReg(vregA) -
2632 shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002633 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002634 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002635 }
2636 case Instruction::MUL_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002637 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002638 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002639 shadow_frame.SetVReg(vregA,
2640 shadow_frame.GetVReg(vregA) *
2641 shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002642 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002643 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002644 }
Sebastien Hertz92c607f2013-06-04 16:18:52 +02002645 case Instruction::DIV_INT_2ADDR: {
2646 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002647 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002648 bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2649 shadow_frame.GetVReg(inst->VRegB_12x()));
2650 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
Sebastien Hertz92c607f2013-06-04 16:18:52 +02002651 break;
2652 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02002653 case Instruction::REM_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002654 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002655 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002656 bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2657 shadow_frame.GetVReg(inst->VRegB_12x()));
2658 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002659 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002660 }
Brian Carlstrom2ce745c2013-07-17 17:44:30 -07002661 case Instruction::SHL_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002662 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002663 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002664 shadow_frame.SetVReg(vregA,
2665 shadow_frame.GetVReg(vregA) <<
2666 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002667 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002668 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002669 }
2670 case Instruction::SHR_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002671 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002672 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002673 shadow_frame.SetVReg(vregA,
2674 shadow_frame.GetVReg(vregA) >>
2675 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002676 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002677 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002678 }
2679 case Instruction::USHR_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002680 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002681 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002682 shadow_frame.SetVReg(vregA,
2683 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
2684 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002685 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002686 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002687 }
2688 case Instruction::AND_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002689 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002690 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002691 shadow_frame.SetVReg(vregA,
2692 shadow_frame.GetVReg(vregA) &
2693 shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002694 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002695 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002696 }
2697 case Instruction::OR_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002698 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002699 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002700 shadow_frame.SetVReg(vregA,
2701 shadow_frame.GetVReg(vregA) |
2702 shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002703 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002704 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002705 }
2706 case Instruction::XOR_INT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002707 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002708 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002709 shadow_frame.SetVReg(vregA,
2710 shadow_frame.GetVReg(vregA) ^
2711 shadow_frame.GetVReg(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002712 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002713 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002714 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02002715 case Instruction::ADD_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002716 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002717 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002718 shadow_frame.SetVRegLong(vregA,
2719 shadow_frame.GetVRegLong(vregA) +
2720 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002721 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002722 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002723 }
2724 case Instruction::SUB_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002725 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002726 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002727 shadow_frame.SetVRegLong(vregA,
2728 shadow_frame.GetVRegLong(vregA) -
2729 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002730 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002731 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002732 }
2733 case Instruction::MUL_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002734 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002735 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002736 shadow_frame.SetVRegLong(vregA,
2737 shadow_frame.GetVRegLong(vregA) *
2738 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002739 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002740 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002741 }
2742 case Instruction::DIV_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002743 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002744 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz0a3b8632013-06-26 11:16:01 +02002745 DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
Sebastien Hertz807a2562013-04-15 09:33:39 +02002746 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Sebastien Hertz1521e952013-07-23 10:02:11 +02002747 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002748 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002749 }
2750 case Instruction::REM_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002751 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002752 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz0a3b8632013-06-26 11:16:01 +02002753 DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
Sebastien Hertz807a2562013-04-15 09:33:39 +02002754 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Sebastien Hertz1521e952013-07-23 10:02:11 +02002755 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002756 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002757 }
2758 case Instruction::AND_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002759 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002760 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002761 shadow_frame.SetVRegLong(vregA,
2762 shadow_frame.GetVRegLong(vregA) &
2763 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002764 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002765 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002766 }
2767 case Instruction::OR_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002768 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002769 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002770 shadow_frame.SetVRegLong(vregA,
2771 shadow_frame.GetVRegLong(vregA) |
2772 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002773 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002774 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002775 }
2776 case Instruction::XOR_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002777 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002778 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002779 shadow_frame.SetVRegLong(vregA,
2780 shadow_frame.GetVRegLong(vregA) ^
2781 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002782 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002783 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002784 }
2785 case Instruction::SHL_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002786 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002787 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002788 shadow_frame.SetVRegLong(vregA,
2789 shadow_frame.GetVRegLong(vregA) <<
2790 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002791 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002792 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002793 }
2794 case Instruction::SHR_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002795 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002796 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002797 shadow_frame.SetVRegLong(vregA,
2798 shadow_frame.GetVRegLong(vregA) >>
2799 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002800 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002801 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002802 }
2803 case Instruction::USHR_LONG_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002804 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002805 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002806 shadow_frame.SetVRegLong(vregA,
2807 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
2808 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
Jeff Hao9cec2472013-05-14 18:17:06 -07002809 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002810 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002811 }
2812 case Instruction::ADD_FLOAT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002813 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002814 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002815 shadow_frame.SetVRegFloat(vregA,
2816 shadow_frame.GetVRegFloat(vregA) +
2817 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002818 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002819 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002820 }
2821 case Instruction::SUB_FLOAT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002822 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002823 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002824 shadow_frame.SetVRegFloat(vregA,
2825 shadow_frame.GetVRegFloat(vregA) -
2826 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002827 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002828 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002829 }
2830 case Instruction::MUL_FLOAT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002831 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002832 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002833 shadow_frame.SetVRegFloat(vregA,
2834 shadow_frame.GetVRegFloat(vregA) *
2835 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002836 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002837 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002838 }
2839 case Instruction::DIV_FLOAT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002840 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002841 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002842 shadow_frame.SetVRegFloat(vregA,
2843 shadow_frame.GetVRegFloat(vregA) /
2844 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002845 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002846 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002847 }
2848 case Instruction::REM_FLOAT_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002849 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002850 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002851 shadow_frame.SetVRegFloat(vregA,
2852 fmodf(shadow_frame.GetVRegFloat(vregA),
2853 shadow_frame.GetVRegFloat(inst->VRegB_12x())));
Jeff Hao9cec2472013-05-14 18:17:06 -07002854 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002855 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002856 }
2857 case Instruction::ADD_DOUBLE_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002858 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002859 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002860 shadow_frame.SetVRegDouble(vregA,
2861 shadow_frame.GetVRegDouble(vregA) +
2862 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002863 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002864 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002865 }
2866 case Instruction::SUB_DOUBLE_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002867 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002868 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002869 shadow_frame.SetVRegDouble(vregA,
2870 shadow_frame.GetVRegDouble(vregA) -
2871 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002872 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002873 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002874 }
2875 case Instruction::MUL_DOUBLE_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002876 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002877 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002878 shadow_frame.SetVRegDouble(vregA,
2879 shadow_frame.GetVRegDouble(vregA) *
2880 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002881 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002882 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002883 }
2884 case Instruction::DIV_DOUBLE_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002885 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002886 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002887 shadow_frame.SetVRegDouble(vregA,
2888 shadow_frame.GetVRegDouble(vregA) /
2889 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002890 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002891 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002892 }
2893 case Instruction::REM_DOUBLE_2ADDR: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002894 PREAMBLE();
Sebastien Hertz5fde12a2013-07-24 09:27:11 +02002895 uint4_t vregA = inst->VRegA_12x();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002896 shadow_frame.SetVRegDouble(vregA,
2897 fmod(shadow_frame.GetVRegDouble(vregA),
2898 shadow_frame.GetVRegDouble(inst->VRegB_12x())));
Jeff Hao9cec2472013-05-14 18:17:06 -07002899 inst = inst->Next_1xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002900 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002901 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002902 case Instruction::ADD_INT_LIT16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002903 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002904 shadow_frame.SetVReg(inst->VRegA_22s(),
2905 shadow_frame.GetVReg(inst->VRegB_22s()) +
2906 inst->VRegC_22s());
Jeff Hao9cec2472013-05-14 18:17:06 -07002907 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002908 break;
2909 case Instruction::RSUB_INT:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002910 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002911 shadow_frame.SetVReg(inst->VRegA_22s(),
2912 inst->VRegC_22s() -
2913 shadow_frame.GetVReg(inst->VRegB_22s()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002914 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002915 break;
2916 case Instruction::MUL_INT_LIT16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002917 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002918 shadow_frame.SetVReg(inst->VRegA_22s(),
2919 shadow_frame.GetVReg(inst->VRegB_22s()) *
2920 inst->VRegC_22s());
Jeff Hao9cec2472013-05-14 18:17:06 -07002921 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002922 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002923 case Instruction::DIV_INT_LIT16: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002924 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002925 bool success = DoIntDivide(shadow_frame, inst->VRegA_22s(),
2926 shadow_frame.GetVReg(inst->VRegB_22s()), inst->VRegC_22s());
2927 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002928 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002929 }
2930 case Instruction::REM_INT_LIT16: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002931 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002932 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22s(),
2933 shadow_frame.GetVReg(inst->VRegB_22s()), inst->VRegC_22s());
2934 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002935 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002936 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002937 case Instruction::AND_INT_LIT16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002938 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002939 shadow_frame.SetVReg(inst->VRegA_22s(),
2940 shadow_frame.GetVReg(inst->VRegB_22s()) &
2941 inst->VRegC_22s());
Jeff Hao9cec2472013-05-14 18:17:06 -07002942 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002943 break;
2944 case Instruction::OR_INT_LIT16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002945 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002946 shadow_frame.SetVReg(inst->VRegA_22s(),
2947 shadow_frame.GetVReg(inst->VRegB_22s()) |
2948 inst->VRegC_22s());
Jeff Hao9cec2472013-05-14 18:17:06 -07002949 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002950 break;
2951 case Instruction::XOR_INT_LIT16:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002952 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002953 shadow_frame.SetVReg(inst->VRegA_22s(),
2954 shadow_frame.GetVReg(inst->VRegB_22s()) ^
2955 inst->VRegC_22s());
Jeff Hao9cec2472013-05-14 18:17:06 -07002956 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002957 break;
2958 case Instruction::ADD_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002959 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002960 shadow_frame.SetVReg(inst->VRegA_22b(),
2961 shadow_frame.GetVReg(inst->VRegB_22b()) +
2962 inst->VRegC_22b());
Jeff Hao9cec2472013-05-14 18:17:06 -07002963 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002964 break;
2965 case Instruction::RSUB_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002966 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002967 shadow_frame.SetVReg(inst->VRegA_22b(),
2968 inst->VRegC_22b() -
2969 shadow_frame.GetVReg(inst->VRegB_22b()));
Jeff Hao9cec2472013-05-14 18:17:06 -07002970 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002971 break;
2972 case Instruction::MUL_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002973 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002974 shadow_frame.SetVReg(inst->VRegA_22b(),
2975 shadow_frame.GetVReg(inst->VRegB_22b()) *
2976 inst->VRegC_22b());
Jeff Hao9cec2472013-05-14 18:17:06 -07002977 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002978 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002979 case Instruction::DIV_INT_LIT8: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002980 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002981 bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(),
2982 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2983 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz807a2562013-04-15 09:33:39 +02002984 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002985 }
2986 case Instruction::REM_INT_LIT8: {
Ian Rogersd8274bc2013-05-15 15:54:45 -07002987 PREAMBLE();
Sebastien Hertz1521e952013-07-23 10:02:11 +02002988 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(),
2989 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2990 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
Sebastien Hertz807a2562013-04-15 09:33:39 +02002991 break;
Sebastien Hertz1521e952013-07-23 10:02:11 +02002992 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02002993 case Instruction::AND_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07002994 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002995 shadow_frame.SetVReg(inst->VRegA_22b(),
2996 shadow_frame.GetVReg(inst->VRegB_22b()) &
2997 inst->VRegC_22b());
Jeff Hao9cec2472013-05-14 18:17:06 -07002998 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02002999 break;
3000 case Instruction::OR_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07003001 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02003002 shadow_frame.SetVReg(inst->VRegA_22b(),
3003 shadow_frame.GetVReg(inst->VRegB_22b()) |
3004 inst->VRegC_22b());
Jeff Hao9cec2472013-05-14 18:17:06 -07003005 inst = inst->Next_2xx();
Sebastien Hertz807a2562013-04-15 09:33:39 +02003006 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003007 case Instruction::XOR_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07003008 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02003009 shadow_frame.SetVReg(inst->VRegA_22b(),
3010 shadow_frame.GetVReg(inst->VRegB_22b()) ^
3011 inst->VRegC_22b());
Jeff Hao9cec2472013-05-14 18:17:06 -07003012 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003013 break;
3014 case Instruction::SHL_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07003015 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02003016 shadow_frame.SetVReg(inst->VRegA_22b(),
3017 shadow_frame.GetVReg(inst->VRegB_22b()) <<
3018 (inst->VRegC_22b() & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07003019 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003020 break;
3021 case Instruction::SHR_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07003022 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02003023 shadow_frame.SetVReg(inst->VRegA_22b(),
3024 shadow_frame.GetVReg(inst->VRegB_22b()) >>
3025 (inst->VRegC_22b() & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07003026 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003027 break;
3028 case Instruction::USHR_INT_LIT8:
Ian Rogersd8274bc2013-05-15 15:54:45 -07003029 PREAMBLE();
Sebastien Hertz807a2562013-04-15 09:33:39 +02003030 shadow_frame.SetVReg(inst->VRegA_22b(),
3031 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
3032 (inst->VRegC_22b() & 0x1f));
Jeff Hao9cec2472013-05-14 18:17:06 -07003033 inst = inst->Next_2xx();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003034 break;
Ian Rogersfa46d3e2013-05-15 00:16:04 -07003035 case Instruction::UNUSED_3E ... Instruction::UNUSED_43:
Sebastien Hertz2d6ba512013-05-17 11:31:37 +02003036 case Instruction::UNUSED_EB ... Instruction::UNUSED_FF:
Ian Rogersfa46d3e2013-05-15 00:16:04 -07003037 case Instruction::UNUSED_79:
3038 case Instruction::UNUSED_7A:
Ian Rogersd8274bc2013-05-15 15:54:45 -07003039 UnexpectedOpcode(inst, mh);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003040 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003041 }
Brian Carlstrom1895ea32013-07-18 13:28:37 -07003042} // NOLINT(readability/fn_size)
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003043
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02003044static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
3045 ShadowFrame& shadow_frame, JValue result_register)
3046 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
3047
3048static inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
3049 ShadowFrame& shadow_frame, JValue result_register) {
Ian Rogers848871b2013-08-05 10:56:33 -07003050 DCHECK(shadow_frame.GetMethod() == mh.GetMethod() ||
3051 shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass());
3052 DCHECK(!shadow_frame.GetMethod()->IsAbstract());
3053 DCHECK(!shadow_frame.GetMethod()->IsNative());
Sebastien Hertz233ea8e2013-06-06 11:57:09 +02003054 if (shadow_frame.GetMethod()->IsPreverified()) {
3055 // Enter the "without access check" interpreter.
3056 return ExecuteImpl<false>(self, mh, code_item, shadow_frame, result_register);
3057 } else {
3058 // Enter the "with access check" interpreter.
3059 return ExecuteImpl<true>(self, mh, code_item, shadow_frame, result_register);
3060 }
3061}
3062
Brian Carlstromea46f952013-07-30 01:26:50 -07003063void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
Jeff Hao6474d192013-03-26 14:08:09 -07003064 uint32_t* args, JValue* result) {
Ian Rogers64b6d142012-10-29 16:34:15 -07003065 DCHECK_EQ(self, Thread::Current());
Jeff Hao790ad902013-05-22 15:02:08 -07003066 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
jeffhaod7521322012-11-21 15:38:24 -08003067 ThrowStackOverflowError(self);
3068 return;
3069 }
3070
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003071 MethodHelper mh(method);
3072 const DexFile::CodeItem* code_item = mh.GetCodeItem();
3073 uint16_t num_regs;
3074 uint16_t num_ins;
3075 if (code_item != NULL) {
3076 num_regs = code_item->registers_size_;
3077 num_ins = code_item->ins_size_;
jeffhao0a9bb732012-11-26 12:28:49 -08003078 } else if (method->IsAbstract()) {
Sebastien Hertz56adf602013-07-09 17:27:07 +02003079 ThrowAbstractMethodError(method);
jeffhao0a9bb732012-11-26 12:28:49 -08003080 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003081 } else {
3082 DCHECK(method->IsNative());
Brian Carlstromea46f952013-07-30 01:26:50 -07003083 num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003084 if (!method->IsStatic()) {
3085 num_regs++;
3086 num_ins++;
3087 }
3088 }
3089 // Set up shadow frame with matching number of reference slots to vregs.
3090 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
Jeff Hao66135192013-05-14 11:02:41 -07003091 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
3092 ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
3093 self->PushShadowFrame(shadow_frame);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003094 size_t cur_reg = num_regs - num_ins;
3095 if (!method->IsStatic()) {
3096 CHECK(receiver != NULL);
TDYa127ce4cc0d2012-11-18 16:59:53 -08003097 shadow_frame->SetVRegReference(cur_reg, receiver);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003098 ++cur_reg;
Sebastien Hertz807a2562013-04-15 09:33:39 +02003099 } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
3100 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3101 if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(),
3102 true, true))) {
3103 CHECK(self->IsExceptionPending());
3104 self->PopShadowFrame();
jeffhao94d6df42012-11-26 16:02:12 -08003105 return;
3106 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003107 CHECK(method->GetDeclaringClass()->IsInitializing());
3108 }
Ian Rogers64b6d142012-10-29 16:34:15 -07003109 const char* shorty = mh.GetShorty();
Jeff Hao5d917302013-02-27 17:57:33 -08003110 for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
3111 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
3112 switch (shorty[shorty_pos + 1]) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003113 case 'L': {
Jeff Hao5d917302013-02-27 17:57:33 -08003114 Object* o = reinterpret_cast<Object*>(args[arg_pos]);
TDYa127ce4cc0d2012-11-18 16:59:53 -08003115 shadow_frame->SetVRegReference(cur_reg, o);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003116 break;
3117 }
Jeff Hao5d917302013-02-27 17:57:33 -08003118 case 'J': case 'D': {
3119 uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
3120 shadow_frame->SetVRegLong(cur_reg, wide_value);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003121 cur_reg++;
Jeff Hao5d917302013-02-27 17:57:33 -08003122 arg_pos++;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003123 break;
Jeff Hao5d917302013-02-27 17:57:33 -08003124 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003125 default:
Jeff Hao5d917302013-02-27 17:57:33 -08003126 shadow_frame->SetVReg(cur_reg, args[arg_pos]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003127 break;
3128 }
3129 }
Ian Rogers64b6d142012-10-29 16:34:15 -07003130 if (LIKELY(!method->IsNative())) {
Jeff Hao66135192013-05-14 11:02:41 -07003131 JValue r = Execute(self, mh, code_item, *shadow_frame, JValue());
Jeff Hao6474d192013-03-26 14:08:09 -07003132 if (result != NULL) {
3133 *result = r;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003134 }
3135 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -07003136 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
3137 // generated stub) except during testing and image writing.
3138 if (!Runtime::Current()->IsStarted()) {
Jeff Hao6474d192013-03-26 14:08:09 -07003139 UnstartedRuntimeJni(self, method, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003140 } else {
Jeff Hao6474d192013-03-26 14:08:09 -07003141 InterpreterJni(self, method, shorty, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003142 }
3143 }
3144 self->PopShadowFrame();
3145}
3146
Ian Rogers62d6c772013-02-27 08:32:07 -08003147void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
Jeff Hao11ffc2d2013-02-01 11:52:17 -08003148 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3149 JValue value;
Ian Rogers62d6c772013-02-27 08:32:07 -08003150 value.SetJ(ret_val->GetJ()); // Set value to last known result in case the shadow frame chain is empty.
3151 MethodHelper mh;
Jeff Hao11ffc2d2013-02-01 11:52:17 -08003152 while (shadow_frame != NULL) {
Ian Rogers62d6c772013-02-27 08:32:07 -08003153 self->SetTopOfShadowStack(shadow_frame);
3154 mh.ChangeMethod(shadow_frame->GetMethod());
3155 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Jeff Hao11ffc2d2013-02-01 11:52:17 -08003156 value = Execute(self, mh, code_item, *shadow_frame, value);
3157 ShadowFrame* old_frame = shadow_frame;
3158 shadow_frame = shadow_frame->GetLink();
Jeff Hao11ffc2d2013-02-01 11:52:17 -08003159 delete old_frame;
3160 }
3161 ret_val->SetJ(value.GetJ());
3162}
3163
Ian Rogers7db619b2013-01-16 18:35:48 -08003164JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
Ian Rogers848871b2013-08-05 10:56:33 -07003165 ShadowFrame& shadow_frame) {
Ian Rogersf3e98552013-03-20 15:49:49 -07003166 DCHECK_EQ(self, Thread::Current());
Jeff Hao790ad902013-05-22 15:02:08 -07003167 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
Ian Rogersf3e98552013-03-20 15:49:49 -07003168 ThrowStackOverflowError(self);
3169 return JValue();
3170 }
3171
Ian Rogers7db619b2013-01-16 18:35:48 -08003172 return Execute(self, mh, code_item, shadow_frame, JValue());
3173}
3174
Ian Rogers848871b2013-08-05 10:56:33 -07003175extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
3176 const DexFile::CodeItem* code_item,
3177 ShadowFrame* shadow_frame, JValue* result) {
Jeff Hao790ad902013-05-22 15:02:08 -07003178 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
Jeff Hao16743632013-05-08 10:59:04 -07003179 ThrowStackOverflowError(self);
Jeff Hao69510672013-05-21 17:34:55 -07003180 return;
Jeff Hao16743632013-05-08 10:59:04 -07003181 }
3182
Brian Carlstromea46f952013-07-30 01:26:50 -07003183 ArtMethod* method = shadow_frame->GetMethod();
Jeff Hao16743632013-05-08 10:59:04 -07003184 if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
3185 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
3186 true, true)) {
3187 DCHECK(Thread::Current()->IsExceptionPending());
Jeff Hao69510672013-05-21 17:34:55 -07003188 return;
Jeff Hao16743632013-05-08 10:59:04 -07003189 }
3190 CHECK(method->GetDeclaringClass()->IsInitializing());
3191 }
3192
3193 self->PushShadowFrame(shadow_frame);
3194
Jeff Hao16743632013-05-08 10:59:04 -07003195 if (LIKELY(!method->IsNative())) {
Jeff Hao69510672013-05-21 17:34:55 -07003196 result->SetJ(Execute(self, mh, code_item, *shadow_frame, JValue()).GetJ());
Jeff Hao16743632013-05-08 10:59:04 -07003197 } else {
3198 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
3199 // generated stub) except during testing and image writing.
3200 CHECK(!Runtime::Current()->IsStarted());
3201 Object* receiver = method->IsStatic() ? NULL : shadow_frame->GetVRegReference(0);
3202 uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
Jeff Hao69510672013-05-21 17:34:55 -07003203 UnstartedRuntimeJni(self, method, receiver, args, result);
Jeff Hao16743632013-05-08 10:59:04 -07003204 }
3205
3206 self->PopShadowFrame();
Jeff Hao69510672013-05-21 17:34:55 -07003207 return;
Jeff Hao16743632013-05-08 10:59:04 -07003208}
3209
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07003210} // namespace interpreter
3211} // namespace art