blob: a3768c7b285ca0512cc8fa06cfddb465bab5aa65 [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 Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "gc/card_table-inl.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070027#include "invoke_arg_array_builder.h"
Ian Rogers64b6d142012-10-29 16:34:15 -070028#include "nth_caller_visitor.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029#include "mirror/class.h"
30#include "mirror/class-inl.h"
31#include "mirror/field-inl.h"
32#include "mirror/abstract_method.h"
33#include "mirror/abstract_method-inl.h"
34#include "mirror/object-inl.h"
35#include "mirror/object_array-inl.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070036#include "object_utils.h"
37#include "runtime_support.h"
38#include "ScopedLocalRef.h"
39#include "scoped_thread_state_change.h"
40#include "thread.h"
41
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080042using namespace art::mirror;
43
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070044namespace art {
Jeff Hao16743632013-05-08 10:59:04 -070045
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070046namespace interpreter {
47
jeffhao87a6edd2012-11-20 18:05:18 -080048static const int32_t kMaxInt = std::numeric_limits<int32_t>::max();
49static const int32_t kMinInt = std::numeric_limits<int32_t>::min();
50static const int64_t kMaxLong = std::numeric_limits<int64_t>::max();
51static const int64_t kMinLong = std::numeric_limits<int64_t>::min();
52
Ian Rogers64b6d142012-10-29 16:34:15 -070053static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method,
Jeff Hao16743632013-05-08 10:59:04 -070054 ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
Ian Rogers64b6d142012-10-29 16:34:15 -070055 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
56 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
57 // problems in core libraries.
58 std::string name(PrettyMethod(target_method));
59 if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") {
Jeff Hao16743632013-05-08 10:59:04 -070060 std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
Ian Rogers64b6d142012-10-29 16:34:15 -070061 ClassLoader* class_loader = NULL; // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
62 Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(),
63 class_loader);
64 CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
65 << PrettyDescriptor(descriptor);
66 result->SetL(found);
67 } else if (name == "java.lang.Object java.lang.Class.newInstance()") {
Jeff Hao16743632013-05-08 10:59:04 -070068 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
Ian Rogers64b6d142012-10-29 16:34:15 -070069 AbstractMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");
70 CHECK(c != NULL);
71 Object* obj = klass->AllocObject(self);
72 CHECK(obj != NULL);
Jeff Hao6474d192013-03-26 14:08:09 -070073 EnterInterpreterFromInvoke(self, c, obj, NULL, NULL);
Ian Rogers64b6d142012-10-29 16:34:15 -070074 result->SetL(obj);
75 } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") {
76 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
77 // going the reflective Dex way.
Jeff Hao16743632013-05-08 10:59:04 -070078 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
79 String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
Ian Rogers64b6d142012-10-29 16:34:15 -070080 Field* found = NULL;
81 FieldHelper fh;
82 ObjectArray<Field>* fields = klass->GetIFields();
83 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
84 Field* f = fields->Get(i);
85 fh.ChangeField(f);
86 if (name->Equals(fh.GetName())) {
87 found = f;
88 }
89 }
90 if (found == NULL) {
91 fields = klass->GetSFields();
92 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
93 Field* f = fields->Get(i);
94 fh.ChangeField(f);
95 if (name->Equals(fh.GetName())) {
96 found = f;
97 }
98 }
99 }
100 CHECK(found != NULL)
101 << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
102 << name->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
103 // TODO: getDeclaredField calls GetType once the field is found to ensure a
104 // NoClassDefFoundError is thrown if the field's type cannot be resolved.
105 result->SetL(found);
106 } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") {
107 // Special case array copying without initializing System.
Jeff Hao16743632013-05-08 10:59:04 -0700108 Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType();
109 jint srcPos = shadow_frame->GetVReg(arg_offset + 1);
110 jint dstPos = shadow_frame->GetVReg(arg_offset + 3);
111 jint length = shadow_frame->GetVReg(arg_offset + 4);
Ian Rogers64b6d142012-10-29 16:34:15 -0700112 if (!ctype->IsPrimitive()) {
Jeff Hao16743632013-05-08 10:59:04 -0700113 ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>();
114 ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>();
Ian Rogers64b6d142012-10-29 16:34:15 -0700115 for (jint i = 0; i < length; ++i) {
116 dst->Set(dstPos + i, src->Get(srcPos + i));
117 }
118 } else if (ctype->IsPrimitiveChar()) {
Jeff Hao16743632013-05-08 10:59:04 -0700119 CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray();
120 CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray();
Ian Rogers64b6d142012-10-29 16:34:15 -0700121 for (jint i = 0; i < length; ++i) {
122 dst->Set(dstPos + i, src->Get(srcPos + i));
123 }
124 } else if (ctype->IsPrimitiveInt()) {
Jeff Hao16743632013-05-08 10:59:04 -0700125 IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray();
126 IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray();
Ian Rogers64b6d142012-10-29 16:34:15 -0700127 for (jint i = 0; i < length; ++i) {
128 dst->Set(dstPos + i, src->Get(srcPos + i));
129 }
130 } else {
131 UNIMPLEMENTED(FATAL) << "System.arraycopy of unexpected type: " << PrettyDescriptor(ctype);
132 }
133 } else {
134 // Not special, continue with regular interpreter execution.
Jeff Hao16743632013-05-08 10:59:04 -0700135 result->SetJ(EnterInterpreterFromInterpreter(self, shadow_frame).GetJ());
Ian Rogers64b6d142012-10-29 16:34:15 -0700136 }
137}
138
139// Hand select a number of methods to be run in a not yet started runtime without using JNI.
140static void UnstartedRuntimeJni(Thread* self, AbstractMethod* method,
Jeff Hao5d917302013-02-27 17:57:33 -0800141 Object* receiver, uint32_t* args, JValue* result)
Ian Rogers64b6d142012-10-29 16:34:15 -0700142 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
143 std::string name(PrettyMethod(method));
144 if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") {
145 result->SetL(NULL);
146 } else if (name == "java.lang.Class dalvik.system.VMStack.getStackClass2()") {
Ian Rogers7a22fa62013-01-23 12:16:16 -0800147 NthCallerVisitor visitor(self, 3);
Ian Rogers64b6d142012-10-29 16:34:15 -0700148 visitor.WalkStack();
149 result->SetL(visitor.caller->GetDeclaringClass());
150 } else if (name == "double java.lang.Math.log(double)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800151 JValue value;
152 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
153 result->SetD(log(value.GetD()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700154 } else if (name == "java.lang.String java.lang.Class.getNameNative()") {
155 result->SetL(receiver->AsClass()->ComputeName());
156 } else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800157 result->SetI(args[0]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700158 } else if (name == "float java.lang.Float.intBitsToFloat(int)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800159 result->SetI(args[0]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700160 } else if (name == "double java.lang.Math.exp(double)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800161 JValue value;
162 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
163 result->SetD(exp(value.GetD()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700164 } else if (name == "java.lang.Object java.lang.Object.internalClone()") {
165 result->SetL(receiver->Clone(self));
166 } else if (name == "void java.lang.Object.notifyAll()") {
Ian Rogers05f30572013-02-20 12:13:11 -0800167 receiver->NotifyAll(self);
Ian Rogers64b6d142012-10-29 16:34:15 -0700168 } else if (name == "int java.lang.String.compareTo(java.lang.String)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800169 String* rhs = reinterpret_cast<Object*>(args[0])->AsString();
Ian Rogers64b6d142012-10-29 16:34:15 -0700170 CHECK(rhs != NULL);
171 result->SetI(receiver->AsString()->CompareTo(rhs));
172 } else if (name == "java.lang.String java.lang.String.intern()") {
173 result->SetL(receiver->AsString()->Intern());
174 } else if (name == "int java.lang.String.fastIndexOf(int, int)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800175 result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700176 } else if (name == "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") {
Jeff Hao5d917302013-02-27 17:57:33 -0800177 result->SetL(Array::CreateMultiArray(self, reinterpret_cast<Object*>(args[0])->AsClass(), reinterpret_cast<Object*>(args[1])->AsIntArray()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700178 } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") {
179 ScopedObjectAccessUnchecked soa(self);
180 result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace(soa)));
181 } else if (name == "boolean java.nio.ByteOrder.isLittleEndian()") {
182 result->SetJ(JNI_TRUE);
183 } else if (name == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800184 Object* obj = reinterpret_cast<Object*>(args[0]);
185 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
186 jint expectedValue = args[3];
187 jint newValue = args[4];
Ian Rogers64b6d142012-10-29 16:34:15 -0700188 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
189 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
190 // Note: android_atomic_release_cas() returns 0 on success, not failure.
191 int r = android_atomic_release_cas(expectedValue, newValue, address);
192 result->SetZ(r == 0);
193 } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
Jeff Hao5d917302013-02-27 17:57:33 -0800194 Object* obj = reinterpret_cast<Object*>(args[0]);
195 Object* newValue = reinterpret_cast<Object*>(args[3]);
196 obj->SetFieldObject(MemberOffset((static_cast<uint64_t>(args[2]) << 32) | args[1]), newValue, false);
Ian Rogers64b6d142012-10-29 16:34:15 -0700197 } else {
198 LOG(FATAL) << "Attempt to invoke native method in non-started runtime: " << name;
199 }
200}
201
202static void InterpreterJni(Thread* self, AbstractMethod* method, StringPiece shorty,
Jeff Hao5d917302013-02-27 17:57:33 -0800203 Object* receiver, uint32_t* args, JValue* result)
Ian Rogers64b6d142012-10-29 16:34:15 -0700204 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
205 // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
206 // it should be removed and JNI compiled stubs used instead.
207 ScopedObjectAccessUnchecked soa(self);
208 if (method->IsStatic()) {
209 if (shorty == "L") {
210 typedef jobject (fnptr)(JNIEnv*, jclass);
211 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
212 ScopedLocalRef<jclass> klass(soa.Env(),
213 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
Ian Rogers556d6372012-11-20 12:19:36 -0800214 jobject jresult;
215 {
216 ScopedThreadStateChange tsc(self, kNative);
217 jresult = fn(soa.Env(), klass.get());
218 }
219 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700220 } else if (shorty == "V") {
221 typedef void (fnptr)(JNIEnv*, jclass);
222 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
223 ScopedLocalRef<jclass> klass(soa.Env(),
224 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
225 ScopedThreadStateChange tsc(self, kNative);
226 fn(soa.Env(), klass.get());
227 } else if (shorty == "Z") {
228 typedef jboolean (fnptr)(JNIEnv*, jclass);
229 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
230 ScopedLocalRef<jclass> klass(soa.Env(),
231 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
232 ScopedThreadStateChange tsc(self, kNative);
233 result->SetZ(fn(soa.Env(), klass.get()));
234 } else if (shorty == "BI") {
235 typedef jbyte (fnptr)(JNIEnv*, jclass, jint);
236 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
237 ScopedLocalRef<jclass> klass(soa.Env(),
238 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
239 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800240 result->SetB(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700241 } else if (shorty == "II") {
242 typedef jint (fnptr)(JNIEnv*, jclass, jint);
243 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
244 ScopedLocalRef<jclass> klass(soa.Env(),
245 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
246 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800247 result->SetI(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700248 } else if (shorty == "LL") {
249 typedef jobject (fnptr)(JNIEnv*, jclass, jobject);
250 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
251 ScopedLocalRef<jclass> klass(soa.Env(),
252 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
253 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800254 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -0800255 jobject jresult;
256 {
257 ScopedThreadStateChange tsc(self, kNative);
258 jresult = fn(soa.Env(), klass.get(), arg0.get());
259 }
260 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700261 } else if (shorty == "IIZ") {
262 typedef jint (fnptr)(JNIEnv*, jclass, jint, jboolean);
263 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
264 ScopedLocalRef<jclass> klass(soa.Env(),
265 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
266 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800267 result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700268 } else if (shorty == "ILI") {
269 typedef jint (fnptr)(JNIEnv*, jclass, jobject, jint);
270 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
271 ScopedLocalRef<jclass> klass(soa.Env(),
272 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
273 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800274 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700275 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800276 result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700277 } else if (shorty == "SIZ") {
278 typedef jshort (fnptr)(JNIEnv*, jclass, jint, jboolean);
279 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
280 ScopedLocalRef<jclass> klass(soa.Env(),
281 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
282 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800283 result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700284 } else if (shorty == "VIZ") {
285 typedef void (fnptr)(JNIEnv*, jclass, jint, jboolean);
286 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
287 ScopedLocalRef<jclass> klass(soa.Env(),
288 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
289 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800290 fn(soa.Env(), klass.get(), args[0], args[1]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700291 } else if (shorty == "ZLL") {
292 typedef jboolean (fnptr)(JNIEnv*, jclass, jobject, jobject);
293 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
294 ScopedLocalRef<jclass> klass(soa.Env(),
295 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
296 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800297 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700298 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800299 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700300 ScopedThreadStateChange tsc(self, kNative);
301 result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
302 } else if (shorty == "ZILL") {
303 typedef jboolean (fnptr)(JNIEnv*, jclass, jint, jobject, jobject);
304 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
305 ScopedLocalRef<jclass> klass(soa.Env(),
306 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
307 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800308 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700309 ScopedLocalRef<jobject> arg2(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800310 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700311 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800312 result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700313 } else if (shorty == "VILII") {
314 typedef void (fnptr)(JNIEnv*, jclass, jint, jobject, jint, jint);
315 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
316 ScopedLocalRef<jclass> klass(soa.Env(),
317 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
318 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800319 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700320 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800321 fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700322 } else if (shorty == "VLILII") {
323 typedef void (fnptr)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
324 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
325 ScopedLocalRef<jclass> klass(soa.Env(),
326 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
327 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800328 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700329 ScopedLocalRef<jobject> arg2(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800330 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700331 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800332 fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700333 } else {
334 LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
335 << " shorty: " << shorty;
336 }
337 } else {
338 if (shorty == "L") {
339 typedef jobject (fnptr)(JNIEnv*, jobject);
340 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
341 ScopedLocalRef<jobject> rcvr(soa.Env(),
342 soa.AddLocalReference<jobject>(receiver));
Ian Rogers556d6372012-11-20 12:19:36 -0800343 jobject jresult;
344 {
345 ScopedThreadStateChange tsc(self, kNative);
346 jresult = fn(soa.Env(), rcvr.get());
347 }
348 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700349 } else if (shorty == "LL") {
350 typedef jobject (fnptr)(JNIEnv*, jobject, jobject);
351 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
352 ScopedLocalRef<jobject> rcvr(soa.Env(),
353 soa.AddLocalReference<jobject>(receiver));
354 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800355 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -0800356 jobject jresult;
357 {
358 ScopedThreadStateChange tsc(self, kNative);
359 jresult = fn(soa.Env(), rcvr.get(), arg0.get());
360
361 }
362 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700363 ScopedThreadStateChange tsc(self, kNative);
Ian Rogers64b6d142012-10-29 16:34:15 -0700364 } else if (shorty == "III") {
365 typedef jint (fnptr)(JNIEnv*, jobject, jint, jint);
366 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
367 ScopedLocalRef<jobject> rcvr(soa.Env(),
368 soa.AddLocalReference<jobject>(receiver));
369 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800370 result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700371 } else {
372 LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
373 << " shorty: " << shorty;
374 }
375 }
376}
377
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700378static void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
379 ref->MonitorEnter(self);
380}
381
382static void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
383 ref->MonitorExit(self);
384}
385
386static void DoInvoke(Thread* self, MethodHelper& mh, ShadowFrame& shadow_frame,
Sebastien Hertz807a2562013-04-15 09:33:39 +0200387 const Instruction* inst, InvokeType type, bool is_range,
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700388 JValue* result)
389 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200390 uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700391 Object* receiver;
392 if (type == kStatic) {
393 receiver = NULL;
394 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200395 receiver = shadow_frame.GetVRegReference(vregC);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700396 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200397 uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700398 AbstractMethod* target_method = FindMethodFromCode(method_idx, receiver,
Sebastien Hertz807a2562013-04-15 09:33:39 +0200399 shadow_frame.GetMethod(),
400 self, true, type);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700401 if (UNLIKELY(target_method == NULL)) {
402 CHECK(self->IsExceptionPending());
403 result->SetJ(0);
404 return;
405 }
406 mh.ChangeMethod(target_method);
Jeff Hao16743632013-05-08 10:59:04 -0700407
408 const DexFile::CodeItem* code_item = mh.GetCodeItem();
409 uint16_t num_regs;
410 uint16_t num_ins;
411 if (code_item != NULL) {
412 num_regs = code_item->registers_size_;
413 num_ins = code_item->ins_size_;
414 } else if (target_method->IsAbstract()) {
415 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
416 self->ThrowNewExceptionF(throw_location, "Ljava/lang/AbstractMethodError;",
417 "abstract method \"%s\"", PrettyMethod(target_method).c_str());
418 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700419 } else {
Jeff Hao16743632013-05-08 10:59:04 -0700420 DCHECK(target_method->IsNative() || target_method->IsProxyMethod());
421 num_regs = num_ins = AbstractMethod::NumArgRegisters(mh.GetShorty());
422 if (!target_method->IsStatic()) {
423 num_regs++;
424 num_ins++;
Jeff Hao5d917302013-02-27 17:57:33 -0800425 }
Jeff Hao16743632013-05-08 10:59:04 -0700426 }
427
428 Runtime* runtime = Runtime::Current();
429 UniquePtr<ShadowFrame> new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame,
430 target_method, 0));
431 size_t cur_reg = num_regs - num_ins;
432 if (receiver != NULL) {
433 new_shadow_frame->SetVRegReference(cur_reg, receiver);
434 ++cur_reg;
435 }
436
437 size_t arg_offset = (receiver == NULL) ? 0 : 1;
438 const char* shorty = mh.GetShorty();
Sebastien Hertz807a2562013-04-15 09:33:39 +0200439 uint32_t arg[5];
440 if (!is_range) {
441 inst->GetArgs(arg);
442 }
Jeff Hao16743632013-05-08 10:59:04 -0700443 for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
444 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
Sebastien Hertz807a2562013-04-15 09:33:39 +0200445 size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
Jeff Hao16743632013-05-08 10:59:04 -0700446 switch (shorty[shorty_pos + 1]) {
447 case 'L': {
448 Object* o = shadow_frame.GetVRegReference(arg_pos);
449 new_shadow_frame->SetVRegReference(cur_reg, o);
450 break;
451 }
452 case 'J': case 'D': {
453 uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
454 static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
455 new_shadow_frame->SetVRegLong(cur_reg, wide_value);
456 cur_reg++;
457 arg_offset++;
458 break;
459 }
460 default:
461 new_shadow_frame->SetVReg(cur_reg, shadow_frame.GetVReg(arg_pos));
462 break;
463 }
464 }
465
466 if (LIKELY(runtime->IsStarted())) {
467 result->SetJ((target_method->GetEntryPointFromInterpreter())(self, new_shadow_frame.get()).GetJ());
468 } else {
469 UnstartedRuntimeInvoke(self, target_method, new_shadow_frame.get(), result, num_regs - num_ins);
Ian Rogers64b6d142012-10-29 16:34:15 -0700470 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700471 mh.ChangeMethod(shadow_frame.GetMethod());
472}
473
474static void DoFieldGet(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz807a2562013-04-15 09:33:39 +0200475 const Instruction* inst, FindFieldType find_type,
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700476 Primitive::Type field_type)
477 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
478 bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200479 uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700480 Field* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
481 find_type, Primitive::FieldSize(field_type));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200482 if (UNLIKELY(f == NULL)) {
483 CHECK(self->IsExceptionPending());
484 return;
485 }
486 Object* obj;
487 if (is_static) {
488 obj = f->GetDeclaringClass();
489 } else {
490 obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
491 if (UNLIKELY(obj == NULL)) {
492 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
493 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700494 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200495 }
496 uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c();
497 switch (field_type) {
498 case Primitive::kPrimBoolean:
499 shadow_frame.SetVReg(vregA, f->GetBoolean(obj));
500 break;
501 case Primitive::kPrimByte:
502 shadow_frame.SetVReg(vregA, f->GetByte(obj));
503 break;
504 case Primitive::kPrimChar:
505 shadow_frame.SetVReg(vregA, f->GetChar(obj));
506 break;
507 case Primitive::kPrimShort:
508 shadow_frame.SetVReg(vregA, f->GetShort(obj));
509 break;
510 case Primitive::kPrimInt:
511 shadow_frame.SetVReg(vregA, f->GetInt(obj));
512 break;
513 case Primitive::kPrimLong:
514 shadow_frame.SetVRegLong(vregA, f->GetLong(obj));
515 break;
516 case Primitive::kPrimNot:
517 shadow_frame.SetVRegReference(vregA, f->GetObject(obj));
518 break;
519 default:
520 LOG(FATAL) << "Unreachable: " << field_type;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700521 }
522}
523
524static void DoFieldPut(Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertz807a2562013-04-15 09:33:39 +0200525 const Instruction* inst, FindFieldType find_type,
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700526 Primitive::Type field_type)
527 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
528 bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200529 uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700530 Field* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
531 find_type, Primitive::FieldSize(field_type));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200532 if (UNLIKELY(f == NULL)) {
533 CHECK(self->IsExceptionPending());
534 return;
535 }
536 Object* obj;
537 if (is_static) {
538 obj = f->GetDeclaringClass();
539 } else {
540 obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
541 if (UNLIKELY(obj == NULL)) {
542 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
543 f, false);
544 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700545 }
546 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200547 uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c();
548 switch (field_type) {
549 case Primitive::kPrimBoolean:
550 f->SetBoolean(obj, shadow_frame.GetVReg(vregA));
551 break;
552 case Primitive::kPrimByte:
553 f->SetByte(obj, shadow_frame.GetVReg(vregA));
554 break;
555 case Primitive::kPrimChar:
556 f->SetChar(obj, shadow_frame.GetVReg(vregA));
557 break;
558 case Primitive::kPrimShort:
559 f->SetShort(obj, shadow_frame.GetVReg(vregA));
560 break;
561 case Primitive::kPrimInt:
562 f->SetInt(obj, shadow_frame.GetVReg(vregA));
563 break;
564 case Primitive::kPrimLong:
565 f->SetLong(obj, shadow_frame.GetVRegLong(vregA));
566 break;
567 case Primitive::kPrimNot:
568 f->SetObj(obj, shadow_frame.GetVRegReference(vregA));
569 break;
570 default:
571 LOG(FATAL) << "Unreachable: " << field_type;
572 }
573}
574
575static String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx) {
576 Class* java_lang_string_class = String::GetJavaLangString();
577 if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
578 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
579 if (UNLIKELY(!class_linker->EnsureInitialized(java_lang_string_class,
580 true, true))) {
581 DCHECK(self->IsExceptionPending());
582 return NULL;
583 }
584 }
585 return mh.ResolveString(string_idx);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700586}
587
jeffhaod91398c2012-11-20 17:17:33 -0800588static void DoIntDivide(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
589 int32_t dividend, int32_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800590 if (UNLIKELY(divisor == 0)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800591 ThrowArithmeticExceptionDivideByZero(self);
jeffhaod91398c2012-11-20 17:17:33 -0800592 } else if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
593 shadow_frame.SetVReg(result_reg, kMinInt);
594 } else {
595 shadow_frame.SetVReg(result_reg, dividend / divisor);
596 }
597}
598
599static void DoIntRemainder(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
600 int32_t dividend, int32_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800601 if (UNLIKELY(divisor == 0)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800602 ThrowArithmeticExceptionDivideByZero(self);
jeffhaod91398c2012-11-20 17:17:33 -0800603 } else if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
604 shadow_frame.SetVReg(result_reg, 0);
605 } else {
606 shadow_frame.SetVReg(result_reg, dividend % divisor);
607 }
608}
609
610static void DoLongDivide(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
611 int64_t dividend, int64_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800612 if (UNLIKELY(divisor == 0)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800613 ThrowArithmeticExceptionDivideByZero(self);
jeffhaod91398c2012-11-20 17:17:33 -0800614 } else if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
615 shadow_frame.SetVRegLong(result_reg, kMinLong);
616 } else {
617 shadow_frame.SetVRegLong(result_reg, dividend / divisor);
618 }
619}
620
621static void DoLongRemainder(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
622 int64_t dividend, int64_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800623 if (UNLIKELY(divisor == 0)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800624 ThrowArithmeticExceptionDivideByZero(self);
jeffhaod91398c2012-11-20 17:17:33 -0800625 } else if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
626 shadow_frame.SetVRegLong(result_reg, 0);
627 } else {
628 shadow_frame.SetVRegLong(result_reg, dividend % divisor);
629 }
630}
631
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700632static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
Ian Rogers306057f2012-11-26 12:45:53 -0800633 ShadowFrame& shadow_frame, JValue result_register)
634 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800635 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
636 LOG(FATAL) << "Invalid shadow frame for interpreter use";
637 return JValue();
638 }
639 self->VerifyStack();
640 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
Sebastien Hertz807a2562013-04-15 09:33:39 +0200641 const uint16_t* const insns = code_item->insns_;
642
643 // As the 'this' object won't change during the execution of current code, we
644 // want to cache it in local variables. Nevertheless, in order to let the
645 // garbage collector access it, we store it into sirt references.
646 SirtRef<Object> this_object_ref(self, shadow_frame.GetThisObject());
647
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700648 const Instruction* inst = Instruction::At(insns + shadow_frame.GetDexPC());
Ian Rogers62d6c772013-02-27 08:32:07 -0800649 if (inst->GetDexPc(insns) == 0) { // We are entering the method as opposed to deoptimizing..
Sebastien Hertz807a2562013-04-15 09:33:39 +0200650 instrumentation->MethodEnterEvent(self, this_object_ref.get(),
651 shadow_frame.GetMethod(), 0);
Ian Rogers62d6c772013-02-27 08:32:07 -0800652 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700653 while (true) {
jeffhao373c52f2012-11-20 16:11:52 -0800654 CheckSuspend(self);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200655 const uint32_t dex_pc = inst->GetDexPc(insns);
jeffhao373c52f2012-11-20 16:11:52 -0800656 shadow_frame.SetDexPC(dex_pc);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200657 instrumentation->DexPcMovedEvent(self, this_object_ref.get(),
658 shadow_frame.GetMethod(), dex_pc);
Ian Rogers64b6d142012-10-29 16:34:15 -0700659 const bool kTracing = false;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700660 if (kTracing) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800661#define TRACE_LOG std::cerr
662 TRACE_LOG << PrettyMethod(shadow_frame.GetMethod())
Sebastien Hertz807a2562013-04-15 09:33:39 +0200663 << StringPrintf("\n0x%x: ", dex_pc)
Ian Rogers62d6c772013-02-27 08:32:07 -0800664 << inst->DumpString(&mh.GetDexFile()) << "\n";
TDYa127ce4cc0d2012-11-18 16:59:53 -0800665 for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800666 uint32_t raw_value = shadow_frame.GetVReg(i);
667 Object* ref_value = shadow_frame.GetVRegReference(i);
668 TRACE_LOG << StringPrintf(" vreg%d=0x%08X", i, raw_value);
669 if (ref_value != NULL) {
670 if (ref_value->GetClass()->IsStringClass() &&
671 ref_value->AsString()->GetCharArray() != NULL) {
672 TRACE_LOG << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700673 } else {
Ian Rogers62d6c772013-02-27 08:32:07 -0800674 TRACE_LOG << "/" << PrettyTypeOf(ref_value);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700675 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700676 }
677 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800678 TRACE_LOG << "\n";
679#undef TRACE_LOG
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700680 }
681 const Instruction* next_inst = inst->Next();
Sebastien Hertz807a2562013-04-15 09:33:39 +0200682 switch (inst->Opcode()) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700683 case Instruction::NOP:
684 break;
685 case Instruction::MOVE:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200686 shadow_frame.SetVReg(inst->VRegA_12x(),
687 shadow_frame.GetVReg(inst->VRegB_12x()));
688 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700689 case Instruction::MOVE_FROM16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200690 shadow_frame.SetVReg(inst->VRegA_22x(),
691 shadow_frame.GetVReg(inst->VRegB_22x()));
692 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700693 case Instruction::MOVE_16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200694 shadow_frame.SetVReg(inst->VRegA_32x(),
695 shadow_frame.GetVReg(inst->VRegB_32x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700696 break;
697 case Instruction::MOVE_WIDE:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200698 shadow_frame.SetVRegLong(inst->VRegA_12x(),
699 shadow_frame.GetVRegLong(inst->VRegB_12x()));
700 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700701 case Instruction::MOVE_WIDE_FROM16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200702 shadow_frame.SetVRegLong(inst->VRegA_22x(),
703 shadow_frame.GetVRegLong(inst->VRegB_22x()));
704 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700705 case Instruction::MOVE_WIDE_16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200706 shadow_frame.SetVRegLong(inst->VRegA_32x(),
707 shadow_frame.GetVRegLong(inst->VRegB_32x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700708 break;
709 case Instruction::MOVE_OBJECT:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200710 shadow_frame.SetVRegReference(inst->VRegA_12x(),
711 shadow_frame.GetVRegReference(inst->VRegB_12x()));
712 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700713 case Instruction::MOVE_OBJECT_FROM16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200714 shadow_frame.SetVRegReference(inst->VRegA_22x(),
715 shadow_frame.GetVRegReference(inst->VRegB_22x()));
716 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700717 case Instruction::MOVE_OBJECT_16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200718 shadow_frame.SetVRegReference(inst->VRegA_32x(),
719 shadow_frame.GetVRegReference(inst->VRegB_32x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700720 break;
721 case Instruction::MOVE_RESULT:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200722 shadow_frame.SetVReg(inst->VRegA_11x(), result_register.GetI());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700723 break;
724 case Instruction::MOVE_RESULT_WIDE:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200725 shadow_frame.SetVRegLong(inst->VRegA_11x(), result_register.GetJ());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700726 break;
727 case Instruction::MOVE_RESULT_OBJECT:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200728 shadow_frame.SetVRegReference(inst->VRegA_11x(), result_register.GetL());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700729 break;
730 case Instruction::MOVE_EXCEPTION: {
Ian Rogers62d6c772013-02-27 08:32:07 -0800731 Throwable* exception = self->GetException(NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700732 self->ClearException();
Sebastien Hertz807a2562013-04-15 09:33:39 +0200733 shadow_frame.SetVRegReference(inst->VRegA_11x(), exception);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700734 break;
735 }
736 case Instruction::RETURN_VOID: {
737 JValue result;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200738 instrumentation->MethodExitEvent(self, this_object_ref.get(),
739 shadow_frame.GetMethod(), dex_pc, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700740 return result;
741 }
742 case Instruction::RETURN: {
743 JValue result;
744 result.SetJ(0);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200745 result.SetI(shadow_frame.GetVReg(inst->VRegA_11x()));
746 instrumentation->MethodExitEvent(self, this_object_ref.get(),
747 shadow_frame.GetMethod(), dex_pc, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700748 return result;
749 }
750 case Instruction::RETURN_WIDE: {
751 JValue result;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200752 result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x()));
753 instrumentation->MethodExitEvent(self, this_object_ref.get(),
754 shadow_frame.GetMethod(), dex_pc, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700755 return result;
756 }
757 case Instruction::RETURN_OBJECT: {
758 JValue result;
759 result.SetJ(0);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200760 result.SetL(shadow_frame.GetVRegReference(inst->VRegA_11x()));
761 instrumentation->MethodExitEvent(self, this_object_ref.get(),
762 shadow_frame.GetMethod(), dex_pc, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700763 return result;
764 }
765 case Instruction::CONST_4: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200766 uint32_t dst = inst->VRegA_11n();
767 int32_t val = static_cast<int32_t>(inst->VRegB_11n() << 28) >> 28;
768 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700769 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200770 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700771 }
772 break;
773 }
774 case Instruction::CONST_16: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200775 uint32_t dst = inst->VRegA_21s();
776 int32_t val = static_cast<int16_t>(inst->VRegB_21s());
777 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700778 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200779 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700780 }
781 break;
782 }
783 case Instruction::CONST: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200784 uint32_t dst = inst->VRegA_31i();
785 int32_t val = inst->VRegB_31i();
786 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700787 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200788 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700789 }
790 break;
791 }
792 case Instruction::CONST_HIGH16: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200793 uint32_t dst = inst->VRegA_21h();
794 int32_t val = inst->VRegB_21h() << 16;
795 shadow_frame.SetVReg(dst, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700796 if (val == 0) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200797 shadow_frame.SetVRegReference(dst, NULL);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700798 }
799 break;
800 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700801 case Instruction::CONST_WIDE_16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200802 shadow_frame.SetVRegLong(inst->VRegA_21s(),
803 static_cast<int16_t>(inst->VRegB_21s()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700804 break;
Ian Rogers64b6d142012-10-29 16:34:15 -0700805 case Instruction::CONST_WIDE_32:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200806 shadow_frame.SetVRegLong(inst->VRegA_31i(),
807 static_cast<int32_t>(inst->VRegB_31i()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700808 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700809 case Instruction::CONST_WIDE:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200810 shadow_frame.SetVRegLong(inst->VRegA_51l(), inst->VRegB_51l());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700811 break;
812 case Instruction::CONST_WIDE_HIGH16:
Sebastien Hertz807a2562013-04-15 09:33:39 +0200813 shadow_frame.SetVRegLong(inst->VRegA_21h(),
814 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700815 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200816 case Instruction::CONST_STRING: {
817 String* s = ResolveString(self, mh, inst->VRegB_21c());
818 if (UNLIKELY(s == NULL)) {
819 CHECK(self->IsExceptionPending());
820 } else {
821 shadow_frame.SetVRegReference( inst->VRegA_21c(), s);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700822 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200823 break;
824 }
825 case Instruction::CONST_STRING_JUMBO: {
826 String* s = ResolveString(self, mh, inst->VRegB_31c());
827 if (UNLIKELY(s == NULL)) {
828 CHECK(self->IsExceptionPending());
829 } else {
830 shadow_frame.SetVRegReference( inst->VRegA_31c(), s);
831 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700832 break;
833 }
jeffhao0a9bb732012-11-26 12:28:49 -0800834 case Instruction::CONST_CLASS: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200835 Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
836 self, false, true);
837 if (UNLIKELY(c == NULL)) {
838 CHECK(self->IsExceptionPending());
839 } else {
840 shadow_frame.SetVRegReference(inst->VRegA_21c(), c);
841 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700842 break;
jeffhao0a9bb732012-11-26 12:28:49 -0800843 }
jeffhao87a6edd2012-11-20 18:05:18 -0800844 case Instruction::MONITOR_ENTER: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200845 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x());
jeffhao87a6edd2012-11-20 18:05:18 -0800846 if (UNLIKELY(obj == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800847 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
jeffhao87a6edd2012-11-20 18:05:18 -0800848 } else {
849 DoMonitorEnter(self, obj);
850 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700851 break;
jeffhao87a6edd2012-11-20 18:05:18 -0800852 }
853 case Instruction::MONITOR_EXIT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200854 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x());
jeffhao87a6edd2012-11-20 18:05:18 -0800855 if (UNLIKELY(obj == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800856 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
jeffhao87a6edd2012-11-20 18:05:18 -0800857 } else {
858 DoMonitorExit(self, obj);
859 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700860 break;
jeffhao87a6edd2012-11-20 18:05:18 -0800861 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700862 case Instruction::CHECK_CAST: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200863 Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
864 self, false, true);
jeffhao87a6edd2012-11-20 18:05:18 -0800865 if (UNLIKELY(c == NULL)) {
866 CHECK(self->IsExceptionPending());
867 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200868 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_21c());
jeffhao87a6edd2012-11-20 18:05:18 -0800869 if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800870 ThrowClassCastException(c, obj->GetClass());
jeffhao87a6edd2012-11-20 18:05:18 -0800871 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700872 }
873 break;
874 }
875 case Instruction::INSTANCE_OF: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200876 Class* c = ResolveVerifyAndClinit(inst->VRegC_22c(), shadow_frame.GetMethod(),
877 self, false, true);
jeffhao87a6edd2012-11-20 18:05:18 -0800878 if (UNLIKELY(c == NULL)) {
879 CHECK(self->IsExceptionPending());
880 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200881 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c());
882 shadow_frame.SetVReg(inst->VRegA_22c(), (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
jeffhao87a6edd2012-11-20 18:05:18 -0800883 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700884 break;
885 }
886 case Instruction::ARRAY_LENGTH: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200887 Object* array = shadow_frame.GetVRegReference(inst->VRegB_12x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700888 if (UNLIKELY(array == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800889 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700890 break;
891 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200892 shadow_frame.SetVReg(inst->VRegA_12x(), array->AsArray()->GetLength());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700893 break;
894 }
895 case Instruction::NEW_INSTANCE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200896 Object* obj = AllocObjectFromCode(inst->VRegB_21c(), shadow_frame.GetMethod(),
897 self, true);
898 if (UNLIKELY(obj == NULL)) {
899 CHECK(self->IsExceptionPending());
900 } else {
901 shadow_frame.SetVRegReference(inst->VRegA_21c(), obj);
902 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700903 break;
904 }
905 case Instruction::NEW_ARRAY: {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200906 int32_t length = shadow_frame.GetVReg(inst->VRegB_22c());
907 Object* obj = AllocArrayFromCode(inst->VRegC_22c(), shadow_frame.GetMethod(),
908 length, self, true);
909 if (UNLIKELY(obj == NULL)) {
910 CHECK(self->IsExceptionPending());
911 } else {
912 shadow_frame.SetVRegReference(inst->VRegA_22c(), obj);
913 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700914 break;
915 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200916 case Instruction::FILLED_NEW_ARRAY: {
917 const int32_t length = inst->VRegA_35c();
918 CHECK(length <= 5);
jeffhao42b4dc42012-12-10 10:25:43 -0800919 if (UNLIKELY(length < 0)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800920 ThrowNegativeArraySizeException(length);
jeffhao42b4dc42012-12-10 10:25:43 -0800921 break;
922 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200923 Class* arrayClass = ResolveVerifyAndClinit(inst->VRegB_35c(), shadow_frame.GetMethod(),
924 self, false, true);
jeffhao42b4dc42012-12-10 10:25:43 -0800925 if (UNLIKELY(arrayClass == NULL)) {
926 CHECK(self->IsExceptionPending());
927 break;
928 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700929 CHECK(arrayClass->IsArrayClass());
jeffhao42b4dc42012-12-10 10:25:43 -0800930 Class* componentClass = arrayClass->GetComponentType();
931 if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
932 if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800933 ThrowRuntimeException("Bad filled array request for type %s",
934 PrettyDescriptor(componentClass).c_str());
jeffhao42b4dc42012-12-10 10:25:43 -0800935 } else {
Ian Rogers62d6c772013-02-27 08:32:07 -0800936 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
937 "Ljava/lang/InternalError;",
jeffhao42b4dc42012-12-10 10:25:43 -0800938 "Found type %s; filled-new-array not implemented for anything but \'int\'",
939 PrettyDescriptor(componentClass).c_str());
940 }
941 break;
942 }
943 Object* newArray = Array::Alloc(self, arrayClass, length);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200944 if (UNLIKELY(newArray == NULL)) {
945 CHECK(self->IsExceptionPending());
946 } else {
947 uint32_t arg[5];
948 inst->GetArgs(arg);
949 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
jeffhao42b4dc42012-12-10 10:25:43 -0800950 for (int32_t i = 0; i < length; ++i) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200951 if (is_primitive_int_component) {
952 newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(arg[i]));
jeffhao42b4dc42012-12-10 10:25:43 -0800953 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200954 newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(arg[i]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700955 }
956 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700957 }
jeffhao42b4dc42012-12-10 10:25:43 -0800958 result_register.SetL(newArray);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700959 break;
Ian Rogers64b6d142012-10-29 16:34:15 -0700960 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200961 case Instruction::FILLED_NEW_ARRAY_RANGE: {
962 int32_t length = inst->VRegA_3rc();
963 if (UNLIKELY(length < 0)) {
964 ThrowNegativeArraySizeException(length);
965 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700966 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200967 Class* arrayClass = ResolveVerifyAndClinit(inst->VRegB_3rc(), shadow_frame.GetMethod(),
968 self, false, true);
969 if (UNLIKELY(arrayClass == NULL)) {
970 CHECK(self->IsExceptionPending());
971 break;
972 }
973 CHECK(arrayClass->IsArrayClass());
974 Class* componentClass = arrayClass->GetComponentType();
975 if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
976 if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
977 ThrowRuntimeException("Bad filled array request for type %s",
978 PrettyDescriptor(componentClass).c_str());
979 } else {
980 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
981 "Ljava/lang/InternalError;",
982 "Found type %s; filled-new-array not implemented for anything but \'int\'",
983 PrettyDescriptor(componentClass).c_str());
984 }
985 break;
986 }
987 Object* newArray = Array::Alloc(self, arrayClass, length);
988 if (UNLIKELY(newArray == NULL)) {
989 CHECK(self->IsExceptionPending());
990 } else {
991 uint32_t vregC = inst->VRegC_3rc();
992 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
993 for (int32_t i = 0; i < length; ++i) {
994 if (is_primitive_int_component) {
995 newArray->AsIntArray()->Set(i, shadow_frame.GetVReg(vregC + i));
996 } else {
997 newArray->AsObjectArray<Object>()->Set(i, shadow_frame.GetVRegReference(vregC + i));
998 }
999 }
1000 }
1001 result_register.SetL(newArray);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001002 break;
1003 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001004 case Instruction::FILL_ARRAY_DATA: {
1005 Object* obj = shadow_frame.GetVRegReference(inst->VRegA_31t());
1006 if (UNLIKELY(obj == NULL)) {
1007 ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
1008 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001009 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001010 Array* array = obj->AsArray();
1011 DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
1012 const Instruction::ArrayDataPayload* payload =
1013 reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + dex_pc + inst->VRegB_31t());
1014 if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
1015 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
1016 "Ljava/lang/ArrayIndexOutOfBoundsException;",
1017 "failed FILL_ARRAY_DATA; length=%d, index=%d",
1018 array->GetLength(), payload->element_count);
1019 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001020 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001021 uint32_t size_in_bytes = payload->element_count * payload->element_width;
1022 memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001023 break;
1024 }
1025 case Instruction::THROW: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001026 Object* exception = shadow_frame.GetVRegReference(inst->VRegA_11x());
1027 if (UNLIKELY(exception == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001028 ThrowNullPointerException(NULL, "throw with null exception");
1029 } else {
1030 self->SetException(shadow_frame.GetCurrentLocationForThrow(), exception->AsThrowable());
1031 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001032 break;
1033 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001034 case Instruction::GOTO: {
1035 next_inst = Instruction::At(insns + dex_pc + inst->VRegA_10t());
1036 break;
1037 }
1038 case Instruction::GOTO_16: {
1039 next_inst = Instruction::At(insns + dex_pc + inst->VRegA_20t());
1040 break;
1041 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001042 case Instruction::GOTO_32: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001043 next_inst = Instruction::At(insns + dex_pc + inst->VRegA_30t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001044 break;
1045 }
Ian Rogers556d6372012-11-20 12:19:36 -08001046 case Instruction::PACKED_SWITCH: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001047 const uint16_t* switch_data = insns + dex_pc + inst->VRegB_31t();
1048 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
Ian Rogers556d6372012-11-20 12:19:36 -08001049 CHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
1050 uint16_t size = switch_data[1];
1051 CHECK_GT(size, 0);
1052 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
1053 CHECK(IsAligned<4>(keys));
1054 int32_t first_key = keys[0];
1055 const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
1056 CHECK(IsAligned<4>(targets));
1057 int32_t index = test_val - first_key;
1058 if (index >= 0 && index < size) {
1059 next_inst = Instruction::At(insns + dex_pc + targets[index]);
1060 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001061 break;
Ian Rogers556d6372012-11-20 12:19:36 -08001062 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001063 case Instruction::SPARSE_SWITCH: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001064 const uint16_t* switch_data = insns + dex_pc + inst->VRegB_31t();
1065 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
Ian Rogers556d6372012-11-20 12:19:36 -08001066 CHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
1067 uint16_t size = switch_data[1];
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001068 CHECK_GT(size, 0);
Ian Rogers556d6372012-11-20 12:19:36 -08001069 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001070 CHECK(IsAligned<4>(keys));
1071 const int32_t* entries = keys + size;
1072 CHECK(IsAligned<4>(entries));
1073 int lo = 0;
1074 int hi = size - 1;
1075 while (lo <= hi) {
1076 int mid = (lo + hi) / 2;
1077 int32_t foundVal = keys[mid];
Ian Rogers556d6372012-11-20 12:19:36 -08001078 if (test_val < foundVal) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001079 hi = mid - 1;
Ian Rogers556d6372012-11-20 12:19:36 -08001080 } else if (test_val > foundVal) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001081 lo = mid + 1;
1082 } else {
1083 next_inst = Instruction::At(insns + dex_pc + entries[mid]);
1084 break;
1085 }
1086 }
1087 break;
1088 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001089 case Instruction::CMPL_FLOAT: {
1090 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
1091 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
1092 int32_t result;
1093 // TODO: we should not test float equality like this. Reorder comparisons
1094 // or use a different comparison mechanism.
1095 if (val1 == val2) {
1096 result = 0;
1097 } else if (val1 > val2) {
1098 result = 1;
1099 } else {
1100 result = -1;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001101 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001102 shadow_frame.SetVReg(inst->VRegA_23x(), result);
1103 break;
1104 }
1105 case Instruction::CMPG_FLOAT: {
1106 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
1107 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
1108 int32_t result;
1109 // TODO: we should not test float equality like this. Reorder comparisons
1110 // or use a different comparison mechanism.
1111 if (val1 == val2) {
1112 result = 0;
1113 } else if (val1 < val2) {
1114 result = -1;
1115 } else {
1116 result = 1;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001117 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001118 shadow_frame.SetVReg(inst->VRegA_23x(), result);
1119 break;
1120 }
1121 case Instruction::CMPL_DOUBLE: {
1122 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
1123 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
1124 int32_t result;
1125 // TODO: we should not test double equality like this. Reorder comparisons
1126 // or use a different comparison mechanism.
1127 if (val1 == val2) {
1128 result = 0;
1129 } else if (val1 > val2) {
1130 result = 1;
1131 } else {
1132 result = -1;
1133 }
1134 shadow_frame.SetVReg(inst->VRegA_23x(), result);
1135 break;
1136 }
1137
1138 case Instruction::CMPG_DOUBLE: {
1139 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
1140 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
1141 int32_t result;
1142 // TODO: we should not test double equality like this. Reorder comparisons
1143 // or use a different comparison mechanism.
1144 if (val1 == val2) {
1145 result = 0;
1146 } else if (val1 < val2) {
1147 result = -1;
1148 } else {
1149 result = 1;
1150 }
1151 shadow_frame.SetVReg(inst->VRegA_23x(), result);
1152 break;
1153 }
1154 case Instruction::CMP_LONG: {
1155 int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
1156 int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
1157 int32_t result;
1158 if (val1 > val2) {
1159 result = 1;
1160 } else if (val1 == val2) {
1161 result = 0;
1162 } else {
1163 result = -1;
1164 }
1165 shadow_frame.SetVReg(inst->VRegA_23x(), result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001166 break;
1167 }
1168 case Instruction::IF_EQ: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001169 if (shadow_frame.GetVReg(inst->VRegA_22t()) == shadow_frame.GetVReg(inst->VRegB_22t())) {
1170 next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001171 }
1172 break;
1173 }
1174 case Instruction::IF_NE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001175 if (shadow_frame.GetVReg(inst->VRegA_22t()) != shadow_frame.GetVReg(inst->VRegB_22t())) {
1176 next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001177 }
1178 break;
1179 }
1180 case Instruction::IF_LT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001181 if (shadow_frame.GetVReg(inst->VRegA_22t()) < shadow_frame.GetVReg(inst->VRegB_22t())) {
1182 next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001183 }
1184 break;
1185 }
1186 case Instruction::IF_GE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001187 if (shadow_frame.GetVReg(inst->VRegA_22t()) >= shadow_frame.GetVReg(inst->VRegB_22t())) {
1188 next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001189 }
1190 break;
1191 }
1192 case Instruction::IF_GT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001193 if (shadow_frame.GetVReg(inst->VRegA_22t()) > shadow_frame.GetVReg(inst->VRegB_22t())) {
1194 next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001195 }
1196 break;
1197 }
1198 case Instruction::IF_LE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001199 if (shadow_frame.GetVReg(inst->VRegA_22t()) <= shadow_frame.GetVReg(inst->VRegB_22t())) {
1200 next_inst = Instruction::At(insns + dex_pc + inst->VRegC_22t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001201 }
1202 break;
1203 }
1204 case Instruction::IF_EQZ: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001205 if (shadow_frame.GetVReg(inst->VRegA_21t()) == 0) {
1206 next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001207 }
1208 break;
1209 }
1210 case Instruction::IF_NEZ: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001211 if (shadow_frame.GetVReg(inst->VRegA_21t()) != 0) {
1212 next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001213 }
1214 break;
1215 }
1216 case Instruction::IF_LTZ: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001217 if (shadow_frame.GetVReg(inst->VRegA_21t()) < 0) {
1218 next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001219 }
1220 break;
1221 }
1222 case Instruction::IF_GEZ: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001223 if (shadow_frame.GetVReg(inst->VRegA_21t()) >= 0) {
1224 next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001225 }
1226 break;
1227 }
1228 case Instruction::IF_GTZ: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001229 if (shadow_frame.GetVReg(inst->VRegA_21t()) > 0) {
1230 next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001231 }
1232 break;
1233 }
1234 case Instruction::IF_LEZ: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001235 if (shadow_frame.GetVReg(inst->VRegA_21t()) <= 0) {
1236 next_inst = Instruction::At(insns + dex_pc + inst->VRegB_21t());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001237 }
1238 break;
1239 }
1240 case Instruction::AGET_BOOLEAN: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001241 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001242 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001243 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001244 break;
1245 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001246 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1247 shadow_frame.SetVReg(inst->VRegA_23x(), a->AsBooleanArray()->Get(index));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001248 break;
1249 }
1250 case Instruction::AGET_BYTE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001251 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001252 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001253 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001254 break;
1255 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001256 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1257 shadow_frame.SetVReg(inst->VRegA_23x(), a->AsByteArray()->Get(index));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001258 break;
1259 }
1260 case Instruction::AGET_CHAR: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001261 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001262 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001263 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001264 break;
1265 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001266 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1267 shadow_frame.SetVReg(inst->VRegA_23x(), a->AsCharArray()->Get(index));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001268 break;
1269 }
1270 case Instruction::AGET_SHORT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001271 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001272 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001273 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001274 break;
1275 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001276 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1277 shadow_frame.SetVReg(inst->VRegA_23x(), a->AsShortArray()->Get(index));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001278 break;
1279 }
1280 case Instruction::AGET: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001281 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001282 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001283 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001284 break;
1285 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001286 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1287 shadow_frame.SetVReg(inst->VRegA_23x(), a->AsIntArray()->Get(index));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001288 break;
1289 }
1290 case Instruction::AGET_WIDE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001291 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001292 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001293 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001294 break;
1295 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001296 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1297 shadow_frame.SetVRegLong(inst->VRegA_23x(), a->AsLongArray()->Get(index));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001298 break;
1299 }
1300 case Instruction::AGET_OBJECT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001301 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001302 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001303 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001304 break;
1305 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001306 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1307 shadow_frame.SetVRegReference(inst->VRegA_23x(), a->AsObjectArray<Object>()->Get(index));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001308 break;
1309 }
1310 case Instruction::APUT_BOOLEAN: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001311 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001312 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001313 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001314 break;
1315 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001316 uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1317 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
jeffhao94d6df42012-11-26 16:02:12 -08001318 a->AsBooleanArray()->Set(index, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001319 break;
1320 }
1321 case Instruction::APUT_BYTE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001322 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001323 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001324 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001325 break;
1326 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001327 int8_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1328 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
jeffhao94d6df42012-11-26 16:02:12 -08001329 a->AsByteArray()->Set(index, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001330 break;
1331 }
1332 case Instruction::APUT_CHAR: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001333 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001334 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001335 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001336 break;
1337 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001338 uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1339 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
jeffhao94d6df42012-11-26 16:02:12 -08001340 a->AsCharArray()->Set(index, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001341 break;
1342 }
1343 case Instruction::APUT_SHORT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001344 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001345 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001346 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001347 break;
1348 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001349 int16_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1350 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
jeffhao94d6df42012-11-26 16:02:12 -08001351 a->AsShortArray()->Set(index, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001352 break;
1353 }
1354 case Instruction::APUT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001355 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001356 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001357 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001358 break;
1359 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001360 int32_t val = shadow_frame.GetVReg(inst->VRegA_23x());
1361 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
jeffhao94d6df42012-11-26 16:02:12 -08001362 a->AsIntArray()->Set(index, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001363 break;
1364 }
1365 case Instruction::APUT_WIDE: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001366 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001367 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001368 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001369 break;
1370 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001371 int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x());
1372 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
jeffhao94d6df42012-11-26 16:02:12 -08001373 a->AsLongArray()->Set(index, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001374 break;
1375 }
1376 case Instruction::APUT_OBJECT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001377 Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001378 if (UNLIKELY(a == NULL)) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001379 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001380 break;
1381 }
Sebastien Hertz807a2562013-04-15 09:33:39 +02001382 Object* val = shadow_frame.GetVRegReference(inst->VRegA_23x());
1383 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
jeffhao94d6df42012-11-26 16:02:12 -08001384 a->AsObjectArray<Object>()->Set(index, val);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001385 break;
1386 }
1387 case Instruction::IGET_BOOLEAN:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001388 DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimBoolean);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001389 break;
1390 case Instruction::IGET_BYTE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001391 DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimByte);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001392 break;
1393 case Instruction::IGET_CHAR:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001394 DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimChar);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001395 break;
1396 case Instruction::IGET_SHORT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001397 DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimShort);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001398 break;
1399 case Instruction::IGET:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001400 DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimInt);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001401 break;
1402 case Instruction::IGET_WIDE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001403 DoFieldGet(self, shadow_frame, inst, InstancePrimitiveRead, Primitive::kPrimLong);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001404 break;
1405 case Instruction::IGET_OBJECT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001406 DoFieldGet(self, shadow_frame, inst, InstanceObjectRead, Primitive::kPrimNot);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001407 break;
1408 case Instruction::SGET_BOOLEAN:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001409 DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimBoolean);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001410 break;
1411 case Instruction::SGET_BYTE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001412 DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimByte);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001413 break;
1414 case Instruction::SGET_CHAR:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001415 DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimChar);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001416 break;
1417 case Instruction::SGET_SHORT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001418 DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimShort);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001419 break;
1420 case Instruction::SGET:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001421 DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimInt);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001422 break;
1423 case Instruction::SGET_WIDE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001424 DoFieldGet(self, shadow_frame, inst, StaticPrimitiveRead, Primitive::kPrimLong);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001425 break;
1426 case Instruction::SGET_OBJECT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001427 DoFieldGet(self, shadow_frame, inst, StaticObjectRead, Primitive::kPrimNot);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001428 break;
1429 case Instruction::IPUT_BOOLEAN:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001430 DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimBoolean);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001431 break;
1432 case Instruction::IPUT_BYTE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001433 DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimByte);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001434 break;
1435 case Instruction::IPUT_CHAR:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001436 DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimChar);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001437 break;
1438 case Instruction::IPUT_SHORT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001439 DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimShort);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001440 break;
1441 case Instruction::IPUT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001442 DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimInt);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001443 break;
1444 case Instruction::IPUT_WIDE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001445 DoFieldPut(self, shadow_frame, inst, InstancePrimitiveWrite, Primitive::kPrimLong);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001446 break;
1447 case Instruction::IPUT_OBJECT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001448 DoFieldPut(self, shadow_frame, inst, InstanceObjectWrite, Primitive::kPrimNot);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001449 break;
1450 case Instruction::SPUT_BOOLEAN:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001451 DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimBoolean);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001452 break;
1453 case Instruction::SPUT_BYTE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001454 DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimByte);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001455 break;
1456 case Instruction::SPUT_CHAR:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001457 DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimChar);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001458 break;
1459 case Instruction::SPUT_SHORT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001460 DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimShort);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001461 break;
1462 case Instruction::SPUT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001463 DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimInt);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001464 break;
1465 case Instruction::SPUT_WIDE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001466 DoFieldPut(self, shadow_frame, inst, StaticPrimitiveWrite, Primitive::kPrimLong);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001467 break;
1468 case Instruction::SPUT_OBJECT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001469 DoFieldPut(self, shadow_frame, inst, StaticObjectWrite, Primitive::kPrimNot);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001470 break;
1471 case Instruction::INVOKE_VIRTUAL:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001472 DoInvoke(self, mh, shadow_frame, inst, kVirtual, false, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001473 break;
1474 case Instruction::INVOKE_VIRTUAL_RANGE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001475 DoInvoke(self, mh, shadow_frame, inst, kVirtual, true, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001476 break;
1477 case Instruction::INVOKE_SUPER:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001478 DoInvoke(self, mh, shadow_frame, inst, kSuper, false, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001479 break;
1480 case Instruction::INVOKE_SUPER_RANGE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001481 DoInvoke(self, mh, shadow_frame, inst, kSuper, true, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001482 break;
1483 case Instruction::INVOKE_DIRECT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001484 DoInvoke(self, mh, shadow_frame, inst, kDirect, false, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001485 break;
1486 case Instruction::INVOKE_DIRECT_RANGE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001487 DoInvoke(self, mh, shadow_frame, inst, kDirect, true, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001488 break;
1489 case Instruction::INVOKE_INTERFACE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001490 DoInvoke(self, mh, shadow_frame, inst, kInterface, false, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001491 break;
1492 case Instruction::INVOKE_INTERFACE_RANGE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001493 DoInvoke(self, mh, shadow_frame, inst, kInterface, true, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001494 break;
1495 case Instruction::INVOKE_STATIC:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001496 DoInvoke(self, mh, shadow_frame, inst, kStatic, false, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001497 break;
1498 case Instruction::INVOKE_STATIC_RANGE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001499 DoInvoke(self, mh, shadow_frame, inst, kStatic, true, &result_register);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001500 break;
1501 case Instruction::NEG_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001502 shadow_frame.SetVReg(inst->VRegA_12x(), -shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001503 break;
1504 case Instruction::NOT_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001505 shadow_frame.SetVReg(inst->VRegA_12x(), ~shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001506 break;
1507 case Instruction::NEG_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001508 shadow_frame.SetVRegLong(inst->VRegA_12x(), -shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001509 break;
1510 case Instruction::NOT_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001511 shadow_frame.SetVRegLong(inst->VRegA_12x(), ~shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001512 break;
1513 case Instruction::NEG_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001514 shadow_frame.SetVRegFloat(inst->VRegA_12x(), -shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001515 break;
1516 case Instruction::NEG_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001517 shadow_frame.SetVRegDouble(inst->VRegA_12x(), -shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001518 break;
1519 case Instruction::INT_TO_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001520 shadow_frame.SetVRegLong(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001521 break;
1522 case Instruction::INT_TO_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001523 shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001524 break;
1525 case Instruction::INT_TO_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001526 shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001527 break;
1528 case Instruction::LONG_TO_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001529 shadow_frame.SetVReg(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001530 break;
1531 case Instruction::LONG_TO_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001532 shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001533 break;
1534 case Instruction::LONG_TO_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001535 shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001536 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001537 case Instruction::FLOAT_TO_INT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001538 uint32_t dst = inst->VRegA_12x();
1539 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
jeffhao87a6edd2012-11-20 18:05:18 -08001540 if (val != val) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001541 shadow_frame.SetVReg(dst, 0);
jeffhao87a6edd2012-11-20 18:05:18 -08001542 } else if (val > static_cast<float>(kMaxInt)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001543 shadow_frame.SetVReg(dst, kMaxInt);
jeffhao87a6edd2012-11-20 18:05:18 -08001544 } else if (val < static_cast<float>(kMinInt)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001545 shadow_frame.SetVReg(dst, kMinInt);
jeffhao87a6edd2012-11-20 18:05:18 -08001546 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001547 shadow_frame.SetVReg(dst, val);
jeffhao87a6edd2012-11-20 18:05:18 -08001548 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001549 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001550 }
1551 case Instruction::FLOAT_TO_LONG: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001552 uint32_t dst = inst->VRegA_12x();
1553 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x());
jeffhao87a6edd2012-11-20 18:05:18 -08001554 if (val != val) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001555 shadow_frame.SetVRegLong(dst, 0);
jeffhao87a6edd2012-11-20 18:05:18 -08001556 } else if (val > static_cast<float>(kMaxLong)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001557 shadow_frame.SetVRegLong(dst, kMaxLong);
jeffhao87a6edd2012-11-20 18:05:18 -08001558 } else if (val < static_cast<float>(kMinLong)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001559 shadow_frame.SetVRegLong(dst, kMinLong);
jeffhao87a6edd2012-11-20 18:05:18 -08001560 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001561 shadow_frame.SetVRegLong(dst, val);
jeffhao87a6edd2012-11-20 18:05:18 -08001562 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001563 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001564 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001565 case Instruction::FLOAT_TO_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001566 shadow_frame.SetVRegDouble(inst->VRegA_12x(), shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001567 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001568 case Instruction::DOUBLE_TO_INT: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001569 uint32_t dst = inst->VRegA_12x();
1570 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
jeffhao87a6edd2012-11-20 18:05:18 -08001571 if (val != val) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001572 shadow_frame.SetVReg(dst, 0);
jeffhao87a6edd2012-11-20 18:05:18 -08001573 } else if (val > static_cast<double>(kMaxInt)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001574 shadow_frame.SetVReg(dst, kMaxInt);
jeffhao87a6edd2012-11-20 18:05:18 -08001575 } else if (val < static_cast<double>(kMinInt)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001576 shadow_frame.SetVReg(dst, kMinInt);
jeffhao87a6edd2012-11-20 18:05:18 -08001577 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001578 shadow_frame.SetVReg(dst, val);
jeffhao87a6edd2012-11-20 18:05:18 -08001579 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001580 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001581 }
1582 case Instruction::DOUBLE_TO_LONG: {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001583 uint32_t dst = inst->VRegA_12x();
1584 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x());
jeffhao87a6edd2012-11-20 18:05:18 -08001585 if (val != val) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001586 shadow_frame.SetVRegLong(dst, 0);
jeffhao87a6edd2012-11-20 18:05:18 -08001587 } else if (val > static_cast<double>(kMaxLong)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001588 shadow_frame.SetVRegLong(dst, kMaxLong);
jeffhao87a6edd2012-11-20 18:05:18 -08001589 } else if (val < static_cast<double>(kMinLong)) {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001590 shadow_frame.SetVRegLong(dst, kMinLong);
jeffhao87a6edd2012-11-20 18:05:18 -08001591 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +02001592 shadow_frame.SetVRegLong(dst, val);
jeffhao87a6edd2012-11-20 18:05:18 -08001593 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001594 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001595 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001596 case Instruction::DOUBLE_TO_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001597 shadow_frame.SetVRegFloat(inst->VRegA_12x(), shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001598 break;
1599 case Instruction::INT_TO_BYTE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001600 shadow_frame.SetVReg(inst->VRegA_12x(),
1601 static_cast<int8_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001602 break;
1603 case Instruction::INT_TO_CHAR:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001604 shadow_frame.SetVReg(inst->VRegA_12x(),
1605 static_cast<uint16_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001606 break;
1607 case Instruction::INT_TO_SHORT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001608 shadow_frame.SetVReg(inst->VRegA_12x(),
1609 static_cast<int16_t>(shadow_frame.GetVReg(inst->VRegB_12x())));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001610 break;
1611 case Instruction::ADD_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001612 shadow_frame.SetVReg(inst->VRegA_23x(),
1613 shadow_frame.GetVReg(inst->VRegB_23x()) +
1614 shadow_frame.GetVReg(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001615 break;
1616 case Instruction::SUB_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001617 shadow_frame.SetVReg(inst->VRegA_23x(),
1618 shadow_frame.GetVReg(inst->VRegB_23x()) -
1619 shadow_frame.GetVReg(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001620 break;
1621 case Instruction::MUL_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001622 shadow_frame.SetVReg(inst->VRegA_23x(),
1623 shadow_frame.GetVReg(inst->VRegB_23x()) *
1624 shadow_frame.GetVReg(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001625 break;
1626 case Instruction::DIV_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001627 DoIntDivide(self, shadow_frame, inst->VRegA_23x(),
1628 shadow_frame.GetVReg(inst->VRegB_23x()),
1629 shadow_frame.GetVReg(inst->VRegC_23x()));
1630 break;
1631 case Instruction::REM_INT:
1632 DoIntRemainder(self, shadow_frame, inst->VRegA_23x(),
1633 shadow_frame.GetVReg(inst->VRegB_23x()),
1634 shadow_frame.GetVReg(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001635 break;
1636 case Instruction::SHL_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001637 shadow_frame.SetVReg(inst->VRegA_23x(),
1638 shadow_frame.GetVReg(inst->VRegB_23x()) <<
1639 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001640 break;
1641 case Instruction::SHR_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001642 shadow_frame.SetVReg(inst->VRegA_23x(),
1643 shadow_frame.GetVReg(inst->VRegB_23x()) >>
1644 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001645 break;
1646 case Instruction::USHR_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001647 shadow_frame.SetVReg(inst->VRegA_23x(),
1648 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
1649 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001650 break;
1651 case Instruction::AND_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001652 shadow_frame.SetVReg(inst->VRegA_23x(),
1653 shadow_frame.GetVReg(inst->VRegB_23x()) &
1654 shadow_frame.GetVReg(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001655 break;
1656 case Instruction::OR_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001657 shadow_frame.SetVReg(inst->VRegA_23x(),
1658 shadow_frame.GetVReg(inst->VRegB_23x()) |
1659 shadow_frame.GetVReg(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001660 break;
1661 case Instruction::XOR_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001662 shadow_frame.SetVReg(inst->VRegA_23x(),
1663 shadow_frame.GetVReg(inst->VRegB_23x()) ^
1664 shadow_frame.GetVReg(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001665 break;
1666 case Instruction::ADD_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001667 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1668 shadow_frame.GetVRegLong(inst->VRegB_23x()) +
1669 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001670 break;
1671 case Instruction::SUB_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001672 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1673 shadow_frame.GetVRegLong(inst->VRegB_23x()) -
1674 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001675 break;
1676 case Instruction::MUL_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001677 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1678 shadow_frame.GetVRegLong(inst->VRegB_23x()) *
1679 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001680 break;
1681 case Instruction::DIV_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001682 DoLongDivide(self, shadow_frame, inst->VRegA_23x(),
1683 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1684 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001685 break;
1686 case Instruction::REM_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001687 DoLongRemainder(self, shadow_frame, inst->VRegA_23x(),
1688 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1689 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001690 break;
1691 case Instruction::AND_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001692 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1693 shadow_frame.GetVRegLong(inst->VRegB_23x()) &
1694 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001695 break;
1696 case Instruction::OR_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001697 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1698 shadow_frame.GetVRegLong(inst->VRegB_23x()) |
1699 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001700 break;
1701 case Instruction::XOR_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001702 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1703 shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
1704 shadow_frame.GetVRegLong(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001705 break;
1706 case Instruction::SHL_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001707 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1708 shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
1709 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001710 break;
1711 case Instruction::SHR_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001712 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1713 shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
1714 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001715 break;
1716 case Instruction::USHR_LONG:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001717 shadow_frame.SetVRegLong(inst->VRegA_23x(),
1718 static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
1719 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001720 break;
1721 case Instruction::ADD_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001722 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
1723 shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
1724 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001725 break;
1726 case Instruction::SUB_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001727 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
1728 shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
1729 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001730 break;
1731 case Instruction::MUL_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001732 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
1733 shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
1734 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001735 break;
1736 case Instruction::DIV_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001737 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
1738 shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
1739 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001740 break;
1741 case Instruction::REM_FLOAT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001742 shadow_frame.SetVRegFloat(inst->VRegA_23x(),
1743 fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
1744 shadow_frame.GetVRegFloat(inst->VRegC_23x())));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001745 break;
1746 case Instruction::ADD_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001747 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
1748 shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
1749 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001750 break;
1751 case Instruction::SUB_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001752 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
1753 shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
1754 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001755 break;
1756 case Instruction::MUL_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001757 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
1758 shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
1759 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001760 break;
1761 case Instruction::DIV_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001762 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
1763 shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
1764 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001765 break;
1766 case Instruction::REM_DOUBLE:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001767 shadow_frame.SetVRegDouble(inst->VRegA_23x(),
1768 fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
1769 shadow_frame.GetVRegDouble(inst->VRegC_23x())));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001770 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001771 case Instruction::ADD_INT_2ADDR: {
1772 uint32_t vregA = inst->VRegA_12x();
1773 shadow_frame.SetVReg(vregA,
1774 shadow_frame.GetVReg(vregA) +
1775 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001776 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001777 }
1778 case Instruction::SUB_INT_2ADDR: {
1779 uint32_t vregA = inst->VRegA_12x();
1780 shadow_frame.SetVReg(vregA,
1781 shadow_frame.GetVReg(vregA) -
1782 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001783 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001784 }
1785 case Instruction::MUL_INT_2ADDR: {
1786 uint32_t vregA = inst->VRegA_12x();
1787 shadow_frame.SetVReg(vregA,
1788 shadow_frame.GetVReg(vregA) *
1789 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001790 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001791 }
1792 case Instruction::REM_INT_2ADDR: {
1793 uint32_t vregA = inst->VRegA_12x();
1794 DoIntRemainder(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
1795 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001796 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001797 }
1798 case Instruction::SHL_INT_2ADDR:{
1799 uint32_t vregA = inst->VRegA_12x();
1800 shadow_frame.SetVReg(vregA,
1801 shadow_frame.GetVReg(vregA) <<
1802 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001803 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001804 }
1805 case Instruction::SHR_INT_2ADDR: {
1806 uint32_t vregA = inst->VRegA_12x();
1807 shadow_frame.SetVReg(vregA,
1808 shadow_frame.GetVReg(vregA) >>
1809 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001810 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001811 }
1812 case Instruction::USHR_INT_2ADDR: {
1813 uint32_t vregA = inst->VRegA_12x();
1814 shadow_frame.SetVReg(vregA,
1815 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
1816 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001817 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001818 }
1819 case Instruction::AND_INT_2ADDR: {
1820 uint32_t vregA = inst->VRegA_12x();
1821 shadow_frame.SetVReg(vregA,
1822 shadow_frame.GetVReg(vregA) &
1823 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001824 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001825 }
1826 case Instruction::OR_INT_2ADDR: {
1827 uint32_t vregA = inst->VRegA_12x();
1828 shadow_frame.SetVReg(vregA,
1829 shadow_frame.GetVReg(vregA) |
1830 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001831 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001832 }
1833 case Instruction::XOR_INT_2ADDR: {
1834 uint32_t vregA = inst->VRegA_12x();
1835 shadow_frame.SetVReg(vregA,
1836 shadow_frame.GetVReg(vregA) ^
1837 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001838 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001839 }
1840 case Instruction::DIV_INT_2ADDR: {
1841 uint32_t vregA = inst->VRegA_12x();
1842 DoIntDivide(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
1843 shadow_frame.GetVReg(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001844 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001845 }
1846 case Instruction::ADD_LONG_2ADDR: {
1847 uint32_t vregA = inst->VRegA_12x();
1848 shadow_frame.SetVRegLong(vregA,
1849 shadow_frame.GetVRegLong(vregA) +
1850 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001851 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001852 }
1853 case Instruction::SUB_LONG_2ADDR: {
1854 uint32_t vregA = inst->VRegA_12x();
1855 shadow_frame.SetVRegLong(vregA,
1856 shadow_frame.GetVRegLong(vregA) -
1857 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001858 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001859 }
1860 case Instruction::MUL_LONG_2ADDR: {
1861 uint32_t vregA = inst->VRegA_12x();
1862 shadow_frame.SetVRegLong(vregA,
1863 shadow_frame.GetVRegLong(vregA) *
1864 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001865 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001866 }
1867 case Instruction::DIV_LONG_2ADDR: {
1868 uint32_t vregA = inst->VRegA_12x();
1869 DoLongDivide(self, shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
1870 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001871 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001872 }
1873 case Instruction::REM_LONG_2ADDR: {
1874 uint32_t vregA = inst->VRegA_12x();
1875 DoLongRemainder(self, shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
1876 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001877 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001878 }
1879 case Instruction::AND_LONG_2ADDR: {
1880 uint32_t vregA = inst->VRegA_12x();
1881 shadow_frame.SetVRegLong(vregA,
1882 shadow_frame.GetVRegLong(vregA) &
1883 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001884 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001885 }
1886 case Instruction::OR_LONG_2ADDR: {
1887 uint32_t vregA = inst->VRegA_12x();
1888 shadow_frame.SetVRegLong(vregA,
1889 shadow_frame.GetVRegLong(vregA) |
1890 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001891 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001892 }
1893 case Instruction::XOR_LONG_2ADDR: {
1894 uint32_t vregA = inst->VRegA_12x();
1895 shadow_frame.SetVRegLong(vregA,
1896 shadow_frame.GetVRegLong(vregA) ^
1897 shadow_frame.GetVRegLong(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001898 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001899 }
1900 case Instruction::SHL_LONG_2ADDR: {
1901 uint32_t vregA = inst->VRegA_12x();
1902 shadow_frame.SetVRegLong(vregA,
1903 shadow_frame.GetVRegLong(vregA) <<
1904 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001905 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001906 }
1907 case Instruction::SHR_LONG_2ADDR: {
1908 uint32_t vregA = inst->VRegA_12x();
1909 shadow_frame.SetVRegLong(vregA,
1910 shadow_frame.GetVRegLong(vregA) >>
1911 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001912 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001913 }
1914 case Instruction::USHR_LONG_2ADDR: {
1915 uint32_t vregA = inst->VRegA_12x();
1916 shadow_frame.SetVRegLong(vregA,
1917 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
1918 (shadow_frame.GetVReg(inst->VRegB_12x()) & 0x3f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001919 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001920 }
1921 case Instruction::ADD_FLOAT_2ADDR: {
1922 uint32_t vregA = inst->VRegA_12x();
1923 shadow_frame.SetVRegFloat(vregA,
1924 shadow_frame.GetVRegFloat(vregA) +
1925 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001926 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001927 }
1928 case Instruction::SUB_FLOAT_2ADDR: {
1929 uint32_t vregA = inst->VRegA_12x();
1930 shadow_frame.SetVRegFloat(vregA,
1931 shadow_frame.GetVRegFloat(vregA) -
1932 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001933 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001934 }
1935 case Instruction::MUL_FLOAT_2ADDR: {
1936 uint32_t vregA = inst->VRegA_12x();
1937 shadow_frame.SetVRegFloat(vregA,
1938 shadow_frame.GetVRegFloat(vregA) *
1939 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001940 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001941 }
1942 case Instruction::DIV_FLOAT_2ADDR: {
1943 uint32_t vregA = inst->VRegA_12x();
1944 shadow_frame.SetVRegFloat(vregA,
1945 shadow_frame.GetVRegFloat(vregA) /
1946 shadow_frame.GetVRegFloat(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001947 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001948 }
1949 case Instruction::REM_FLOAT_2ADDR: {
1950 uint32_t vregA = inst->VRegA_12x();
1951 shadow_frame.SetVRegFloat(vregA,
1952 fmodf(shadow_frame.GetVRegFloat(vregA),
1953 shadow_frame.GetVRegFloat(inst->VRegB_12x())));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001954 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001955 }
1956 case Instruction::ADD_DOUBLE_2ADDR: {
1957 uint32_t vregA = inst->VRegA_12x();
1958 shadow_frame.SetVRegDouble(vregA,
1959 shadow_frame.GetVRegDouble(vregA) +
1960 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001961 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001962 }
1963 case Instruction::SUB_DOUBLE_2ADDR: {
1964 uint32_t vregA = inst->VRegA_12x();
1965 shadow_frame.SetVRegDouble(vregA,
1966 shadow_frame.GetVRegDouble(vregA) -
1967 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001968 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001969 }
1970 case Instruction::MUL_DOUBLE_2ADDR: {
1971 uint32_t vregA = inst->VRegA_12x();
1972 shadow_frame.SetVRegDouble(vregA,
1973 shadow_frame.GetVRegDouble(vregA) *
1974 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001975 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001976 }
1977 case Instruction::DIV_DOUBLE_2ADDR: {
1978 uint32_t vregA = inst->VRegA_12x();
1979 shadow_frame.SetVRegDouble(vregA,
1980 shadow_frame.GetVRegDouble(vregA) /
1981 shadow_frame.GetVRegDouble(inst->VRegB_12x()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001982 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001983 }
1984 case Instruction::REM_DOUBLE_2ADDR: {
1985 uint32_t vregA = inst->VRegA_12x();
1986 shadow_frame.SetVRegDouble(vregA,
1987 fmod(shadow_frame.GetVRegDouble(vregA),
1988 shadow_frame.GetVRegDouble(inst->VRegB_12x())));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001989 break;
Sebastien Hertz807a2562013-04-15 09:33:39 +02001990 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001991 case Instruction::ADD_INT_LIT16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001992 shadow_frame.SetVReg(inst->VRegA_22s(),
1993 shadow_frame.GetVReg(inst->VRegB_22s()) +
1994 inst->VRegC_22s());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001995 break;
1996 case Instruction::RSUB_INT:
Sebastien Hertz807a2562013-04-15 09:33:39 +02001997 shadow_frame.SetVReg(inst->VRegA_22s(),
1998 inst->VRegC_22s() -
1999 shadow_frame.GetVReg(inst->VRegB_22s()));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002000 break;
2001 case Instruction::MUL_INT_LIT16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002002 shadow_frame.SetVReg(inst->VRegA_22s(),
2003 shadow_frame.GetVReg(inst->VRegB_22s()) *
2004 inst->VRegC_22s());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002005 break;
2006 case Instruction::DIV_INT_LIT16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002007 DoIntDivide(self, shadow_frame, inst->VRegA_22s(),
2008 shadow_frame.GetVReg(inst->VRegB_22s()), inst->VRegC_22s());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002009 break;
2010 case Instruction::REM_INT_LIT16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002011 DoIntRemainder(self, shadow_frame, inst->VRegA_22s(),
2012 shadow_frame.GetVReg(inst->VRegB_22s()), inst->VRegC_22s());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002013 break;
2014 case Instruction::AND_INT_LIT16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002015 shadow_frame.SetVReg(inst->VRegA_22s(),
2016 shadow_frame.GetVReg(inst->VRegB_22s()) &
2017 inst->VRegC_22s());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002018 break;
2019 case Instruction::OR_INT_LIT16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002020 shadow_frame.SetVReg(inst->VRegA_22s(),
2021 shadow_frame.GetVReg(inst->VRegB_22s()) |
2022 inst->VRegC_22s());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002023 break;
2024 case Instruction::XOR_INT_LIT16:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002025 shadow_frame.SetVReg(inst->VRegA_22s(),
2026 shadow_frame.GetVReg(inst->VRegB_22s()) ^
2027 inst->VRegC_22s());
2028 break;
2029 case Instruction::ADD_INT_LIT8:
2030 shadow_frame.SetVReg(inst->VRegA_22b(),
2031 shadow_frame.GetVReg(inst->VRegB_22b()) +
2032 inst->VRegC_22b());
2033 break;
2034 case Instruction::RSUB_INT_LIT8:
2035 shadow_frame.SetVReg(inst->VRegA_22b(),
2036 inst->VRegC_22b() -
2037 shadow_frame.GetVReg(inst->VRegB_22b()));
2038 break;
2039 case Instruction::MUL_INT_LIT8:
2040 shadow_frame.SetVReg(inst->VRegA_22b(),
2041 shadow_frame.GetVReg(inst->VRegB_22b()) *
2042 inst->VRegC_22b());
2043 break;
2044 case Instruction::DIV_INT_LIT8:
2045 DoIntDivide(self, shadow_frame, inst->VRegA_22b(),
2046 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2047 break;
2048 case Instruction::REM_INT_LIT8:
2049 DoIntRemainder(self, shadow_frame, inst->VRegA_22b(),
2050 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2051 break;
2052 case Instruction::AND_INT_LIT8:
2053 shadow_frame.SetVReg(inst->VRegA_22b(),
2054 shadow_frame.GetVReg(inst->VRegB_22b()) &
2055 inst->VRegC_22b());
2056 break;
2057 case Instruction::OR_INT_LIT8:
2058 shadow_frame.SetVReg(inst->VRegA_22b(),
2059 shadow_frame.GetVReg(inst->VRegB_22b()) |
2060 inst->VRegC_22b());
2061 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002062 case Instruction::XOR_INT_LIT8:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002063 shadow_frame.SetVReg(inst->VRegA_22b(),
2064 shadow_frame.GetVReg(inst->VRegB_22b()) ^
2065 inst->VRegC_22b());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002066 break;
2067 case Instruction::SHL_INT_LIT8:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002068 shadow_frame.SetVReg(inst->VRegA_22b(),
2069 shadow_frame.GetVReg(inst->VRegB_22b()) <<
2070 (inst->VRegC_22b() & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002071 break;
2072 case Instruction::SHR_INT_LIT8:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002073 shadow_frame.SetVReg(inst->VRegA_22b(),
2074 shadow_frame.GetVReg(inst->VRegB_22b()) >>
2075 (inst->VRegC_22b() & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002076 break;
2077 case Instruction::USHR_INT_LIT8:
Sebastien Hertz807a2562013-04-15 09:33:39 +02002078 shadow_frame.SetVReg(inst->VRegA_22b(),
2079 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
2080 (inst->VRegC_22b() & 0x1f));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002081 break;
2082 default:
2083 LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(&mh.GetDexFile());
2084 break;
2085 }
2086 if (UNLIKELY(self->IsExceptionPending())) {
Ian Rogers62d6c772013-02-27 08:32:07 -08002087 self->VerifyStack();
2088 ThrowLocation throw_location;
2089 mirror::Throwable* exception = self->GetException(&throw_location);
Sebastien Hertz807a2562013-04-15 09:33:39 +02002090 uint32_t found_dex_pc = shadow_frame.GetMethod()->FindCatchBlock(exception->GetClass(), dex_pc);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002091 if (found_dex_pc == DexFile::kDexNoIndex) {
2092 JValue result;
2093 result.SetJ(0);
Sebastien Hertz807a2562013-04-15 09:33:39 +02002094 instrumentation->MethodUnwindEvent(self, this_object_ref.get(),
2095 shadow_frame.GetMethod(), dex_pc);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002096 return result; // Handler in caller.
2097 } else {
Sebastien Hertz807a2562013-04-15 09:33:39 +02002098 instrumentation->ExceptionCaughtEvent(self, throw_location,
2099 shadow_frame.GetMethod(),
2100 found_dex_pc, exception);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002101 next_inst = Instruction::At(insns + found_dex_pc);
2102 }
2103 }
2104 inst = next_inst;
2105 }
2106}
2107
2108void EnterInterpreterFromInvoke(Thread* self, AbstractMethod* method, Object* receiver,
Jeff Hao6474d192013-03-26 14:08:09 -07002109 uint32_t* args, JValue* result) {
Ian Rogers64b6d142012-10-29 16:34:15 -07002110 DCHECK_EQ(self, Thread::Current());
jeffhaod7521322012-11-21 15:38:24 -08002111 if (__builtin_frame_address(0) < self->GetStackEnd()) {
2112 ThrowStackOverflowError(self);
2113 return;
2114 }
2115
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002116 MethodHelper mh(method);
2117 const DexFile::CodeItem* code_item = mh.GetCodeItem();
2118 uint16_t num_regs;
2119 uint16_t num_ins;
2120 if (code_item != NULL) {
2121 num_regs = code_item->registers_size_;
2122 num_ins = code_item->ins_size_;
jeffhao0a9bb732012-11-26 12:28:49 -08002123 } else if (method->IsAbstract()) {
Ian Rogers62d6c772013-02-27 08:32:07 -08002124 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
2125 self->ThrowNewExceptionF(throw_location, "Ljava/lang/AbstractMethodError;",
2126 "abstract method \"%s\"", PrettyMethod(method).c_str());
jeffhao0a9bb732012-11-26 12:28:49 -08002127 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002128 } else {
2129 DCHECK(method->IsNative());
2130 num_regs = num_ins = AbstractMethod::NumArgRegisters(mh.GetShorty());
2131 if (!method->IsStatic()) {
2132 num_regs++;
2133 num_ins++;
2134 }
2135 }
2136 // Set up shadow frame with matching number of reference slots to vregs.
2137 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
TDYa127ce4cc0d2012-11-18 16:59:53 -08002138 UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(num_regs,
Ian Rogers7db619b2013-01-16 18:35:48 -08002139 last_shadow_frame,
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002140 method, 0));
2141 self->PushShadowFrame(shadow_frame.get());
2142 size_t cur_reg = num_regs - num_ins;
2143 if (!method->IsStatic()) {
2144 CHECK(receiver != NULL);
TDYa127ce4cc0d2012-11-18 16:59:53 -08002145 shadow_frame->SetVRegReference(cur_reg, receiver);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002146 ++cur_reg;
Sebastien Hertz807a2562013-04-15 09:33:39 +02002147 } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
2148 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
2149 if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(),
2150 true, true))) {
2151 CHECK(self->IsExceptionPending());
2152 self->PopShadowFrame();
jeffhao94d6df42012-11-26 16:02:12 -08002153 return;
2154 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002155 CHECK(method->GetDeclaringClass()->IsInitializing());
2156 }
Ian Rogers64b6d142012-10-29 16:34:15 -07002157 const char* shorty = mh.GetShorty();
Jeff Hao5d917302013-02-27 17:57:33 -08002158 for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
2159 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
2160 switch (shorty[shorty_pos + 1]) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002161 case 'L': {
Jeff Hao5d917302013-02-27 17:57:33 -08002162 Object* o = reinterpret_cast<Object*>(args[arg_pos]);
TDYa127ce4cc0d2012-11-18 16:59:53 -08002163 shadow_frame->SetVRegReference(cur_reg, o);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002164 break;
2165 }
Jeff Hao5d917302013-02-27 17:57:33 -08002166 case 'J': case 'D': {
2167 uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
2168 shadow_frame->SetVRegLong(cur_reg, wide_value);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002169 cur_reg++;
Jeff Hao5d917302013-02-27 17:57:33 -08002170 arg_pos++;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002171 break;
Jeff Hao5d917302013-02-27 17:57:33 -08002172 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002173 default:
Jeff Hao5d917302013-02-27 17:57:33 -08002174 shadow_frame->SetVReg(cur_reg, args[arg_pos]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002175 break;
2176 }
2177 }
Ian Rogers64b6d142012-10-29 16:34:15 -07002178 if (LIKELY(!method->IsNative())) {
Ian Rogers306057f2012-11-26 12:45:53 -08002179 JValue r = Execute(self, mh, code_item, *shadow_frame.get(), JValue());
Jeff Hao6474d192013-03-26 14:08:09 -07002180 if (result != NULL) {
2181 *result = r;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002182 }
2183 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -07002184 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
2185 // generated stub) except during testing and image writing.
2186 if (!Runtime::Current()->IsStarted()) {
Jeff Hao6474d192013-03-26 14:08:09 -07002187 UnstartedRuntimeJni(self, method, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002188 } else {
Jeff Hao6474d192013-03-26 14:08:09 -07002189 InterpreterJni(self, method, shorty, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002190 }
2191 }
2192 self->PopShadowFrame();
2193}
2194
Ian Rogers62d6c772013-02-27 08:32:07 -08002195void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
Jeff Hao11ffc2d2013-02-01 11:52:17 -08002196 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2197 JValue value;
Ian Rogers62d6c772013-02-27 08:32:07 -08002198 value.SetJ(ret_val->GetJ()); // Set value to last known result in case the shadow frame chain is empty.
2199 MethodHelper mh;
Jeff Hao11ffc2d2013-02-01 11:52:17 -08002200 while (shadow_frame != NULL) {
Ian Rogers62d6c772013-02-27 08:32:07 -08002201 self->SetTopOfShadowStack(shadow_frame);
2202 mh.ChangeMethod(shadow_frame->GetMethod());
2203 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Jeff Hao11ffc2d2013-02-01 11:52:17 -08002204 value = Execute(self, mh, code_item, *shadow_frame, value);
2205 ShadowFrame* old_frame = shadow_frame;
2206 shadow_frame = shadow_frame->GetLink();
Jeff Hao11ffc2d2013-02-01 11:52:17 -08002207 delete old_frame;
2208 }
2209 ret_val->SetJ(value.GetJ());
2210}
2211
Ian Rogers7db619b2013-01-16 18:35:48 -08002212JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
2213 ShadowFrame& shadow_frame)
2214 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogersf3e98552013-03-20 15:49:49 -07002215 DCHECK_EQ(self, Thread::Current());
2216 if (__builtin_frame_address(0) < self->GetStackEnd()) {
2217 ThrowStackOverflowError(self);
2218 return JValue();
2219 }
2220
Ian Rogers7db619b2013-01-16 18:35:48 -08002221 return Execute(self, mh, code_item, shadow_frame, JValue());
2222}
2223
Jeff Hao16743632013-05-08 10:59:04 -07002224JValue EnterInterpreterFromInterpreter(Thread* self, ShadowFrame* shadow_frame)
2225 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2226 if (__builtin_frame_address(0) < self->GetStackEnd()) {
2227 ThrowStackOverflowError(self);
2228 return JValue();
2229 }
2230
2231 AbstractMethod* method = shadow_frame->GetMethod();
2232 if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
2233 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
2234 true, true)) {
2235 DCHECK(Thread::Current()->IsExceptionPending());
2236 return JValue();
2237 }
2238 CHECK(method->GetDeclaringClass()->IsInitializing());
2239 }
2240
2241 self->PushShadowFrame(shadow_frame);
2242
2243 MethodHelper mh(method);
2244 const DexFile::CodeItem* code_item = mh.GetCodeItem();
2245 JValue result;
2246 if (LIKELY(!method->IsNative())) {
2247 result = Execute(self, mh, code_item, *shadow_frame, JValue());
2248 } else {
2249 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
2250 // generated stub) except during testing and image writing.
2251 CHECK(!Runtime::Current()->IsStarted());
2252 Object* receiver = method->IsStatic() ? NULL : shadow_frame->GetVRegReference(0);
2253 uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
2254 UnstartedRuntimeJni(self, method, receiver, args, &result);
2255 }
2256
2257 self->PopShadowFrame();
2258 return result;
2259}
2260
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07002261} // namespace interpreter
2262} // namespace art