From d128827a3428e655ef65142407cae7cdd0ca986b Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 7 Sep 2016 13:31:00 +0300 Subject: [PATCH] Inherit FunctionReference from CallableReference This became possible now because FunctionImpl is no longer a class --- .../jvm/internal/ReflectionFactoryImpl.java | 5 - .../jvm/internal/CallableReference.java | 47 ++++---- .../jvm/internal/FunctionReference.java | 100 ++---------------- .../jvm/internal/PropertyReference.java | 3 +- 4 files changed, 36 insertions(+), 119 deletions(-) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java index 8090e9bc8e4..cef8d24ebbd 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java @@ -105,9 +105,4 @@ public class ReflectionFactoryImpl extends ReflectionFactory { KDeclarationContainer owner = reference.getOwner(); return owner instanceof KDeclarationContainerImpl ? ((KDeclarationContainerImpl) owner) : EmptyContainerForLocal.INSTANCE; } - - private static KDeclarationContainerImpl getOwner(FunctionReference reference) { - KDeclarationContainer owner = reference.getOwner(); - return owner instanceof KDeclarationContainerImpl ? ((KDeclarationContainerImpl) owner) : EmptyContainerForLocal.INSTANCE; - } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java index da51704a44c..16e6024d28c 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java @@ -28,14 +28,36 @@ import java.util.Map; /** * A superclass for all classes generated by Kotlin compiler for callable references. * - * All methods from reflection API should be implemented here to throw informative exceptions (see KotlinReflectionNotSupportedError) + * All methods from KCallable should be implemented here and should delegate to the actual implementation, loaded dynamically + * and stored in the {@link CallableReference#reflected} field. */ @SuppressWarnings({"unchecked", "NullableProblems"}) public abstract class CallableReference implements KCallable { - protected KCallable reflected; + // This field is not volatile intentionally: + // 1) It's fine if the value is computed multiple times in different threads; + // 2) An uninitialized value cannot be observed in this field from other thread because only already initialized or safely initialized + // objects are written to it. The latter is guaranteed because both KFunctionImpl and KPropertyImpl have at least one final field. + private KCallable reflected; protected abstract KCallable computeReflected(); + public KCallable compute() { + KCallable result = reflected; + if (result == null) { + result = computeReflected(); + reflected = result; + } + return result; + } + + protected KCallable getReflected() { + KCallable result = compute(); + if (result == this) { + throw new KotlinReflectionNotSupportedError(); + } + return result; + } + // The following methods provide the information identifying this callable, which is used by the reflection implementation. // They are supposed to be overridden in each subclass (each anonymous class generated for a callable reference). @@ -66,8 +88,8 @@ public abstract class CallableReference implements KCallable { throw new AbstractMethodError(); } - // The following methods are the stub implementations of reflection functions. - // They are called when you're using reflection on a property reference without the reflection implementation in the classpath. + // The following methods are the delegating implementations of reflection functions. They are called when you're using reflection + // on a callable reference. Without kotlin-reflect.jar in the classpath, getReflected() throws an exception. @Override public List getParameters() { @@ -120,21 +142,4 @@ public abstract class CallableReference implements KCallable { public boolean isAbstract() { return getReflected().isAbstract(); } - - public KCallable compute() { - KCallable result = reflected; - if (result == null) { - result = computeReflected(); - reflected = result; - } - return result; - } - - protected KCallable getReflected() { - KCallable result = compute(); - if (result == this) { - throw new KotlinReflectionNotSupportedError(); - } - return result; - } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java index adfc7c530e9..27feeeefcf4 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java @@ -16,19 +16,11 @@ package kotlin.jvm.internal; -import kotlin.jvm.KotlinReflectionNotSupportedError; -import kotlin.reflect.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import kotlin.reflect.KCallable; +import kotlin.reflect.KFunction; -import java.lang.annotation.Annotation; -import java.util.List; -import java.util.Map; - -@SuppressWarnings({"unchecked", "NullableProblems"}) -public class FunctionReference implements FunctionImpl, KFunction { +public class FunctionReference extends CallableReference implements FunctionImpl, KFunction { private final int arity; - private KFunction reflected; public FunctionReference(int arity) { this.arity = arity; @@ -39,71 +31,14 @@ public class FunctionReference implements FunctionImpl, KFunction { return arity; } - // Most of the following methods are copies from CallableReference, since this class cannot inherit from it - - public KDeclarationContainer getOwner() { - throw new AbstractMethodError(); + @Override + protected KFunction getReflected() { + return (KFunction) super.getReflected(); } @Override - public String getName() { - throw new AbstractMethodError(); - } - - public String getSignature() { - throw new AbstractMethodError(); - } - - @Override - public List getParameters() { - return getReflected().getParameters(); - } - - @Override - public KType getReturnType() { - return getReflected().getReturnType(); - } - - @Override - public List getAnnotations() { - return getReflected().getAnnotations(); - } - - @NotNull - @Override - public List getTypeParameters() { - return getReflected().getTypeParameters(); - } - - @Override - public Object call(@NotNull Object... args) { - return getReflected().call(args); - } - - @Override - public Object callBy(@NotNull Map args) { - return getReflected().callBy(args); - } - - @Nullable - @Override - public KVisibility getVisibility() { - return getReflected().getVisibility(); - } - - @Override - public boolean isFinal() { - return getReflected().isFinal(); - } - - @Override - public boolean isOpen() { - return getReflected().isOpen(); - } - - @Override - public boolean isAbstract() { - return getReflected().isAbstract(); + protected KCallable computeReflected() { + return Reflection.function(this); } @Override @@ -158,7 +93,7 @@ public class FunctionReference implements FunctionImpl, KFunction { @Override public String toString() { - KFunction reflected = compute(); + KCallable reflected = compute(); if (reflected != this) { return reflected.toString(); } @@ -168,21 +103,4 @@ public class FunctionReference implements FunctionImpl, KFunction { ? "constructor" + Reflection.REFLECTION_NOT_AVAILABLE : "function " + getName() + Reflection.REFLECTION_NOT_AVAILABLE; } - - public KFunction compute() { - KFunction result = reflected; - if (result == null) { - result = Reflection.function(this); - reflected = result; - } - return result; - } - - private KFunction getReflected() { - KFunction result = compute(); - if (result == this) { - throw new KotlinReflectionNotSupportedError(); - } - return result; - } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java index 3341ea18968..71512db7ba0 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java @@ -45,8 +45,7 @@ public abstract class PropertyReference extends CallableReference implements KPr getSignature().equals(other.getSignature()); } if (obj instanceof KProperty) { - compute(); - return obj.equals(reflected); + return obj.equals(compute()); } return false; }