Handle interface methods in JNI invocation
Change-Id: I7c9d25177fc6fdf9512beb2a882969a9aaf835ba
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 2f1a5d7..7a93d48 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -201,8 +201,8 @@
// supers as well. These interfaces don't have any methods, so we
// don't have to worry about the ifviPool either.
array_iftable_ = new InterfaceEntry[2];
- array_iftable_[0].SetClass(array_interfaces_->Get(0));
- array_iftable_[1].SetClass(array_interfaces_->Get(1));
+ array_iftable_[0].SetInterface(array_interfaces_->Get(0));
+ array_iftable_[1].SetInterface(array_interfaces_->Get(1));
// now FindClass can be used for non-primitive array classes
// run Object[] through FindClass to complete initialization
@@ -1153,7 +1153,7 @@
}
for (size_t i = 0; i < klass->iftable_count_; ++i) {
const InterfaceEntry* iftable = &klass->iftable_[i];
- Class* interface = iftable->GetClass();
+ Class* interface = iftable->GetInterface();
if (klass->GetClassLoader() != interface->GetClassLoader()) {
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
uint32_t vtable_index = iftable->method_index_array_[j];
@@ -1517,9 +1517,9 @@
LG << "Class implements non-interface class"; // TODO: IncompatibleClassChangeError
return false;
}
- klass->iftable_[idx++].SetClass(interf);
+ klass->iftable_[idx++].SetInterface(interf);
for (size_t j = 0; j < interf->iftable_count_; j++) {
- klass->iftable_[idx++].SetClass(interf->iftable_[j].GetClass());
+ klass->iftable_[idx++].SetInterface(interf->iftable_[j].GetInterface());
}
}
CHECK_EQ(idx, ifcount);
@@ -1528,7 +1528,7 @@
return true;
}
for (size_t i = super_ifcount; i < ifcount; i++) {
- pool_size += klass->iftable_[i].GetClass()->NumVirtualMethods();
+ pool_size += klass->iftable_[i].GetInterface()->NumVirtualMethods();
}
if (pool_size == 0) {
return true;
@@ -1538,7 +1538,7 @@
std::vector<Method*> miranda_list;
for (size_t i = super_ifcount; i < ifcount; ++i) {
klass->iftable_[i].method_index_array_ = klass->ifvi_pool_ + pool_offset;
- Class* interface = klass->iftable_[i].GetClass();
+ Class* interface = klass->iftable_[i].GetInterface();
pool_offset += interface->NumVirtualMethods(); // end here
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
Method* interface_method = interface->GetVirtualMethod(j);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index b5c03fb..9e96439 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -516,4 +516,37 @@
EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("robot"));
}
+TEST_F(ClassLinkerTest, Interfaces) {
+ scoped_ptr<DexFile> dex(OpenDexFileBase64(kInterfacesDex, "kInterfacesDex"));
+ PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+ Class* I = class_linker_->FindClass("LInterfaces$I;", class_loader);
+ Class* J = class_linker_->FindClass("LInterfaces$J;", class_loader);
+ Class* A = class_linker_->FindClass("LInterfaces$A;", class_loader);
+ EXPECT_TRUE(I->IsAssignableFrom(A));
+ EXPECT_TRUE(J->IsAssignableFrom(A));
+
+ Method* Ii = I->FindVirtualMethod("i", "()V");
+ Method* Jj1 = J->FindVirtualMethod("j1", "()V");
+ Method* Jj2 = J->FindVirtualMethod("j2", "()V");
+ Method* Ai = A->FindVirtualMethod("i", "()V");
+ Method* Aj1 = A->FindVirtualMethod("j1", "()V");
+ Method* Aj2 = A->FindVirtualMethod("j2", "()V");
+ ASSERT_TRUE(Ii != NULL);
+ ASSERT_TRUE(Jj1 != NULL);
+ ASSERT_TRUE(Jj2 != NULL);
+ ASSERT_TRUE(Ai != NULL);
+ ASSERT_TRUE(Aj1 != NULL);
+ ASSERT_TRUE(Aj2 != NULL);
+ ASSERT_TRUE(Ii != NULL);
+ EXPECT_NE(Ii, Ai);
+ EXPECT_NE(Jj1, Aj1);
+ EXPECT_NE(Jj2, Aj2);
+ EXPECT_EQ(Ai, A->FindVirtualMethodForInterface(Ii));
+ EXPECT_EQ(Aj1, A->FindVirtualMethodForInterface(Jj1));
+ EXPECT_EQ(Aj2, A->FindVirtualMethodForInterface(Jj2));
+ EXPECT_EQ(Ai, A->FindVirtualMethodForVirtualOrInterface(Ii));
+ EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1));
+ EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
+}
+
} // namespace art
diff --git a/src/common_test.h b/src/common_test.h
index 1b0404e..e56a3a0 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -349,30 +349,69 @@
// }
//}
static const char kFibonacciDex[] =
-"ZGV4CjAzNQBaslnMUQxaXYgC3gD9FGHjVb8cHZ60G8ckBQAAcAAAAHhWNBIAAAAAAAAAAIQEAAAa"
-"AAAAcAAAAAsAAADYAAAABgAAAAQBAAABAAAATAEAAAcAAABUAQAAAgAAAIwBAABYAwAAzAEAAPoC"
-"AAACAwAAEgMAABUDAAAZAwAAHQMAACoDAAAuAwAAMwMAAEoDAABfAwAAggMAAJYDAACqAwAAvgMA"
-"AMsDAADOAwAA0gMAAOcDAAD8AwAABwQAABoEAAAgBAAAJQQAAC8EAAA3BAAAAgAAAAUAAAAIAAAA"
-"CQAAAAoAAAALAAAADAAAAA0AAAAPAAAAEQAAABIAAAADAAAAAAAAANwCAAAEAAAAAAAAAOQCAAAH"
-"AAAAAgAAAOwCAAAGAAAAAwAAANwCAAAPAAAACAAAAAAAAAAQAAAACAAAAPQCAAAHAAIAFgAAAAEA"
-"BAAAAAAAAQAAABMAAAABAAUAFQAAAAIAAgAYAAAAAwABABcAAAADAAMAGQAAAAUABAAAAAAABQAA"
-"AAEAAAD/////AAAAAA4AAAAAAAAAaAQAAAAAAAABAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAByBAAA"
-"AAAAAAEAAQAAAAAAQAQAAAEAAAAOAAAAAQABAAEAAABFBAAABAAAAHAQBgAAAA4ABQABAAAAAABK"
-"BAAAEwAAABIROQQEABIADwASMAESARMBAQEwNkH6/7AC2AEBAQEjAQIBMCj4AAAIAAEAAwABAFcE"
-"AABIAAAAEhEhcDMQQwASAEYABwBxEAQAAAAKAHEQAQAAAAoBYgIAABoDFAASJCNECQASBXEQBQAA"
-"AAwGTQYEBRIVcRAFAAEADAFNAQQFbjADADIE2AEAAXEQAQABAAoBYgIAABoDFAASJCNECQASBXEQ"
-"BQAAAAwATQAEBRIQcRAFAAEADAFNAQQAbjADADIEDgANACj+AQAAAEQAAQABAQRGAQAAAAAAAAAB"
-"AAAABgAAAAIAAAAGAAkAAQAAAAoABjxpbml0PgAORmlib25hY2NpLmphdmEAAUkAAklJAAJJTAAL"
-"TEZpYm9uYWNjaTsAAkxJAANMTEwAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwATTGphdmEvbGFuZy9J"
-"bnRlZ2VyOwAhTGphdmEvbGFuZy9OdW1iZXJGb3JtYXRFeGNlcHRpb247ABJMamF2YS9sYW5nL09i"
-"amVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAtPYmplY3QuamF2"
-"YQABVgACVkwAE1tMamF2YS9sYW5nL09iamVjdDsAE1tMamF2YS9sYW5nL1N0cmluZzsACWZpYm9u"
-"YWNjaQARZmlib25hY2NpKCVkKT0lZAoABG1haW4AA291dAAIcGFyc2VJbnQABnByaW50ZgAHdmFs"
-"dWVPZgADAAcOAAEABw4ADwEABx0tJgJ7HXgcAB4BAAcdPHhLARgPaQEYERwAAAABAAaBgATMAwAA"
-"AwAAgIAE4AMBCPgDAQmwBA0AAAAAAAAAAQAAAAAAAAABAAAAGgAAAHAAAAACAAAACwAAANgAAAAD"
-"AAAABgAAAAQBAAAEAAAAAQAAAEwBAAAFAAAABwAAAFQBAAAGAAAAAgAAAIwBAAABIAAABAAAAMwB"
-"AAABEAAABAAAANwCAAACIAAAGgAAAPoCAAADIAAABAAAAEAEAAAAIAAAAgAAAGgEAAAAEAAAAQAA"
-"AIQEAAA=";
+ "ZGV4CjAzNQBaslnMUQxaXYgC3gD9FGHjVb8cHZ60G8ckBQAAcAAAAHhWNBIAAAAAAAAAAIQEAAAa"
+ "AAAAcAAAAAsAAADYAAAABgAAAAQBAAABAAAATAEAAAcAAABUAQAAAgAAAIwBAABYAwAAzAEAAPoC"
+ "AAACAwAAEgMAABUDAAAZAwAAHQMAACoDAAAuAwAAMwMAAEoDAABfAwAAggMAAJYDAACqAwAAvgMA"
+ "AMsDAADOAwAA0gMAAOcDAAD8AwAABwQAABoEAAAgBAAAJQQAAC8EAAA3BAAAAgAAAAUAAAAIAAAA"
+ "CQAAAAoAAAALAAAADAAAAA0AAAAPAAAAEQAAABIAAAADAAAAAAAAANwCAAAEAAAAAAAAAOQCAAAH"
+ "AAAAAgAAAOwCAAAGAAAAAwAAANwCAAAPAAAACAAAAAAAAAAQAAAACAAAAPQCAAAHAAIAFgAAAAEA"
+ "BAAAAAAAAQAAABMAAAABAAUAFQAAAAIAAgAYAAAAAwABABcAAAADAAMAGQAAAAUABAAAAAAABQAA"
+ "AAEAAAD/////AAAAAA4AAAAAAAAAaAQAAAAAAAABAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAByBAAA"
+ "AAAAAAEAAQAAAAAAQAQAAAEAAAAOAAAAAQABAAEAAABFBAAABAAAAHAQBgAAAA4ABQABAAAAAABK"
+ "BAAAEwAAABIROQQEABIADwASMAESARMBAQEwNkH6/7AC2AEBAQEjAQIBMCj4AAAIAAEAAwABAFcE"
+ "AABIAAAAEhEhcDMQQwASAEYABwBxEAQAAAAKAHEQAQAAAAoBYgIAABoDFAASJCNECQASBXEQBQAA"
+ "AAwGTQYEBRIVcRAFAAEADAFNAQQFbjADADIE2AEAAXEQAQABAAoBYgIAABoDFAASJCNECQASBXEQ"
+ "BQAAAAwATQAEBRIQcRAFAAEADAFNAQQAbjADADIEDgANACj+AQAAAEQAAQABAQRGAQAAAAAAAAAB"
+ "AAAABgAAAAIAAAAGAAkAAQAAAAoABjxpbml0PgAORmlib25hY2NpLmphdmEAAUkAAklJAAJJTAAL"
+ "TEZpYm9uYWNjaTsAAkxJAANMTEwAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwATTGphdmEvbGFuZy9J"
+ "bnRlZ2VyOwAhTGphdmEvbGFuZy9OdW1iZXJGb3JtYXRFeGNlcHRpb247ABJMamF2YS9sYW5nL09i"
+ "amVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAtPYmplY3QuamF2"
+ "YQABVgACVkwAE1tMamF2YS9sYW5nL09iamVjdDsAE1tMamF2YS9sYW5nL1N0cmluZzsACWZpYm9u"
+ "YWNjaQARZmlib25hY2NpKCVkKT0lZAoABG1haW4AA291dAAIcGFyc2VJbnQABnByaW50ZgAHdmFs"
+ "dWVPZgADAAcOAAEABw4ADwEABx0tJgJ7HXgcAB4BAAcdPHhLARgPaQEYERwAAAABAAaBgATMAwAA"
+ "AwAAgIAE4AMBCPgDAQmwBA0AAAAAAAAAAQAAAAAAAAABAAAAGgAAAHAAAAACAAAACwAAANgAAAAD"
+ "AAAABgAAAAQBAAAEAAAAAQAAAEwBAAAFAAAABwAAAFQBAAAGAAAAAgAAAIwBAAABIAAABAAAAMwB"
+ "AAABEAAABAAAANwCAAACIAAAGgAAAPoCAAADIAAABAAAAEAEAAAAIAAAAgAAAGgEAAAAEAAAAQAA"
+ "AIQEAAA=";
+
+// class Interfaces {
+// interface I {
+// public void i();
+// }
+// interface J {
+// public void j1();
+// public void j2();
+// }
+// class A implements I, J {
+// public void i() {};
+// public void j1() {};
+// public void j2() {};
+// }
+// }
+static const char kInterfacesDex[] =
+ "ZGV4CjAzNQCRmX4RyqEIAGU0Pzgm7w3FvyUvYlel/coUBQAAcAAAAHhWNBIAAAAAAAAAAFAEAAAW"
+ "AAAAcAAAAAkAAADIAAAAAgAAAOwAAAABAAAABAEAAAkAAAAMAQAABAAAAFQBAABAAwAA1AEAAL4C"
+ "AADGAgAAyQIAAMwCAADdAgAA4AIAAPACAAAAAwAAEAMAAB4DAABCAwAAYgMAAIUDAACZAwAAnAMA"
+ "AKADAACtAwAAsAMAALQDAAC4AwAAvgMAAMYDAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAALAAAA"
+ "DAAAAA0AAAANAAAACAAAAAAAAAAOAAAACAAAALgCAAAAAAMAFAAAAAAAAQAAAAAAAAAAABAAAAAA"
+ "AAAAEQAAAAAAAAASAAAAAQAAABAAAAACAAAAEQAAAAIAAAASAAAAAwAAAAAAAAAHAAAAAAAAAAEA"
+ "AAAABgAABwAAAAAAAAADAAAAcAIAABcEAAAAAAAAAgAAAAAGAAAHAAAAAAAAAAMAAACAAgAAHwQA"
+ "AAAAAAAAAAAAAAAAAAcAAACwAgAAAwAAAJACAAArBAAAAAAAAAMAAAAAAAAABwAAAAAAAAADAAAA"
+ "oAIAAEQEAAAAAAAAAgAAAOgDAADuAwAAAgAAAOgDAAD4AwAAAgAAAOgDAAACBAAAAQAAAAsEAAAC"
+ "AAIAAQAAAM0DAAAGAAAAWwEAAHAQCAAAAA4AAQABAAAAAADTAwAAAQAAAA4AAAABAAEAAAAAANgD"
+ "AAABAAAADgAAAAEAAQAAAAAA3QMAAAEAAAAOAAAAAQABAAEAAADiAwAABAAAAHAQCAAAAA4A1AEA"
+ "AAAAAAAAAAAAAAAAAOABAAAAAAAAAAAAAAAAAADsAQAAAAAAAAAAAAAAAAAA+AEAAAAAAAAAAAAA"
+ "AAAAAAIAAAABAAIAAQAAAAMABjxpbml0PgABQQABSQAPSW50ZXJmYWNlcy5qYXZhAAFKAA5MSW50"
+ "ZXJmYWNlcyRBOwAOTEludGVyZmFjZXMkSTsADkxJbnRlcmZhY2VzJEo7AAxMSW50ZXJmYWNlczsA"
+ "IkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9J"
+ "bm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABJMamF2YS9sYW5n"
+ "L09iamVjdDsAAVYAAlZMAAthY2Nlc3NGbGFncwABaQACajEAAmoyAARuYW1lAAZ0aGlzJDAABXZh"
+ "bHVlAAoBAAcOAAsABw4ADAAHDgANAAcOAAIABw5DAAIEARUYAwIFAg8kCAYTFwICBQIPJAgGExcE"
+ "AgUCDwQAExcBAgYBFRwDGAAYAhgBAAAAAQSBCAAAAAACBYEIAAGBCAAAAQEDAJAgAICABIAEAQGc"
+ "BAEBsAQBAcQEAAABAAeAgATYBAAAEAAAAAAAAAABAAAAAAAAAAEAAAAWAAAAcAAAAAIAAAAJAAAA"
+ "yAAAAAMAAAACAAAA7AAAAAQAAAABAAAABAEAAAUAAAAJAAAADAEAAAYAAAAEAAAAVAEAAAMQAAAE"
+ "AAAA1AEAAAEgAAAFAAAAAAIAAAYgAAAEAAAAcAIAAAEQAAACAAAAsAIAAAIgAAAWAAAAvgIAAAMg"
+ "AAAFAAAAzQMAAAQgAAAFAAAA6AMAAAAgAAAEAAAAFwQAAAAQAAABAAAAUAQAAA==";
static inline DexFile* OpenDexFileBase64(const char* base64,
const std::string& location) {
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 89519c4..0d7b256 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -293,17 +293,17 @@
}
Method* FindVirtualMethod(Object* receiver, Method* method) {
- return receiver->GetClass()->GetMethodByVtableIndex(method->GetVtableIndex());
+ return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method);
}
-JValue InvokeVirtualWithJValues(ScopedJniThreadState& ts, jobject obj, jmethodID mid, jvalue* args) {
+JValue InvokeVirtualOrInterfaceWithJValues(ScopedJniThreadState& ts, jobject obj, jmethodID mid, jvalue* args) {
Object* receiver = Decode<Object*>(ts, obj);
Method* method = FindVirtualMethod(receiver, DecodeMethod(ts, mid));
scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
return InvokeWithArgArray(ts, receiver, method, arg_array.get());
}
-JValue InvokeVirtualWithVarArgs(ScopedJniThreadState& ts, jobject obj, jmethodID mid, va_list args) {
+JValue InvokeVirtualOrInterfaceWithVarArgs(ScopedJniThreadState& ts, jobject obj, jmethodID mid, va_list args) {
Object* receiver = Decode<Object*>(ts, obj);
Method* method = FindVirtualMethod(receiver, DecodeMethod(ts, mid));
scoped_array<byte> arg_array(CreateArgArray(ts, method, args));
@@ -1001,20 +1001,20 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return AddLocalReference<jobject>(ts, result.l);
}
static jobject CallObjectMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, args);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args);
return AddLocalReference<jobject>(ts, result.l);
}
static jobject CallObjectMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- JValue result = InvokeVirtualWithJValues(ts, obj, mid, args);
+ JValue result = InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args);
return AddLocalReference<jobject>(ts, result.l);
}
@@ -1022,170 +1022,170 @@
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.z;
}
static jboolean CallBooleanMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).z;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).z;
}
static jboolean CallBooleanMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).z;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).z;
}
static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.b;
}
static jbyte CallByteMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).b;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).b;
}
static jbyte CallByteMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).b;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).b;
}
static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.c;
}
static jchar CallCharMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).c;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).c;
}
static jchar CallCharMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).c;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).c;
}
static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.d;
}
static jdouble CallDoubleMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).d;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).d;
}
static jdouble CallDoubleMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).d;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).d;
}
static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.f;
}
static jfloat CallFloatMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).f;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).f;
}
static jfloat CallFloatMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).f;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).f;
}
static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.i;
}
static jint CallIntMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).i;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).i;
}
static jint CallIntMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).i;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).i;
}
static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.j;
}
static jlong CallLongMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).j;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).j;
}
static jlong CallLongMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).j;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).j;
}
static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
return result.s;
}
static jshort CallShortMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithVarArgs(ts, obj, mid, args).s;
+ return InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args).s;
}
static jshort CallShortMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- return InvokeVirtualWithJValues(ts, obj, mid, args).s;
+ return InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args).s;
}
static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
ScopedJniThreadState ts(env);
va_list ap;
va_start(ap, mid);
- JValue result = InvokeVirtualWithVarArgs(ts, obj, mid, ap);
+ JValue result = InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, ap);
va_end(ap);
}
static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
ScopedJniThreadState ts(env);
- InvokeVirtualWithVarArgs(ts, obj, mid, args);
+ InvokeVirtualOrInterfaceWithVarArgs(ts, obj, mid, args);
}
static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
ScopedJniThreadState ts(env);
- InvokeVirtualWithJValues(ts, obj, mid, args);
+ InvokeVirtualOrInterfaceWithJValues(ts, obj, mid, args);
}
static jobject CallNonvirtualObjectMethod(JNIEnv* env,
diff --git a/src/object.cc b/src/object.cc
index d06c3e3..5d64466 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -25,7 +25,7 @@
// recursively all super-interfaces of those interfaces, are listed
// in iftable_, so we can just do a linear scan through that.
for (size_t i = 0; i < iftable_count_; i++) {
- if (iftable_[i].GetClass() == klass) {
+ if (iftable_[i].GetInterface() == klass) {
return true;
}
}
@@ -434,6 +434,20 @@
this->GetSignature()->Equals(that->GetSignature()));
}
+Method* Class::FindVirtualMethodForInterface(Method* method) {
+ Class* declaring_class = method->GetDeclaringClass();
+ DCHECK(declaring_class->IsInterface());
+ // TODO cache to improve lookup speed
+ for (size_t i = 0; i < iftable_count_; i++) {
+ InterfaceEntry& interface_entry = iftable_[i];
+ if (interface_entry.GetInterface() == declaring_class) {
+ return vtable_->Get(interface_entry.method_index_array_[method->method_index_]);
+ }
+ }
+ UNIMPLEMENTED(FATAL) << "Need to throw an error of some kind";
+ return NULL;
+}
+
Method* Class::FindDeclaredDirectMethod(const StringPiece& name,
const StringPiece& signature) {
for (size_t i = 0; i < NumDirectMethods(); ++i) {
diff --git a/src/object.h b/src/object.h
index 2657872..6c8fd6b 100644
--- a/src/object.h
+++ b/src/object.h
@@ -498,10 +498,6 @@
return pc;
}
- size_t GetVtableIndex() const {
- return method_index_;
- }
-
public: // TODO: private
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// the class we are a part of
@@ -670,10 +666,10 @@
uint32_t access_flags_;
// For concrete virtual methods, this is the offset of the method
- // in "vtable".
+ // in Class::vtable_.
//
// For abstract methods in an interface class, this is the offset
- // of the method in "iftable[n]->methodIndexArray".
+ // of the method in "iftable_[n]->method_index_array_".
uint16_t method_index_;
// Method bounds; not needed for an abstract method.
@@ -1117,8 +1113,26 @@
virtual_methods_->Set(i, f);
}
- Method* GetMethodByVtableIndex(size_t vtable_index) {
- return vtable_->Get(vtable_index);
+ // Given a method implemented by this class but potentially from a
+ // super class, return the specific implementation
+ // method for this class.
+ Method* FindVirtualMethodForVirtual(Method* method) {
+ DCHECK(!method->GetDeclaringClass()->IsInterface());
+ // The argument method may from a super class.
+ // Use the index to a potentially overriden one for this instance's class.
+ return vtable_->Get(method->method_index_);
+ }
+
+ // Given a method implemented by this class, but potentially from a
+ // super class or interface, return the specific implementation
+ // method for this class.
+ Method* FindVirtualMethodForInterface(Method* method);
+
+ Method* FindVirtualMethodForVirtualOrInterface(Method* method) {
+ if (method->GetDeclaringClass()->IsInterface()) {
+ return FindVirtualMethodForInterface(method);
+ }
+ return FindVirtualMethodForVirtual(method);
}
Method* FindDeclaredVirtualMethod(const StringPiece& name,
@@ -1289,7 +1303,7 @@
// our class either replace those from the super or are appended.
ObjectArray<Method>* vtable_;
- // Interface table (iftable), one entry per interface supported by
+ // Interface table (iftable_), one entry per interface supported by
// this class. That means one entry for each interface we support
// directly, indirectly via superclass, or indirectly via
// superinterface. This will be null if neither we nor our
@@ -1303,12 +1317,14 @@
// For every interface a concrete class implements, we create a list
// of virtualMethod indices for the methods in the interface.
size_t iftable_count_;
+ // TODO convert to ObjectArray<?>
InterfaceEntry* iftable_;
// The interface vtable indices for iftable get stored here. By
// placing them all in a single pool for each class that implements
// interfaces, we decrease the number of allocations.
size_t ifvi_pool_count_;
+ // TODO convert to IntArray
uint32_t* ifvi_pool_;
// instance fields
@@ -1694,24 +1710,26 @@
class InterfaceEntry {
public:
- InterfaceEntry() : klass_(NULL), method_index_array_(NULL) {
+ InterfaceEntry() : interface_(NULL), method_index_array_(NULL) {
}
- Class* GetClass() const {
- return klass_;
+ Class* GetInterface() const {
+ DCHECK(interface_ != NULL);
+ return interface_;
}
- void SetClass(Class* klass) {
- klass_ = klass;
+ void SetInterface(Class* interface) {
+ DCHECK(interface->IsInterface());
+ interface_ = interface;
}
private:
// Points to the interface class.
- Class* klass_;
+ Class* interface_;
public: // TODO: private
// Index into array of vtable offsets. This points into the
- // ifviPool, which holds the vtables for all interfaces declared by
+ // ifvi_pool_, which holds the vtables for all interfaces declared by
// this class.
uint32_t* method_index_array_;