interpreter.cc revision 2c88b38ec22278c325c2917fdc60f0674e8b7976
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"
182dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
192fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace art {
202fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogersnamespace interpreter {
212fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
2264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers// Hand select a number of methods to be run in a not yet started runtime without using JNI.
23ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic void UnstartedRuntimeJni(Thread* self, ArtMethod* method,
245d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                Object* receiver, uint32_t* args, JValue* result)
2564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  std::string name(PrettyMethod(method));
2764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (name == "java.lang.ClassLoader dalvik.system.VMStack.getCallingClassLoader()") {
2864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(NULL);
2964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Class dalvik.system.VMStack.getStackClass2()") {
307a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers    NthCallerVisitor visitor(self, 3);
3164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    visitor.WalkStack();
3264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(visitor.caller->GetDeclaringClass());
3364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "double java.lang.Math.log(double)") {
345d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    JValue value;
355d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
365d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetD(log(value.GetD()));
3764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.String java.lang.Class.getNameNative()") {
3864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->AsClass()->ComputeName());
3964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.Float.floatToRawIntBits(float)") {
405d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(args[0]);
4164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "float java.lang.Float.intBitsToFloat(int)") {
425d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(args[0]);
4364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "double java.lang.Math.exp(double)") {
445d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    JValue value;
455d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
465d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetD(exp(value.GetD()));
4764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.Object.internalClone()") {
4864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->Clone(self));
4964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "void java.lang.Object.notifyAll()") {
5005f3057d6a4d23d712092ccd36a531590bff323bIan Rogers    receiver->NotifyAll(self);
5164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.String.compareTo(java.lang.String)") {
525d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    String* rhs = reinterpret_cast<Object*>(args[0])->AsString();
5364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    CHECK(rhs != NULL);
5464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetI(receiver->AsString()->CompareTo(rhs));
5564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.String java.lang.String.intern()") {
5664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(receiver->AsString()->Intern());
5764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "int java.lang.String.fastIndexOf(int, int)") {
585d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
5964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.reflect.Array.createMultiArray(java.lang.Class, int[])") {
605d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    result->SetL(Array::CreateMultiArray(self, reinterpret_cast<Object*>(args[0])->AsClass(), reinterpret_cast<Object*>(args[1])->AsIntArray()));
6164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "java.lang.Object java.lang.Throwable.nativeFillInStackTrace()") {
6264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    ScopedObjectAccessUnchecked soa(self);
6364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetL(soa.Decode<Object*>(self->CreateInternalStackTrace(soa)));
6464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "boolean java.nio.ByteOrder.isLittleEndian()") {
6564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetJ(JNI_TRUE);
6664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
675d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* obj = reinterpret_cast<Object*>(args[0]);
685d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
695d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jint expectedValue = args[3];
705d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    jint newValue = args[4];
7164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
7264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    volatile int32_t* address = reinterpret_cast<volatile int32_t*>(raw_addr);
7364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // Note: android_atomic_release_cas() returns 0 on success, not failure.
7464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    int r = android_atomic_release_cas(expectedValue, newValue, address);
7564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    result->SetZ(r == 0);
7664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else if (name == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
775d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* obj = reinterpret_cast<Object*>(args[0]);
785d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    Object* newValue = reinterpret_cast<Object*>(args[3]);
795d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    obj->SetFieldObject(MemberOffset((static_cast<uint64_t>(args[2]) << 32) | args[1]), newValue, false);
8064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else {
8164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    LOG(FATAL) << "Attempt to invoke native method in non-started runtime: " << name;
8264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  }
8364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers}
8464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
85fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogersstatic void InterpreterJni(Thread* self, ArtMethod* method, const StringPiece& shorty,
865d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                           Object* receiver, uint32_t* args, JValue* result)
8764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
8864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  // TODO: The following enters JNI code using a typedef-ed function rather than the JNI compiler,
8964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  //       it should be removed and JNI compiled stubs used instead.
9064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  ScopedObjectAccessUnchecked soa(self);
9164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (method->IsStatic()) {
9264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
9364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jobject (fnptr)(JNIEnv*, jclass);
94d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
9564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
9664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
97556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
98556d637764b71563030c479bc35364a75188d559Ian Rogers      {
99556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
100556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get());
101556d637764b71563030c479bc35364a75188d559Ian Rogers      }
102556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
10364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "V") {
10464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef void (fnptr)(JNIEnv*, jclass);
105d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
10664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
10764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
10864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
10964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      fn(soa.Env(), klass.get());
11064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "Z") {
11164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jboolean (fnptr)(JNIEnv*, jclass);
112d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
11364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
11464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
11564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
11664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get()));
11764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "BI") {
11864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jbyte (fnptr)(JNIEnv*, jclass, jint);
119d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
12064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
12164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
12264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1235d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetB(fn(soa.Env(), klass.get(), args[0]));
12464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "II") {
12564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jint (fnptr)(JNIEnv*, jclass, jint);
126d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
12764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
12864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
12964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1305d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0]));
13164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
13264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jobject (fnptr)(JNIEnv*, jclass, jobject);
133d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
13464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
13564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
13664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1375d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
138556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
139556d637764b71563030c479bc35364a75188d559Ian Rogers      {
140556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
141556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), klass.get(), arg0.get());
142556d637764b71563030c479bc35364a75188d559Ian Rogers      }
143556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
14464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "IIZ") {
14564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jint (fnptr)(JNIEnv*, jclass, jint, jboolean);
146d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
14764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
14864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
14964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1505d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), args[0], args[1]));
15164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ILI") {
15264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jint (fnptr)(JNIEnv*, jclass, jobject, jint);
153d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
15464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
15564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
15664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1575d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
15864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1595d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), klass.get(), arg0.get(), args[1]));
16064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "SIZ") {
16164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jshort (fnptr)(JNIEnv*, jclass, jint, jboolean);
162d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
16364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
16464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
16564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1665d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetS(fn(soa.Env(), klass.get(), args[0], args[1]));
16764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VIZ") {
16864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef void (fnptr)(JNIEnv*, jclass, jint, jboolean);
169d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
17064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
17164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
17264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1735d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], args[1]);
17464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZLL") {
17564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jboolean (fnptr)(JNIEnv*, jclass, jobject, jobject);
176d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
17764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
17864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
17964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
1805d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
18164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
1825d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
18364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
18464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      result->SetZ(fn(soa.Env(), klass.get(), arg0.get(), arg1.get()));
18564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "ZILL") {
18664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jboolean (fnptr)(JNIEnv*, jclass, jint, jobject, jobject);
187d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
18864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
18964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
19064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
1915d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
19264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
1935d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
19464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
1955d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetZ(fn(soa.Env(), klass.get(), args[0], arg1.get(), arg2.get()));
19664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VILII") {
19764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef void (fnptr)(JNIEnv*, jclass, jint, jobject, jint, jint);
198d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
19964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
20064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
20164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg1(soa.Env(),
2025d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[1])));
20364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2045d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), args[0], arg1.get(), args[2], args[3]);
20564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "VLILII") {
20664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef void (fnptr)(JNIEnv*, jclass, jobject, jint, jobject, jint, jint);
207d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
20864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jclass> klass(soa.Env(),
20964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jclass>(method->GetDeclaringClass()));
21064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2115d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
21264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg2(soa.Env(),
2135d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[2])));
21464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2155d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      fn(soa.Env(), klass.get(), arg0.get(), args[1], arg2.get(), args[3], args[4]);
21664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
21764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with static native method: " << PrettyMethod(method)
21864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
21964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
22064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  } else {
22164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (shorty == "L") {
22264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jobject (fnptr)(JNIEnv*, jobject);
223d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
22464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
22564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
226556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
227556d637764b71563030c479bc35364a75188d559Ian Rogers      {
228556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
229556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get());
230556d637764b71563030c479bc35364a75188d559Ian Rogers      }
231556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
2323dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao    } else if (shorty == "V") {
2333dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      typedef void (fnptr)(JNIEnv*, jobject);
2343dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
2353dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedLocalRef<jobject> rcvr(soa.Env(),
2363dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao                                   soa.AddLocalReference<jobject>(receiver));
2373dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      ScopedThreadStateChange tsc(self, kNative);
2383dd9f76ff8fa99be9ff6b18354528c5def7b26f7Jeff Hao      fn(soa.Env(), rcvr.get());
23964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "LL") {
24064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jobject (fnptr)(JNIEnv*, jobject, jobject);
241d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
24264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
24364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
24464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> arg0(soa.Env(),
2455d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao                                   soa.AddLocalReference<jobject>(reinterpret_cast<Object*>(args[0])));
246556d637764b71563030c479bc35364a75188d559Ian Rogers      jobject jresult;
247556d637764b71563030c479bc35364a75188d559Ian Rogers      {
248556d637764b71563030c479bc35364a75188d559Ian Rogers        ScopedThreadStateChange tsc(self, kNative);
249556d637764b71563030c479bc35364a75188d559Ian Rogers        jresult = fn(soa.Env(), rcvr.get(), arg0.get());
250556d637764b71563030c479bc35364a75188d559Ian Rogers      }
251556d637764b71563030c479bc35364a75188d559Ian Rogers      result->SetL(soa.Decode<Object*>(jresult));
25264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
25364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (shorty == "III") {
25464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      typedef jint (fnptr)(JNIEnv*, jobject, jint, jint);
255d8274bcbc565fff1254574b3cbf46dc4e7b52812Ian Rogers      const fnptr* fn = reinterpret_cast<const fnptr*>(method->GetNativeMethod());
25664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedLocalRef<jobject> rcvr(soa.Env(),
25764b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers                                   soa.AddLocalReference<jobject>(receiver));
25864b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      ScopedThreadStateChange tsc(self, kNative);
2595d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      result->SetI(fn(soa.Env(), rcvr.get(), args[0], args[1]));
26064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else {
26164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers      LOG(FATAL) << "Do something with native method: " << PrettyMethod(method)
26264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers          << " shorty: " << shorty;
26364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    }
26464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  }
26564b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers}
26664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers
2678ece050d85fc244c72610244e440b0e00aa618faSebastien Hertzenum InterpreterImplKind {
2688ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  kSwitchImpl,            // switch-based interpreter implementation.
2698ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  kComputedGotoImplKind   // computed-goto-based interpreter implementation.
2708ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz};
271fa46d3ee8cba2985c5c8bdfe47d15daf0613ebdcIan Rogers
2722c88b38ec22278c325c2917fdc60f0674e8b7976Sebastien Hertzstatic const InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKind;
2732fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
274233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertzstatic JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
275233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz                      ShadowFrame& shadow_frame, JValue result_register)
276233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
277233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
278233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertzstatic inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
279233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz                             ShadowFrame& shadow_frame, JValue result_register) {
280848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(shadow_frame.GetMethod() == mh.GetMethod() ||
281848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers         shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass());
282848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsAbstract());
283848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  DCHECK(!shadow_frame.GetMethod()->IsNative());
2848ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz
2858ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz  if (LIKELY(shadow_frame.GetMethod()->IsPreverified())) {
286233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "without access check" interpreter.
2878ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
2888ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      return ExecuteSwitchImpl<false>(self, mh, code_item, shadow_frame, result_register);
2898ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
2908ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
2918ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      return ExecuteGotoImpl<false>(self, mh, code_item, shadow_frame, result_register);
2928ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
293233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  } else {
294233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz    // Enter the "with access check" interpreter.
2958ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    if (kInterpreterImplKind == kSwitchImpl) {
2968ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      return ExecuteSwitchImpl<true>(self, mh, code_item, shadow_frame, result_register);
2978ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    } else {
2988ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
2998ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz      return ExecuteGotoImpl<true>(self, mh, code_item, shadow_frame, result_register);
3008ece050d85fc244c72610244e440b0e00aa618faSebastien Hertz    }
301233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz  }
302233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz}
303233ea8e084a95ad2a3af746dddbadb155db6a814Sebastien Hertz
304ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromvoid EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receiver,
3056474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao                                uint32_t* args, JValue* result) {
30664b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  DCHECK_EQ(self, Thread::Current());
307790ad90ccd2f3e297e2cf0a47adbf4f9ffb10149Jeff Hao  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
308d752132c73072084a3def9257cca4fcee76047b6jeffhao    ThrowStackOverflowError(self);
309d752132c73072084a3def9257cca4fcee76047b6jeffhao    return;
310d752132c73072084a3def9257cca4fcee76047b6jeffhao  }
311d752132c73072084a3def9257cca4fcee76047b6jeffhao
312e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
3132fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  MethodHelper mh(method);
3142fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  const DexFile::CodeItem* code_item = mh.GetCodeItem();
3152fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_regs;
3162fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  uint16_t num_ins;
3172fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (code_item != NULL) {
3182fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_regs =  code_item->registers_size_;
3192fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    num_ins = code_item->ins_size_;
3200a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao  } else if (method->IsAbstract()) {
321e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    self->EndAssertNoThreadSuspension(old_cause);
32256adf601ed9d1d11a2c462caa262e7de66a9e172Sebastien Hertz    ThrowAbstractMethodError(method);
3230a9bb73c70298922ad33d67c209a4e440b216fa2jeffhao    return;
3242fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
3252fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    DCHECK(method->IsNative());
326ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
3272fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    if (!method->IsStatic()) {
3282fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_regs++;
3292fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      num_ins++;
3302fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3312fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
3322fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  // Set up shadow frame with matching number of reference slots to vregs.
3332fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
3346613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
3356613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
3366613519990bdb5616f2858c146f162ef760f03d2Jeff Hao  self->PushShadowFrame(shadow_frame);
337e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  self->EndAssertNoThreadSuspension(old_cause);
338e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier
3392fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  size_t cur_reg = num_regs - num_ins;
3402fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  if (!method->IsStatic()) {
3412fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    CHECK(receiver != NULL);
342ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    shadow_frame->SetVRegReference(cur_reg, receiver);
3432fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    ++cur_reg;
344807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz  } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
345807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
346e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(), true, true))) {
347807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz      CHECK(self->IsExceptionPending());
348807a25640d4f4de8143b160b3bb8f552ffbf6f4aSebastien Hertz      self->PopShadowFrame();
34994d6df471a406a03bb1afba8ca3ae9c0fbf366b5jeffhao      return;
35094d6df471a406a03bb1afba8ca3ae9c0fbf366b5jeffhao    }
3512fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    CHECK(method->GetDeclaringClass()->IsInitializing());
3522fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
35364b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  const char* shorty = mh.GetShorty();
3545d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao  for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
3555d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
3565d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao    switch (shorty[shorty_pos + 1]) {
3572fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      case 'L': {
3585d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        Object* o = reinterpret_cast<Object*>(args[arg_pos]);
359ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa        shadow_frame->SetVRegReference(cur_reg, o);
3602fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
3612fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      }
3625d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      case 'J': case 'D': {
3635d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        uint64_t wide_value = (static_cast<uint64_t>(args[arg_pos + 1]) << 32) | args[arg_pos];
3645d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVRegLong(cur_reg, wide_value);
3652fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        cur_reg++;
3665d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        arg_pos++;
3672fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
3685d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao      }
3692fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      default:
3705d9173014c1ca09f7249a6b07629aa37778b5f8fJeff Hao        shadow_frame->SetVReg(cur_reg, args[arg_pos]);
3712fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers        break;
3722fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3732fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
37464b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers  if (LIKELY(!method->IsNative())) {
3756613519990bdb5616f2858c146f162ef760f03d2Jeff Hao    JValue r = Execute(self, mh, code_item, *shadow_frame, JValue());
3766474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao    if (result != NULL) {
3776474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      *result = r;
3782fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3792fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  } else {
38064b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
38164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    // generated stub) except during testing and image writing.
38264b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    if (!Runtime::Current()->IsStarted()) {
3836474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      UnstartedRuntimeJni(self, method, receiver, args, result);
3842fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    } else {
3856474d190d5604898354ebf767f1944b6e3e9b445Jeff Hao      InterpreterJni(self, method, shorty, receiver, args, result);
3862fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers    }
3872fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  }
3882fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers  self->PopShadowFrame();
3892fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}
3902fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers
39162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JValue* ret_val)
39211ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
39311ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  JValue value;
39462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  value.SetJ(ret_val->GetJ());  // Set value to last known result in case the shadow frame chain is empty.
39562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  MethodHelper mh;
39611ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  while (shadow_frame != NULL) {
39762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    self->SetTopOfShadowStack(shadow_frame);
39862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    mh.ChangeMethod(shadow_frame->GetMethod());
39962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    const DexFile::CodeItem* code_item = mh.GetCodeItem();
40011ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    value = Execute(self, mh, code_item, *shadow_frame, value);
40111ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    ShadowFrame* old_frame = shadow_frame;
40211ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    shadow_frame = shadow_frame->GetLink();
40311ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao    delete old_frame;
40411ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  }
40511ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao  ret_val->SetJ(value.GetJ());
40611ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao}
40711ffc2d02b7d979f26a8a04013fce3eb4f9a2816Jeff Hao
4087db619bb2a4e01e8532a04b613745d4926b205d7Ian RogersJValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
409848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                                ShadowFrame& shadow_frame) {
410f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  DCHECK_EQ(self, Thread::Current());
411790ad90ccd2f3e297e2cf0a47adbf4f9ffb10149Jeff Hao  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
412f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    ThrowStackOverflowError(self);
413f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    return JValue();
414f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers  }
415f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers
4167db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers  return Execute(self, mh, code_item, shadow_frame, JValue());
4177db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers}
4187db619bb2a4e01e8532a04b613745d4926b205d7Ian Rogers
419848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogersextern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh,
420848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                                                  const DexFile::CodeItem* code_item,
421848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers                                                  ShadowFrame* shadow_frame, JValue* result) {
422790ad90ccd2f3e297e2cf0a47adbf4f9ffb10149Jeff Hao  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
423167436311a08a65dea28dda079a137893821c9c7Jeff Hao    ThrowStackOverflowError(self);
4246951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    return;
425167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
426167436311a08a65dea28dda079a137893821c9c7Jeff Hao
427e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier  self->PushShadowFrame(shadow_frame);
428ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  ArtMethod* method = shadow_frame->GetMethod();
429c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz  // Ensure static methods are initialized.
430c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz  if (method->IsStatic()) {
431c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz    Class* declaringClass = method->GetDeclaringClass();
432c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz    if (UNLIKELY(!declaringClass->IsInitializing())) {
433c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz      if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
434c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz                                                                            true, true))) {
435c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz        DCHECK(Thread::Current()->IsExceptionPending());
436e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier        self->PopShadowFrame();
437c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz        return;
438c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz      }
439c61124bdeaae94f977ffc36ac69535e792c226f2Sebastien Hertz      CHECK(declaringClass->IsInitializing());
440167436311a08a65dea28dda079a137893821c9c7Jeff Hao    }
441167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
442167436311a08a65dea28dda079a137893821c9c7Jeff Hao
443167436311a08a65dea28dda079a137893821c9c7Jeff Hao  if (LIKELY(!method->IsNative())) {
4446951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    result->SetJ(Execute(self, mh, code_item, *shadow_frame, JValue()).GetJ());
445167436311a08a65dea28dda079a137893821c9c7Jeff Hao  } else {
446167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
447167436311a08a65dea28dda079a137893821c9c7Jeff Hao    // generated stub) except during testing and image writing.
448167436311a08a65dea28dda079a137893821c9c7Jeff Hao    CHECK(!Runtime::Current()->IsStarted());
449e861ebd5d9490cc86200f3859f3d36fadad4588cMathieu Chartier    Object* receiver = method->IsStatic() ? nullptr : shadow_frame->GetVRegReference(0);
450167436311a08a65dea28dda079a137893821c9c7Jeff Hao    uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
4516951067ee14754454e17221fdef0d3d5ed7c4f7eJeff Hao    UnstartedRuntimeJni(self, method, receiver, args, result);
452167436311a08a65dea28dda079a137893821c9c7Jeff Hao  }
453167436311a08a65dea28dda079a137893821c9c7Jeff Hao
454167436311a08a65dea28dda079a137893821c9c7Jeff Hao  self->PopShadowFrame();
455167436311a08a65dea28dda079a137893821c9c7Jeff Hao}
456167436311a08a65dea28dda079a137893821c9c7Jeff Hao
4572fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace interpreter
4582fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers}  // namespace art
459