interpreter.cc revision 270a0e16c3b8e5b95cbfdbd8996ac137c7c6322b
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
178ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz#include "interpreter_common.h"
18b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers
19d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include <limits>
202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
21b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
22b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers
232fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace art {
242fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace interpreter {
252fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
2664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers// Hand select a number of methods to be run in a not yet started runtime without using JNI.
27ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic void UnstartedRuntimeJni(Thread* self, ArtMethod* method,
285d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                Object* receiver, uint32_t* args, JValue* result)
2964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  std::string name(PrettyMethod(method));
31a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers  if (name == "java.lang.Object dalvik.system.VMRuntime.newUnpaddedArray(java.lang.Class, int)") {
32a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers    int32_t length = args[1];
33a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers    DCHECK_GE(length, 0);
34a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers    mirror::Class* element_class = reinterpret_cast<Object*>(args[0])->AsClass();
35a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers    Runtime* runtime = Runtime::Current();
36b74cd29802f364b4cec88f4913fa38ade26b8fabMathieu Chartier    mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(self, &element_class);
37a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers    DCHECK(array_class != nullptr);
38a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers    gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
39f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchi    result->SetL(mirror::Array::Alloc<true, true>(self, array_class, length,
40f0edfc355893d53d1104b05501c99ad5ccf305c4Hiroshi Yamauchi                                                  array_class->GetComponentSizeShift(), allocator));
41a4e7413aa3420d54e41f37f286866a8025caa373Ian Rogers  } else if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") {
4264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(NULL);
4364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Class dalvik.system.VMStack.getStackClass2()") {
447a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers    NthCallerVisitor visitor(self, 3);
4564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    visitor.WalkStack();
4664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(visitor.caller->GetDeclaringClass());
4764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "double java.lang.Math.log(double)") {
485d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    JValue value;
495d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetD(log(value.GetD()));
5164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.String java.lang.Class.getNameNative()") {
52f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier    StackHandleScope<1> hs(self);
53f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier    result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
5464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
555d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(args[0]);
5664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "float java.lang.Float.intBitsToFloat(int)") {
575d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(args[0]);
5864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "double java.lang.Math.exp(double)") {
595d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    JValue value;
605d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
615d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetD(exp(value.GetD()));
6264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.Object.internalClone()") {
6364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->Clone(self));
6464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "void java.lang.Object.notifyAll()") {
6505f3057d6a4d23d712092ccd36a531590bff323bIan Rogers    receiver->NotifyAll(self);
6664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.String.compareTo(java.lang.String)") {
675d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    String* rhs = reinterpret_cast<Object*>(args[0])->AsString();
6864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    CHECK(rhs != NULL);
6964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetI(receiver->AsString()->CompareTo(rhs));
7064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.String java.lang.String.intern()") {
7164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->AsString()->Intern());
7264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.String.fastIndexOf(int, int)") {
735d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
7464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") {
75eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<2> hs(self);
76eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    auto h_class(hs.NewHandle(reinterpret_cast<mirror::Class*>(args[0])->AsClass()));
77eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    auto h_dimensions(hs.NewHandle(reinterpret_cast<mirror::IntArray*>(args[1])->AsIntArray()));
78eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    result->SetL(Array::CreateMultiArray(self, h_class, h_dimensions));
7964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") {
8064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    ScopedObjectAccessUnchecked soa(self);
815d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    if (Runtime::Current()->IsActiveTransaction()) {
825d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers      result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace<true>(soa)));
835d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    } else {
845d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers      result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace<false>(soa)));
855d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    }
86f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz  } else if (name == "int java.lang.System.identityHashCode(java.lang.Object)") {
87f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz    mirror::Object* obj = reinterpret_cast<Object*>(args[0]);
88f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz    result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
8964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "boolean java.nio.ByteOrder.isLittleEndian()") {
90f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz    result->SetZ(JNI_TRUE);
9164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
925d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* obj = reinterpret_cast<Object*>(args[0]);
935d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
945d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jint expectedValue = args[3];
955d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jint newValue = args[4];
965d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    bool success;
975d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    if (Runtime::Current()->IsActiveTransaction()) {
98d8434439dc64add41cdfa69ddf96b960af9050deHans Boehm      success = obj->CasFieldStrongSequentiallyConsistent32<true>(MemberOffset(offset),
99d8434439dc64add41cdfa69ddf96b960af9050deHans Boehm                                                                  expectedValue, newValue);
1005d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    } else {
101d8434439dc64add41cdfa69ddf96b960af9050deHans Boehm      success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
102d8434439dc64add41cdfa69ddf96b960af9050deHans Boehm                                                                   expectedValue, newValue);
1035d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    }
104f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz    result->SetZ(success ? JNI_TRUE : JNI_FALSE);
10564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
1065d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* obj = reinterpret_cast<Object*>(args[0]);
107f48644b6cfd35fd029fc85dc7c837ad19b4a5ba3Sebastien Hertz    jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
1085d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* newValue = reinterpret_cast<Object*>(args[3]);
1095d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    if (Runtime::Current()->IsActiveTransaction()) {
1105d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers      obj->SetFieldObject<true>(MemberOffset(offset), newValue);
1115d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    } else {
1125d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers      obj->SetFieldObject<false>(MemberOffset(offset), newValue);
1135d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    }
1144d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi  } else if (name == "int sun.misc.Unsafe.getArrayBaseOffsetForComponentType(java.lang.Class)") {
1154d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass();
1164d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    Primitive::Type primitive_type = component->GetPrimitiveType();
1174d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
1184d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi  } else if (name == "int sun.misc.Unsafe.getArrayIndexScaleForComponentType(java.lang.Class)") {
1194d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass();
1204d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    Primitive::Type primitive_type = component->GetPrimitiveType();
1214d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    result->SetI(Primitive::ComponentSize(primitive_type));
1225d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers  } else if (Runtime::Current()->IsActiveTransaction()) {
123b2c7ead6bb5c98282cdfbc89db8984a004bea030Mathieu Chartier    AbortTransaction(self, "Attempt to invoke native method in non-started runtime: %s",
124b2c7ead6bb5c98282cdfbc89db8984a004bea030Mathieu Chartier                     name.c_str());
1255d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers
1265d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers  } else {
1275d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers    LOG(FATAL) << "Calling native method " << PrettyMethod(method) << " in an unstarted "
1285d27fafdf03f259e92eaee9f6319b9349cc8d62eIan Rogers        "non-transactional runtime";
12964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  }
13064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers}
13164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
132fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogersstatic void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
1335d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                           Object* receiver, uint32_t* args, JValue* result)
13464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
13564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
13664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  //       it should be removed and JNI compiled stubs used instead.
13764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  ScopedObjectAccessUnchecked soa(self);
13864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (method->IsStatic()) {
13964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
140460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jclass);
1412d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
14264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
14364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
144556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
145556d637764b71563030c479bc35364a75188d559Ian Rogers      {
146556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
147556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get());
148556d637764b71563030c479bc35364a75188d559Ian Rogers      }
149556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
15064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "V") {
151460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass);
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      ScopedThreadStateChange tsc(self, kNative);
15664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      fn(soa.Env(), klass.get());
15764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "Z") {
158460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass);
1592d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
16064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
16164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
16264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
16364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get()));
16464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "BI") {
165460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jbyte (fntype)(JNIEnv*, jclass, jint);
1662d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
16764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
16864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
16964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1705d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetB(fn(soa.Env(), klass.get(), args[0]));
17164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "II") {
172460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jint);
1732d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
17464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
17564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
17664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1775d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0]));
17864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
179460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jclass, jobject);
1802d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
18164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
18264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
18364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1845d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
185556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
186556d637764b71563030c479bc35364a75188d559Ian Rogers      {
187556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
188556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get(), arg0.get());
189556d637764b71563030c479bc35364a75188d559Ian Rogers      }
190556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
19164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "IIZ") {
192460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
1932d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
19464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
19564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
19664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1975d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
19864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ILI") {
199460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jobject, jint);
2002d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(
2012d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier          method->GetEntryPointFromJni()));
20264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
20364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
20464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2055d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
20664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2075d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
20864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "SIZ") {
209460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean);
2102d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetEntryPointFromJni()));
21164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
21264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
21364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2145d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
21564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VIZ") {
216460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jint, jboolean);
2172d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
21864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
21964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
22064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2215d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], args[1]);
22264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZLL") {
223460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject);
2242d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
22564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
22664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
22764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2285d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
22964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
2305d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
23164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
23264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
23364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZILL") {
234460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject);
2352d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
23664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
23764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
23864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
2395d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
24064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
2415d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
24264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2435d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
24464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VILII") {
245460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint);
2462d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
24764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
24864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
24964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
2505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
25164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2525d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
25364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VLILII") {
254460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
2552d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
25664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
25764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
25864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2595d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
26064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
2615d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
26264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2635d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
26464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
26564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
26664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
26764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
26864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else {
26964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
270460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jobject);
2712d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
27264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
27364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
274556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
275556d637764b71563030c479bc35364a75188d559Ian Rogers      {
276556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
277556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get());
278556d637764b71563030c479bc35364a75188d559Ian Rogers      }
279556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
2803dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao    } else if (shorty == "V") {
281460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jobject);
2822d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
2833dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedLocalRef<jobject> rcvr(soa.Env(),
2843dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao                                   soa.AddLocalReference<jobject>(receiver));
2853dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedThreadStateChange tsc(self, kNative);
2863dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      fn(soa.Env(), rcvr.get());
28764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
288460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jobject, jobject);
2892d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
29064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
29164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
29264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2935d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
294556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
295556d637764b71563030c479bc35364a75188d559Ian Rogers      {
296556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
297556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get(), arg0.get());
298556d637764b71563030c479bc35364a75188d559Ian Rogers      }
299556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
30064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
30164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "III") {
302460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
3032d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      fntype* const fn = reinterpret_cast<fntype*>(method->GetEntryPointFromJni());
30464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
30564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
30664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
3075d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
30864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
30964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
31064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
31164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
31264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  }
31364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers}
31464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
3158ece050d85fc244c72610244e440b0e00aa618faSebastien Hertzenum InterpreterImplKind {
316b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers  kSwitchImpl,            // Switch-based interpreter implementation.
317b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers  kComputedGotoImplKind   // Computed-goto-based interpreter implementation.
3188ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz};
319277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampestatic std::ostream& operator<<(std::ostream& os, const InterpreterImplKind& rhs) {
3206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  os << ((rhs == kSwitchImpl) ? "Switch-based interpreter" : "Computed-goto-based interpreter");
3216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  return os;
3226a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers}
323fa46d3ee8cba2985c5c8bdfe47d15daf0613ebdcIan Rogers
324fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz#if !defined(__clang__)
325b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogersstatic constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
326fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz#else
327fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz// Clang 3.4 fails to build the goto interpreter implementation.
328fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertzstatic constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImpl;
329fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertztemplate<bool do_access_check, bool transaction_active>
330e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) {
331fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz  LOG(FATAL) << "UNREACHABLE";
3322c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers  UNREACHABLE();
333fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz}
334fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz// Explicit definitions of ExecuteGotoImpl.
335fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertztemplate<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
336e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item,
337fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz                                    ShadowFrame& shadow_frame, JValue result_register);
338fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertztemplate<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
339e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item,
340fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz                                     ShadowFrame& shadow_frame, JValue result_register);
341fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertztemplate<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
342e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<true, true>(Thread* self,  const DexFile::CodeItem* code_item,
343e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers                                   ShadowFrame& shadow_frame, JValue result_register);
344fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertztemplate<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
345e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item,
346e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers                                    ShadowFrame& shadow_frame, JValue result_register);
347fa888d06fd9ae90565254456e9b2e0cd62fbc91fSebastien Hertz#endif
3482fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
349e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogersstatic JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame,
350e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers                      JValue result_register)
351233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
352233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
353e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogersstatic inline JValue Execute(Thread* self, const DexFile::CodeItem* code_item,
354233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz                             ShadowFrame& shadow_frame, JValue result_register) {
355848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsAbstract());
356848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsNative());
3574e99b3d8955131f3fc71aa113f0fa71f0092cb6fSebastien Hertz  shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
3588ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz
359d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  bool transaction_active = Runtime::Current()->IsActiveTransaction();
3608ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) {
361233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "without access check" interpreter.
3628ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
363d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
364e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register);
365d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
366e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register);
367d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3688ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
3698ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
370d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
371e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<false, true>(self, code_item, shadow_frame, result_register);
372d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
373e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register);
374d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3758ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
376233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  } else {
377233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "with access check" interpreter.
3788ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
379d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
380e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register);
381d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
382e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register);
383d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3848ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
3858ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
386d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
387e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<true, true>(self, code_item, shadow_frame, result_register);
388d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
389e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers        return ExecuteGotoImpl<true, false>(self, code_item, shadow_frame, result_register);
390d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3918ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
392233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  }
393233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz}
394233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
395ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
3966474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao                                uint32_t* args, JValue* result) {
39764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  DCHECK_EQ(self, Thread::Current());
398535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
399535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
400d752132c73072084a3def9257cca4fcee76047b6jeffhao    ThrowStackOverflowError(self);
401d752132c73072084a3def9257cca4fcee76047b6jeffhao    return;
402d752132c73072084a3def9257cca4fcee76047b6jeffhao  }
403d752132c73072084a3def9257cca4fcee76047b6jeffhao
404e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
405bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const DexFile::CodeItem* code_item = method->GetCodeItem();
4062fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_regs;
4072fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_ins;
4082fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (code_item != NULL) {
4092fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_regs =  code_item->registers_size_;
4102fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_ins = code_item->ins_size_;
4110a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao  } else if (method->IsAbstract()) {
412e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    self->EndAssertNoThreadSuspension(old_cause);
41356adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz    ThrowAbstractMethodError(method);
4140a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao    return;
4152fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
4162fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    DCHECK(method->IsNative());
417bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty());
4182fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    if (!method->IsStatic()) {
4192fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_regs++;
4202fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_ins++;
4212fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
4222fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
4232fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  // Set up shadow frame with matching number of reference slots to vregs.
4242fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
4256613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
4266613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
4276613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  self->PushShadowFrame(shadow_frame);
428e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier
4292fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  size_t cur_reg = num_regs - num_ins;
4302fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (!method->IsStatic()) {
4312fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    CHECK(receiver != NULL);
432ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    shadow_frame->SetVRegReference(cur_reg, receiver);
4332fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    ++cur_reg;
4342fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
435bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  uint32_t shorty_len = 0;
436bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier  const char* shorty = method->GetShorty(&shorty_len);
4375d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao  for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
438bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier    DCHECK_LT(shorty_pos + 1, shorty_len);
4395d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    switch (shorty[shorty_pos + 1]) {
4402fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      case 'L': {
441ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
442ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa        shadow_frame->SetVRegReference(cur_reg, o);
4432fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
4442fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      }
4455d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      case 'J': case 'D': {
4465d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
4475d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVRegLong(cur_reg, wide_value);
4482fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        cur_reg++;
4495d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        arg_pos++;
4502fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
4515d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      }
4522fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      default:
4535d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVReg(cur_reg, args[arg_pos]);
4542fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
4552fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
4562fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
45792246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier  self->EndAssertNoThreadSuspension(old_cause);
45892246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier  // Do this after populating the shadow frame in case EnsureInitialized causes a GC.
4596c5cb212fa7010ae7caf9dc765533aa967c95342Ian Rogers  if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitialized())) {
46092246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
461eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<1> hs(self);
462eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
4637b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers    if (UNLIKELY(!class_linker->EnsureInitialized(self, h_class, true, true))) {
46492246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier      CHECK(self->IsExceptionPending());
46592246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier      self->PopShadowFrame();
46692246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier      return;
46792246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    }
46892246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier  }
46964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (LIKELY(!method->IsNative())) {
470e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    JValue r = Execute(self, code_item, *shadow_frame, JValue());
4716474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao    if (result != NULL) {
4726474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      *result = r;
4732fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
4742fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
47564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
47664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // generated stub) except during testing and image writing.
47792246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    // Update args to be the args in the shadow frame since the input ones could hold stale
47892246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    // references pointers due to moving GC.
47992246bb5d6caae4fdb09cd3c8c10d78e41932d45Mathieu Chartier    args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
48064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (!Runtime::Current()->IsStarted()) {
4816474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      UnstartedRuntimeJni(self, method, receiver, args, result);
4822fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    } else {
4836474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      InterpreterJni(self, method, shorty, receiver, args, result);
4842fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
4852fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
4862fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  self->PopShadowFrame();
4872fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}
4882fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
48962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
49011ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
49111ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  JValue value;
49262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  value.SetJ(ret_val->GetJ());  // Set value to last known result in case the shadow frame chain is empty.
49311ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  while (shadow_frame != NULL) {
49462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    self->SetTopOfShadowStack(shadow_frame);
495e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem();
496270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    const uint32_t dex_pc = shadow_frame->GetDexPC();
497270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    uint32_t new_dex_pc;
498270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    if (UNLIKELY(self->IsExceptionPending())) {
499270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      const instrumentation::Instrumentation* const instrumentation =
500270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz          Runtime::Current()->GetInstrumentation();
501270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      uint32_t found_dex_pc = FindNextInstructionFollowingException(self, *shadow_frame, dex_pc,
502270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz                                                                    instrumentation);
503270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      new_dex_pc = found_dex_pc;  // the dex pc of a matching catch handler
504270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz                                  // or DexFile::kDexNoIndex if there is none.
505270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    } else {
506270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
507270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      new_dex_pc = dex_pc + instr->SizeInCodeUnits();  // the dex pc of the next instruction.
508270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    }
509270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    if (new_dex_pc != DexFile::kDexNoIndex) {
510270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      shadow_frame->SetDexPC(new_dex_pc);
511270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz      value = Execute(self, code_item, *shadow_frame, value);
512270a0e16c3b8e5b95cbfdbd8996ac137c7c6322bSebastien Hertz    }
51311ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    ShadowFrame* old_frame = shadow_frame;
51411ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    shadow_frame = shadow_frame->GetLink();
51511ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    delete old_frame;
51611ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  }
51711ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  ret_val->SetJ(value.GetJ());
51811ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao}
51911ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao
520e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian RogersJValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item,
5216f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                                      ShadowFrame* shadow_frame) {
522f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  DCHECK_EQ(self, Thread::Current());
523535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
524535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
525f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    ThrowStackOverflowError(self);
526f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    return JValue();
527f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  }
528f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers
529e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  return Execute(self, code_item, *shadow_frame, JValue());
5307db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers}
5317db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers
532e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogersextern "C" void artInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* code_item,
533848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                                                  ShadowFrame* shadow_frame, JValue* result) {
534535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
535535a3fbc08e1577f43aec7402cab80c14ca64c41Nicolas Geoffray  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) {
536167436311a08a65dea28dda079a137893821c9c7Jeff Hao    ThrowStackOverflowError(self);
5376951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    return;
538167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
539167436311a08a65dea28dda079a137893821c9c7Jeff Hao
540e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  self->PushShadowFrame(shadow_frame);
541c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz  // Ensure static methods are initialized.
542e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  const bool is_static = shadow_frame->GetMethod()->IsStatic();
543e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  if (is_static) {
544e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    mirror::Class* declaring_class = shadow_frame->GetMethod()->GetDeclaringClass();
5456c5cb212fa7010ae7caf9dc765533aa967c95342Ian Rogers    if (UNLIKELY(!declaring_class->IsInitialized())) {
5460cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      StackHandleScope<1> hs(self);
5470cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      HandleWrapper<Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class));
5480cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
5497b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers          self, h_declaring_class, true, true))) {
5500cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier        DCHECK(self->IsExceptionPending());
551e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier        self->PopShadowFrame();
552c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz        return;
553c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz      }
5540cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier      CHECK(h_declaring_class->IsInitializing());
555167436311a08a65dea28dda079a137893821c9c7Jeff Hao    }
556167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
557167436311a08a65dea28dda079a137893821c9c7Jeff Hao
558e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers  if (LIKELY(!shadow_frame->GetMethod()->IsNative())) {
559e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ());
560167436311a08a65dea28dda079a137893821c9c7Jeff Hao  } else {
561167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
562167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // generated stub) except during testing and image writing.
563167436311a08a65dea28dda079a137893821c9c7Jeff Hao    CHECK(!Runtime::Current()->IsStarted());
564e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    Object* receiver = is_static ? nullptr : shadow_frame->GetVRegReference(0);
565e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    uint32_t* args = shadow_frame->GetVRegArgs(is_static ? 0 : 1);
566e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers    UnstartedRuntimeJni(self, shadow_frame->GetMethod(), receiver, args, result);
567167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
568167436311a08a65dea28dda079a137893821c9c7Jeff Hao
569167436311a08a65dea28dda079a137893821c9c7Jeff Hao  self->PopShadowFrame();
570167436311a08a65dea28dda079a137893821c9c7Jeff Hao}
571167436311a08a65dea28dda079a137893821c9c7Jeff Hao
5722fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace interpreter
5732fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace art
574