interpreter.cc revision d2fe10a3a34af171bf1631219cd2d6ff6b7778b5
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"
18d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz#include <limits>
192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
202fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace art {
212fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace interpreter {
222fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
2364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers// Hand select a number of methods to be run in a not yet started runtime without using JNI.
24ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic void UnstartedRuntimeJni(Thread* self, ArtMethod* method,
255d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                Object* receiver, uint32_t* args, JValue* result)
2664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
27d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(Runtime::Current()->IsActiveTransaction()) << "Calling native method "
28d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                                    << PrettyMethod(method)
29d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                                    << " in unstarted runtime should only happen"
30d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                                                    << " in a transaction";
3164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  std::string name(PrettyMethod(method));
3264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") {
3364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(NULL);
3464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Class dalvik.system.VMStack.getStackClass2()") {
357a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers    NthCallerVisitor visitor(self, 3);
3664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    visitor.WalkStack();
3764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(visitor.caller->GetDeclaringClass());
3864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "double java.lang.Math.log(double)") {
395d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    JValue value;
405d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
415d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetD(log(value.GetD()));
4264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.String java.lang.Class.getNameNative()") {
4364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->AsClass()->ComputeName());
4464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
455d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(args[0]);
4664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "float java.lang.Float.intBitsToFloat(int)") {
475d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(args[0]);
4864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "double java.lang.Math.exp(double)") {
495d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    JValue value;
505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
515d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetD(exp(value.GetD()));
5264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.Object.internalClone()") {
5364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->Clone(self));
5464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "void java.lang.Object.notifyAll()") {
5505f3057d6a4d23d712092ccd36a531590bff323bIan Rogers    receiver->NotifyAll(self);
5664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.String.compareTo(java.lang.String)") {
575d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    String* rhs = reinterpret_cast<Object*>(args[0])->AsString();
5864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    CHECK(rhs != NULL);
5964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetI(receiver->AsString()->CompareTo(rhs));
6064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.String java.lang.String.intern()") {
6164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->AsString()->Intern());
6264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.String.fastIndexOf(int, int)") {
635d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
6464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") {
655bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier    SirtRef<mirror::Class> sirt_class(self, reinterpret_cast<Object*>(args[0])->AsClass());
665bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier    SirtRef<mirror::IntArray> sirt_dimensions(self,
675bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier                                              reinterpret_cast<Object*>(args[1])->AsIntArray());
685bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier    result->SetL(Array::CreateMultiArray(self, sirt_class, sirt_dimensions));
6964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") {
7064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    ScopedObjectAccessUnchecked soa(self);
7164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace(soa)));
7264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "boolean java.nio.ByteOrder.isLittleEndian()") {
7364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetJ(JNI_TRUE);
7464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
755d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* obj = reinterpret_cast<Object*>(args[0]);
765d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
775d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jint expectedValue = args[3];
785d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jint newValue = args[4];
7964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
8064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
81d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // Check offset is 32bits to fit in MemberOffset.
82d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK_GE(offset, static_cast<jlong>(std::numeric_limits<int32_t>::min()));
83d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    CHECK_LE(offset, static_cast<jlong>(std::numeric_limits<int32_t>::max()));
84d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    Runtime::Current()->RecordWriteField32(obj, MemberOffset(offset), *address, true);
8564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // Note: android_atomic_release_cas() returns 0 on success, not failure.
8664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    int r = android_atomic_release_cas(expectedValue, newValue, address);
8764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetZ(r == 0);
8864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
895d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* obj = reinterpret_cast<Object*>(args[0]);
905d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* newValue = reinterpret_cast<Object*>(args[3]);
91d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    obj->SetFieldObject<true>(MemberOffset((static_cast<uint64_t>(args[2]) << 32) | args[1]),
92d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                              newValue, false);
934d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi  } else if (name == "int sun.misc.Unsafe.getArrayBaseOffsetForComponentType(java.lang.Class)") {
944d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass();
954d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    Primitive::Type primitive_type = component->GetPrimitiveType();
964d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
974d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi  } else if (name == "int sun.misc.Unsafe.getArrayIndexScaleForComponentType(java.lang.Class)") {
984d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    mirror::Class* component = reinterpret_cast<Object*>(args[0])->AsClass();
994d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    Primitive::Type primitive_type = component->GetPrimitiveType();
1004d2efce8bf1947880b90efc44448b4940c8016fbHiroshi Yamauchi    result->SetI(Primitive::ComponentSize(primitive_type));
10164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else {
102d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    // Throw an exception so we can abort the transaction and undo every change.
103d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    ThrowLocation throw_location;
104d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz    self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;",
105d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                             "Attempt to invoke native method in non-started runtime: %s",
106d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz                             name.c_str());
10764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  }
10864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers}
10964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
110fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogersstatic void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
1115d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                           Object* receiver, uint32_t* args, JValue* result)
11264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
11364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
11464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  //       it should be removed and JNI compiled stubs used instead.
11564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  ScopedObjectAccessUnchecked soa(self);
11664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (method->IsStatic()) {
11764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
118460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jclass);
119460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
12064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
12164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
122556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
123556d637764b71563030c479bc35364a75188d559Ian Rogers      {
124556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
125556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get());
126556d637764b71563030c479bc35364a75188d559Ian Rogers      }
127556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
12864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "V") {
129460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass);
130460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
13164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
13264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
13364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
13464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      fn(soa.Env(), klass.get());
13564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "Z") {
136460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass);
137460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
13864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
13964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
14064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
14164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get()));
14264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "BI") {
143460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jbyte (fntype)(JNIEnv*, jclass, jint);
144460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
14564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
14664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
14764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1485d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetB(fn(soa.Env(), klass.get(), args[0]));
14964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "II") {
150460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jint);
151460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
15264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
15364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
15464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1555d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0]));
15664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
157460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jclass, jobject);
158460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
15964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
16064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
16164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1625d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
163556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
164556d637764b71563030c479bc35364a75188d559Ian Rogers      {
165556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
166556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get(), arg0.get());
167556d637764b71563030c479bc35364a75188d559Ian Rogers      }
168556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
16964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "IIZ") {
170460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jint, jboolean);
171460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
17264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
17364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
17464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1755d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
17664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ILI") {
177460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jclass, jobject, jint);
178460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
17964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
18064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
18164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1825d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
18364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1845d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
18564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "SIZ") {
186460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jshort (fntype)(JNIEnv*, jclass, jint, jboolean);
187460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
18864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
18964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
19064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1915d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
19264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VIZ") {
193460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jint, jboolean);
194460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
19564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
19664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
19764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1985d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], args[1]);
19964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZLL") {
200460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass, jobject, jobject);
201460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
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      ScopedLocalRef<jobject> arg1(soa.Env(),
2075d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
20864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
20964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
21064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZILL") {
211460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jboolean (fntype)(JNIEnv*, jclass, jint, jobject, jobject);
212460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
21364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
21464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
21564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
2165d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
21764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
2185d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
21964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2205d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
22164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VILII") {
222460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jint, jobject, jint, jint);
223460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
22464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
22564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
22664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
2275d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
22864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2295d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
23064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VLILII") {
231460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
232460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
23364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
23464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
23564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2365d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
23764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
2385d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
23964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2405d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
24164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
24264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
24364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
24464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
24564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else {
24664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
247460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jobject);
248460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
24964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
25064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
251556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
252556d637764b71563030c479bc35364a75188d559Ian Rogers      {
253556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
254556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get());
255556d637764b71563030c479bc35364a75188d559Ian Rogers      }
256556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
2573dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao    } else if (shorty == "V") {
258460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef void (fntype)(JNIEnv*, jobject);
259460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
2603dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedLocalRef<jobject> rcvr(soa.Env(),
2613dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao                                   soa.AddLocalReference<jobject>(receiver));
2623dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedThreadStateChange tsc(self, kNative);
2633dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      fn(soa.Env(), rcvr.get());
26464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
265460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jobject (fntype)(JNIEnv*, jobject, jobject);
266460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
26764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
26864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
26964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2705d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
271556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
272556d637764b71563030c479bc35364a75188d559Ian Rogers      {
273556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
274556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get(), arg0.get());
275556d637764b71563030c479bc35364a75188d559Ian Rogers      }
276556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
27764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
27864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "III") {
279460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      typedef jint (fntype)(JNIEnv*, jobject, jint, jint);
280460536209b741bc469f1b0857775449abb2102fbBernhard Rosenkränzer      fntype* const fn = reinterpret_cast<fntype*>(const_cast<void*>(method->GetNativeMethod()));
28164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
28264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
28364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2845d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
28564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
28664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
28764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
28864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
28964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  }
29064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers}
29164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
2928ece050d85fc244c72610244e440b0e00aa618faSebastien Hertzenum InterpreterImplKind {
2938ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  kSwitchImpl,            // switch-based interpreter implementation.
2948ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  kComputedGotoImplKind   // computed-goto-based interpreter implementation.
2958ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz};
296fa46d3ee8cba2985c5c8bdfe47d15daf0613ebdcIan Rogers
2972c88b38ec22278c325c2917fdc60f0674e8b7976Sebastien Hertzstatic const InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
2982fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
299233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertzstatic JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
300233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz                      ShadowFrame& shadow_frame, JValue result_register)
301233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
302233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
303233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertzstatic inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
304233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz                             ShadowFrame& shadow_frame, JValue result_register) {
305848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(shadow_frame.GetMethod() == mh.GetMethod() ||
306848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers         shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass());
307848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsAbstract());
308848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsNative());
3098ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz
310d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  bool transaction_active = Runtime::Current()->IsActiveTransaction();
3118ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) {
312233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "without access check" interpreter.
3138ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
314d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
315d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteSwitchImpl<false, true>(self, mh, code_item, shadow_frame, result_register);
316d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
317d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteSwitchImpl<false, false>(self, mh, code_item, shadow_frame, result_register);
318d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3198ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
3208ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
321d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
322d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteGotoImpl<false, true>(self, mh, code_item, shadow_frame, result_register);
323d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
324d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteGotoImpl<false, false>(self, mh, code_item, shadow_frame, result_register);
325d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3268ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
327233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  } else {
328233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "with access check" interpreter.
3298ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
330d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
331d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteSwitchImpl<true, true>(self, mh, code_item, shadow_frame, result_register);
332d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
333d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteSwitchImpl<true, false>(self, mh, code_item, shadow_frame, result_register);
334d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3358ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
3368ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
337d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      if (transaction_active) {
338d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteGotoImpl<true, true>(self, mh, code_item, shadow_frame, result_register);
339d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      } else {
340d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz        return ExecuteGotoImpl<true, false>(self, mh, code_item, shadow_frame, result_register);
341d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz      }
3428ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
343233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  }
344233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz}
345233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
346ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
3476474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao                                uint32_t* args, JValue* result) {
34864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  DCHECK_EQ(self, Thread::Current());
349790ad90ccd2f3e297e2cf0a47adbf4f9ffb10149Jeff Hao  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
350d752132c73072084a3def9257cca4fcee76047b6jeffhao    ThrowStackOverflowError(self);
351d752132c73072084a3def9257cca4fcee76047b6jeffhao    return;
352d752132c73072084a3def9257cca4fcee76047b6jeffhao  }
353d752132c73072084a3def9257cca4fcee76047b6jeffhao
354e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
3552fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  MethodHelper mh(method);
3562fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  const DexFile::CodeItem* code_item = mh.GetCodeItem();
3572fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_regs;
3582fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_ins;
3592fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (code_item != NULL) {
3602fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_regs =  code_item->registers_size_;
3612fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_ins = code_item->ins_size_;
3620a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao  } else if (method->IsAbstract()) {
363e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    self->EndAssertNoThreadSuspension(old_cause);
36456adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz    ThrowAbstractMethodError(method);
3650a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao    return;
3662fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
3672fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    DCHECK(method->IsNative());
368ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
3692fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    if (!method->IsStatic()) {
3702fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_regs++;
3712fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_ins++;
3722fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3732fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
3742fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  // Set up shadow frame with matching number of reference slots to vregs.
3752fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
3766613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
3776613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
3786613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  self->PushShadowFrame(shadow_frame);
379e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  self->EndAssertNoThreadSuspension(old_cause);
380e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier
3812fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  size_t cur_reg = num_regs - num_ins;
3822fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (!method->IsStatic()) {
3832fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    CHECK(receiver != NULL);
384ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    shadow_frame->SetVRegReference(cur_reg, receiver);
3852fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    ++cur_reg;
386807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz  } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
387807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
388c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier    SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
389c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier    if (UNLIKELY(!class_linker->EnsureInitialized(sirt_c, true, true))) {
390807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz      CHECK(self->IsExceptionPending());
391807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz      self->PopShadowFrame();
39294d6df471a406a03bb1afba8ca3ae9c0fbf366b5jeffhao      return;
39394d6df471a406a03bb1afba8ca3ae9c0fbf366b5jeffhao    }
394c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier    CHECK(sirt_c->IsInitializing());
3952fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
39664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  const char* shorty = mh.GetShorty();
3975d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao  for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
3985d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
3995d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    switch (shorty[shorty_pos + 1]) {
4002fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      case 'L': {
401ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr();
402ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa        shadow_frame->SetVRegReference(cur_reg, o);
4032fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
4042fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      }
4055d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      case 'J': case 'D': {
4065d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
4075d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVRegLong(cur_reg, wide_value);
4082fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        cur_reg++;
4095d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        arg_pos++;
4102fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
4115d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      }
4122fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      default:
4135d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVReg(cur_reg, args[arg_pos]);
4142fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
4152fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
4162fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
41764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (LIKELY(!method->IsNative())) {
4186613519990bdb5616f2858c146f162ef760f03d2Jeff Hao    JValue r = Execute(self, mh, code_item, *shadow_frame, JValue());
4196474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao    if (result != NULL) {
4206474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      *result = r;
4212fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
4222fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
42364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
42464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // generated stub) except during testing and image writing.
42564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (!Runtime::Current()->IsStarted()) {
4266474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      UnstartedRuntimeJni(self, method, receiver, args, result);
4272fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    } else {
4286474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      InterpreterJni(self, method, shorty, receiver, args, result);
4292fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
4302fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
4312fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  self->PopShadowFrame();
4322fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}
4332fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
43462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
43511ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
43611ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  JValue value;
43762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  value.SetJ(ret_val->GetJ());  // Set value to last known result in case the shadow frame chain is empty.
43862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  MethodHelper mh;
43911ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  while (shadow_frame != NULL) {
44062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    self->SetTopOfShadowStack(shadow_frame);
44162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    mh.ChangeMethod(shadow_frame->GetMethod());
44262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    const DexFile::CodeItem* code_item = mh.GetCodeItem();
44311ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    value = Execute(self, mh, code_item, *shadow_frame, value);
44411ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    ShadowFrame* old_frame = shadow_frame;
44511ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    shadow_frame = shadow_frame->GetLink();
44611ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    delete old_frame;
44711ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  }
44811ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  ret_val->SetJ(value.GetJ());
44911ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao}
45011ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao
4517db619bb2a4e01e8532a04b613745d4926b205d7Ian RogersJValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
452848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                                ShadowFrame& shadow_frame) {
453f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  DCHECK_EQ(self, Thread::Current());
454790ad90ccd2f3e297e2cf0a47adbf4f9ffb10149Jeff Hao  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
455f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    ThrowStackOverflowError(self);
456f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    return JValue();
457f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  }
458f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers
4597db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers  return Execute(self, mh, code_item, shadow_frame, JValue());
4607db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers}
4617db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers
462848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogersextern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
463848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                                                  const DexFile::CodeItem* code_item,
464848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                                                  ShadowFrame* shadow_frame, JValue* result) {
465790ad90ccd2f3e297e2cf0a47adbf4f9ffb10149Jeff Hao  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
466167436311a08a65dea28dda079a137893821c9c7Jeff Hao    ThrowStackOverflowError(self);
4676951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    return;
468167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
469167436311a08a65dea28dda079a137893821c9c7Jeff Hao
470e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  self->PushShadowFrame(shadow_frame);
471ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  ArtMethod* method = shadow_frame->GetMethod();
472c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz  // Ensure static methods are initialized.
473c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz  if (method->IsStatic()) {
474c528dba35b5faece51ca658fc008b688f8b690adMathieu Chartier    SirtRef<Class> declaringClass(self, method->GetDeclaringClass());
475c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz    if (UNLIKELY(!declaringClass->IsInitializing())) {
476590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass, true,
477590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                                                                            true))) {
478c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz        DCHECK(Thread::Current()->IsExceptionPending());
479e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier        self->PopShadowFrame();
480c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz        return;
481c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz      }
482c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz      CHECK(declaringClass->IsInitializing());
483167436311a08a65dea28dda079a137893821c9c7Jeff Hao    }
484167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
485167436311a08a65dea28dda079a137893821c9c7Jeff Hao
486167436311a08a65dea28dda079a137893821c9c7Jeff Hao  if (LIKELY(!method->IsNative())) {
4876951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    result->SetJ(Execute(self, mh, code_item, *shadow_frame, JValue()).GetJ());
488167436311a08a65dea28dda079a137893821c9c7Jeff Hao  } else {
489167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
490167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // generated stub) except during testing and image writing.
491167436311a08a65dea28dda079a137893821c9c7Jeff Hao    CHECK(!Runtime::Current()->IsStarted());
492e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    Object* receiver = method->IsStatic() ? nullptr : shadow_frame->GetVRegReference(0);
493167436311a08a65dea28dda079a137893821c9c7Jeff Hao    uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
4946951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    UnstartedRuntimeJni(self, method, receiver, args, result);
495167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
496167436311a08a65dea28dda079a137893821c9c7Jeff Hao
497167436311a08a65dea28dda079a137893821c9c7Jeff Hao  self->PopShadowFrame();
498167436311a08a65dea28dda079a137893821c9c7Jeff Hao}
499167436311a08a65dea28dda079a137893821c9c7Jeff Hao
5002fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace interpreter
5012fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace art
502