blob: cb9e2e8409bdf6d07592d7680830caaf58ad02fa [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);
71 result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace(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.
99 ThrowLocation throw_location;
100 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 {
289 kSwitchImpl, // switch-based interpreter implementation.
290 kComputedGotoImplKind // computed-goto-based interpreter implementation.
291};
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700292
Sebastien Hertz2c88b382013-10-18 10:35:39 +0200293static const InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700294
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200295static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
296 ShadowFrame& shadow_frame, JValue result_register)
297 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
298
299static inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
300 ShadowFrame& shadow_frame, JValue result_register) {
Ian Rogers848871b2013-08-05 10:56:33 -0700301 DCHECK(shadow_frame.GetMethod() == mh.GetMethod() ||
302 shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass());
303 DCHECK(!shadow_frame.GetMethod()->IsAbstract());
304 DCHECK(!shadow_frame.GetMethod()->IsNative());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200305
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100306 bool transaction_active = Runtime::Current()->IsActiveTransaction();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200307 if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) {
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200308 // Enter the "without access check" interpreter.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200309 if (kInterpreterImplKind == kSwitchImpl) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100310 if (transaction_active) {
311 return ExecuteSwitchImpl<false, true>(self, mh, code_item, shadow_frame, result_register);
312 } else {
313 return ExecuteSwitchImpl<false, false>(self, mh, code_item, shadow_frame, result_register);
314 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200315 } else {
316 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100317 if (transaction_active) {
318 return ExecuteGotoImpl<false, true>(self, mh, code_item, shadow_frame, result_register);
319 } else {
320 return ExecuteGotoImpl<false, false>(self, mh, code_item, shadow_frame, result_register);
321 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200322 }
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200323 } else {
324 // Enter the "with access check" interpreter.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200325 if (kInterpreterImplKind == kSwitchImpl) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100326 if (transaction_active) {
327 return ExecuteSwitchImpl<true, true>(self, mh, code_item, shadow_frame, result_register);
328 } else {
329 return ExecuteSwitchImpl<true, false>(self, mh, code_item, shadow_frame, result_register);
330 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200331 } else {
332 DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100333 if (transaction_active) {
334 return ExecuteGotoImpl<true, true>(self, mh, code_item, shadow_frame, result_register);
335 } else {
336 return ExecuteGotoImpl<true, false>(self, mh, code_item, shadow_frame, result_register);
337 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200338 }
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200339 }
340}
341
Brian Carlstromea46f952013-07-30 01:26:50 -0700342void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
Jeff Hao6474d192013-03-26 14:08:09 -0700343 uint32_t* args, JValue* result) {
Ian Rogers64b6d142012-10-29 16:34:15 -0700344 DCHECK_EQ(self, Thread::Current());
Jeff Hao790ad902013-05-22 15:02:08 -0700345 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
jeffhaod7521322012-11-21 15:38:24 -0800346 ThrowStackOverflowError(self);
347 return;
348 }
349
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700350 const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700351 MethodHelper mh(method);
352 const DexFile::CodeItem* code_item = mh.GetCodeItem();
353 uint16_t num_regs;
354 uint16_t num_ins;
355 if (code_item != NULL) {
356 num_regs = code_item->registers_size_;
357 num_ins = code_item->ins_size_;
jeffhao0a9bb732012-11-26 12:28:49 -0800358 } else if (method->IsAbstract()) {
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700359 self->EndAssertNoThreadSuspension(old_cause);
Sebastien Hertz56adf602013-07-09 17:27:07 +0200360 ThrowAbstractMethodError(method);
jeffhao0a9bb732012-11-26 12:28:49 -0800361 return;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700362 } else {
363 DCHECK(method->IsNative());
Brian Carlstromea46f952013-07-30 01:26:50 -0700364 num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700365 if (!method->IsStatic()) {
366 num_regs++;
367 num_ins++;
368 }
369 }
370 // Set up shadow frame with matching number of reference slots to vregs.
371 ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
Jeff Hao66135192013-05-14 11:02:41 -0700372 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
373 ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
374 self->PushShadowFrame(shadow_frame);
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700375 self->EndAssertNoThreadSuspension(old_cause);
376
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700377 size_t cur_reg = num_regs - num_ins;
378 if (!method->IsStatic()) {
379 CHECK(receiver != NULL);
TDYa127ce4cc0d2012-11-18 16:59:53 -0800380 shadow_frame->SetVRegReference(cur_reg, receiver);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700381 ++cur_reg;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200382 } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
383 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800384 SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
385 if (UNLIKELY(!class_linker->EnsureInitialized(sirt_c, true, true))) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200386 CHECK(self->IsExceptionPending());
387 self->PopShadowFrame();
jeffhao94d6df42012-11-26 16:02:12 -0800388 return;
389 }
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800390 CHECK(sirt_c->IsInitializing());
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700391 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700392 const char* shorty = mh.GetShorty();
Jeff Hao5d917302013-02-27 17:57:33 -0800393 for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
394 DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
395 switch (shorty[shorty_pos + 1]) {
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700396 case 'L': {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800397 Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
TDYa127ce4cc0d2012-11-18 16:59:53 -0800398 shadow_frame->SetVRegReference(cur_reg, o);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700399 break;
400 }
Jeff Hao5d917302013-02-27 17:57:33 -0800401 case 'J': case 'D': {
402 uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
403 shadow_frame->SetVRegLong(cur_reg, wide_value);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700404 cur_reg++;
Jeff Hao5d917302013-02-27 17:57:33 -0800405 arg_pos++;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700406 break;
Jeff Hao5d917302013-02-27 17:57:33 -0800407 }
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700408 default:
Jeff Hao5d917302013-02-27 17:57:33 -0800409 shadow_frame->SetVReg(cur_reg, args[arg_pos]);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700410 break;
411 }
412 }
Ian Rogers64b6d142012-10-29 16:34:15 -0700413 if (LIKELY(!method->IsNative())) {
Jeff Hao66135192013-05-14 11:02:41 -0700414 JValue r = Execute(self, mh, code_item, *shadow_frame, JValue());
Jeff Hao6474d192013-03-26 14:08:09 -0700415 if (result != NULL) {
416 *result = r;
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700417 }
418 } else {
Ian Rogers64b6d142012-10-29 16:34:15 -0700419 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
420 // generated stub) except during testing and image writing.
421 if (!Runtime::Current()->IsStarted()) {
Jeff Hao6474d192013-03-26 14:08:09 -0700422 UnstartedRuntimeJni(self, method, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700423 } else {
Jeff Hao6474d192013-03-26 14:08:09 -0700424 InterpreterJni(self, method, shorty, receiver, args, result);
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700425 }
426 }
427 self->PopShadowFrame();
428}
429
Ian Rogers62d6c772013-02-27 08:32:07 -0800430void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800431 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
432 JValue value;
Ian Rogers62d6c772013-02-27 08:32:07 -0800433 value.SetJ(ret_val->GetJ()); // Set value to last known result in case the shadow frame chain is empty.
434 MethodHelper mh;
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800435 while (shadow_frame != NULL) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800436 self->SetTopOfShadowStack(shadow_frame);
437 mh.ChangeMethod(shadow_frame->GetMethod());
438 const DexFile::CodeItem* code_item = mh.GetCodeItem();
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800439 value = Execute(self, mh, code_item, *shadow_frame, value);
440 ShadowFrame* old_frame = shadow_frame;
441 shadow_frame = shadow_frame->GetLink();
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800442 delete old_frame;
443 }
444 ret_val->SetJ(value.GetJ());
445}
446
Ian Rogers7db619b2013-01-16 18:35:48 -0800447JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
Ian Rogers848871b2013-08-05 10:56:33 -0700448 ShadowFrame& shadow_frame) {
Ian Rogersf3e98552013-03-20 15:49:49 -0700449 DCHECK_EQ(self, Thread::Current());
Jeff Hao790ad902013-05-22 15:02:08 -0700450 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
Ian Rogersf3e98552013-03-20 15:49:49 -0700451 ThrowStackOverflowError(self);
452 return JValue();
453 }
454
Ian Rogers7db619b2013-01-16 18:35:48 -0800455 return Execute(self, mh, code_item, shadow_frame, JValue());
456}
457
Ian Rogers848871b2013-08-05 10:56:33 -0700458extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
459 const DexFile::CodeItem* code_item,
460 ShadowFrame* shadow_frame, JValue* result) {
Jeff Hao790ad902013-05-22 15:02:08 -0700461 if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
Jeff Hao16743632013-05-08 10:59:04 -0700462 ThrowStackOverflowError(self);
Jeff Hao69510672013-05-21 17:34:55 -0700463 return;
Jeff Hao16743632013-05-08 10:59:04 -0700464 }
465
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700466 self->PushShadowFrame(shadow_frame);
Brian Carlstromea46f952013-07-30 01:26:50 -0700467 ArtMethod* method = shadow_frame->GetMethod();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200468 // Ensure static methods are initialized.
469 if (method->IsStatic()) {
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800470 SirtRef<Class> declaringClass(self, method->GetDeclaringClass());
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200471 if (UNLIKELY(!declaringClass->IsInitializing())) {
Mathieu Chartier590fee92013-09-13 13:46:47 -0700472 if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass, true,
473 true))) {
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200474 DCHECK(Thread::Current()->IsExceptionPending());
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700475 self->PopShadowFrame();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200476 return;
477 }
478 CHECK(declaringClass->IsInitializing());
Jeff Hao16743632013-05-08 10:59:04 -0700479 }
Jeff Hao16743632013-05-08 10:59:04 -0700480 }
Jeff Hao16743632013-05-08 10:59:04 -0700481
Jeff Hao16743632013-05-08 10:59:04 -0700482 if (LIKELY(!method->IsNative())) {
Jeff Hao69510672013-05-21 17:34:55 -0700483 result->SetJ(Execute(self, mh, code_item, *shadow_frame, JValue()).GetJ());
Jeff Hao16743632013-05-08 10:59:04 -0700484 } else {
485 // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
486 // generated stub) except during testing and image writing.
487 CHECK(!Runtime::Current()->IsStarted());
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700488 Object* receiver = method->IsStatic() ? nullptr : shadow_frame->GetVRegReference(0);
Jeff Hao16743632013-05-08 10:59:04 -0700489 uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
Jeff Hao69510672013-05-21 17:34:55 -0700490 UnstartedRuntimeJni(self, method, receiver, args, result);
Jeff Hao16743632013-05-08 10:59:04 -0700491 }
492
493 self->PopShadowFrame();
Jeff Hao16743632013-05-08 10:59:04 -0700494}
495
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700496} // namespace interpreter
497} // namespace art