blob: d8031c14f441b6adc19121524b18a3b529029346 [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
21#include "common_throws.h"
jeffhao373c52f2012-11-20 16:11:52 -080022#include "debugger.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070023#include "dex_instruction.h"
24#include "invoke_arg_array_builder.h"
25#include "logging.h"
Ian Rogers64b6d142012-10-29 16:34:15 -070026#include "nth_caller_visitor.h"
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070027#include "object.h"
28#include "object_utils.h"
29#include "runtime_support.h"
30#include "ScopedLocalRef.h"
31#include "scoped_thread_state_change.h"
32#include "thread.h"
33
34namespace art {
35namespace interpreter {
36
jeffhao87a6edd2012-11-20 18:05:18 -080037static const int32_t kMaxInt = std::numeric_limits<int32_t>::max();
38static const int32_t kMinInt = std::numeric_limits<int32_t>::min();
39static const int64_t kMaxLong = std::numeric_limits<int64_t>::max();
40static const int64_t kMinLong = std::numeric_limits<int64_t>::min();
41
Ian Rogers64b6d142012-10-29 16:34:15 -070042static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method,
43 Object* receiver, JValue* args, JValue* result)
44 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
45 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
46 // problems in core libraries.
47 std::string name(PrettyMethod(target_method));
48 if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") {
49 std::string descriptor(DotToDescriptor(args[0].GetL()->AsString()->ToModifiedUtf8().c_str()));
50 ClassLoader* class_loader = NULL; // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
51 Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(),
52 class_loader);
53 CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
54 << PrettyDescriptor(descriptor);
55 result->SetL(found);
56 } else if (name == "java.lang.Object java.lang.Class.newInstance()") {
57 Class* klass = receiver->AsClass();
58 AbstractMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");
59 CHECK(c != NULL);
60 Object* obj = klass->AllocObject(self);
61 CHECK(obj != NULL);
62 EnterInterpreterFromInvoke(self, c, obj, NULL, NULL);
63 result->SetL(obj);
64 } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") {
65 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
66 // going the reflective Dex way.
67 Class* klass = receiver->AsClass();
68 String* name = args[0].GetL()->AsString();
69 Field* found = NULL;
70 FieldHelper fh;
71 ObjectArray<Field>* fields = klass->GetIFields();
72 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
73 Field* f = fields->Get(i);
74 fh.ChangeField(f);
75 if (name->Equals(fh.GetName())) {
76 found = f;
77 }
78 }
79 if (found == NULL) {
80 fields = klass->GetSFields();
81 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
82 Field* f = fields->Get(i);
83 fh.ChangeField(f);
84 if (name->Equals(fh.GetName())) {
85 found = f;
86 }
87 }
88 }
89 CHECK(found != NULL)
90 << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
91 << name->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
92 // TODO: getDeclaredField calls GetType once the field is found to ensure a
93 // NoClassDefFoundError is thrown if the field's type cannot be resolved.
94 result->SetL(found);
95 } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") {
96 // Special case array copying without initializing System.
97 Class* ctype = args[0].GetL()->GetClass()->GetComponentType();
98 jint srcPos = args[1].GetI();
99 jint dstPos = args[3].GetI();
100 jint length = args[4].GetI();
101 if (!ctype->IsPrimitive()) {
102 ObjectArray<Object>* src = args[0].GetL()->AsObjectArray<Object>();
103 ObjectArray<Object>* dst = args[2].GetL()->AsObjectArray<Object>();
104 for (jint i = 0; i < length; ++i) {
105 dst->Set(dstPos + i, src->Get(srcPos + i));
106 }
107 } else if (ctype->IsPrimitiveChar()) {
108 CharArray* src = args[0].GetL()->AsCharArray();
109 CharArray* dst = args[2].GetL()->AsCharArray();
110 for (jint i = 0; i < length; ++i) {
111 dst->Set(dstPos + i, src->Get(srcPos + i));
112 }
113 } else if (ctype->IsPrimitiveInt()) {
114 IntArray* src = args[0].GetL()->AsIntArray();
115 IntArray* dst = args[2].GetL()->AsIntArray();
116 for (jint i = 0; i < length; ++i) {
117 dst->Set(dstPos + i, src->Get(srcPos + i));
118 }
119 } else {
120 UNIMPLEMENTED(FATAL) << "System.arraycopy of unexpected type: " << PrettyDescriptor(ctype);
121 }
122 } else {
123 // Not special, continue with regular interpreter execution.
124 EnterInterpreterFromInvoke(self, target_method, receiver, args, result);
125 }
126}
127
128// Hand select a number of methods to be run in a not yet started runtime without using JNI.
129static void UnstartedRuntimeJni(Thread* self, AbstractMethod* method,
130 Object* receiver, JValue* args, JValue* result)
131 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
132 std::string name(PrettyMethod(method));
133 if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") {
134 result->SetL(NULL);
135 } else if (name == "java.lang.Class dalvik.system.VMStack.getStackClass2()") {
136 NthCallerVisitor visitor(self->GetManagedStack(), NULL, 3);
137 visitor.WalkStack();
138 result->SetL(visitor.caller->GetDeclaringClass());
139 } else if (name == "double java.lang.Math.log(double)") {
140 result->SetD(log(args[0].GetD()));
141 } else if (name == "java.lang.String java.lang.Class.getNameNative()") {
142 result->SetL(receiver->AsClass()->ComputeName());
143 } else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
144 result->SetI(args[0].GetI());
145 } else if (name == "float java.lang.Float.intBitsToFloat(int)") {
146 result->SetF(args[0].GetF());
147 } else if (name == "double java.lang.Math.exp(double)") {
148 result->SetD(exp(args[0].GetD()));
149 } else if (name == "java.lang.Object java.lang.Object.internalClone()") {
150 result->SetL(receiver->Clone(self));
151 } else if (name == "void java.lang.Object.notifyAll()") {
152 receiver->NotifyAll();
153 } else if (name == "int java.lang.String.compareTo(java.lang.String)") {
154 String* rhs = args[0].GetL()->AsString();
155 CHECK(rhs != NULL);
156 result->SetI(receiver->AsString()->CompareTo(rhs));
157 } else if (name == "java.lang.String java.lang.String.intern()") {
158 result->SetL(receiver->AsString()->Intern());
159 } else if (name == "int java.lang.String.fastIndexOf(int, int)") {
160 result->SetI(receiver->AsString()->FastIndexOf(args[0].GetI(), args[1].GetI()));
161 } else if (name == "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") {
162 result->SetL(Array::CreateMultiArray(self, args[0].GetL()->AsClass(), args[1].GetL()->AsIntArray()));
163 } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") {
164 ScopedObjectAccessUnchecked soa(self);
165 result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace(soa)));
166 } else if (name == "boolean java.nio.ByteOrder.isLittleEndian()") {
167 result->SetJ(JNI_TRUE);
168 } else if (name == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
169 Object* obj = args[0].GetL();
170 jlong offset = args[1].GetJ();
171 jint expectedValue = args[2].GetI();
172 jint newValue = args[3].GetI();
173 byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
174 volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
175 // Note: android_atomic_release_cas() returns 0 on success, not failure.
176 int r = android_atomic_release_cas(expectedValue, newValue, address);
177 result->SetZ(r == 0);
178 } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
179 Object* obj = args[0].GetL();
180 Object* newValue = args[2].GetL();
181 obj->SetFieldObject(MemberOffset(args[1].GetJ()), newValue, false);
182 } else {
183 LOG(FATAL) << "Attempt to invoke native method in non-started runtime: " << name;
184 }
185}
186
187static void InterpreterJni(Thread* self, AbstractMethod* method, StringPiece shorty,
188 Object* receiver, JValue* args, JValue* result)
189 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
190 // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
191 // it should be removed and JNI compiled stubs used instead.
192 ScopedObjectAccessUnchecked soa(self);
193 if (method->IsStatic()) {
194 if (shorty == "L") {
195 typedef jobject (fnptr)(JNIEnv*, jclass);
196 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
197 ScopedLocalRef<jclass> klass(soa.Env(),
198 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
Ian Rogers556d6372012-11-20 12:19:36 -0800199 jobject jresult;
200 {
201 ScopedThreadStateChange tsc(self, kNative);
202 jresult = fn(soa.Env(), klass.get());
203 }
204 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700205 } else if (shorty == "V") {
206 typedef void (fnptr)(JNIEnv*, jclass);
207 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
208 ScopedLocalRef<jclass> klass(soa.Env(),
209 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
210 ScopedThreadStateChange tsc(self, kNative);
211 fn(soa.Env(), klass.get());
212 } else if (shorty == "Z") {
213 typedef jboolean (fnptr)(JNIEnv*, jclass);
214 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
215 ScopedLocalRef<jclass> klass(soa.Env(),
216 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
217 ScopedThreadStateChange tsc(self, kNative);
218 result->SetZ(fn(soa.Env(), klass.get()));
219 } else if (shorty == "BI") {
220 typedef jbyte (fnptr)(JNIEnv*, jclass, jint);
221 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
222 ScopedLocalRef<jclass> klass(soa.Env(),
223 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
224 ScopedThreadStateChange tsc(self, kNative);
225 result->SetB(fn(soa.Env(), klass.get(), args[0].GetI()));
226 } else if (shorty == "II") {
227 typedef jint (fnptr)(JNIEnv*, jclass, jint);
228 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
229 ScopedLocalRef<jclass> klass(soa.Env(),
230 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
231 ScopedThreadStateChange tsc(self, kNative);
232 result->SetI(fn(soa.Env(), klass.get(), args[0].GetI()));
233 } else if (shorty == "LL") {
234 typedef jobject (fnptr)(JNIEnv*, jclass, jobject);
235 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
236 ScopedLocalRef<jclass> klass(soa.Env(),
237 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
238 ScopedLocalRef<jobject> arg0(soa.Env(),
239 soa.AddLocalReference<jobject>(args[0].GetL()));
Ian Rogers556d6372012-11-20 12:19:36 -0800240 jobject jresult;
241 {
242 ScopedThreadStateChange tsc(self, kNative);
243 jresult = fn(soa.Env(), klass.get(), arg0.get());
244 }
245 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700246 } else if (shorty == "IIZ") {
247 typedef jint (fnptr)(JNIEnv*, jclass, jint, jboolean);
248 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
249 ScopedLocalRef<jclass> klass(soa.Env(),
250 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
251 ScopedThreadStateChange tsc(self, kNative);
252 result->SetI(fn(soa.Env(), klass.get(), args[0].GetI(), args[1].GetZ()));
253 } else if (shorty == "ILI") {
254 typedef jint (fnptr)(JNIEnv*, jclass, jobject, jint);
255 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
256 ScopedLocalRef<jclass> klass(soa.Env(),
257 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
258 ScopedLocalRef<jobject> arg0(soa.Env(),
259 soa.AddLocalReference<jobject>(args[0].GetL()));
260 ScopedThreadStateChange tsc(self, kNative);
261 result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1].GetI()));
262 } else if (shorty == "SIZ") {
263 typedef jshort (fnptr)(JNIEnv*, jclass, jint, jboolean);
264 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
265 ScopedLocalRef<jclass> klass(soa.Env(),
266 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
267 ScopedThreadStateChange tsc(self, kNative);
268 result->SetS(fn(soa.Env(), klass.get(), args[0].GetI(), args[1].GetZ()));
269 } else if (shorty == "VIZ") {
270 typedef void (fnptr)(JNIEnv*, jclass, jint, jboolean);
271 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
272 ScopedLocalRef<jclass> klass(soa.Env(),
273 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
274 ScopedThreadStateChange tsc(self, kNative);
275 fn(soa.Env(), klass.get(), args[0].GetI(), args[1].GetZ());
276 } else if (shorty == "ZLL") {
277 typedef jboolean (fnptr)(JNIEnv*, jclass, jobject, jobject);
278 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
279 ScopedLocalRef<jclass> klass(soa.Env(),
280 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
281 ScopedLocalRef<jobject> arg0(soa.Env(),
282 soa.AddLocalReference<jobject>(args[0].GetL()));
283 ScopedLocalRef<jobject> arg1(soa.Env(),
284 soa.AddLocalReference<jobject>(args[1].GetL()));
285 ScopedThreadStateChange tsc(self, kNative);
286 result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
287 } else if (shorty == "ZILL") {
288 typedef jboolean (fnptr)(JNIEnv*, jclass, jint, jobject, jobject);
289 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
290 ScopedLocalRef<jclass> klass(soa.Env(),
291 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
292 ScopedLocalRef<jobject> arg1(soa.Env(),
293 soa.AddLocalReference<jobject>(args[1].GetL()));
294 ScopedLocalRef<jobject> arg2(soa.Env(),
295 soa.AddLocalReference<jobject>(args[2].GetL()));
296 ScopedThreadStateChange tsc(self, kNative);
297 result->SetZ(fn(soa.Env(), klass.get(), args[0].GetI(), arg1.get(), arg2.get()));
298 } else if (shorty == "VILII") {
299 typedef void (fnptr)(JNIEnv*, jclass, jint, jobject, jint, jint);
300 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
301 ScopedLocalRef<jclass> klass(soa.Env(),
302 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
303 ScopedLocalRef<jobject> arg1(soa.Env(),
304 soa.AddLocalReference<jobject>(args[1].GetL()));
305 ScopedThreadStateChange tsc(self, kNative);
306 fn(soa.Env(), klass.get(), args[0].GetI(), arg1.get(), args[2].GetI(), args[3].GetI());
307 } else if (shorty == "VLILII") {
308 typedef void (fnptr)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
309 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
310 ScopedLocalRef<jclass> klass(soa.Env(),
311 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
312 ScopedLocalRef<jobject> arg0(soa.Env(),
313 soa.AddLocalReference<jobject>(args[0].GetL()));
314 ScopedLocalRef<jobject> arg2(soa.Env(),
315 soa.AddLocalReference<jobject>(args[2].GetL()));
316 ScopedThreadStateChange tsc(self, kNative);
317 fn(soa.Env(), klass.get(), arg0.get(), args[1].GetI(), arg2.get(), args[3].GetI(),
318 args[4].GetI());
319 } else {
320 LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
321 << " shorty: " << shorty;
322 }
323 } else {
324 if (shorty == "L") {
325 typedef jobject (fnptr)(JNIEnv*, jobject);
326 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
327 ScopedLocalRef<jobject> rcvr(soa.Env(),
328 soa.AddLocalReference<jobject>(receiver));
Ian Rogers556d6372012-11-20 12:19:36 -0800329 jobject jresult;
330 {
331 ScopedThreadStateChange tsc(self, kNative);
332 jresult = fn(soa.Env(), rcvr.get());
333 }
334 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700335 } else if (shorty == "LL") {
336 typedef jobject (fnptr)(JNIEnv*, jobject, jobject);
337 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
338 ScopedLocalRef<jobject> rcvr(soa.Env(),
339 soa.AddLocalReference<jobject>(receiver));
340 ScopedLocalRef<jobject> arg0(soa.Env(),
341 soa.AddLocalReference<jobject>(args[0].GetL()));
Ian Rogers556d6372012-11-20 12:19:36 -0800342 jobject jresult;
343 {
344 ScopedThreadStateChange tsc(self, kNative);
345 jresult = fn(soa.Env(), rcvr.get(), arg0.get());
346
347 }
348 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700349 ScopedThreadStateChange tsc(self, kNative);
Ian Rogers64b6d142012-10-29 16:34:15 -0700350 } else if (shorty == "III") {
351 typedef jint (fnptr)(JNIEnv*, jobject, jint, jint);
352 fnptr* fn = reinterpret_cast<fnptr*>(method->GetNativeMethod());
353 ScopedLocalRef<jobject> rcvr(soa.Env(),
354 soa.AddLocalReference<jobject>(receiver));
355 ScopedThreadStateChange tsc(self, kNative);
356 result->SetI(fn(soa.Env(), rcvr.get(), args[0].GetI(), args[1].GetI()));
357 } else {
358 LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
359 << " shorty: " << shorty;
360 }
361 }
362}
363
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700364static void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
365 ref->MonitorEnter(self);
366}
367
368static void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
369 ref->MonitorExit(self);
370}
371
372static void DoInvoke(Thread* self, MethodHelper& mh, ShadowFrame& shadow_frame,
373 const DecodedInstruction& dec_insn, InvokeType type, bool is_range,
374 JValue* result)
375 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
376 Object* receiver;
377 if (type == kStatic) {
378 receiver = NULL;
379 } else {
380 receiver = shadow_frame.GetReference(dec_insn.vC);
381 if (UNLIKELY(receiver == NULL)) {
382 ThrowNullPointerExceptionForMethodAccess(shadow_frame.GetMethod(), dec_insn.vB, type);
383 result->SetJ(0);
384 return;
385 }
386 }
387 uint32_t method_idx = dec_insn.vB;
388 AbstractMethod* target_method = FindMethodFromCode(method_idx, receiver,
389 shadow_frame.GetMethod(), self, true,
390 type);
391 if (UNLIKELY(target_method == NULL)) {
392 CHECK(self->IsExceptionPending());
393 result->SetJ(0);
394 return;
395 }
396 mh.ChangeMethod(target_method);
397 ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
398 if (is_range) {
399 arg_array.BuildArgArray(shadow_frame, dec_insn.vC + (type != kStatic ? 1 : 0));
400 } else {
401 arg_array.BuildArgArray(shadow_frame, dec_insn.arg + (type != kStatic ? 1 : 0));
402 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700403 if (LIKELY(Runtime::Current()->IsStarted())) {
404 target_method->Invoke(self, receiver, arg_array.get(), result);
405 } else {
406 UnstartedRuntimeInvoke(self, target_method, receiver, arg_array.get(), result);
407 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700408 if (!mh.GetReturnType()->IsPrimitive() && result->GetL() != NULL) {
409 CHECK(mh.GetReturnType()->IsAssignableFrom(result->GetL()->GetClass()));
410 }
411 mh.ChangeMethod(shadow_frame.GetMethod());
412}
413
414static void DoFieldGet(Thread* self, ShadowFrame& shadow_frame,
415 const DecodedInstruction& dec_insn, FindFieldType find_type,
416 Primitive::Type field_type)
417 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
418 bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
419 uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC;
420 Field* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
421 find_type, Primitive::FieldSize(field_type));
422 if (LIKELY(f != NULL)) {
423 Object* obj;
424 if (is_static) {
425 obj = f->GetDeclaringClass();
426 } else {
427 obj = shadow_frame.GetReference(dec_insn.vB);
428 if (UNLIKELY(obj == NULL)) {
429 ThrowNullPointerExceptionForFieldAccess(f, true);
Ian Rogers689d9f02012-11-20 16:30:29 -0800430 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700431 }
432 }
433 switch (field_type) {
434 case Primitive::kPrimBoolean:
435 shadow_frame.SetVReg(dec_insn.vA, f->GetBoolean(obj));
436 break;
437 case Primitive::kPrimByte:
438 shadow_frame.SetVReg(dec_insn.vA, f->GetByte(obj));
439 break;
440 case Primitive::kPrimChar:
441 shadow_frame.SetVReg(dec_insn.vA, f->GetChar(obj));
442 break;
443 case Primitive::kPrimShort:
444 shadow_frame.SetVReg(dec_insn.vA, f->GetShort(obj));
445 break;
446 case Primitive::kPrimInt:
447 shadow_frame.SetVReg(dec_insn.vA, f->GetInt(obj));
448 break;
449 case Primitive::kPrimLong:
450 shadow_frame.SetVRegLong(dec_insn.vA, f->GetLong(obj));
451 break;
452 case Primitive::kPrimNot:
453 shadow_frame.SetReferenceAndVReg(dec_insn.vA, f->GetObject(obj));
454 break;
455 default:
456 LOG(FATAL) << "Unreachable: " << field_type;
457 }
458 }
459}
460
461static void DoFieldPut(Thread* self, ShadowFrame& shadow_frame,
462 const DecodedInstruction& dec_insn, FindFieldType find_type,
463 Primitive::Type field_type)
464 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
465 bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
466 uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC;
467 Field* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self,
468 find_type, Primitive::FieldSize(field_type));
469 if (LIKELY(f != NULL)) {
470 Object* obj;
471 if (is_static) {
472 obj = f->GetDeclaringClass();
473 } else {
474 obj = shadow_frame.GetReference(dec_insn.vB);
475 if (UNLIKELY(obj == NULL)) {
476 ThrowNullPointerExceptionForFieldAccess(f, false);
Ian Rogers689d9f02012-11-20 16:30:29 -0800477 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700478 }
479 }
480 switch (field_type) {
481 case Primitive::kPrimBoolean:
482 f->SetBoolean(obj, shadow_frame.GetVReg(dec_insn.vA));
483 break;
484 case Primitive::kPrimByte:
485 f->SetByte(obj, shadow_frame.GetVReg(dec_insn.vA));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700486 break;
487 case Primitive::kPrimChar:
488 f->SetChar(obj, shadow_frame.GetVReg(dec_insn.vA));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700489 break;
490 case Primitive::kPrimShort:
491 f->SetShort(obj, shadow_frame.GetVReg(dec_insn.vA));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700492 break;
493 case Primitive::kPrimInt:
494 f->SetInt(obj, shadow_frame.GetVReg(dec_insn.vA));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700495 break;
496 case Primitive::kPrimLong:
497 f->SetLong(obj, shadow_frame.GetVRegLong(dec_insn.vA));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700498 break;
499 case Primitive::kPrimNot:
500 f->SetObj(obj, shadow_frame.GetReference(dec_insn.vA));
501 break;
502 default:
503 LOG(FATAL) << "Unreachable: " << field_type;
504 }
505 }
506}
507
jeffhaod91398c2012-11-20 17:17:33 -0800508static void DoIntDivide(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
509 int32_t dividend, int32_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800510 if (UNLIKELY(divisor == 0)) {
511 self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
512 } else if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
513 shadow_frame.SetVReg(result_reg, kMinInt);
514 } else {
515 shadow_frame.SetVReg(result_reg, dividend / divisor);
516 }
517}
518
519static void DoIntRemainder(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
520 int32_t dividend, int32_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800521 if (UNLIKELY(divisor == 0)) {
522 self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
523 } else if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
524 shadow_frame.SetVReg(result_reg, 0);
525 } else {
526 shadow_frame.SetVReg(result_reg, dividend % divisor);
527 }
528}
529
530static void DoLongDivide(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
531 int64_t dividend, int64_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800532 if (UNLIKELY(divisor == 0)) {
533 self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
534 } else if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
535 shadow_frame.SetVRegLong(result_reg, kMinLong);
536 } else {
537 shadow_frame.SetVRegLong(result_reg, dividend / divisor);
538 }
539}
540
541static void DoLongRemainder(Thread* self, ShadowFrame& shadow_frame, size_t result_reg,
542 int64_t dividend, int64_t divisor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
jeffhaod91398c2012-11-20 17:17:33 -0800543 if (UNLIKELY(divisor == 0)) {
544 self->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
545 } else if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
546 shadow_frame.SetVRegLong(result_reg, 0);
547 } else {
548 shadow_frame.SetVRegLong(result_reg, dividend % divisor);
549 }
550}
551
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700552static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
553 ShadowFrame& shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
554 const uint16_t* insns = code_item->insns_;
555 const Instruction* inst = Instruction::At(insns + shadow_frame.GetDexPC());
556 JValue result_register;
557 while (true) {
jeffhao373c52f2012-11-20 16:11:52 -0800558 CheckSuspend(self);
559 uint32_t dex_pc = inst->GetDexPc(insns);
560 shadow_frame.SetDexPC(dex_pc);
561 Dbg::UpdateDebugger(dex_pc, self);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700562 DecodedInstruction dec_insn(inst);
Ian Rogers64b6d142012-10-29 16:34:15 -0700563 const bool kTracing = false;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700564 if (kTracing) {
565 LOG(INFO) << PrettyMethod(shadow_frame.GetMethod())
566 << StringPrintf("\n0x%x: %s\nReferences:",
567 inst->GetDexPc(insns), inst->DumpString(&mh.GetDexFile()).c_str());
568 for (size_t i = 0; i < shadow_frame.NumberOfReferences(); ++i) {
569 Object* o = shadow_frame.GetReference(i);
570 if (o != NULL) {
571 if (o->GetClass()->IsStringClass() && o->AsString()->GetCharArray() != NULL) {
572 LOG(INFO) << i << ": java.lang.String " << static_cast<void*>(o)
573 << " \"" << o->AsString()->ToModifiedUtf8() << "\"";
574 } else {
575 LOG(INFO) << i << ": " << PrettyTypeOf(o) << " " << static_cast<void*>(o);
576 }
577 } else {
578 LOG(INFO) << i << ": null";
579 }
580 }
581 LOG(INFO) << "vregs:";
582 for (size_t i = 0; i < shadow_frame.NumberOfReferences(); ++i) {
583 LOG(INFO) << StringPrintf("%d: %08x", i, shadow_frame.GetVReg(i));
584 }
585 }
586 const Instruction* next_inst = inst->Next();
587 switch (dec_insn.opcode) {
588 case Instruction::NOP:
589 break;
590 case Instruction::MOVE:
591 case Instruction::MOVE_FROM16:
592 case Instruction::MOVE_16:
593 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
594 break;
595 case Instruction::MOVE_WIDE:
596 case Instruction::MOVE_WIDE_FROM16:
597 case Instruction::MOVE_WIDE_16:
598 shadow_frame.SetVRegLong(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
599 break;
600 case Instruction::MOVE_OBJECT:
601 case Instruction::MOVE_OBJECT_FROM16:
602 case Instruction::MOVE_OBJECT_16:
603 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
604 shadow_frame.SetReference(dec_insn.vA, shadow_frame.GetReference(dec_insn.vB));
605 break;
606 case Instruction::MOVE_RESULT:
607 shadow_frame.SetVReg(dec_insn.vA, result_register.GetI());
608 break;
609 case Instruction::MOVE_RESULT_WIDE:
610 shadow_frame.SetVRegLong(dec_insn.vA, result_register.GetJ());
611 break;
612 case Instruction::MOVE_RESULT_OBJECT:
613 shadow_frame.SetReferenceAndVReg(dec_insn.vA, result_register.GetL());
614 break;
615 case Instruction::MOVE_EXCEPTION: {
616 Throwable* exception = self->GetException();
617 self->ClearException();
618 shadow_frame.SetReferenceAndVReg(dec_insn.vA, exception);
619 break;
620 }
621 case Instruction::RETURN_VOID: {
622 JValue result;
623 result.SetJ(0);
624 return result;
625 }
626 case Instruction::RETURN: {
627 JValue result;
628 result.SetJ(0);
629 result.SetI(shadow_frame.GetVReg(dec_insn.vA));
630 return result;
631 }
632 case Instruction::RETURN_WIDE: {
633 JValue result;
634 result.SetJ(shadow_frame.GetVRegLong(dec_insn.vA));
635 return result;
636 }
637 case Instruction::RETURN_OBJECT: {
638 JValue result;
639 result.SetJ(0);
640 result.SetL(shadow_frame.GetReference(dec_insn.vA));
641 return result;
642 }
643 case Instruction::CONST_4: {
Ian Rogers64b6d142012-10-29 16:34:15 -0700644 int32_t val = static_cast<int32_t>(dec_insn.vB << 28) >> 28;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700645 shadow_frame.SetVReg(dec_insn.vA, val);
646 if (val == 0) {
647 shadow_frame.SetReference(dec_insn.vA, NULL);
648 }
649 break;
650 }
651 case Instruction::CONST_16: {
652 int32_t val = static_cast<int16_t>(dec_insn.vB);
653 shadow_frame.SetVReg(dec_insn.vA, val);
654 if (val == 0) {
655 shadow_frame.SetReference(dec_insn.vA, NULL);
656 }
657 break;
658 }
659 case Instruction::CONST: {
660 int32_t val = dec_insn.vB;
661 shadow_frame.SetVReg(dec_insn.vA, val);
662 if (val == 0) {
663 shadow_frame.SetReference(dec_insn.vA, NULL);
664 }
665 break;
666 }
667 case Instruction::CONST_HIGH16: {
668 int32_t val = dec_insn.vB << 16;
669 shadow_frame.SetVReg(dec_insn.vA, val);
670 if (val == 0) {
671 shadow_frame.SetReference(dec_insn.vA, NULL);
672 }
673 break;
674 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700675 case Instruction::CONST_WIDE_16:
676 shadow_frame.SetVRegLong(dec_insn.vA, static_cast<int16_t>(dec_insn.vB));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700677 break;
Ian Rogers64b6d142012-10-29 16:34:15 -0700678 case Instruction::CONST_WIDE_32:
679 shadow_frame.SetVRegLong(dec_insn.vA, static_cast<int32_t>(dec_insn.vB));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700680 break;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700681 case Instruction::CONST_WIDE:
Ian Rogers64b6d142012-10-29 16:34:15 -0700682 shadow_frame.SetVRegLong(dec_insn.vA, dec_insn.vB_wide);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700683 break;
684 case Instruction::CONST_WIDE_HIGH16:
Ian Rogers64b6d142012-10-29 16:34:15 -0700685 shadow_frame.SetVRegLong(dec_insn.vA, static_cast<uint64_t>(dec_insn.vB) << 48);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700686 break;
687 case Instruction::CONST_STRING:
688 case Instruction::CONST_STRING_JUMBO: {
689 if (UNLIKELY(!String::GetJavaLangString()->IsInitialized())) {
690 Runtime::Current()->GetClassLinker()->EnsureInitialized(String::GetJavaLangString(),
691 true, true);
692 }
693 String* s = mh.ResolveString(dec_insn.vB);
694 shadow_frame.SetReferenceAndVReg(dec_insn.vA, s);
695 break;
696 }
697 case Instruction::CONST_CLASS:
Ian Rogers17ffcab2012-11-20 15:27:41 -0800698 shadow_frame.SetReferenceAndVReg(dec_insn.vA, mh.ResolveClass(dec_insn.vB));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700699 break;
jeffhao87a6edd2012-11-20 18:05:18 -0800700 case Instruction::MONITOR_ENTER: {
701 Object* obj = shadow_frame.GetReference(dec_insn.vA);
702 if (UNLIKELY(obj == NULL)) {
703 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
704 } else {
705 DoMonitorEnter(self, obj);
706 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700707 break;
jeffhao87a6edd2012-11-20 18:05:18 -0800708 }
709 case Instruction::MONITOR_EXIT: {
710 Object* obj = shadow_frame.GetReference(dec_insn.vA);
711 if (UNLIKELY(obj == NULL)) {
712 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
713 } else {
714 DoMonitorExit(self, obj);
715 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700716 break;
jeffhao87a6edd2012-11-20 18:05:18 -0800717 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700718 case Instruction::CHECK_CAST: {
719 Class* c = mh.ResolveClass(dec_insn.vB);
jeffhao87a6edd2012-11-20 18:05:18 -0800720 if (UNLIKELY(c == NULL)) {
721 CHECK(self->IsExceptionPending());
722 } else {
723 Object* obj = shadow_frame.GetReference(dec_insn.vA);
724 if (UNLIKELY(obj != NULL && !obj->InstanceOf(c))) {
725 self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
726 "%s cannot be cast to %s",
727 PrettyDescriptor(obj->GetClass()).c_str(),
728 PrettyDescriptor(c).c_str());
729 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700730 }
731 break;
732 }
733 case Instruction::INSTANCE_OF: {
734 Class* c = mh.ResolveClass(dec_insn.vC);
jeffhao87a6edd2012-11-20 18:05:18 -0800735 if (UNLIKELY(c == NULL)) {
736 CHECK(self->IsExceptionPending());
737 } else {
738 Object* obj = shadow_frame.GetReference(dec_insn.vB);
739 shadow_frame.SetVReg(dec_insn.vA, (obj != NULL && obj->InstanceOf(c)) ? 1 : 0);
740 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700741 break;
742 }
743 case Instruction::ARRAY_LENGTH: {
Ian Rogers64b6d142012-10-29 16:34:15 -0700744 Object* array = shadow_frame.GetReference(dec_insn.vB);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700745 if (UNLIKELY(array == NULL)) {
746 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
747 break;
748 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700749 shadow_frame.SetVReg(dec_insn.vA, array->AsArray()->GetLength());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700750 break;
751 }
752 case Instruction::NEW_INSTANCE: {
753 Object* obj = AllocObjectFromCode(dec_insn.vB, shadow_frame.GetMethod(), self, true);
754 shadow_frame.SetReferenceAndVReg(dec_insn.vA, obj);
755 break;
756 }
757 case Instruction::NEW_ARRAY: {
758 int32_t length = shadow_frame.GetVReg(dec_insn.vB);
759 Object* obj = AllocArrayFromCode(dec_insn.vC, shadow_frame.GetMethod(), length, self, true);
760 shadow_frame.SetReferenceAndVReg(dec_insn.vA, obj);
761 break;
762 }
763 case Instruction::FILLED_NEW_ARRAY:
Ian Rogers64b6d142012-10-29 16:34:15 -0700764 case Instruction::FILLED_NEW_ARRAY_RANGE: {
765 bool is_range = (dec_insn.opcode == Instruction::FILLED_NEW_ARRAY_RANGE);
766 int32_t length = dec_insn.vA;
767 CHECK(is_range || length <= 5);
768 Class* arrayClass = mh.ResolveClass(dec_insn.vB);
769 CHECK(arrayClass->IsArrayClass());
770 if (arrayClass->GetComponentType()->IsPrimitiveInt()) {
771 IntArray* newArray = IntArray::Alloc(self, length);
772 if (newArray != NULL) {
773 for (int32_t i = 0; i < length; ++i) {
774 if (is_range) {
775 newArray->Set(i, shadow_frame.GetVReg(dec_insn.vC + i));
776 } else {
777 newArray->Set(i, shadow_frame.GetVReg(dec_insn.arg[i]));
778 }
779 }
780 }
781 result_register.SetL(newArray);
782 } else {
783 UNIMPLEMENTED(FATAL) << inst->DumpString(&mh.GetDexFile())
784 << " for array type: " << PrettyDescriptor(arrayClass);
785 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700786 break;
Ian Rogers64b6d142012-10-29 16:34:15 -0700787 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700788 case Instruction::CMPL_FLOAT: {
789 float val1 = shadow_frame.GetVRegFloat(dec_insn.vB);
790 float val2 = shadow_frame.GetVRegFloat(dec_insn.vC);
791 int32_t result;
792 if (val1 == val2) {
793 result = 0;
794 } else if (val1 > val2) {
795 result = 1;
796 } else {
797 result = -1;
798 }
799 shadow_frame.SetVReg(dec_insn.vA, result);
800 break;
801 }
802 case Instruction::CMPG_FLOAT: {
803 float val1 = shadow_frame.GetVRegFloat(dec_insn.vB);
804 float val2 = shadow_frame.GetVRegFloat(dec_insn.vC);
805 int32_t result;
806 if (val1 == val2) {
807 result = 0;
808 } else if (val1 < val2) {
809 result = -1;
810 } else {
811 result = 1;
812 }
813 shadow_frame.SetVReg(dec_insn.vA, result);
814 break;
815 }
816 case Instruction::CMPL_DOUBLE: {
817 double val1 = shadow_frame.GetVRegDouble(dec_insn.vB);
818 double val2 = shadow_frame.GetVRegDouble(dec_insn.vC);
819 int32_t result;
820 if (val1 == val2) {
821 result = 0;
Ian Rogers58bf0c62012-11-20 16:24:12 -0800822 } else if (val1 > val2) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700823 result = 1;
824 } else {
825 result = -1;
826 }
827 shadow_frame.SetVReg(dec_insn.vA, result);
828 break;
829 }
830
831 case Instruction::CMPG_DOUBLE: {
832 double val1 = shadow_frame.GetVRegDouble(dec_insn.vB);
833 double val2 = shadow_frame.GetVRegDouble(dec_insn.vC);
834 int32_t result;
835 if (val1 == val2) {
836 result = 0;
Ian Rogers58bf0c62012-11-20 16:24:12 -0800837 } else if (val1 < val2) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700838 result = -1;
839 } else {
840 result = 1;
841 }
842 shadow_frame.SetVReg(dec_insn.vA, result);
843 break;
844 }
845 case Instruction::CMP_LONG: {
846 int64_t val1 = shadow_frame.GetVRegLong(dec_insn.vB);
847 int64_t val2 = shadow_frame.GetVRegLong(dec_insn.vC);
848 int32_t result;
jeffhao87a6edd2012-11-20 18:05:18 -0800849 if (val1 > val2) {
Ian Rogers64b6d142012-10-29 16:34:15 -0700850 result = 1;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700851 } else if (val1 == val2) {
852 result = 0;
853 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -0700854 result = -1;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700855 }
856 shadow_frame.SetVReg(dec_insn.vA, result);
857 break;
858 }
859 case Instruction::THROW: {
860 Throwable* t = shadow_frame.GetReference(dec_insn.vA)->AsThrowable();
861 self->SetException(t);
862 break;
863 }
864 case Instruction::GOTO:
865 case Instruction::GOTO_16:
866 case Instruction::GOTO_32: {
867 uint32_t dex_pc = inst->GetDexPc(insns);
868 next_inst = Instruction::At(insns + dex_pc + dec_insn.vA);
869 break;
870 }
Ian Rogers556d6372012-11-20 12:19:36 -0800871 case Instruction::PACKED_SWITCH: {
872 uint32_t dex_pc = inst->GetDexPc(insns);
873 const uint16_t* switch_data = insns + dex_pc + dec_insn.vB;
874 int32_t test_val = shadow_frame.GetVReg(dec_insn.vA);
875 CHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
876 uint16_t size = switch_data[1];
877 CHECK_GT(size, 0);
878 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
879 CHECK(IsAligned<4>(keys));
880 int32_t first_key = keys[0];
881 const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
882 CHECK(IsAligned<4>(targets));
883 int32_t index = test_val - first_key;
884 if (index >= 0 && index < size) {
885 next_inst = Instruction::At(insns + dex_pc + targets[index]);
886 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700887 break;
Ian Rogers556d6372012-11-20 12:19:36 -0800888 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700889 case Instruction::SPARSE_SWITCH: {
890 uint32_t dex_pc = inst->GetDexPc(insns);
Ian Rogers556d6372012-11-20 12:19:36 -0800891 const uint16_t* switch_data = insns + dex_pc + dec_insn.vB;
892 int32_t test_val = shadow_frame.GetVReg(dec_insn.vA);
893 CHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
894 uint16_t size = switch_data[1];
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700895 CHECK_GT(size, 0);
Ian Rogers556d6372012-11-20 12:19:36 -0800896 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700897 CHECK(IsAligned<4>(keys));
898 const int32_t* entries = keys + size;
899 CHECK(IsAligned<4>(entries));
900 int lo = 0;
901 int hi = size - 1;
902 while (lo <= hi) {
903 int mid = (lo + hi) / 2;
904 int32_t foundVal = keys[mid];
Ian Rogers556d6372012-11-20 12:19:36 -0800905 if (test_val < foundVal) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700906 hi = mid - 1;
Ian Rogers556d6372012-11-20 12:19:36 -0800907 } else if (test_val > foundVal) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700908 lo = mid + 1;
909 } else {
910 next_inst = Instruction::At(insns + dex_pc + entries[mid]);
911 break;
912 }
913 }
914 break;
915 }
916 case Instruction::FILL_ARRAY_DATA: {
917 Array* array = shadow_frame.GetReference(dec_insn.vA)->AsArray();
918 if (UNLIKELY(array == NULL)) {
919 Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
920 "null array in FILL_ARRAY_DATA");
921 break;
922 }
923 DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
924 uint32_t dex_pc = inst->GetDexPc(insns);
925 const Instruction::ArrayDataPayload* payload =
926 reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + dex_pc + dec_insn.vB);
927 if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
928 Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
929 "failed FILL_ARRAY_DATA; length=%d, index=%d",
930 array->GetLength(), payload->element_count);
931 break;
932 }
933 uint32_t size_in_bytes = payload->element_count * payload->element_width;
934 memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
935 break;
936 }
937 case Instruction::IF_EQ: {
938 if (shadow_frame.GetVReg(dec_insn.vA) == shadow_frame.GetVReg(dec_insn.vB)) {
939 uint32_t dex_pc = inst->GetDexPc(insns);
940 next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
941 }
942 break;
943 }
944 case Instruction::IF_NE: {
945 if (shadow_frame.GetVReg(dec_insn.vA) != shadow_frame.GetVReg(dec_insn.vB)) {
946 uint32_t dex_pc = inst->GetDexPc(insns);
947 next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
948 }
949 break;
950 }
951 case Instruction::IF_LT: {
952 if (shadow_frame.GetVReg(dec_insn.vA) < shadow_frame.GetVReg(dec_insn.vB)) {
953 uint32_t dex_pc = inst->GetDexPc(insns);
954 next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
955 }
956 break;
957 }
958 case Instruction::IF_GE: {
959 if (shadow_frame.GetVReg(dec_insn.vA) >= shadow_frame.GetVReg(dec_insn.vB)) {
960 uint32_t dex_pc = inst->GetDexPc(insns);
961 next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
962 }
963 break;
964 }
965 case Instruction::IF_GT: {
966 if (shadow_frame.GetVReg(dec_insn.vA) > shadow_frame.GetVReg(dec_insn.vB)) {
967 uint32_t dex_pc = inst->GetDexPc(insns);
968 next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
969 }
970 break;
971 }
972 case Instruction::IF_LE: {
973 if (shadow_frame.GetVReg(dec_insn.vA) <= shadow_frame.GetVReg(dec_insn.vB)) {
974 uint32_t dex_pc = inst->GetDexPc(insns);
975 next_inst = Instruction::At(insns + dex_pc + dec_insn.vC);
976 }
977 break;
978 }
979 case Instruction::IF_EQZ: {
980 if (shadow_frame.GetVReg(dec_insn.vA) == 0) {
981 uint32_t dex_pc = inst->GetDexPc(insns);
982 next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
983 }
984 break;
985 }
986 case Instruction::IF_NEZ: {
987 if (shadow_frame.GetVReg(dec_insn.vA) != 0) {
988 uint32_t dex_pc = inst->GetDexPc(insns);
989 next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
990 }
991 break;
992 }
993 case Instruction::IF_LTZ: {
994 if (shadow_frame.GetVReg(dec_insn.vA) < 0) {
995 uint32_t dex_pc = inst->GetDexPc(insns);
996 next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
997 }
998 break;
999 }
1000 case Instruction::IF_GEZ: {
1001 if (shadow_frame.GetVReg(dec_insn.vA) >= 0) {
1002 uint32_t dex_pc = inst->GetDexPc(insns);
1003 next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
1004 }
1005 break;
1006 }
1007 case Instruction::IF_GTZ: {
1008 if (shadow_frame.GetVReg(dec_insn.vA) > 0) {
1009 uint32_t dex_pc = inst->GetDexPc(insns);
1010 next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
1011 }
1012 break;
1013 }
1014 case Instruction::IF_LEZ: {
1015 if (shadow_frame.GetVReg(dec_insn.vA) <= 0) {
1016 uint32_t dex_pc = inst->GetDexPc(insns);
1017 next_inst = Instruction::At(insns + dex_pc + dec_insn.vB);
1018 }
1019 break;
1020 }
1021 case Instruction::AGET_BOOLEAN: {
1022 BooleanArray* a = shadow_frame.GetReference(dec_insn.vB)->AsBooleanArray();
1023 if (UNLIKELY(a == NULL)) {
1024 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1025 break;
1026 }
1027 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1028 shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
1029 break;
1030 }
1031 case Instruction::AGET_BYTE: {
1032 ByteArray* a = shadow_frame.GetReference(dec_insn.vB)->AsByteArray();
1033 if (UNLIKELY(a == NULL)) {
1034 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1035 break;
1036 }
1037 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1038 shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
1039 break;
1040 }
1041 case Instruction::AGET_CHAR: {
1042 CharArray* a = shadow_frame.GetReference(dec_insn.vB)->AsCharArray();
1043 if (UNLIKELY(a == NULL)) {
1044 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1045 break;
1046 }
1047 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1048 shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
1049 break;
1050 }
1051 case Instruction::AGET_SHORT: {
1052 ShortArray* a = shadow_frame.GetReference(dec_insn.vB)->AsShortArray();
1053 if (UNLIKELY(a == NULL)) {
1054 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1055 break;
1056 }
1057 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1058 shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
1059 break;
1060 }
1061 case Instruction::AGET: {
1062 IntArray* a = shadow_frame.GetReference(dec_insn.vB)->AsIntArray();
1063 if (UNLIKELY(a == NULL)) {
1064 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1065 break;
1066 }
1067 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1068 shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
1069 break;
1070 }
1071 case Instruction::AGET_WIDE: {
1072 LongArray* a = shadow_frame.GetReference(dec_insn.vB)->AsLongArray();
1073 if (UNLIKELY(a == NULL)) {
1074 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1075 break;
1076 }
1077 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1078 shadow_frame.SetVRegLong(dec_insn.vA, a->Get(index));
1079 break;
1080 }
1081 case Instruction::AGET_OBJECT: {
1082 ObjectArray<Object>* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray<Object>();
1083 if (UNLIKELY(a == NULL)) {
1084 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1085 break;
1086 }
1087 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1088 Object* o = a->Get(index);
1089 shadow_frame.SetReferenceAndVReg(dec_insn.vA, o);
1090 break;
1091 }
1092 case Instruction::APUT_BOOLEAN: {
1093 uint8_t val = shadow_frame.GetVReg(dec_insn.vA);
1094 BooleanArray* a = shadow_frame.GetReference(dec_insn.vB)->AsBooleanArray();
1095 if (UNLIKELY(a == NULL)) {
1096 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1097 break;
1098 }
1099 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1100 a->Set(index, val);
1101 break;
1102 }
1103 case Instruction::APUT_BYTE: {
1104 int8_t val = shadow_frame.GetVReg(dec_insn.vA);
1105 ByteArray* a = shadow_frame.GetReference(dec_insn.vB)->AsByteArray();
1106 if (UNLIKELY(a == NULL)) {
1107 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1108 break;
1109 }
1110 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1111 a->Set(index, val);
1112 break;
1113 }
1114 case Instruction::APUT_CHAR: {
1115 uint16_t val = shadow_frame.GetVReg(dec_insn.vA);
1116 CharArray* a = shadow_frame.GetReference(dec_insn.vB)->AsCharArray();
1117 if (UNLIKELY(a == NULL)) {
1118 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1119 break;
1120 }
1121 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1122 a->Set(index, val);
1123 break;
1124 }
1125 case Instruction::APUT_SHORT: {
1126 int16_t val = shadow_frame.GetVReg(dec_insn.vA);
1127 ShortArray* a = shadow_frame.GetReference(dec_insn.vB)->AsShortArray();
1128 if (UNLIKELY(a == NULL)) {
1129 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1130 break;
1131 }
1132 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1133 a->Set(index, val);
1134 break;
1135 }
1136 case Instruction::APUT: {
1137 int32_t val = shadow_frame.GetVReg(dec_insn.vA);
1138 IntArray* a = shadow_frame.GetReference(dec_insn.vB)->AsIntArray();
1139 if (UNLIKELY(a == NULL)) {
1140 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1141 break;
1142 }
1143 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1144 a->Set(index, val);
1145 break;
1146 }
1147 case Instruction::APUT_WIDE: {
1148 int64_t val = shadow_frame.GetVRegLong(dec_insn.vA);
1149 LongArray* a = shadow_frame.GetReference(dec_insn.vB)->AsLongArray();
1150 if (UNLIKELY(a == NULL)) {
1151 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1152 break;
1153 }
1154 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1155 a->Set(index, val);
1156 break;
1157 }
1158 case Instruction::APUT_OBJECT: {
1159 Object* val = shadow_frame.GetReference(dec_insn.vA);
1160 ObjectArray<Object>* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray<Object>();
1161 if (UNLIKELY(a == NULL)) {
1162 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
1163 break;
1164 }
1165 int32_t index = shadow_frame.GetVReg(dec_insn.vC);
1166 a->Set(index, val);
1167 break;
1168 }
1169 case Instruction::IGET_BOOLEAN:
1170 DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimBoolean);
1171 break;
1172 case Instruction::IGET_BYTE:
1173 DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimByte);
1174 break;
1175 case Instruction::IGET_CHAR:
1176 DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimChar);
1177 break;
1178 case Instruction::IGET_SHORT:
1179 DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimShort);
1180 break;
1181 case Instruction::IGET:
1182 DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimInt);
1183 break;
1184 case Instruction::IGET_WIDE:
1185 DoFieldGet(self, shadow_frame, dec_insn, InstancePrimitiveRead, Primitive::kPrimLong);
1186 break;
1187 case Instruction::IGET_OBJECT:
1188 DoFieldGet(self, shadow_frame, dec_insn, InstanceObjectRead, Primitive::kPrimNot);
1189 break;
1190 case Instruction::SGET_BOOLEAN:
1191 DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimBoolean);
1192 break;
1193 case Instruction::SGET_BYTE:
1194 DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimByte);
1195 break;
1196 case Instruction::SGET_CHAR:
1197 DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimChar);
1198 break;
1199 case Instruction::SGET_SHORT:
1200 DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimShort);
1201 break;
1202 case Instruction::SGET:
1203 DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimInt);
1204 break;
1205 case Instruction::SGET_WIDE:
1206 DoFieldGet(self, shadow_frame, dec_insn, StaticPrimitiveRead, Primitive::kPrimLong);
1207 break;
1208 case Instruction::SGET_OBJECT:
1209 DoFieldGet(self, shadow_frame, dec_insn, StaticObjectRead, Primitive::kPrimNot);
1210 break;
1211 case Instruction::IPUT_BOOLEAN:
1212 DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimBoolean);
1213 break;
1214 case Instruction::IPUT_BYTE:
1215 DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimByte);
1216 break;
1217 case Instruction::IPUT_CHAR:
1218 DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimChar);
1219 break;
1220 case Instruction::IPUT_SHORT:
1221 DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimShort);
1222 break;
1223 case Instruction::IPUT:
1224 DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimInt);
1225 break;
1226 case Instruction::IPUT_WIDE:
1227 DoFieldPut(self, shadow_frame, dec_insn, InstancePrimitiveWrite, Primitive::kPrimLong);
1228 break;
1229 case Instruction::IPUT_OBJECT:
1230 DoFieldPut(self, shadow_frame, dec_insn, InstanceObjectWrite, Primitive::kPrimNot);
1231 break;
1232 case Instruction::SPUT_BOOLEAN:
1233 DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimBoolean);
1234 break;
1235 case Instruction::SPUT_BYTE:
1236 DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimByte);
1237 break;
1238 case Instruction::SPUT_CHAR:
1239 DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimChar);
1240 break;
1241 case Instruction::SPUT_SHORT:
1242 DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimShort);
1243 break;
1244 case Instruction::SPUT:
1245 DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimInt);
1246 break;
1247 case Instruction::SPUT_WIDE:
1248 DoFieldPut(self, shadow_frame, dec_insn, StaticPrimitiveWrite, Primitive::kPrimLong);
1249 break;
1250 case Instruction::SPUT_OBJECT:
1251 DoFieldPut(self, shadow_frame, dec_insn, StaticObjectWrite, Primitive::kPrimNot);
1252 break;
1253 case Instruction::INVOKE_VIRTUAL:
1254 DoInvoke(self, mh, shadow_frame, dec_insn, kVirtual, false, &result_register);
1255 break;
1256 case Instruction::INVOKE_VIRTUAL_RANGE:
1257 DoInvoke(self, mh, shadow_frame, dec_insn, kVirtual, true, &result_register);
1258 break;
1259 case Instruction::INVOKE_SUPER:
1260 DoInvoke(self, mh, shadow_frame, dec_insn, kSuper, false, &result_register);
1261 break;
1262 case Instruction::INVOKE_SUPER_RANGE:
1263 DoInvoke(self, mh, shadow_frame, dec_insn, kSuper, true, &result_register);
1264 break;
1265 case Instruction::INVOKE_DIRECT:
1266 DoInvoke(self, mh, shadow_frame, dec_insn, kDirect, false, &result_register);
1267 break;
1268 case Instruction::INVOKE_DIRECT_RANGE:
1269 DoInvoke(self, mh, shadow_frame, dec_insn, kDirect, true, &result_register);
1270 break;
1271 case Instruction::INVOKE_INTERFACE:
1272 DoInvoke(self, mh, shadow_frame, dec_insn, kInterface, false, &result_register);
1273 break;
1274 case Instruction::INVOKE_INTERFACE_RANGE:
1275 DoInvoke(self, mh, shadow_frame, dec_insn, kInterface, true, &result_register);
1276 break;
1277 case Instruction::INVOKE_STATIC:
1278 DoInvoke(self, mh, shadow_frame, dec_insn, kStatic, false, &result_register);
1279 break;
1280 case Instruction::INVOKE_STATIC_RANGE:
1281 DoInvoke(self, mh, shadow_frame, dec_insn, kStatic, true, &result_register);
1282 break;
1283 case Instruction::NEG_INT:
1284 shadow_frame.SetVReg(dec_insn.vA, -shadow_frame.GetVReg(dec_insn.vB));
1285 break;
1286 case Instruction::NOT_INT:
1287 shadow_frame.SetVReg(dec_insn.vA, 0 ^ shadow_frame.GetVReg(dec_insn.vB));
1288 break;
1289 case Instruction::NEG_LONG:
1290 shadow_frame.SetVRegLong(dec_insn.vA, -shadow_frame.GetVRegLong(dec_insn.vB));
1291 break;
1292 case Instruction::NOT_LONG:
1293 shadow_frame.SetVRegLong(dec_insn.vA, 0 ^ shadow_frame.GetVRegLong(dec_insn.vB));
1294 break;
1295 case Instruction::NEG_FLOAT:
1296 shadow_frame.SetVRegFloat(dec_insn.vA, -shadow_frame.GetVRegFloat(dec_insn.vB));
1297 break;
1298 case Instruction::NEG_DOUBLE:
1299 shadow_frame.SetVRegDouble(dec_insn.vA, -shadow_frame.GetVRegDouble(dec_insn.vB));
1300 break;
1301 case Instruction::INT_TO_LONG:
1302 shadow_frame.SetVRegLong(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
1303 break;
1304 case Instruction::INT_TO_FLOAT:
1305 shadow_frame.SetVRegFloat(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
1306 break;
1307 case Instruction::INT_TO_DOUBLE:
1308 shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB));
1309 break;
1310 case Instruction::LONG_TO_INT:
1311 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
1312 break;
1313 case Instruction::LONG_TO_FLOAT:
1314 shadow_frame.SetVRegFloat(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
1315 break;
1316 case Instruction::LONG_TO_DOUBLE:
1317 shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB));
1318 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001319 case Instruction::FLOAT_TO_INT: {
1320 float val = shadow_frame.GetVRegFloat(dec_insn.vB);
1321 if (val != val) {
1322 shadow_frame.SetVReg(dec_insn.vA, 0);
1323 } else if (val > static_cast<float>(kMaxInt)) {
1324 shadow_frame.SetVReg(dec_insn.vA, kMaxInt);
1325 } else if (val < static_cast<float>(kMinInt)) {
1326 shadow_frame.SetVReg(dec_insn.vA, kMinInt);
1327 } else {
1328 shadow_frame.SetVReg(dec_insn.vA, val);
1329 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001330 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001331 }
1332 case Instruction::FLOAT_TO_LONG: {
1333 float val = shadow_frame.GetVRegFloat(dec_insn.vB);
1334 if (val != val) {
1335 shadow_frame.SetVRegLong(dec_insn.vA, 0);
1336 } else if (val > static_cast<float>(kMaxLong)) {
1337 shadow_frame.SetVRegLong(dec_insn.vA, kMaxLong);
1338 } else if (val < static_cast<float>(kMinLong)) {
1339 shadow_frame.SetVRegLong(dec_insn.vA, kMinLong);
1340 } else {
1341 shadow_frame.SetVRegLong(dec_insn.vA, val);
1342 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001343 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001344 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001345 case Instruction::FLOAT_TO_DOUBLE:
1346 shadow_frame.SetVRegDouble(dec_insn.vA, shadow_frame.GetVRegFloat(dec_insn.vB));
1347 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001348 case Instruction::DOUBLE_TO_INT: {
1349 double val = shadow_frame.GetVRegDouble(dec_insn.vB);
1350 if (val != val) {
1351 shadow_frame.SetVReg(dec_insn.vA, 0);
1352 } else if (val > static_cast<double>(kMaxInt)) {
1353 shadow_frame.SetVReg(dec_insn.vA, kMaxInt);
1354 } else if (val < static_cast<double>(kMinInt)) {
1355 shadow_frame.SetVReg(dec_insn.vA, kMinInt);
1356 } else {
1357 shadow_frame.SetVReg(dec_insn.vA, val);
1358 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001359 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001360 }
1361 case Instruction::DOUBLE_TO_LONG: {
1362 double val = shadow_frame.GetVRegDouble(dec_insn.vB);
1363 if (val != val) {
1364 shadow_frame.SetVRegLong(dec_insn.vA, 0);
1365 } else if (val > static_cast<double>(kMaxLong)) {
1366 shadow_frame.SetVRegLong(dec_insn.vA, kMaxLong);
1367 } else if (val < static_cast<double>(kMinLong)) {
1368 shadow_frame.SetVRegLong(dec_insn.vA, kMinLong);
1369 } else {
1370 shadow_frame.SetVRegLong(dec_insn.vA, val);
1371 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001372 break;
jeffhao87a6edd2012-11-20 18:05:18 -08001373 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001374 case Instruction::DOUBLE_TO_FLOAT:
1375 shadow_frame.SetVRegFloat(dec_insn.vA, shadow_frame.GetVRegDouble(dec_insn.vB));
1376 break;
1377 case Instruction::INT_TO_BYTE:
1378 shadow_frame.SetVReg(dec_insn.vA, static_cast<int8_t>(shadow_frame.GetVReg(dec_insn.vB)));
1379 break;
1380 case Instruction::INT_TO_CHAR:
1381 shadow_frame.SetVReg(dec_insn.vA, static_cast<uint16_t>(shadow_frame.GetVReg(dec_insn.vB)));
1382 break;
1383 case Instruction::INT_TO_SHORT:
1384 shadow_frame.SetVReg(dec_insn.vA, static_cast<int16_t>(shadow_frame.GetVReg(dec_insn.vB)));
1385 break;
1386 case Instruction::ADD_INT:
1387 shadow_frame.SetVReg(dec_insn.vA,
1388 shadow_frame.GetVReg(dec_insn.vB) + shadow_frame.GetVReg(dec_insn.vC));
1389 break;
1390 case Instruction::SUB_INT:
1391 shadow_frame.SetVReg(dec_insn.vA,
1392 shadow_frame.GetVReg(dec_insn.vB) - shadow_frame.GetVReg(dec_insn.vC));
1393 break;
1394 case Instruction::MUL_INT:
1395 shadow_frame.SetVReg(dec_insn.vA,
1396 shadow_frame.GetVReg(dec_insn.vB) * shadow_frame.GetVReg(dec_insn.vC));
1397 break;
1398 case Instruction::REM_INT:
jeffhaod91398c2012-11-20 17:17:33 -08001399 DoIntRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
1400 shadow_frame.GetVReg(dec_insn.vC));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001401 break;
1402 case Instruction::DIV_INT:
jeffhaod91398c2012-11-20 17:17:33 -08001403 DoIntDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
1404 shadow_frame.GetVReg(dec_insn.vC));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001405 break;
1406 case Instruction::SHL_INT:
1407 shadow_frame.SetVReg(dec_insn.vA,
1408 shadow_frame.GetVReg(dec_insn.vB) << shadow_frame.GetVReg(dec_insn.vC));
1409 break;
1410 case Instruction::SHR_INT:
1411 shadow_frame.SetVReg(dec_insn.vA,
1412 shadow_frame.GetVReg(dec_insn.vB) >> shadow_frame.GetVReg(dec_insn.vC));
1413 break;
1414 case Instruction::USHR_INT:
1415 shadow_frame.SetVReg(dec_insn.vA,
1416 static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vB)) >>
1417 shadow_frame.GetVReg(dec_insn.vC));
1418 break;
1419 case Instruction::AND_INT:
1420 shadow_frame.SetVReg(dec_insn.vA,
1421 shadow_frame.GetVReg(dec_insn.vB) & shadow_frame.GetVReg(dec_insn.vC));
1422 break;
1423 case Instruction::OR_INT:
1424 shadow_frame.SetVReg(dec_insn.vA,
1425 shadow_frame.GetVReg(dec_insn.vB) | shadow_frame.GetVReg(dec_insn.vC));
1426 break;
1427 case Instruction::XOR_INT:
1428 shadow_frame.SetVReg(dec_insn.vA,
1429 shadow_frame.GetVReg(dec_insn.vB) ^ shadow_frame.GetVReg(dec_insn.vC));
1430 break;
1431 case Instruction::ADD_LONG:
1432 shadow_frame.SetVRegLong(dec_insn.vA,
1433 shadow_frame.GetVRegLong(dec_insn.vB) +
1434 shadow_frame.GetVRegLong(dec_insn.vC));
1435 break;
1436 case Instruction::SUB_LONG:
1437 shadow_frame.SetVRegLong(dec_insn.vA,
1438 shadow_frame.GetVRegLong(dec_insn.vB) -
1439 shadow_frame.GetVRegLong(dec_insn.vC));
1440 break;
1441 case Instruction::MUL_LONG:
1442 shadow_frame.SetVRegLong(dec_insn.vA,
1443 shadow_frame.GetVRegLong(dec_insn.vB) *
1444 shadow_frame.GetVRegLong(dec_insn.vC));
1445 break;
1446 case Instruction::DIV_LONG:
jeffhaod91398c2012-11-20 17:17:33 -08001447 DoLongDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB),
1448 shadow_frame.GetVRegLong(dec_insn.vC));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001449 break;
1450 case Instruction::REM_LONG:
jeffhaod91398c2012-11-20 17:17:33 -08001451 DoLongRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vB),
1452 shadow_frame.GetVRegLong(dec_insn.vC));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001453 break;
1454 case Instruction::AND_LONG:
1455 shadow_frame.SetVRegLong(dec_insn.vA,
1456 shadow_frame.GetVRegLong(dec_insn.vB) &
1457 shadow_frame.GetVRegLong(dec_insn.vC));
1458 break;
1459 case Instruction::OR_LONG:
1460 shadow_frame.SetVRegLong(dec_insn.vA,
1461 shadow_frame.GetVRegLong(dec_insn.vB) |
1462 shadow_frame.GetVRegLong(dec_insn.vC));
1463 break;
1464 case Instruction::XOR_LONG:
1465 shadow_frame.SetVRegLong(dec_insn.vA,
1466 shadow_frame.GetVRegLong(dec_insn.vB) ^
1467 shadow_frame.GetVRegLong(dec_insn.vC));
1468 break;
1469 case Instruction::SHL_LONG:
1470 shadow_frame.SetVRegLong(dec_insn.vA,
1471 shadow_frame.GetVRegLong(dec_insn.vB) <<
1472 shadow_frame.GetVReg(dec_insn.vC));
1473 break;
1474 case Instruction::SHR_LONG:
1475 shadow_frame.SetVRegLong(dec_insn.vA,
1476 shadow_frame.GetVRegLong(dec_insn.vB) >>
1477 shadow_frame.GetVReg(dec_insn.vC));
1478 break;
1479 case Instruction::USHR_LONG:
1480 shadow_frame.SetVRegLong(dec_insn.vA,
1481 static_cast<uint64_t>(shadow_frame.GetVRegLong(dec_insn.vB)) >>
1482 shadow_frame.GetVReg(dec_insn.vC));
1483 break;
1484 case Instruction::ADD_FLOAT:
1485 shadow_frame.SetVRegFloat(dec_insn.vA,
1486 shadow_frame.GetVRegFloat(dec_insn.vB) +
1487 shadow_frame.GetVRegFloat(dec_insn.vC));
1488 break;
1489 case Instruction::SUB_FLOAT:
1490 shadow_frame.SetVRegFloat(dec_insn.vA,
1491 shadow_frame.GetVRegFloat(dec_insn.vB) -
1492 shadow_frame.GetVRegFloat(dec_insn.vC));
1493 break;
1494 case Instruction::MUL_FLOAT:
1495 shadow_frame.SetVRegFloat(dec_insn.vA,
1496 shadow_frame.GetVRegFloat(dec_insn.vB) *
1497 shadow_frame.GetVRegFloat(dec_insn.vC));
1498 break;
1499 case Instruction::DIV_FLOAT:
1500 shadow_frame.SetVRegFloat(dec_insn.vA,
1501 shadow_frame.GetVRegFloat(dec_insn.vB) /
1502 shadow_frame.GetVRegFloat(dec_insn.vC));
1503 break;
1504 case Instruction::REM_FLOAT:
1505 shadow_frame.SetVRegFloat(dec_insn.vA,
1506 fmodf(shadow_frame.GetVRegFloat(dec_insn.vB),
1507 shadow_frame.GetVRegFloat(dec_insn.vC)));
1508 break;
1509 case Instruction::ADD_DOUBLE:
1510 shadow_frame.SetVRegDouble(dec_insn.vA,
1511 shadow_frame.GetVRegDouble(dec_insn.vB) +
1512 shadow_frame.GetVRegDouble(dec_insn.vC));
1513 break;
1514 case Instruction::SUB_DOUBLE:
1515 shadow_frame.SetVRegDouble(dec_insn.vA,
1516 shadow_frame.GetVRegDouble(dec_insn.vB) -
1517 shadow_frame.GetVRegDouble(dec_insn.vC));
1518 break;
1519 case Instruction::MUL_DOUBLE:
1520 shadow_frame.SetVRegDouble(dec_insn.vA,
1521 shadow_frame.GetVRegDouble(dec_insn.vB) *
1522 shadow_frame.GetVRegDouble(dec_insn.vC));
1523 break;
1524 case Instruction::DIV_DOUBLE:
1525 shadow_frame.SetVRegDouble(dec_insn.vA,
1526 shadow_frame.GetVRegDouble(dec_insn.vB) /
1527 shadow_frame.GetVRegDouble(dec_insn.vC));
1528 break;
1529 case Instruction::REM_DOUBLE:
1530 shadow_frame.SetVRegDouble(dec_insn.vA,
1531 fmod(shadow_frame.GetVRegDouble(dec_insn.vB),
1532 shadow_frame.GetVRegDouble(dec_insn.vC)));
1533 break;
1534 case Instruction::ADD_INT_2ADDR:
1535 shadow_frame.SetVReg(dec_insn.vA,
1536 shadow_frame.GetVReg(dec_insn.vA) + shadow_frame.GetVReg(dec_insn.vB));
1537 break;
1538 case Instruction::SUB_INT_2ADDR:
1539 shadow_frame.SetVReg(dec_insn.vA,
1540 shadow_frame.GetVReg(dec_insn.vA) - shadow_frame.GetVReg(dec_insn.vB));
1541 break;
1542 case Instruction::MUL_INT_2ADDR:
1543 shadow_frame.SetVReg(dec_insn.vA,
1544 shadow_frame.GetVReg(dec_insn.vA) * shadow_frame.GetVReg(dec_insn.vB));
1545 break;
1546 case Instruction::REM_INT_2ADDR:
jeffhaod91398c2012-11-20 17:17:33 -08001547 DoIntRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA),
1548 shadow_frame.GetVReg(dec_insn.vB));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001549 break;
1550 case Instruction::SHL_INT_2ADDR:
1551 shadow_frame.SetVReg(dec_insn.vA,
1552 shadow_frame.GetVReg(dec_insn.vA) << shadow_frame.GetVReg(dec_insn.vB));
1553 break;
1554 case Instruction::SHR_INT_2ADDR:
1555 shadow_frame.SetVReg(dec_insn.vA,
1556 shadow_frame.GetVReg(dec_insn.vA) >> shadow_frame.GetVReg(dec_insn.vB));
1557 break;
1558 case Instruction::USHR_INT_2ADDR:
1559 shadow_frame.SetVReg(dec_insn.vA,
1560 static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vA)) >>
1561 shadow_frame.GetVReg(dec_insn.vB));
1562 break;
1563 case Instruction::AND_INT_2ADDR:
1564 shadow_frame.SetVReg(dec_insn.vA,
1565 shadow_frame.GetVReg(dec_insn.vA) & shadow_frame.GetVReg(dec_insn.vB));
1566 break;
1567 case Instruction::OR_INT_2ADDR:
1568 shadow_frame.SetVReg(dec_insn.vA,
1569 shadow_frame.GetVReg(dec_insn.vA) | shadow_frame.GetVReg(dec_insn.vB));
1570 break;
1571 case Instruction::XOR_INT_2ADDR:
1572 shadow_frame.SetVReg(dec_insn.vA,
1573 shadow_frame.GetVReg(dec_insn.vA) ^ shadow_frame.GetVReg(dec_insn.vB));
1574 break;
1575 case Instruction::DIV_INT_2ADDR:
jeffhaod91398c2012-11-20 17:17:33 -08001576 DoIntDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vA),
1577 shadow_frame.GetVReg(dec_insn.vB));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001578 break;
1579 case Instruction::ADD_LONG_2ADDR:
1580 shadow_frame.SetVRegLong(dec_insn.vA,
1581 shadow_frame.GetVRegLong(dec_insn.vA) +
1582 shadow_frame.GetVRegLong(dec_insn.vB));
1583 break;
1584 case Instruction::SUB_LONG_2ADDR:
1585 shadow_frame.SetVRegLong(dec_insn.vA,
1586 shadow_frame.GetVRegLong(dec_insn.vA) -
1587 shadow_frame.GetVRegLong(dec_insn.vB));
1588 break;
1589 case Instruction::MUL_LONG_2ADDR:
1590 shadow_frame.SetVRegLong(dec_insn.vA,
Ian Rogers64b6d142012-10-29 16:34:15 -07001591 shadow_frame.GetVRegLong(dec_insn.vA) *
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001592 shadow_frame.GetVRegLong(dec_insn.vB));
1593 break;
1594 case Instruction::DIV_LONG_2ADDR:
jeffhaod91398c2012-11-20 17:17:33 -08001595 DoLongDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vA),
1596 shadow_frame.GetVRegLong(dec_insn.vB));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001597 break;
1598 case Instruction::REM_LONG_2ADDR:
jeffhaod91398c2012-11-20 17:17:33 -08001599 DoLongRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVRegLong(dec_insn.vA),
1600 shadow_frame.GetVRegLong(dec_insn.vB));
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001601 break;
1602 case Instruction::AND_LONG_2ADDR:
1603 shadow_frame.SetVRegLong(dec_insn.vA,
1604 shadow_frame.GetVRegLong(dec_insn.vA) &
1605 shadow_frame.GetVRegLong(dec_insn.vB));
1606 break;
1607 case Instruction::OR_LONG_2ADDR:
1608 shadow_frame.SetVRegLong(dec_insn.vA,
1609 shadow_frame.GetVRegLong(dec_insn.vA) |
1610 shadow_frame.GetVRegLong(dec_insn.vB));
1611 break;
1612 case Instruction::XOR_LONG_2ADDR:
1613 shadow_frame.SetVRegLong(dec_insn.vA,
1614 shadow_frame.GetVRegLong(dec_insn.vA) ^
1615 shadow_frame.GetVRegLong(dec_insn.vB));
1616 break;
1617 case Instruction::SHL_LONG_2ADDR:
1618 shadow_frame.SetVRegLong(dec_insn.vA,
1619 shadow_frame.GetVRegLong(dec_insn.vA) <<
1620 shadow_frame.GetVReg(dec_insn.vB));
1621 break;
1622 case Instruction::SHR_LONG_2ADDR:
1623 shadow_frame.SetVRegLong(dec_insn.vA,
1624 shadow_frame.GetVRegLong(dec_insn.vA) >>
1625 shadow_frame.GetVReg(dec_insn.vB));
1626 break;
1627 case Instruction::USHR_LONG_2ADDR:
1628 shadow_frame.SetVRegLong(dec_insn.vA,
1629 static_cast<uint64_t>(shadow_frame.GetVRegLong(dec_insn.vA)) >>
1630 shadow_frame.GetVReg(dec_insn.vB));
1631 break;
1632 case Instruction::ADD_FLOAT_2ADDR:
1633 shadow_frame.SetVRegFloat(dec_insn.vA,
1634 shadow_frame.GetVRegFloat(dec_insn.vA) +
1635 shadow_frame.GetVRegFloat(dec_insn.vB));
1636 break;
1637 case Instruction::SUB_FLOAT_2ADDR:
1638 shadow_frame.SetVRegFloat(dec_insn.vA,
1639 shadow_frame.GetVRegFloat(dec_insn.vA) -
1640 shadow_frame.GetVRegFloat(dec_insn.vB));
1641 break;
1642 case Instruction::MUL_FLOAT_2ADDR:
1643 shadow_frame.SetVRegFloat(dec_insn.vA,
1644 shadow_frame.GetVRegFloat(dec_insn.vA) *
1645 shadow_frame.GetVRegFloat(dec_insn.vB));
1646 break;
1647 case Instruction::DIV_FLOAT_2ADDR:
1648 shadow_frame.SetVRegFloat(dec_insn.vA,
1649 shadow_frame.GetVRegFloat(dec_insn.vA) /
1650 shadow_frame.GetVRegFloat(dec_insn.vB));
1651 break;
1652 case Instruction::REM_FLOAT_2ADDR:
1653 shadow_frame.SetVRegFloat(dec_insn.vA,
1654 fmodf(shadow_frame.GetVRegFloat(dec_insn.vA),
1655 shadow_frame.GetVRegFloat(dec_insn.vB)));
1656 break;
1657 case Instruction::ADD_DOUBLE_2ADDR:
1658 shadow_frame.SetVRegDouble(dec_insn.vA,
1659 shadow_frame.GetVRegDouble(dec_insn.vA) +
1660 shadow_frame.GetVRegDouble(dec_insn.vB));
1661 break;
1662 case Instruction::SUB_DOUBLE_2ADDR:
1663 shadow_frame.SetVRegDouble(dec_insn.vA,
1664 shadow_frame.GetVRegDouble(dec_insn.vA) -
1665 shadow_frame.GetVRegDouble(dec_insn.vB));
1666 break;
1667 case Instruction::MUL_DOUBLE_2ADDR:
1668 shadow_frame.SetVRegDouble(dec_insn.vA,
1669 shadow_frame.GetVRegDouble(dec_insn.vA) *
1670 shadow_frame.GetVRegDouble(dec_insn.vB));
1671 break;
1672 case Instruction::DIV_DOUBLE_2ADDR:
1673 shadow_frame.SetVRegDouble(dec_insn.vA,
1674 shadow_frame.GetVRegDouble(dec_insn.vA) /
1675 shadow_frame.GetVRegDouble(dec_insn.vB));
1676 break;
1677 case Instruction::REM_DOUBLE_2ADDR:
1678 shadow_frame.SetVRegDouble(dec_insn.vA,
1679 fmod(shadow_frame.GetVRegDouble(dec_insn.vA),
1680 shadow_frame.GetVRegDouble(dec_insn.vB)));
1681 break;
1682 case Instruction::ADD_INT_LIT16:
1683 case Instruction::ADD_INT_LIT8:
1684 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) + dec_insn.vC);
1685 break;
1686 case Instruction::RSUB_INT:
1687 case Instruction::RSUB_INT_LIT8:
1688 shadow_frame.SetVReg(dec_insn.vA, dec_insn.vC - shadow_frame.GetVReg(dec_insn.vB));
1689 break;
1690 case Instruction::MUL_INT_LIT16:
1691 case Instruction::MUL_INT_LIT8:
1692 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) * dec_insn.vC);
1693 break;
1694 case Instruction::DIV_INT_LIT16:
1695 case Instruction::DIV_INT_LIT8:
jeffhaod91398c2012-11-20 17:17:33 -08001696 DoIntDivide(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
1697 dec_insn.vC);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001698 break;
1699 case Instruction::REM_INT_LIT16:
1700 case Instruction::REM_INT_LIT8:
jeffhaod91398c2012-11-20 17:17:33 -08001701 DoIntRemainder(self, shadow_frame, dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB),
1702 dec_insn.vC);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001703 break;
1704 case Instruction::AND_INT_LIT16:
1705 case Instruction::AND_INT_LIT8:
1706 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) & dec_insn.vC);
1707 break;
1708 case Instruction::OR_INT_LIT16:
1709 case Instruction::OR_INT_LIT8:
1710 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) | dec_insn.vC);
1711 break;
1712 case Instruction::XOR_INT_LIT16:
1713 case Instruction::XOR_INT_LIT8:
1714 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) ^ dec_insn.vC);
1715 break;
1716 case Instruction::SHL_INT_LIT8:
1717 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) << dec_insn.vC);
1718 break;
1719 case Instruction::SHR_INT_LIT8:
1720 shadow_frame.SetVReg(dec_insn.vA, shadow_frame.GetVReg(dec_insn.vB) >> dec_insn.vC);
1721 break;
1722 case Instruction::USHR_INT_LIT8:
1723 shadow_frame.SetVReg(dec_insn.vA,
1724 static_cast<uint32_t>(shadow_frame.GetVReg(dec_insn.vB)) >>
1725 dec_insn.vC);
1726 break;
1727 default:
1728 LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(&mh.GetDexFile());
1729 break;
1730 }
1731 if (UNLIKELY(self->IsExceptionPending())) {
1732 uint32_t found_dex_pc =
1733 shadow_frame.GetMethod()->FindCatchBlock(self->GetException()->GetClass(),
1734 inst->GetDexPc(insns));
1735 if (found_dex_pc == DexFile::kDexNoIndex) {
1736 JValue result;
1737 result.SetJ(0);
1738 return result; // Handler in caller.
1739 } else {
1740 next_inst = Instruction::At(insns + found_dex_pc);
1741 }
1742 }
1743 inst = next_inst;
1744 }
1745}
1746
1747void EnterInterpreterFromInvoke(Thread* self, AbstractMethod* method, Object* receiver,
1748 JValue* args, JValue* result) {
Ian Rogers64b6d142012-10-29 16:34:15 -07001749 DCHECK_EQ(self, Thread::Current());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001750 MethodHelper mh(method);
1751 const DexFile::CodeItem* code_item = mh.GetCodeItem();
1752 uint16_t num_regs;
1753 uint16_t num_ins;
1754 if (code_item != NULL) {
1755 num_regs = code_item->registers_size_;
1756 num_ins = code_item->ins_size_;
1757 } else {
1758 DCHECK(method->IsNative());
1759 num_regs = num_ins = AbstractMethod::NumArgRegisters(mh.GetShorty());
1760 if (!method->IsStatic()) {
1761 num_regs++;
1762 num_ins++;
1763 }
1764 }
1765 // Set up shadow frame with matching number of reference slots to vregs.
1766 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
1767 UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(num_regs, num_regs,
1768 (last_shadow_frame == NULL) ? NULL : last_shadow_frame->GetLink(),
1769 method, 0));
1770 self->PushShadowFrame(shadow_frame.get());
1771 size_t cur_reg = num_regs - num_ins;
1772 if (!method->IsStatic()) {
1773 CHECK(receiver != NULL);
1774 shadow_frame->SetReferenceAndVReg(cur_reg, receiver);
1775 ++cur_reg;
1776 } else if (!method->GetDeclaringClass()->IsInitializing()) {
1777 Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
1778 true, true);
1779 CHECK(method->GetDeclaringClass()->IsInitializing());
1780 }
Ian Rogers64b6d142012-10-29 16:34:15 -07001781 const char* shorty = mh.GetShorty();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001782 size_t arg_pos = 0;
1783 for (; cur_reg < num_regs; ++cur_reg, ++arg_pos) {
1784 DCHECK_LT(arg_pos + 1, mh.GetShortyLength());
1785 switch (shorty[arg_pos + 1]) {
1786 case 'L': {
1787 Object* o = args[arg_pos].GetL();
1788 shadow_frame->SetReferenceAndVReg(cur_reg, o);
1789 break;
1790 }
1791 case 'J': case 'D':
1792 shadow_frame->SetVRegLong(cur_reg, args[arg_pos].GetJ());
1793 cur_reg++;
1794 break;
1795 default:
1796 shadow_frame->SetVReg(cur_reg, args[arg_pos].GetI());
1797 break;
1798 }
1799 }
Ian Rogers64b6d142012-10-29 16:34:15 -07001800 if (LIKELY(!method->IsNative())) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001801 JValue r = Execute(self, mh, code_item, *shadow_frame.get());
1802 if (result != NULL) {
1803 *result = r;
1804 }
1805 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -07001806 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
1807 // generated stub) except during testing and image writing.
1808 if (!Runtime::Current()->IsStarted()) {
1809 UnstartedRuntimeJni(self, method, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001810 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -07001811 InterpreterJni(self, method, shorty, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -07001812 }
1813 }
1814 self->PopShadowFrame();
1815}
1816
1817} // namespace interpreter
1818} // namespace art