diff options
| -rw-r--r-- | runtime/mirror/var_handle.cc | 67 | ||||
| -rw-r--r-- | runtime/mirror/var_handle.h | 7 | ||||
| -rw-r--r-- | runtime/well_known_classes.cc | 3 | ||||
| -rw-r--r-- | runtime/well_known_classes.h | 1 |
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; |