Interpreter.
The opcodes filled-new-array and packed-switch aren't implemented but
are trivial given that they are variants of implemented opcodes.
Refactor Field::Get routines to take the declaring class in the case of
static field accesses. This avoids a check on every use of a field.
Refactor arg array builder to be shared by JNI invokes and invocations
into the interpreter.
Fix benign bug in const decoding in the verifier.
Change-Id: I8dee6c1f4b7f033e6c003422c56e9471cfaccda8
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 60b49de..097d587 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -24,6 +24,7 @@
#include "class_linker.h"
#include "class_loader.h"
+#include "invoke_arg_array_builder.h"
#include "jni.h"
#include "logging.h"
#include "mutex.h"
@@ -74,120 +75,6 @@
}
}
-size_t NumArgArrayBytes(const char* shorty, uint32_t shorty_len) {
- size_t num_bytes = 0;
- for (size_t i = 1; i < shorty_len; ++i) {
- char ch = shorty[i];
- if (ch == 'D' || ch == 'J') {
- num_bytes += 8;
- } else if (ch == 'L') {
- // Argument is a reference or an array. The shorty descriptor
- // does not distinguish between these types.
- num_bytes += sizeof(Object*);
- } else {
- num_bytes += 4;
- }
- }
- return num_bytes;
-}
-
-class ArgArray {
- public:
- explicit ArgArray(AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- MethodHelper mh(method);
- shorty_ = mh.GetShorty();
- shorty_len_ = mh.GetShortyLength();
- if (shorty_len_ - 1 < kSmallArgArraySize) {
- arg_array_ = small_arg_array_;
- } else {
- large_arg_array_.reset(new JValue[shorty_len_ - 1]);
- arg_array_ = large_arg_array_.get();
- }
- }
-
- JValue* get() {
- return arg_array_;
- }
-
- void BuildArgArray(const ScopedObjectAccess& soa, va_list ap)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
- switch (shorty_[i]) {
- case 'Z':
- arg_array_[offset].SetZ(va_arg(ap, jint));
- break;
- case 'B':
- arg_array_[offset].SetB(va_arg(ap, jint));
- break;
- case 'C':
- arg_array_[offset].SetC(va_arg(ap, jint));
- break;
- case 'S':
- arg_array_[offset].SetS(va_arg(ap, jint));
- break;
- case 'I':
- arg_array_[offset].SetI(va_arg(ap, jint));
- break;
- case 'F':
- arg_array_[offset].SetF(va_arg(ap, jdouble));
- break;
- case 'L':
- arg_array_[offset].SetL(soa.Decode<Object*>(va_arg(ap, jobject)));
- break;
- case 'D':
- arg_array_[offset].SetD(va_arg(ap, jdouble));
- break;
- case 'J':
- arg_array_[offset].SetJ(va_arg(ap, jlong));
- break;
- }
- }
- }
-
- void BuildArgArray(const ScopedObjectAccess& soa, jvalue* args)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- for (size_t i = 1, offset = 0; i < shorty_len_; ++i, ++offset) {
- switch (shorty_[i]) {
- case 'Z':
- arg_array_[offset].SetZ(args[offset].z);
- break;
- case 'B':
- arg_array_[offset].SetB(args[offset].b);
- break;
- case 'C':
- arg_array_[offset].SetC(args[offset].c);
- break;
- case 'S':
- arg_array_[offset].SetS(args[offset].s);
- break;
- case 'I':
- arg_array_[offset].SetI(args[offset].i);
- break;
- case 'F':
- arg_array_[offset].SetF(args[offset].f);
- break;
- case 'L':
- arg_array_[offset].SetL(soa.Decode<Object*>(args[offset].l));
- break;
- case 'D':
- arg_array_[offset].SetD(args[offset].d);
- break;
- case 'J':
- arg_array_[offset].SetJ(args[offset].j);
- break;
- }
- }
- }
-
- private:
- enum { kSmallArgArraySize = 16 };
- const char* shorty_;
- uint32_t shorty_len_;
- JValue* arg_array_;
- JValue small_arg_array_[kSmallArgArraySize];
- UniquePtr<JValue[]> large_arg_array_;
-};
-
static jweak AddWeakGlobalReference(ScopedObjectAccess& soa, Object* obj)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (obj == NULL) {
@@ -253,7 +140,8 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = soa.DecodeMethod(mid);
- ArgArray arg_array(method);
+ MethodHelper mh(method);
+ ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, args);
return InvokeWithArgArray(soa, receiver, method, arg_array.get());
}
@@ -268,7 +156,8 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
- ArgArray arg_array(method);
+ MethodHelper mh(method);
+ ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, args);
return InvokeWithArgArray(soa, receiver, method, arg_array.get());
}
@@ -278,7 +167,8 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
- ArgArray arg_array(method);
+ MethodHelper mh(method);
+ ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, args);
return InvokeWithArgArray(soa, receiver, method, arg_array.get());
}
@@ -670,7 +560,8 @@
jvalue* args) {
Object* receiver = soa.Decode<Object*>(obj);
AbstractMethod* method = soa.DecodeMethod(mid);
- ArgArray arg_array(method);
+ MethodHelper mh(method);
+ ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, args);
return InvokeWithArgArray(soa, receiver, method, arg_array.get());
}
@@ -1415,7 +1306,7 @@
static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
ScopedObjectAccess soa(env);
Field* f = soa.DecodeField(fid);
- return soa.AddLocalReference<jobject>(f->GetObject(NULL));
+ return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass()));
}
static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
@@ -1430,7 +1321,7 @@
ScopedObjectAccess soa(env);
Object* v = soa.Decode<Object*>(java_value);
Field* f = soa.DecodeField(fid);
- f->SetObject(NULL, v);
+ f->SetObject(f->GetDeclaringClass(), v);
}
#define GET_PRIMITIVE_FIELD(fn, instance) \
@@ -1439,12 +1330,22 @@
Field* f = soa.DecodeField(fid); \
return f->fn(o)
+#define GET_STATIC_PRIMITIVE_FIELD(fn) \
+ ScopedObjectAccess soa(env); \
+ Field* f = soa.DecodeField(fid); \
+ return f->fn(f->GetDeclaringClass())
+
#define SET_PRIMITIVE_FIELD(fn, instance, value) \
ScopedObjectAccess soa(env); \
Object* o = soa.Decode<Object*>(instance); \
Field* f = soa.DecodeField(fid); \
f->fn(o, value)
+#define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
+ ScopedObjectAccess soa(env); \
+ Field* f = soa.DecodeField(fid); \
+ f->fn(f->GetDeclaringClass(), value)
+
static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
GET_PRIMITIVE_FIELD(GetBoolean, obj);
}
@@ -1478,35 +1379,35 @@
}
static jboolean GetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetBoolean, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetBoolean);
}
static jbyte GetStaticByteField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetByte, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetByte);
}
static jchar GetStaticCharField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetChar, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetChar);
}
static jshort GetStaticShortField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetShort, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetShort);
}
static jint GetStaticIntField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetInt, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetInt);
}
static jlong GetStaticLongField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetLong, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetLong);
}
static jfloat GetStaticFloatField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetFloat, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetFloat);
}
static jdouble GetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid) {
- GET_PRIMITIVE_FIELD(GetDouble, NULL);
+ GET_STATIC_PRIMITIVE_FIELD(GetDouble);
}
static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fid, jboolean v) {
@@ -1542,35 +1443,35 @@
}
static void SetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid, jboolean v) {
- SET_PRIMITIVE_FIELD(SetBoolean, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetBoolean, v);
}
static void SetStaticByteField(JNIEnv* env, jclass, jfieldID fid, jbyte v) {
- SET_PRIMITIVE_FIELD(SetByte, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetByte, v);
}
static void SetStaticCharField(JNIEnv* env, jclass, jfieldID fid, jchar v) {
- SET_PRIMITIVE_FIELD(SetChar, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetChar, v);
}
static void SetStaticFloatField(JNIEnv* env, jclass, jfieldID fid, jfloat v) {
- SET_PRIMITIVE_FIELD(SetFloat, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetFloat, v);
}
static void SetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid, jdouble v) {
- SET_PRIMITIVE_FIELD(SetDouble, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetDouble, v);
}
static void SetStaticIntField(JNIEnv* env, jclass, jfieldID fid, jint v) {
- SET_PRIMITIVE_FIELD(SetInt, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetInt, v);
}
static void SetStaticLongField(JNIEnv* env, jclass, jfieldID fid, jlong v) {
- SET_PRIMITIVE_FIELD(SetLong, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetLong, v);
}
static void SetStaticShortField(JNIEnv* env, jclass, jfieldID fid, jshort v) {
- SET_PRIMITIVE_FIELD(SetShort, NULL, v);
+ SET_STATIC_PRIMITIVE_FIELD(SetShort, v);
}
static jobject CallStaticObjectMethod(JNIEnv* env, jclass, jmethodID mid, ...) {