blob: f783b04b95228dca97f38514987584146168e65c [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
Sebastien Hertz8ece0502013-08-07 11:26:41 +020017#include "interpreter_common.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070018
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010019#include <limits>
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070021#include "mirror/string-inl.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070022#include "scoped_thread_state_change.h"
23#include "ScopedLocalRef.h"
Andreas Gampeb3025922015-09-01 14:45:00 -070024#include "stack.h"
Andreas Gampe2969bcd2015-03-09 12:57:41 -070025#include "unstarted_runtime.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070026
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070027namespace art {
28namespace interpreter {
29
Ian Rogersfc0e94b2013-09-23 23:51:32 -070030static void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
Jeff Hao5d917302013-02-27 17:57:33 -080031 Object* receiver, uint32_t* args, JValue* result)
Mathieu Chartier90443472015-07-16 20:32:27 -070032 SHARED_REQUIRES(Locks::mutator_lock_) {
Ian Rogers64b6d142012-10-29 16:34:15 -070033 // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
34 // it should be removed and JNI compiled stubs used instead.
35 ScopedObjectAccessUnchecked soa(self);
36 if (method->IsStatic()) {
37 if (shorty == "L") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010038 typedef jobject (fntype)(JNIEnv*, jclass);
Mathieu Chartier2d721012014-11-10 11:08:06 -080039 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -070040 ScopedLocalRef<jclass> klass(soa.Env(),
41 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
Ian Rogers556d6372012-11-20 12:19:36 -080042 jobject jresult;
43 {
44 ScopedThreadStateChange tsc(self, kNative);
45 jresult = fn(soa.Env(), klass.get());
46 }
47 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -070048 } else if (shorty == "V") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010049 typedef void (fntype)(JNIEnv*, jclass);
Mathieu Chartier2d721012014-11-10 11:08:06 -080050 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -070051 ScopedLocalRef<jclass> klass(soa.Env(),
52 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
53 ScopedThreadStateChange tsc(self, kNative);
54 fn(soa.Env(), klass.get());
55 } else if (shorty == "Z") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010056 typedef jboolean (fntype)(JNIEnv*, jclass);
Mathieu Chartier2d721012014-11-10 11:08:06 -080057 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -070058 ScopedLocalRef<jclass> klass(soa.Env(),
59 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
60 ScopedThreadStateChange tsc(self, kNative);
61 result->SetZ(fn(soa.Env(), klass.get()));
62 } else if (shorty == "BI") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010063 typedef jbyte (fntype)(JNIEnv*, jclass, jint);
Mathieu Chartier2d721012014-11-10 11:08:06 -080064 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -070065 ScopedLocalRef<jclass> klass(soa.Env(),
66 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
67 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -080068 result->SetB(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -070069 } else if (shorty == "II") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010070 typedef jint (fntype)(JNIEnv*, jclass, jint);
Mathieu Chartier2d721012014-11-10 11:08:06 -080071 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -070072 ScopedLocalRef<jclass> klass(soa.Env(),
73 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
74 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -080075 result->SetI(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -070076 } else if (shorty == "LL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010077 typedef jobject (fntype)(JNIEnv*, jclass, jobject);
Mathieu Chartier2d721012014-11-10 11:08:06 -080078 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -070079 ScopedLocalRef<jclass> klass(soa.Env(),
80 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
81 ScopedLocalRef<jobject> arg0(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -070082 soa.AddLocalReference<jobject>(
83 reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -080084 jobject jresult;
85 {
86 ScopedThreadStateChange tsc(self, kNative);
87 jresult = fn(soa.Env(), klass.get(), arg0.get());
88 }
89 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -070090 } else if (shorty == "IIZ") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010091 typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
Mathieu Chartier2d721012014-11-10 11:08:06 -080092 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -070093 ScopedLocalRef<jclass> klass(soa.Env(),
94 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
95 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -080096 result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -070097 } else if (shorty == "ILI") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +010098 typedef jint (fntype)(JNIEnv*, jclass, jobject, jint);
Mathieu Chartier2d721012014-11-10 11:08:06 -080099 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(
100 method->GetEntryPointFromJni()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700101 ScopedLocalRef<jclass> klass(soa.Env(),
102 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
103 ScopedLocalRef<jobject> arg0(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700104 soa.AddLocalReference<jobject>(
105 reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700106 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800107 result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700108 } else if (shorty == "SIZ") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100109 typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700110 fntype* const fn =
111 reinterpret_cast<fntype*>(const_cast<void*>(method->GetEntryPointFromJni()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700112 ScopedLocalRef<jclass> klass(soa.Env(),
113 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
114 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800115 result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700116 } else if (shorty == "VIZ") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100117 typedef void (fntype)(JNIEnv*, jclass, jint, jboolean);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800118 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700119 ScopedLocalRef<jclass> klass(soa.Env(),
120 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
121 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800122 fn(soa.Env(), klass.get(), args[0], args[1]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700123 } else if (shorty == "ZLL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100124 typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800125 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700126 ScopedLocalRef<jclass> klass(soa.Env(),
127 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
128 ScopedLocalRef<jobject> arg0(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700129 soa.AddLocalReference<jobject>(
130 reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700131 ScopedLocalRef<jobject> arg1(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700132 soa.AddLocalReference<jobject>(
133 reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700134 ScopedThreadStateChange tsc(self, kNative);
135 result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
136 } else if (shorty == "ZILL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100137 typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800138 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700139 ScopedLocalRef<jclass> klass(soa.Env(),
140 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
141 ScopedLocalRef<jobject> arg1(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700142 soa.AddLocalReference<jobject>(
143 reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700144 ScopedLocalRef<jobject> arg2(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700145 soa.AddLocalReference<jobject>(
146 reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700147 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800148 result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700149 } else if (shorty == "VILII") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100150 typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800151 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700152 ScopedLocalRef<jclass> klass(soa.Env(),
153 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
154 ScopedLocalRef<jobject> arg1(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700155 soa.AddLocalReference<jobject>(
156 reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700157 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800158 fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700159 } else if (shorty == "VLILII") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100160 typedef void (fntype)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800161 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700162 ScopedLocalRef<jclass> klass(soa.Env(),
163 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
164 ScopedLocalRef<jobject> arg0(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700165 soa.AddLocalReference<jobject>(
166 reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700167 ScopedLocalRef<jobject> arg2(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700168 soa.AddLocalReference<jobject>(
169 reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700170 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800171 fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700172 } else {
173 LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
174 << " shorty: " << shorty;
175 }
176 } else {
177 if (shorty == "L") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100178 typedef jobject (fntype)(JNIEnv*, jobject);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800179 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700180 ScopedLocalRef<jobject> rcvr(soa.Env(),
181 soa.AddLocalReference<jobject>(receiver));
Ian Rogers556d6372012-11-20 12:19:36 -0800182 jobject jresult;
183 {
184 ScopedThreadStateChange tsc(self, kNative);
185 jresult = fn(soa.Env(), rcvr.get());
186 }
187 result->SetL(soa.Decode<Object*>(jresult));
Jeff Hao3dd9f762013-07-08 13:09:25 -0700188 } else if (shorty == "V") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100189 typedef void (fntype)(JNIEnv*, jobject);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800190 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Jeff Hao3dd9f762013-07-08 13:09:25 -0700191 ScopedLocalRef<jobject> rcvr(soa.Env(),
192 soa.AddLocalReference<jobject>(receiver));
193 ScopedThreadStateChange tsc(self, kNative);
194 fn(soa.Env(), rcvr.get());
Ian Rogers64b6d142012-10-29 16:34:15 -0700195 } else if (shorty == "LL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100196 typedef jobject (fntype)(JNIEnv*, jobject, jobject);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800197 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700198 ScopedLocalRef<jobject> rcvr(soa.Env(),
199 soa.AddLocalReference<jobject>(receiver));
200 ScopedLocalRef<jobject> arg0(soa.Env(),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700201 soa.AddLocalReference<jobject>(
202 reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -0800203 jobject jresult;
204 {
205 ScopedThreadStateChange tsc(self, kNative);
206 jresult = fn(soa.Env(), rcvr.get(), arg0.get());
Ian Rogers556d6372012-11-20 12:19:36 -0800207 }
208 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700209 ScopedThreadStateChange tsc(self, kNative);
Ian Rogers64b6d142012-10-29 16:34:15 -0700210 } else if (shorty == "III") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100211 typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
Mathieu Chartier2d721012014-11-10 11:08:06 -0800212 fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
Ian Rogers64b6d142012-10-29 16:34:15 -0700213 ScopedLocalRef<jobject> rcvr(soa.Env(),
214 soa.AddLocalReference<jobject>(receiver));
215 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800216 result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700217 } else {
218 LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
219 << " shorty: " << shorty;
220 }
221 }
222}
223
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200224enum InterpreterImplKind {
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800225 kSwitchImpl, // Switch-based interpreter implementation.
226 kComputedGotoImplKind // Computed-goto-based interpreter implementation.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200227};
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800228static std::ostream& operator<<(std::ostream& os, const InterpreterImplKind& rhs) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700229 os << ((rhs == kSwitchImpl) ? "Switch-based interpreter" : "Computed-goto-based interpreter");
230 return os;
231}
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700232
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200233#if !defined(__clang__)
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800234static constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200235#else
236// Clang 3.4 fails to build the goto interpreter implementation.
237static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImpl;
238template<bool do_access_check, bool transaction_active>
Ian Rogerse94652f2014-12-02 11:13:19 -0800239JValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) {
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200240 LOG(FATAL) << "UNREACHABLE";
Ian Rogers2c4257b2014-10-24 14:20:06 -0700241 UNREACHABLE();
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200242}
243// Explicit definitions of ExecuteGotoImpl.
Mathieu Chartier90443472015-07-16 20:32:27 -0700244template<> SHARED_REQUIRES(Locks::mutator_lock_)
Ian Rogerse94652f2014-12-02 11:13:19 -0800245JValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item,
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200246 ShadowFrame& shadow_frame, JValue result_register);
Mathieu Chartier90443472015-07-16 20:32:27 -0700247template<> SHARED_REQUIRES(Locks::mutator_lock_)
Ian Rogerse94652f2014-12-02 11:13:19 -0800248JValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item,
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200249 ShadowFrame& shadow_frame, JValue result_register);
Mathieu Chartier90443472015-07-16 20:32:27 -0700250template<> SHARED_REQUIRES(Locks::mutator_lock_)
Ian Rogerse94652f2014-12-02 11:13:19 -0800251JValue ExecuteGotoImpl<true, true>(Thread* self, const DexFile::CodeItem* code_item,
252 ShadowFrame& shadow_frame, JValue result_register);
Mathieu Chartier90443472015-07-16 20:32:27 -0700253template<> SHARED_REQUIRES(Locks::mutator_lock_)
Ian Rogerse94652f2014-12-02 11:13:19 -0800254JValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item,
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200255 ShadowFrame& shadow_frame, JValue result_register);
Sebastien Hertzfa888d02014-09-30 12:00:11 +0200256#endif
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700257
Ian Rogerse94652f2014-12-02 11:13:19 -0800258static JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame,
259 JValue result_register)
Mathieu Chartier90443472015-07-16 20:32:27 -0700260 SHARED_REQUIRES(Locks::mutator_lock_);
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200261
Ian Rogerse94652f2014-12-02 11:13:19 -0800262static inline JValue Execute(Thread* self, const DexFile::CodeItem* code_item,
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200263 ShadowFrame& shadow_frame, JValue result_register) {
Ian Rogers848871b2013-08-05 10:56:33 -0700264 DCHECK(!shadow_frame.GetMethod()->IsAbstract());
265 DCHECK(!shadow_frame.GetMethod()->IsNative());
Sebastien Hertz4e99b3d2014-06-24 14:35:40 +0200266 shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200267
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100268 bool transaction_active = Runtime::Current()->IsActiveTransaction();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200269 if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) {
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200270 // Enter the "without access check" interpreter.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200271 if (kInterpreterImplKind == kSwitchImpl) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100272 if (transaction_active) {
Ian Rogerse94652f2014-12-02 11:13:19 -0800273 return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100274 } else {
Ian Rogerse94652f2014-12-02 11:13:19 -0800275 return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100276 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200277 } else {
278 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100279 if (transaction_active) {
Ian Rogerse94652f2014-12-02 11:13:19 -0800280 return ExecuteGotoImpl<false, true>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100281 } else {
Ian Rogerse94652f2014-12-02 11:13:19 -0800282 return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100283 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200284 }
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200285 } else {
286 // Enter the "with access check" interpreter.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200287 if (kInterpreterImplKind == kSwitchImpl) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100288 if (transaction_active) {
Ian Rogerse94652f2014-12-02 11:13:19 -0800289 return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100290 } else {
Ian Rogerse94652f2014-12-02 11:13:19 -0800291 return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100292 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200293 } else {
294 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100295 if (transaction_active) {
Ian Rogerse94652f2014-12-02 11:13:19 -0800296 return ExecuteGotoImpl<true, true>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100297 } else {
Ian Rogerse94652f2014-12-02 11:13:19 -0800298 return ExecuteGotoImpl<true, false>(self, code_item, shadow_frame, result_register);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100299 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200300 }
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200301 }
302}
303
Brian Carlstromea46f952013-07-30 01:26:50 -0700304void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
Jeff Hao6474d192013-03-26 14:08:09 -0700305 uint32_t* args, JValue* result) {
Ian Rogers64b6d142012-10-29 16:34:15 -0700306 DCHECK_EQ(self, Thread::Current());
Nicolas Geoffray535a3fb2014-07-22 15:17:38 +0100307 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
308 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
jeffhaod7521322012-11-21 15:38:24 -0800309 ThrowStackOverflowError(self);
310 return;
311 }
312
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700313 const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700314 const DexFile::CodeItem* code_item = method->GetCodeItem();
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700315 uint16_t num_regs;
316 uint16_t num_ins;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700317 if (code_item != nullptr) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700318 num_regs = code_item->registers_size_;
319 num_ins = code_item->ins_size_;
jeffhao0a9bb732012-11-26 12:28:49 -0800320 } else if (method->IsAbstract()) {
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700321 self->EndAssertNoThreadSuspension(old_cause);
Sebastien Hertz56adf602013-07-09 17:27:07 +0200322 ThrowAbstractMethodError(method);
jeffhao0a9bb732012-11-26 12:28:49 -0800323 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700324 } else {
325 DCHECK(method->IsNative());
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700326 num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700327 if (!method->IsStatic()) {
328 num_regs++;
329 num_ins++;
330 }
331 }
332 // Set up shadow frame with matching number of reference slots to vregs.
333 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
Andreas Gampeb3025922015-09-01 14:45:00 -0700334 ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
335 CREATE_SHADOW_FRAME(num_regs, last_shadow_frame, method, 0);
336 ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
Jeff Hao66135192013-05-14 11:02:41 -0700337 self->PushShadowFrame(shadow_frame);
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700338
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700339 size_t cur_reg = num_regs - num_ins;
340 if (!method->IsStatic()) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700341 CHECK(receiver != nullptr);
TDYa127ce4cc0d2012-11-18 16:59:53 -0800342 shadow_frame->SetVRegReference(cur_reg, receiver);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700343 ++cur_reg;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700344 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700345 uint32_t shorty_len = 0;
346 const char* shorty = method->GetShorty(&shorty_len);
Jeff Hao5d917302013-02-27 17:57:33 -0800347 for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700348 DCHECK_LT(shorty_pos + 1, shorty_len);
Jeff Hao5d917302013-02-27 17:57:33 -0800349 switch (shorty[shorty_pos + 1]) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700350 case 'L': {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800351 Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
TDYa127ce4cc0d2012-11-18 16:59:53 -0800352 shadow_frame->SetVRegReference(cur_reg, o);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700353 break;
354 }
Jeff Hao5d917302013-02-27 17:57:33 -0800355 case 'J': case 'D': {
356 uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
357 shadow_frame->SetVRegLong(cur_reg, wide_value);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700358 cur_reg++;
Jeff Hao5d917302013-02-27 17:57:33 -0800359 arg_pos++;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700360 break;
Jeff Hao5d917302013-02-27 17:57:33 -0800361 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700362 default:
Jeff Hao5d917302013-02-27 17:57:33 -0800363 shadow_frame->SetVReg(cur_reg, args[arg_pos]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700364 break;
365 }
366 }
Mathieu Chartier92246bb2014-02-25 18:22:39 -0800367 self->EndAssertNoThreadSuspension(old_cause);
368 // Do this after populating the shadow frame in case EnsureInitialized causes a GC.
Ian Rogers6c5cb212014-06-18 16:07:20 -0700369 if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitialized())) {
Mathieu Chartier92246bb2014-02-25 18:22:39 -0800370 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700371 StackHandleScope<1> hs(self);
372 Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
Ian Rogers7b078e82014-09-10 14:44:24 -0700373 if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) {
Mathieu Chartier92246bb2014-02-25 18:22:39 -0800374 CHECK(self->IsExceptionPending());
375 self->PopShadowFrame();
376 return;
377 }
378 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700379 if (LIKELY(!method->IsNative())) {
Ian Rogerse94652f2014-12-02 11:13:19 -0800380 JValue r = Execute(self, code_item, *shadow_frame, JValue());
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700381 if (result != nullptr) {
Jeff Hao6474d192013-03-26 14:08:09 -0700382 *result = r;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700383 }
384 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -0700385 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
386 // generated stub) except during testing and image writing.
Mathieu Chartier92246bb2014-02-25 18:22:39 -0800387 // Update args to be the args in the shadow frame since the input ones could hold stale
388 // references pointers due to moving GC.
389 args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
Ian Rogers64b6d142012-10-29 16:34:15 -0700390 if (!Runtime::Current()->IsStarted()) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700391 UnstartedRuntime::Jni(self, method, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700392 } else {
Jeff Hao6474d192013-03-26 14:08:09 -0700393 InterpreterJni(self, method, shorty, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700394 }
395 }
396 self->PopShadowFrame();
397}
398
Ian Rogers62d6c772013-02-27 08:32:07 -0800399void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
Mathieu Chartier90443472015-07-16 20:32:27 -0700400 SHARED_REQUIRES(Locks::mutator_lock_) {
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800401 JValue value;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700402 // Set value to last known result in case the shadow frame chain is empty.
403 value.SetJ(ret_val->GetJ());
Sebastien Hertz520633b2015-09-08 17:03:36 +0200404 // Are we executing the first shadow frame?
405 bool first = true;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700406 while (shadow_frame != nullptr) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800407 self->SetTopOfShadowStack(shadow_frame);
Ian Rogerse94652f2014-12-02 11:13:19 -0800408 const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem();
Sebastien Hertz270a0e12015-01-16 19:49:09 +0100409 const uint32_t dex_pc = shadow_frame->GetDexPC();
410 uint32_t new_dex_pc;
411 if (UNLIKELY(self->IsExceptionPending())) {
Sebastien Hertz520633b2015-09-08 17:03:36 +0200412 // If we deoptimize from the QuickExceptionHandler, we already reported the exception to
413 // the instrumentation. To prevent from reporting it a second time, we simply pass a
414 // null Instrumentation*.
Sebastien Hertz270a0e12015-01-16 19:49:09 +0100415 const instrumentation::Instrumentation* const instrumentation =
Sebastien Hertz520633b2015-09-08 17:03:36 +0200416 first ? nullptr : Runtime::Current()->GetInstrumentation();
Sebastien Hertz270a0e12015-01-16 19:49:09 +0100417 uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc,
418 instrumentation);
419 new_dex_pc = found_dex_pc; // the dex pc of a matching catch handler
420 // or DexFile::kDexNoIndex if there is none.
421 } else {
422 const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700423 // For an invoke, use the dex pc of the next instruction.
424 // TODO: should be tested more once b/17586779 is fixed.
425 new_dex_pc = dex_pc + (instr->IsInvoke() ? instr->SizeInCodeUnits() : 0);
Sebastien Hertz270a0e12015-01-16 19:49:09 +0100426 }
427 if (new_dex_pc != DexFile::kDexNoIndex) {
428 shadow_frame->SetDexPC(new_dex_pc);
429 value = Execute(self, code_item, *shadow_frame, value);
430 }
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800431 ShadowFrame* old_frame = shadow_frame;
432 shadow_frame = shadow_frame->GetLink();
Christopher Ferris241a9582015-04-27 15:19:41 -0700433 ShadowFrame::DeleteDeoptimizedFrame(old_frame);
Sebastien Hertz520633b2015-09-08 17:03:36 +0200434 first = false;
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800435 }
436 ret_val->SetJ(value.GetJ());
437}
438
Ian Rogerse94652f2014-12-02 11:13:19 -0800439JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item,
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700440 ShadowFrame* shadow_frame) {
Ian Rogersf3e98552013-03-20 15:49:49 -0700441 DCHECK_EQ(self, Thread::Current());
Nicolas Geoffray535a3fb2014-07-22 15:17:38 +0100442 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
443 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
Ian Rogersf3e98552013-03-20 15:49:49 -0700444 ThrowStackOverflowError(self);
445 return JValue();
446 }
447
Ian Rogerse94652f2014-12-02 11:13:19 -0800448 return Execute(self, code_item, *shadow_frame, JValue());
Ian Rogers7db619b2013-01-16 18:35:48 -0800449}
450
Ian Rogerse94652f2014-12-02 11:13:19 -0800451extern "C" void artInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* code_item,
Ian Rogers848871b2013-08-05 10:56:33 -0700452 ShadowFrame* shadow_frame, JValue* result) {
Nicolas Geoffray535a3fb2014-07-22 15:17:38 +0100453 bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
454 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
Jeff Hao16743632013-05-08 10:59:04 -0700455 ThrowStackOverflowError(self);
Jeff Hao69510672013-05-21 17:34:55 -0700456 return;
Jeff Hao16743632013-05-08 10:59:04 -0700457 }
458
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700459 self->PushShadowFrame(shadow_frame);
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200460 // Ensure static methods are initialized.
Ian Rogerse94652f2014-12-02 11:13:19 -0800461 const bool is_static = shadow_frame->GetMethod()->IsStatic();
462 if (is_static) {
463 mirror::Class* declaring_class = shadow_frame->GetMethod()->GetDeclaringClass();
Ian Rogers6c5cb212014-06-18 16:07:20 -0700464 if (UNLIKELY(!declaring_class->IsInitialized())) {
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700465 StackHandleScope<1> hs(self);
466 HandleWrapper<Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class));
467 if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
Ian Rogers7b078e82014-09-10 14:44:24 -0700468 self, h_declaring_class, true, true))) {
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700469 DCHECK(self->IsExceptionPending());
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700470 self->PopShadowFrame();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200471 return;
472 }
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700473 CHECK(h_declaring_class->IsInitializing());
Jeff Hao16743632013-05-08 10:59:04 -0700474 }
Jeff Hao16743632013-05-08 10:59:04 -0700475 }
Jeff Hao16743632013-05-08 10:59:04 -0700476
Ian Rogerse94652f2014-12-02 11:13:19 -0800477 if (LIKELY(!shadow_frame->GetMethod()->IsNative())) {
478 result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ());
Jeff Hao16743632013-05-08 10:59:04 -0700479 } else {
480 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
481 // generated stub) except during testing and image writing.
482 CHECK(!Runtime::Current()->IsStarted());
Ian Rogerse94652f2014-12-02 11:13:19 -0800483 Object* receiver = is_static ? nullptr : shadow_frame->GetVRegReference(0);
484 uint32_t* args = shadow_frame->GetVRegArgs(is_static ? 0 : 1);
Andreas Gampe799681b2015-05-15 19:24:12 -0700485 UnstartedRuntime::Jni(self, shadow_frame->GetMethod(), receiver, args, result);
Jeff Hao16743632013-05-08 10:59:04 -0700486 }
487
488 self->PopShadowFrame();
Jeff Hao16743632013-05-08 10:59:04 -0700489}
490
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700491} // namespace interpreter
492} // namespace art