interpreter.cc revision 3cfa4d05afa76e19ca99ec964b535a15c73683f0
12fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers/*
22fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * Copyright (C) 2012 The Android Open Source Project
32fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *
42fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * Licensed under the Apache License, Version 2.0 (the "License");
52fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * you may not use this file except in compliance with the License.
62fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * You may obtain a copy of the License at
72fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *
82fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *      http://www.apache.org/licenses/LICENSE-2.0
92fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers *
102fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * Unless required by applicable law or agreed to in writing, software
112fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * distributed under the License is distributed on an "AS IS" BASIS,
122fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * See the License for the specific language governing permissions and
142fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers * limitations under the License.
152fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers */
162fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
173cfa4d05afa76e19ca99ec964b535a15c73683f0Andreas Gampe#include "interpreter.h"
18b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers
19d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include <limits>
202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
213cfa4d05afa76e19ca99ec964b535a15c73683f0Andreas Gampe#include "interpreter_common.h"
22b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
232969bcdcd80624e4a4fef696b54c2c76b44b6853Andreas Gampe#include "scoped_thread_state_change.h"
242969bcdcd80624e4a4fef696b54c2c76b44b6853Andreas Gampe#include "ScopedLocalRef.h"
25b30259251b22430fad12f1adeab671e4bf8f88f5Andreas Gampe#include "stack.h"
262969bcdcd80624e4a4fef696b54c2c76b44b6853Andreas Gampe#include "unstarted_runtime.h"
27b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers
282fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace art {
292fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace interpreter {
302fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
31fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogersstatic void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
325d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                           Object* receiver, uint32_t* args, JValue* result)
3390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
3464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
3564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  //       it should be removed and JNI compiled stubs used instead.
3664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  ScopedObjectAccessUnchecked soa(self);
3764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (method->IsStatic()) {
3864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
39460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jclass);
402d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
4164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
4264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
43556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
44556d637764b71563030c479bc35364a75188d559Ian Rogers      {
45556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
46556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get());
47556d637764b71563030c479bc35364a75188d559Ian Rogers      }
48556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
4964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "V") {
50460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass);
512d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
5264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
5364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
5464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
5564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      fn(soa.Env(), klass.get());
5664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "Z") {
57460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass);
582d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
5964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
6064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
6164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
6264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get()));
6364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "BI") {
64460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jbyte (fntype)(JNIEnv*, jclass, jint);
652d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
6664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
6764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
6864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
695d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetB(fn(soa.Env(), klass.get(), args[0]));
7064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "II") {
71460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jint);
722d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
7364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
7464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
7564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
765d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0]));
7764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
78460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jclass, jobject);
792d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
8064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
8164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
8264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
832cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
842cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[0])));
85556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
86556d637764b71563030c479bc35364a75188d559Ian Rogers      {
87556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
88556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get(), arg0.get());
89556d637764b71563030c479bc35364a75188d559Ian Rogers      }
90556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
9164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "IIZ") {
92460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
932d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
9464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
9564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
9664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
975d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
9864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ILI") {
99460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jobject, jint);
1002d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(
1012d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier          method->GetEntryPointFromJni()));
10264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
10364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
10464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1062cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[0])));
10764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1085d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
10964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "SIZ") {
110460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean);
1112cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      fntype* const fn =
1122cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier          reinterpret_cast<fntype*>(const_cast<void*>(method->GetEntryPointFromJni()));
11364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
11464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
11564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1165d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
11764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VIZ") {
118460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jint, jboolean);
1192d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
12064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
12164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
12264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1235d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], args[1]);
12464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZLL") {
125460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject);
1262d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
12764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
12864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
12964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1302cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1312cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[0])));
13264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
1332cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1342cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[1])));
13564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
13664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
13764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZILL") {
138460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject);
1392d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
14064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
14164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
14264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
1432cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1442cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[1])));
14564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
1462cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1472cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[2])));
14864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1495d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
15064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VILII") {
151460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint);
1522d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
15364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
15464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
15564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
1562cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1572cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[1])));
15864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1595d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
16064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VLILII") {
161460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
1622d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
16364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
16464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
16564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1662cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1672cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[0])));
16864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
1692cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
1702cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[2])));
17164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1725d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
17364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
17464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
17564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
17664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
17764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else {
17864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
179460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jobject);
1802d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
18164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
18264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
183556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
184556d637764b71563030c479bc35364a75188d559Ian Rogers      {
185556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
186556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get());
187556d637764b71563030c479bc35364a75188d559Ian Rogers      }
188556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
1893dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao    } else if (shorty == "V") {
190460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jobject);
1912d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
1923dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedLocalRef<jobject> rcvr(soa.Env(),
1933dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao                                   soa.AddLocalReference<jobject>(receiver));
1943dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedThreadStateChange tsc(self, kNative);
1953dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      fn(soa.Env(), rcvr.get());
19664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
197460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jobject, jobject);
1982d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
19964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
20064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
20164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2022cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                   soa.AddLocalReference<jobject>(
2032cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier                                       reinterpret_cast<Object*>(args[0])));
204556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
205556d637764b71563030c479bc35364a75188d559Ian Rogers      {
206556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
207556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get(), arg0.get());
208556d637764b71563030c479bc35364a75188d559Ian Rogers      }
209556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
21064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
21164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "III") {
212460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
2132d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
21464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
21564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
21664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2175d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
21864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
21964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
22064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
22164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
22264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  }
22364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers}
22464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
2258ece050d85fc244c72610244e440b0e00aa618faSebastien Hertzenum InterpreterImplKind {
226b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers  kSwitchImpl,            // Switch-based interpreter implementation.
227b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers  kComputedGotoImplKind   // Computed-goto-based interpreter implementation.
2288ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz};
229277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampestatic std::ostream& operator<<(std::ostream& os, const InterpreterImplKind& rhs) {
2306a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  os << ((rhs == kSwitchImpl) ? "Switch-based interpreter" : "Computed-goto-based interpreter");
2316a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  return os;
2326a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers}
233fa46d3ee8cba2985c5c8bdfe47d15daf0613ebdcIan Rogers
234fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz#if !defined(__clang__)
235b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogersstatic constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
236fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz#else
237fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz// Clang 3.4 fails to build the goto interpreter implementation.
238fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertzstatic constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImpl;
239fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertztemplate<bool do_access_check, bool transaction_active>
240e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) {
241fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz  LOG(FATAL) << "UNREACHABLE";
2422c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers  UNREACHABLE();
243fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz}
244fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz// Explicit definitions of ExecuteGotoImpl.
24590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartiertemplate<> SHARED_REQUIRES(Locks::mutator_lock_)
246e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item,
247fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz                                    ShadowFrame& shadow_frame, JValue result_register);
24890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartiertemplate<> SHARED_REQUIRES(Locks::mutator_lock_)
249e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item,
250fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz                                     ShadowFrame& shadow_frame, JValue result_register);
25190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartiertemplate<> SHARED_REQUIRES(Locks::mutator_lock_)
252e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<true, true>(Thread* self,  const DexFile::CodeItem* code_item,
253e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers                                   ShadowFrame& shadow_frame, JValue result_register);
25490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartiertemplate<> SHARED_REQUIRES(Locks::mutator_lock_)
255e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item,
256e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers                                    ShadowFrame& shadow_frame, JValue result_register);
257fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz#endif
2582fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
259e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogersstatic JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame,
260e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers                      JValue result_register)
26190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_);
262233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
263e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogersstatic inline JValue Execute(Thread* self, const DexFile::CodeItem* code_item,
264233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz                             ShadowFrame& shadow_frame, JValue result_register) {
265848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsAbstract());
266848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsNative());
2674e99b3d8955131f3fc71aa113f0fa71f0092cb6fSebastien Hertz  shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
2688ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz
269d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  bool transaction_active = Runtime::Current()->IsActiveTransaction();
2708ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) {
271233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "without access check" interpreter.
2728ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
273d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
274e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register);
275d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
276e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register);
277d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
2788ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
2798ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
280d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
281e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<false, true>(self, code_item, shadow_frame, result_register);
282d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
283e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register);
284d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
2858ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
286233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  } else {
287233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "with access check" interpreter.
2888ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
289d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
290e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register);
291d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
292e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register);
293d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
2948ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
2958ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
296d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
297e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<true, true>(self, code_item, shadow_frame, result_register);
298d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
299e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<true, false>(self, code_item, shadow_frame, result_register);
300d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3018ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
302233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  }
303233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz}
304233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
305ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
3066474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao                                uint32_t* args, JValue* result) {
30764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  DCHECK_EQ(self, Thread::Current());
308535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
309535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
310d752132c73072084a3def9257cca4fcee76047b6jeffhao    ThrowStackOverflowError(self);
311d752132c73072084a3def9257cca4fcee76047b6jeffhao    return;
312d752132c73072084a3def9257cca4fcee76047b6jeffhao  }
313d752132c73072084a3def9257cca4fcee76047b6jeffhao
314e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
315bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const DexFile::CodeItem* code_item = method->GetCodeItem();
3162fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_regs;
3172fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_ins;
3182cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (code_item != nullptr) {
3192fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_regs =  code_item->registers_size_;
3202fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_ins = code_item->ins_size_;
3210a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao  } else if (method->IsAbstract()) {
322e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    self->EndAssertNoThreadSuspension(old_cause);
32356adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz    ThrowAbstractMethodError(method);
3240a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao    return;
3252fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
3262fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    DCHECK(method->IsNative());
327bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty());
3282fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    if (!method->IsStatic()) {
3292fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_regs++;
3302fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_ins++;
3312fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3322fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
3332fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  // Set up shadow frame with matching number of reference slots to vregs.
3342fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
335b30259251b22430fad12f1adeab671e4bf8f88f5Andreas Gampe  ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
336b30259251b22430fad12f1adeab671e4bf8f88f5Andreas Gampe      CREATE_SHADOW_FRAME(num_regs, last_shadow_frame, method, 0);
337b30259251b22430fad12f1adeab671e4bf8f88f5Andreas Gampe  ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
3386613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  self->PushShadowFrame(shadow_frame);
339e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier
3402fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  size_t cur_reg = num_regs - num_ins;
3412fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (!method->IsStatic()) {
3422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    CHECK(receiver != nullptr);
343ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    shadow_frame->SetVRegReference(cur_reg, receiver);
3442fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    ++cur_reg;
3452fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
346bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  uint32_t shorty_len = 0;
347bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const char* shorty = method->GetShorty(&shorty_len);
3485d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao  for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
349bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    DCHECK_LT(shorty_pos + 1, shorty_len);
3505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    switch (shorty[shorty_pos + 1]) {
3512fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      case 'L': {
352ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
353ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa        shadow_frame->SetVRegReference(cur_reg, o);
3542fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
3552fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      }
3565d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      case 'J': case 'D': {
3575d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
3585d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVRegLong(cur_reg, wide_value);
3592fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        cur_reg++;
3605d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        arg_pos++;
3612fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
3625d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      }
3632fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      default:
3645d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVReg(cur_reg, args[arg_pos]);
3652fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
3662fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3672fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
36892246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier  self->EndAssertNoThreadSuspension(old_cause);
36992246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier  // Do this after populating the shadow frame in case EnsureInitialized causes a GC.
3706c5cb212fa7010ae7caf9dc765533aa967c95342Ian Rogers  if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitialized())) {
37192246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
372eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<1> hs(self);
373eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
3747b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers    if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) {
37592246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier      CHECK(self->IsExceptionPending());
37692246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier      self->PopShadowFrame();
37792246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier      return;
37892246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    }
37992246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier  }
38064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (LIKELY(!method->IsNative())) {
381e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    JValue r = Execute(self, code_item, *shadow_frame, JValue());
3822cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    if (result != nullptr) {
3836474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      *result = r;
3842fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3852fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
38664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
38764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // generated stub) except during testing and image writing.
38892246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    // Update args to be the args in the shadow frame since the input ones could hold stale
38992246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    // references pointers due to moving GC.
39092246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
39164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (!Runtime::Current()->IsStarted()) {
392799681b176ad25437ce2849639f54f610dcbf684Andreas Gampe      UnstartedRuntime::Jni(self, method, receiver, args, result);
3932fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    } else {
3946474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      InterpreterJni(self, method, shorty, receiver, args, result);
3952fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3962fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
3972fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  self->PopShadowFrame();
3982fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}
3992fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
40062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
40190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier    SHARED_REQUIRES(Locks::mutator_lock_) {
40211ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  JValue value;
4032cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Set value to last known result in case the shadow frame chain is empty.
4042cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  value.SetJ(ret_val->GetJ());
405520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  // Are we executing the first shadow frame?
406520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz  bool first = true;
4072cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  while (shadow_frame != nullptr) {
40862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    self->SetTopOfShadowStack(shadow_frame);
409e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem();
410270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    const uint32_t dex_pc = shadow_frame->GetDexPC();
411270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    uint32_t new_dex_pc;
412270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    if (UNLIKELY(self->IsExceptionPending())) {
413520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // If we deoptimize from the QuickExceptionHandler, we already reported the exception to
414520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // the instrumentation. To prevent from reporting it a second time, we simply pass a
415520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz      // null Instrumentation*.
416270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      const instrumentation::Instrumentation* const instrumentation =
417520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz          first ? nullptr : Runtime::Current()->GetInstrumentation();
418270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc,
419270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz                                                                    instrumentation);
420270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      new_dex_pc = found_dex_pc;  // the dex pc of a matching catch handler
421270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz                                  // or DexFile::kDexNoIndex if there is none.
422270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    } else {
423270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
424d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang      // For an invoke, use the dex pc of the next instruction.
425d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang      // TODO: should be tested more once b/17586779 is fixed.
426d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang      new_dex_pc = dex_pc + (instr->IsInvoke() ? instr->SizeInCodeUnits() : 0);
427270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    }
428270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    if (new_dex_pc != DexFile::kDexNoIndex) {
429270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      shadow_frame->SetDexPC(new_dex_pc);
430270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      value = Execute(self, code_item, *shadow_frame, value);
431270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    }
43211ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    ShadowFrame* old_frame = shadow_frame;
43311ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    shadow_frame = shadow_frame->GetLink();
434241a9588c6d7d0fcb4c92da40c7141863930083aChristopher Ferris    ShadowFrame::DeleteDeoptimizedFrame(old_frame);
435520633bebd2bf4d70884d30f179dbde9f275aac6Sebastien Hertz    first = false;
43611ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  }
43711ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  ret_val->SetJ(value.GetJ());
43811ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao}
43911ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao
440e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item,
4416f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                                      ShadowFrame* shadow_frame) {
442f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  DCHECK_EQ(self, Thread::Current());
443535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
444535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
445f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    ThrowStackOverflowError(self);
446f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    return JValue();
447f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  }
448f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers
449e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  return Execute(self, code_item, *shadow_frame, JValue());
4507db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers}
4517db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers
4523cfa4d05afa76e19ca99ec964b535a15c73683f0Andreas Gampevoid ArtInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* code_item,
4533cfa4d05afa76e19ca99ec964b535a15c73683f0Andreas Gampe                                       ShadowFrame* shadow_frame, JValue* result) {
454535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
455535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
456167436311a08a65dea28dda079a137893821c9c7Jeff Hao    ThrowStackOverflowError(self);
4576951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    return;
458167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
459167436311a08a65dea28dda079a137893821c9c7Jeff Hao
460e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  self->PushShadowFrame(shadow_frame);
461c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz  // Ensure static methods are initialized.
462e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  const bool is_static = shadow_frame->GetMethod()->IsStatic();
463e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  if (is_static) {
464e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    mirror::Class* declaring_class = shadow_frame->GetMethod()->GetDeclaringClass();
4656c5cb212fa7010ae7caf9dc765533aa967c95342Ian Rogers    if (UNLIKELY(!declaring_class->IsInitialized())) {
4660cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      StackHandleScope<1> hs(self);
4670cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      HandleWrapper<Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class));
4680cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
4697b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers          self, h_declaring_class, true, true))) {
4700cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier        DCHECK(self->IsExceptionPending());
471e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier        self->PopShadowFrame();
472c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz        return;
473c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz      }
4740cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      CHECK(h_declaring_class->IsInitializing());
475167436311a08a65dea28dda079a137893821c9c7Jeff Hao    }
476167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
477167436311a08a65dea28dda079a137893821c9c7Jeff Hao
478e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  if (LIKELY(!shadow_frame->GetMethod()->IsNative())) {
479e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ());
480167436311a08a65dea28dda079a137893821c9c7Jeff Hao  } else {
481167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
482167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // generated stub) except during testing and image writing.
483167436311a08a65dea28dda079a137893821c9c7Jeff Hao    CHECK(!Runtime::Current()->IsStarted());
484e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    Object* receiver = is_static ? nullptr : shadow_frame->GetVRegReference(0);
485e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    uint32_t* args = shadow_frame->GetVRegArgs(is_static ? 0 : 1);
486799681b176ad25437ce2849639f54f610dcbf684Andreas Gampe    UnstartedRuntime::Jni(self, shadow_frame->GetMethod(), receiver, args, result);
487167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
488167436311a08a65dea28dda079a137893821c9c7Jeff Hao
489167436311a08a65dea28dda079a137893821c9c7Jeff Hao  self->PopShadowFrame();
490167436311a08a65dea28dda079a137893821c9c7Jeff Hao}
491167436311a08a65dea28dda079a137893821c9c7Jeff Hao
4922fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace interpreter
4932fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace art
494