summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/mirror/var_handle.cc67
-rw-r--r--runtime/mirror/var_handle.h7
-rw-r--r--runtime/well_known_classes.cc3
-rw-r--r--runtime/well_known_classes.h1
4 files changed, 20 insertions, 58 deletions
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc
index 9a78758608..202134a1dc 100644
--- a/runtime/mirror/var_handle.cc
+++ b/runtime/mirror/var_handle.cc
@@ -1429,18 +1429,19 @@ VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode acces
ObjPtr<VarHandle> vh = this;
ObjPtr<Class> var_type = vh->GetVarType();
ObjPtr<Class> mt_rtype = method_type->GetRType();
+ ObjPtr<Class> void_type = WellKnownClasses::ToClass(WellKnownClasses::java_lang_Void);
AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
- // Check return type first. If the return type of the method
- // of the VarHandle is immaterial.
- if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid) {
- ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
- if (vh_rtype != mt_rtype) {
- if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
- return MatchKind::kNone;
- }
- match = MatchKind::kWithConversions;
+ // Check return type first.
+ ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
+ if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid &&
+ !mt_rtype->IsAssignableFrom(vh_rtype)) {
+ // Call-site is an expression (expects a return value) and the value returned by the accessor
+ // is not assignable to the expected return type.
+ if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
+ return MatchKind::kNone;
}
+ match = MatchKind::kWithConversions;
}
// Check the number of parameters matches.
@@ -1457,7 +1458,12 @@ VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode acces
// Check the parameter types are compatible.
ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
for (int32_t i = 0; i < vh_ptypes_count; ++i) {
- if (mt_ptypes->Get(i) == vh_ptypes[i]) {
+ if (vh_ptypes[i]->IsAssignableFrom(mt_ptypes->Get(i))) {
+ continue;
+ }
+ if (mt_ptypes->Get(i) == void_type && !vh_ptypes[i]->IsPrimitive()) {
+ // The expected parameter is a reference and the parameter type from the call site is j.l.Void
+ // which means the value is null. It is always valid for a reference parameter to be null.
continue;
}
if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) {
@@ -1468,47 +1474,6 @@ VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode acces
return match;
}
-bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode,
- ObjPtr<MethodType> method_type) {
- StackHandleScope<3> hs(Thread::Current());
- Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType()));
- Handle<VarHandle> vh(hs.NewHandle(this));
- Handle<Class> var_type(hs.NewHandle(vh->GetVarType()));
- AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
-
- // Check return type first.
- if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
- // The result of the operation will be discarded. The return type
- // of the VarHandle is immaterial.
- } else {
- ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get()));
- if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) {
- return false;
- }
- }
-
- // Check the number of parameters matches (ignoring the VarHandle parameter).
- static const int32_t kVarHandleParameters = 1;
- ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
- const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
- access_mode_template,
- var_type.Get(),
- GetCoordinateType0(),
- GetCoordinateType1());
- if (vh_ptypes_count != method_type->GetPTypes()->GetLength() - kVarHandleParameters) {
- return false;
- }
-
- // Check the parameter types are compatible (ignoring the VarHandle parameter).
- ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
- for (int32_t i = 0; i < vh_ptypes_count; ++i) {
- if (!IsParameterTypeConvertible(mt_ptypes->Get(i + kVarHandleParameters), vh_ptypes[i])) {
- return false;
- }
- }
- return true;
-}
-
ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self,
ObjPtr<VarHandle> var_handle,
AccessMode access_mode) {
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index 01920bdf61..83cf2e1111 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -111,13 +111,6 @@ class MANAGED VarHandle : public Object {
MatchKind GetMethodTypeMatchForAccessMode(AccessMode access_mode, ObjPtr<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Returns true if the MethodType specified is compatible with the
- // specified access_mode if the first parameter of method_type is
- // ignored. This is useful for comparing MethodType instances when
- // invoking a VarHandleAccessor via a MethodHandle invoker.
- bool IsInvokerMethodTypeCompatible(AccessMode access_mode, ObjPtr<MethodType> method_type)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// Allocates and returns the MethodType associated with the
// AccessMode. No check is made for whether the AccessMode is a
// supported operation so the MethodType can be used when raising a
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 8f0581e4db..3b3a1a3f9f 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -75,6 +75,7 @@ jclass WellKnownClasses::java_lang_System;
jclass WellKnownClasses::java_lang_Thread;
jclass WellKnownClasses::java_lang_ThreadGroup;
jclass WellKnownClasses::java_lang_Throwable;
+jclass WellKnownClasses::java_lang_Void;
jclass WellKnownClasses::java_nio_Buffer;
jclass WellKnownClasses::java_nio_ByteBuffer;
jclass WellKnownClasses::java_nio_DirectByteBuffer;
@@ -366,6 +367,7 @@ void WellKnownClasses::Init(JNIEnv* env) {
java_lang_Thread = CacheClass(env, "java/lang/Thread");
java_lang_ThreadGroup = CacheClass(env, "java/lang/ThreadGroup");
java_lang_Throwable = CacheClass(env, "java/lang/Throwable");
+ java_lang_Void = CacheClass(env, "java/lang/Void");
java_nio_Buffer = CacheClass(env, "java/nio/Buffer");
java_nio_ByteBuffer = CacheClass(env, "java/nio/ByteBuffer");
java_nio_DirectByteBuffer = CacheClass(env, "java/nio/DirectByteBuffer");
@@ -543,6 +545,7 @@ void WellKnownClasses::Clear() {
java_lang_Thread = nullptr;
java_lang_ThreadGroup = nullptr;
java_lang_Throwable = nullptr;
+ java_lang_Void = nullptr;
java_util_Collections = nullptr;
java_nio_Buffer = nullptr;
java_nio_ByteBuffer = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 35c007d9f2..b2e01aed55 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -88,6 +88,7 @@ struct WellKnownClasses {
static jclass java_lang_Thread;
static jclass java_lang_ThreadGroup;
static jclass java_lang_Throwable;
+ static jclass java_lang_Void;
static jclass java_nio_Buffer;
static jclass java_nio_ByteBuffer;
static jclass java_nio_DirectByteBuffer;