blob: e3f3cd0abed38c651cd065b4802242cc2faa5af8 [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"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010018#include <limits>
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019
Ian Rogers2fa6b2e2012-10-17 00:10:17 -070020namespace art {
21namespace interpreter {
22
Ian Rogers64b6d142012-10-29 16:34:15 -070023// Hand select a number of methods to be run in a not yet started runtime without using JNI.
Brian Carlstromea46f952013-07-30 01:26:50 -070024static void UnstartedRuntimeJni(Thread* self, ArtMethod* method,
Jeff Hao5d917302013-02-27 17:57:33 -080025 Object* receiver, uint32_t* args, JValue* result)
Ian Rogers64b6d142012-10-29 16:34:15 -070026 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027 DCHECK(Runtime::Current()->IsActiveTransaction()) << "Calling native method "
28 << PrettyMethod(method)
29 << " in unstarted runtime should only happen"
30 << " in a transaction";
Ian Rogers64b6d142012-10-29 16:34:15 -070031 std::string name(PrettyMethod(method));
32 if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") {
33 result->SetL(NULL);
34 } else if (name == "java.lang.Class dalvik.system.VMStack.getStackClass2()") {
Ian Rogers7a22fa62013-01-23 12:16:16 -080035 NthCallerVisitor visitor(self, 3);
Ian Rogers64b6d142012-10-29 16:34:15 -070036 visitor.WalkStack();
37 result->SetL(visitor.caller->GetDeclaringClass());
38 } else if (name == "double java.lang.Math.log(double)") {
Jeff Hao5d917302013-02-27 17:57:33 -080039 JValue value;
40 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
41 result->SetD(log(value.GetD()));
Ian Rogers64b6d142012-10-29 16:34:15 -070042 } else if (name == "java.lang.String java.lang.Class.getNameNative()") {
43 result->SetL(receiver->AsClass()->ComputeName());
44 } else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
Jeff Hao5d917302013-02-27 17:57:33 -080045 result->SetI(args[0]);
Ian Rogers64b6d142012-10-29 16:34:15 -070046 } else if (name == "float java.lang.Float.intBitsToFloat(int)") {
Jeff Hao5d917302013-02-27 17:57:33 -080047 result->SetI(args[0]);
Ian Rogers64b6d142012-10-29 16:34:15 -070048 } else if (name == "double java.lang.Math.exp(double)") {
Jeff Hao5d917302013-02-27 17:57:33 -080049 JValue value;
50 value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
51 result->SetD(exp(value.GetD()));
Ian Rogers64b6d142012-10-29 16:34:15 -070052 } else if (name == "java.lang.Object java.lang.Object.internalClone()") {
53 result->SetL(receiver->Clone(self));
54 } else if (name == "void java.lang.Object.notifyAll()") {
Ian Rogers05f30572013-02-20 12:13:11 -080055 receiver->NotifyAll(self);
Ian Rogers64b6d142012-10-29 16:34:15 -070056 } else if (name == "int java.lang.String.compareTo(java.lang.String)") {
Jeff Hao5d917302013-02-27 17:57:33 -080057 String* rhs = reinterpret_cast<Object*>(args[0])->AsString();
Ian Rogers64b6d142012-10-29 16:34:15 -070058 CHECK(rhs != NULL);
59 result->SetI(receiver->AsString()->CompareTo(rhs));
60 } else if (name == "java.lang.String java.lang.String.intern()") {
61 result->SetL(receiver->AsString()->Intern());
62 } else if (name == "int java.lang.String.fastIndexOf(int, int)") {
Jeff Hao5d917302013-02-27 17:57:33 -080063 result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -070064 } else if (name == "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") {
Mathieu Chartier5bb99032014-02-08 16:20:58 -080065 SirtRef<mirror::Class> sirt_class(self, reinterpret_cast<Object*>(args[0])->AsClass());
66 SirtRef<mirror::IntArray> sirt_dimensions(self,
67 reinterpret_cast<Object*>(args[1])->AsIntArray());
68 result->SetL(Array::CreateMultiArray(self, sirt_class, sirt_dimensions));
Ian Rogers64b6d142012-10-29 16:34:15 -070069 } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") {
70 ScopedObjectAccessUnchecked soa(self);
Sebastien Hertzee1d79a2014-02-21 15:46:30 +010071 result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace<true>(soa)));
Sebastien Hertzf48644b2014-02-17 15:16:03 +010072 } else if (name == "int java.lang.System.identityHashCode(java.lang.Object)") {
73 mirror::Object* obj = reinterpret_cast<Object*>(args[0]);
74 result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
Ian Rogers64b6d142012-10-29 16:34:15 -070075 } else if (name == "boolean java.nio.ByteOrder.isLittleEndian()") {
Sebastien Hertzf48644b2014-02-17 15:16:03 +010076 result->SetZ(JNI_TRUE);
Ian Rogers64b6d142012-10-29 16:34:15 -070077 } else if (name == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
Jeff Hao5d917302013-02-27 17:57:33 -080078 Object* obj = reinterpret_cast<Object*>(args[0]);
79 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
80 jint expectedValue = args[3];
81 jint newValue = args[4];
Sebastien Hertzf48644b2014-02-17 15:16:03 +010082 bool success = obj->CasField32<true>(MemberOffset(offset), expectedValue, newValue);
83 result->SetZ(success ? JNI_TRUE : JNI_FALSE);
Ian Rogers64b6d142012-10-29 16:34:15 -070084 } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
Jeff Hao5d917302013-02-27 17:57:33 -080085 Object* obj = reinterpret_cast<Object*>(args[0]);
Sebastien Hertzf48644b2014-02-17 15:16:03 +010086 jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
Jeff Hao5d917302013-02-27 17:57:33 -080087 Object* newValue = reinterpret_cast<Object*>(args[3]);
Sebastien Hertzf48644b2014-02-17 15:16:03 +010088 obj->SetFieldObject<true>(MemberOffset(offset), newValue, false);
Hiroshi Yamauchi4d2efce2014-02-10 16:19:09 -080089 } else if (name == "int sun.misc.Unsafe.getArrayBaseOffsetForComponentType(java.lang.Class)") {
90 mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass();
91 Primitive::Type primitive_type = component->GetPrimitiveType();
92 result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
93 } else if (name == "int sun.misc.Unsafe.getArrayIndexScaleForComponentType(java.lang.Class)") {
94 mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass();
95 Primitive::Type primitive_type = component->GetPrimitiveType();
96 result->SetI(Primitive::ComponentSize(primitive_type));
Ian Rogers64b6d142012-10-29 16:34:15 -070097 } else {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010098 // Throw an exception so we can abort the transaction and undo every change.
Sebastien Hertzee1d79a2014-02-21 15:46:30 +010099 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100100 self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;",
101 "Attempt to invoke native method in non-started runtime: %s",
102 name.c_str());
Ian Rogers64b6d142012-10-29 16:34:15 -0700103 }
104}
105
Ian Rogersfc0e94b2013-09-23 23:51:32 -0700106static void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
Jeff Hao5d917302013-02-27 17:57:33 -0800107 Object* receiver, uint32_t* args, JValue* result)
Ian Rogers64b6d142012-10-29 16:34:15 -0700108 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
109 // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
110 // it should be removed and JNI compiled stubs used instead.
111 ScopedObjectAccessUnchecked soa(self);
112 if (method->IsStatic()) {
113 if (shorty == "L") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100114 typedef jobject (fntype)(JNIEnv*, jclass);
115 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700116 ScopedLocalRef<jclass> klass(soa.Env(),
117 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
Ian Rogers556d6372012-11-20 12:19:36 -0800118 jobject jresult;
119 {
120 ScopedThreadStateChange tsc(self, kNative);
121 jresult = fn(soa.Env(), klass.get());
122 }
123 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700124 } else if (shorty == "V") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100125 typedef void (fntype)(JNIEnv*, jclass);
126 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700127 ScopedLocalRef<jclass> klass(soa.Env(),
128 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
129 ScopedThreadStateChange tsc(self, kNative);
130 fn(soa.Env(), klass.get());
131 } else if (shorty == "Z") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100132 typedef jboolean (fntype)(JNIEnv*, jclass);
133 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700134 ScopedLocalRef<jclass> klass(soa.Env(),
135 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
136 ScopedThreadStateChange tsc(self, kNative);
137 result->SetZ(fn(soa.Env(), klass.get()));
138 } else if (shorty == "BI") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100139 typedef jbyte (fntype)(JNIEnv*, jclass, jint);
140 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700141 ScopedLocalRef<jclass> klass(soa.Env(),
142 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
143 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800144 result->SetB(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700145 } else if (shorty == "II") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100146 typedef jint (fntype)(JNIEnv*, jclass, jint);
147 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700148 ScopedLocalRef<jclass> klass(soa.Env(),
149 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
150 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800151 result->SetI(fn(soa.Env(), klass.get(), args[0]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700152 } else if (shorty == "LL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100153 typedef jobject (fntype)(JNIEnv*, jclass, jobject);
154 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700155 ScopedLocalRef<jclass> klass(soa.Env(),
156 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
157 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800158 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -0800159 jobject jresult;
160 {
161 ScopedThreadStateChange tsc(self, kNative);
162 jresult = fn(soa.Env(), klass.get(), arg0.get());
163 }
164 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700165 } else if (shorty == "IIZ") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100166 typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
167 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700168 ScopedLocalRef<jclass> klass(soa.Env(),
169 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
170 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800171 result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700172 } else if (shorty == "ILI") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100173 typedef jint (fntype)(JNIEnv*, jclass, jobject, jint);
174 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700175 ScopedLocalRef<jclass> klass(soa.Env(),
176 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
177 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800178 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700179 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800180 result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700181 } else if (shorty == "SIZ") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100182 typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean);
183 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700184 ScopedLocalRef<jclass> klass(soa.Env(),
185 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
186 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800187 result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700188 } else if (shorty == "VIZ") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100189 typedef void (fntype)(JNIEnv*, jclass, jint, jboolean);
190 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700191 ScopedLocalRef<jclass> klass(soa.Env(),
192 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
193 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800194 fn(soa.Env(), klass.get(), args[0], args[1]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700195 } else if (shorty == "ZLL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100196 typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject);
197 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700198 ScopedLocalRef<jclass> klass(soa.Env(),
199 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
200 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800201 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700202 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800203 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700204 ScopedThreadStateChange tsc(self, kNative);
205 result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
206 } else if (shorty == "ZILL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100207 typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject);
208 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700209 ScopedLocalRef<jclass> klass(soa.Env(),
210 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
211 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800212 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700213 ScopedLocalRef<jobject> arg2(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800214 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700215 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800216 result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700217 } else if (shorty == "VILII") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100218 typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint);
219 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700220 ScopedLocalRef<jclass> klass(soa.Env(),
221 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
222 ScopedLocalRef<jobject> arg1(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800223 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700224 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800225 fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700226 } else if (shorty == "VLILII") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100227 typedef void (fntype)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
228 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700229 ScopedLocalRef<jclass> klass(soa.Env(),
230 soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
231 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800232 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700233 ScopedLocalRef<jobject> arg2(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800234 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
Ian Rogers64b6d142012-10-29 16:34:15 -0700235 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800236 fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
Ian Rogers64b6d142012-10-29 16:34:15 -0700237 } else {
238 LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
239 << " shorty: " << shorty;
240 }
241 } else {
242 if (shorty == "L") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100243 typedef jobject (fntype)(JNIEnv*, jobject);
244 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700245 ScopedLocalRef<jobject> rcvr(soa.Env(),
246 soa.AddLocalReference<jobject>(receiver));
Ian Rogers556d6372012-11-20 12:19:36 -0800247 jobject jresult;
248 {
249 ScopedThreadStateChange tsc(self, kNative);
250 jresult = fn(soa.Env(), rcvr.get());
251 }
252 result->SetL(soa.Decode<Object*>(jresult));
Jeff Hao3dd9f762013-07-08 13:09:25 -0700253 } else if (shorty == "V") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100254 typedef void (fntype)(JNIEnv*, jobject);
255 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Jeff Hao3dd9f762013-07-08 13:09:25 -0700256 ScopedLocalRef<jobject> rcvr(soa.Env(),
257 soa.AddLocalReference<jobject>(receiver));
258 ScopedThreadStateChange tsc(self, kNative);
259 fn(soa.Env(), rcvr.get());
Ian Rogers64b6d142012-10-29 16:34:15 -0700260 } else if (shorty == "LL") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100261 typedef jobject (fntype)(JNIEnv*, jobject, jobject);
262 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700263 ScopedLocalRef<jobject> rcvr(soa.Env(),
264 soa.AddLocalReference<jobject>(receiver));
265 ScopedLocalRef<jobject> arg0(soa.Env(),
Jeff Hao5d917302013-02-27 17:57:33 -0800266 soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
Ian Rogers556d6372012-11-20 12:19:36 -0800267 jobject jresult;
268 {
269 ScopedThreadStateChange tsc(self, kNative);
270 jresult = fn(soa.Env(), rcvr.get(), arg0.get());
Ian Rogers556d6372012-11-20 12:19:36 -0800271 }
272 result->SetL(soa.Decode<Object*>(jresult));
Ian Rogers64b6d142012-10-29 16:34:15 -0700273 ScopedThreadStateChange tsc(self, kNative);
Ian Rogers64b6d142012-10-29 16:34:15 -0700274 } else if (shorty == "III") {
Bernhard Rosenkränzer46053622013-12-12 02:15:52 +0100275 typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
276 fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
Ian Rogers64b6d142012-10-29 16:34:15 -0700277 ScopedLocalRef<jobject> rcvr(soa.Env(),
278 soa.AddLocalReference<jobject>(receiver));
279 ScopedThreadStateChange tsc(self, kNative);
Jeff Hao5d917302013-02-27 17:57:33 -0800280 result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
Ian Rogers64b6d142012-10-29 16:34:15 -0700281 } else {
282 LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
283 << " shorty: " << shorty;
284 }
285 }
286}
287
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200288enum InterpreterImplKind {
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800289 kSwitchImpl, // Switch-based interpreter implementation.
290 kComputedGotoImplKind // Computed-goto-based interpreter implementation.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200291};
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700292
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800293#if !defined(__clang__)
294static constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
295#else
296// Clang 3.4 fails to build the goto interpreter implementation.
297static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImpl;
298template<bool do_access_check, bool transaction_active>
299JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
300 ShadowFrame& shadow_frame, JValue result_register) {
301 LOG(FATAL) << "UNREACHABLE";
302 exit(0);
303}
304// Explicit definitions of ExecuteGotoImpl.
Stephen Hines861ea562014-04-23 16:03:57 -0700305template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800306JValue ExecuteGotoImpl<true, false>(Thread* self, MethodHelper& mh,
307 const DexFile::CodeItem* code_item,
308 ShadowFrame& shadow_frame, JValue result_register);
Stephen Hines861ea562014-04-23 16:03:57 -0700309template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800310JValue ExecuteGotoImpl<false, false>(Thread* self, MethodHelper& mh,
311 const DexFile::CodeItem* code_item,
312 ShadowFrame& shadow_frame, JValue result_register);
Stephen Hines861ea562014-04-23 16:03:57 -0700313template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800314JValue ExecuteGotoImpl<true, true>(Thread* self, MethodHelper& mh,
315 const DexFile::CodeItem* code_item,
316 ShadowFrame& shadow_frame, JValue result_register);
Stephen Hines861ea562014-04-23 16:03:57 -0700317template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800318JValue ExecuteGotoImpl<false, true>(Thread* self, MethodHelper& mh,
319 const DexFile::CodeItem* code_item,
320 ShadowFrame& shadow_frame, JValue result_register);
321#endif
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700322
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200323static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
324 ShadowFrame& shadow_frame, JValue result_register)
325 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
326
327static inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
328 ShadowFrame& shadow_frame, JValue result_register) {
Ian Rogers848871b2013-08-05 10:56:33 -0700329 DCHECK(shadow_frame.GetMethod() == mh.GetMethod() ||
330 shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass());
331 DCHECK(!shadow_frame.GetMethod()->IsAbstract());
332 DCHECK(!shadow_frame.GetMethod()->IsNative());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200333
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100334 bool transaction_active = Runtime::Current()->IsActiveTransaction();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200335 if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) {
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200336 // Enter the "without access check" interpreter.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200337 if (kInterpreterImplKind == kSwitchImpl) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100338 if (transaction_active) {
339 return ExecuteSwitchImpl<false, true>(self, mh, code_item, shadow_frame, result_register);
340 } else {
341 return ExecuteSwitchImpl<false, false>(self, mh, code_item, shadow_frame, result_register);
342 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200343 } else {
344 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100345 if (transaction_active) {
346 return ExecuteGotoImpl<false, true>(self, mh, code_item, shadow_frame, result_register);
347 } else {
348 return ExecuteGotoImpl<false, false>(self, mh, code_item, shadow_frame, result_register);
349 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200350 }
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200351 } else {
352 // Enter the "with access check" interpreter.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200353 if (kInterpreterImplKind == kSwitchImpl) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100354 if (transaction_active) {
355 return ExecuteSwitchImpl<true, true>(self, mh, code_item, shadow_frame, result_register);
356 } else {
357 return ExecuteSwitchImpl<true, false>(self, mh, code_item, shadow_frame, result_register);
358 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200359 } else {
360 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100361 if (transaction_active) {
362 return ExecuteGotoImpl<true, true>(self, mh, code_item, shadow_frame, result_register);
363 } else {
364 return ExecuteGotoImpl<true, false>(self, mh, code_item, shadow_frame, result_register);
365 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200366 }
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200367 }
368}
369
Brian Carlstromea46f952013-07-30 01:26:50 -0700370void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
Jeff Hao6474d192013-03-26 14:08:09 -0700371 uint32_t* args, JValue* result) {
Ian Rogers64b6d142012-10-29 16:34:15 -0700372 DCHECK_EQ(self, Thread::Current());
Jeff Hao790ad902013-05-22 15:02:08 -0700373 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
jeffhaod7521322012-11-21 15:38:24 -0800374 ThrowStackOverflowError(self);
375 return;
376 }
377
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700378 const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700379 MethodHelper mh(method);
380 const DexFile::CodeItem* code_item = mh.GetCodeItem();
381 uint16_t num_regs;
382 uint16_t num_ins;
383 if (code_item != NULL) {
384 num_regs = code_item->registers_size_;
385 num_ins = code_item->ins_size_;
jeffhao0a9bb732012-11-26 12:28:49 -0800386 } else if (method->IsAbstract()) {
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700387 self->EndAssertNoThreadSuspension(old_cause);
Sebastien Hertz56adf602013-07-09 17:27:07 +0200388 ThrowAbstractMethodError(method);
jeffhao0a9bb732012-11-26 12:28:49 -0800389 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700390 } else {
391 DCHECK(method->IsNative());
Brian Carlstromea46f952013-07-30 01:26:50 -0700392 num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700393 if (!method->IsStatic()) {
394 num_regs++;
395 num_ins++;
396 }
397 }
398 // Set up shadow frame with matching number of reference slots to vregs.
399 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
Jeff Hao66135192013-05-14 11:02:41 -0700400 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
401 ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
402 self->PushShadowFrame(shadow_frame);
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700403
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700404 size_t cur_reg = num_regs - num_ins;
405 if (!method->IsStatic()) {
406 CHECK(receiver != NULL);
TDYa127ce4cc0d2012-11-18 16:59:53 -0800407 shadow_frame->SetVRegReference(cur_reg, receiver);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700408 ++cur_reg;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700409 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700410 const char* shorty = mh.GetShorty();
Jeff Hao5d917302013-02-27 17:57:33 -0800411 for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
412 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
413 switch (shorty[shorty_pos + 1]) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700414 case 'L': {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800415 Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
TDYa127ce4cc0d2012-11-18 16:59:53 -0800416 shadow_frame->SetVRegReference(cur_reg, o);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700417 break;
418 }
Jeff Hao5d917302013-02-27 17:57:33 -0800419 case 'J': case 'D': {
420 uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
421 shadow_frame->SetVRegLong(cur_reg, wide_value);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700422 cur_reg++;
Jeff Hao5d917302013-02-27 17:57:33 -0800423 arg_pos++;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700424 break;
Jeff Hao5d917302013-02-27 17:57:33 -0800425 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700426 default:
Jeff Hao5d917302013-02-27 17:57:33 -0800427 shadow_frame->SetVReg(cur_reg, args[arg_pos]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700428 break;
429 }
430 }
Mathieu Chartier92246bb2014-02-25 18:22:39 -0800431 self->EndAssertNoThreadSuspension(old_cause);
432 // Do this after populating the shadow frame in case EnsureInitialized causes a GC.
433 if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
434 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
435 SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
436 if (UNLIKELY(!class_linker->EnsureInitialized(sirt_c, true, true))) {
437 CHECK(self->IsExceptionPending());
438 self->PopShadowFrame();
439 return;
440 }
441 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700442 if (LIKELY(!method->IsNative())) {
Jeff Hao66135192013-05-14 11:02:41 -0700443 JValue r = Execute(self, mh, code_item, *shadow_frame, JValue());
Jeff Hao6474d192013-03-26 14:08:09 -0700444 if (result != NULL) {
445 *result = r;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700446 }
447 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -0700448 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
449 // generated stub) except during testing and image writing.
Mathieu Chartier92246bb2014-02-25 18:22:39 -0800450 // Update args to be the args in the shadow frame since the input ones could hold stale
451 // references pointers due to moving GC.
452 args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
Ian Rogers64b6d142012-10-29 16:34:15 -0700453 if (!Runtime::Current()->IsStarted()) {
Jeff Hao6474d192013-03-26 14:08:09 -0700454 UnstartedRuntimeJni(self, method, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700455 } else {
Jeff Hao6474d192013-03-26 14:08:09 -0700456 InterpreterJni(self, method, shorty, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700457 }
458 }
459 self->PopShadowFrame();
460}
461
Ian Rogers62d6c772013-02-27 08:32:07 -0800462void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800463 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
464 JValue value;
Ian Rogers62d6c772013-02-27 08:32:07 -0800465 value.SetJ(ret_val->GetJ()); // Set value to last known result in case the shadow frame chain is empty.
466 MethodHelper mh;
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800467 while (shadow_frame != NULL) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800468 self->SetTopOfShadowStack(shadow_frame);
469 mh.ChangeMethod(shadow_frame->GetMethod());
470 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800471 value = Execute(self, mh, code_item, *shadow_frame, value);
472 ShadowFrame* old_frame = shadow_frame;
473 shadow_frame = shadow_frame->GetLink();
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800474 delete old_frame;
475 }
476 ret_val->SetJ(value.GetJ());
477}
478
Ian Rogers7db619b2013-01-16 18:35:48 -0800479JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
Ian Rogers848871b2013-08-05 10:56:33 -0700480 ShadowFrame& shadow_frame) {
Ian Rogersf3e98552013-03-20 15:49:49 -0700481 DCHECK_EQ(self, Thread::Current());
Jeff Hao790ad902013-05-22 15:02:08 -0700482 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
Ian Rogersf3e98552013-03-20 15:49:49 -0700483 ThrowStackOverflowError(self);
484 return JValue();
485 }
486
Ian Rogers7db619b2013-01-16 18:35:48 -0800487 return Execute(self, mh, code_item, shadow_frame, JValue());
488}
489
Ian Rogers848871b2013-08-05 10:56:33 -0700490extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
491 const DexFile::CodeItem* code_item,
492 ShadowFrame* shadow_frame, JValue* result) {
Jeff Hao790ad902013-05-22 15:02:08 -0700493 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
Jeff Hao16743632013-05-08 10:59:04 -0700494 ThrowStackOverflowError(self);
Jeff Hao69510672013-05-21 17:34:55 -0700495 return;
Jeff Hao16743632013-05-08 10:59:04 -0700496 }
497
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700498 self->PushShadowFrame(shadow_frame);
Brian Carlstromea46f952013-07-30 01:26:50 -0700499 ArtMethod* method = shadow_frame->GetMethod();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200500 // Ensure static methods are initialized.
501 if (method->IsStatic()) {
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800502 SirtRef<Class> declaringClass(self, method->GetDeclaringClass());
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200503 if (UNLIKELY(!declaringClass->IsInitializing())) {
Mathieu Chartier590fee92013-09-13 13:46:47 -0700504 if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass, true,
505 true))) {
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200506 DCHECK(Thread::Current()->IsExceptionPending());
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700507 self->PopShadowFrame();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200508 return;
509 }
510 CHECK(declaringClass->IsInitializing());
Jeff Hao16743632013-05-08 10:59:04 -0700511 }
Jeff Hao16743632013-05-08 10:59:04 -0700512 }
Jeff Hao16743632013-05-08 10:59:04 -0700513
Jeff Hao16743632013-05-08 10:59:04 -0700514 if (LIKELY(!method->IsNative())) {
Jeff Hao69510672013-05-21 17:34:55 -0700515 result->SetJ(Execute(self, mh, code_item, *shadow_frame, JValue()).GetJ());
Jeff Hao16743632013-05-08 10:59:04 -0700516 } else {
517 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
518 // generated stub) except during testing and image writing.
519 CHECK(!Runtime::Current()->IsStarted());
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700520 Object* receiver = method->IsStatic() ? nullptr : shadow_frame->GetVRegReference(0);
Jeff Hao16743632013-05-08 10:59:04 -0700521 uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
Jeff Hao69510672013-05-21 17:34:55 -0700522 UnstartedRuntimeJni(self, method, receiver, args, result);
Jeff Hao16743632013-05-08 10:59:04 -0700523 }
524
525 self->PopShadowFrame();
Jeff Hao16743632013-05-08 10:59:04 -0700526}
527
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700528} // namespace interpreter
529} // namespace art