Prepare JVM runtime for support of reflection on functions

Introduce abstract class FunctionReference, which is supposed to be a
superclass for all anonymous classes generated for function references. Each
anonymous subclass will have statically-generated symbol info, which will be
used by reflection to locate the symbol
This commit is contained in:
Alexander Udalov
2015-05-21 05:00:12 +03:00
parent 9aeae7ddc6
commit 9ba6d91e2e
12 changed files with 95 additions and 117 deletions
@@ -53,6 +53,7 @@ import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
@@ -215,7 +216,10 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
}
@NotNull
public StackValue putInstanceOnStack(@NotNull final ExpressionCodegen codegen) {
public StackValue putInstanceOnStack(
@NotNull final ExpressionCodegen codegen,
@Nullable final FunctionDescriptor functionReferenceTarget
) {
return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
@@ -229,11 +233,37 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator);
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
}
if (functionReferenceTarget != null) {
equipFunctionReferenceWithReflection(v, functionReferenceTarget);
}
return Unit.INSTANCE$;
}
});
}
private static void equipFunctionReferenceWithReflection(@NotNull InstructionAdapter v, @NotNull FunctionDescriptor target) {
DeclarationDescriptor container = target.getContainingDeclaration();
Type type;
if (container instanceof PackageFragmentDescriptor) {
type = target.getExtensionReceiverParameter() != null
? K_TOP_LEVEL_EXTENSION_FUNCTION
: K_TOP_LEVEL_FUNCTION;
}
else if (container instanceof ClassDescriptor) {
type = K_MEMBER_FUNCTION;
}
else {
type = K_LOCAL_FUNCTION;
}
Method method = method("function", K_FUNCTION, FUNCTION_REFERENCE);
v.invokestatic(REFLECTION, method.getName(), method.getDescriptor(), false);
StackValue.coerce(K_FUNCTION, type, v);
}
private void generateConstInstance() {
MethodVisitor mv = v.newMethod(OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY);
@@ -1396,7 +1396,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText();
return genClosure(
declaration, descriptor, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), samType, kind
declaration, descriptor, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), samType, kind, null
);
}
@@ -1406,7 +1406,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@NotNull FunctionDescriptor descriptor,
@NotNull FunctionGenerationStrategy strategy,
@Nullable SamType samType,
@NotNull KotlinSyntheticClass.Kind kind
@NotNull KotlinSyntheticClass.Kind kind,
@Nullable FunctionDescriptor functionReferenceTarget
) {
ClassBuilder cv = state.getFactory().newVisitor(
OtherOrigin(declaration, descriptor),
@@ -1425,7 +1426,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages());
}
return closureCodegen.putInstanceOnStack(this);
return closureCodegen.putInstanceOnStack(this, functionReferenceTarget);
}
@Override
@@ -2702,7 +2703,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
if (functionDescriptor != null) {
FunctionReferenceGenerationStrategy strategy = new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall);
return genClosure(expression, functionDescriptor, strategy, null, KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER);
return genClosure(expression, functionDescriptor, strategy, null, KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER,
(FunctionDescriptor) resolvedCall.getResultingDescriptor());
}
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.builtins.ReflectionTypes;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
@@ -28,26 +27,19 @@ import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM;
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
import org.jetbrains.kotlin.types.JetType;
import org.jetbrains.kotlin.types.JetTypeImpl;
import org.jetbrains.kotlin.types.TypeProjection;
import org.jetbrains.kotlin.types.TypeProjectionImpl;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
public class JvmRuntimeTypes {
private final ReflectionTypes reflectionTypes;
private final ClassDescriptor lambda;
private final ClassDescriptor functionImpl;
private final ClassDescriptor memberFunctionImpl;
private final ClassDescriptor extensionFunctionImpl;
public JvmRuntimeTypes(@NotNull ReflectionTypes reflectionTypes) {
this.reflectionTypes = reflectionTypes;
private final ClassDescriptor functionReference;
public JvmRuntimeTypes() {
ModuleDescriptorImpl module = new ModuleDescriptorImpl(
Name.special("<jvm functions impl>"),
LockBasedStorageManager.NO_LOCKS,
@@ -56,9 +48,7 @@ public class JvmRuntimeTypes {
PackageFragmentDescriptor kotlinJvmInternal = new MutablePackageFragmentDescriptor(module, new FqName("kotlin.jvm.internal"));
this.lambda = createClass(kotlinJvmInternal, "Lambda");
this.functionImpl = createClass(kotlinJvmInternal, "FunctionImpl");
this.memberFunctionImpl = createClass(kotlinJvmInternal, "MemberFunctionImpl");
this.extensionFunctionImpl = createClass(kotlinJvmInternal, "ExtensionFunctionImpl");
this.functionReference = createClass(kotlinJvmInternal, "FunctionReference");
}
@NotNull
@@ -95,41 +85,8 @@ public class JvmRuntimeTypes {
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
ReceiverParameterDescriptor dispatchReceiver = descriptor.getDispatchReceiverParameter();
List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(2);
ClassDescriptor kFunctionClass;
ClassDescriptor functionImplClass;
JetType receiverType;
if (extensionReceiver != null) {
functionImplClass = extensionFunctionImpl;
receiverType = extensionReceiver.getType();
kFunctionClass = reflectionTypes.getkExtensionFunction();
typeArguments.add(new TypeProjectionImpl(receiverType));
}
else if (dispatchReceiver != null) {
functionImplClass = memberFunctionImpl;
receiverType = dispatchReceiver.getType();
kFunctionClass = reflectionTypes.getkMemberFunction();
typeArguments.add(new TypeProjectionImpl(receiverType));
}
else {
functionImplClass = functionImpl;
receiverType = null;
kFunctionClass = reflectionTypes.getkFunction();
}
JetType functionImplType = functionImplClass.getDefaultType();
//noinspection ConstantConditions
typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
JetType kFunctionType = new JetTypeImpl(
kFunctionClass.getDefaultType().getAnnotations(),
kFunctionClass.getTypeConstructor(),
false,
typeArguments,
kFunctionClass.getMemberScope(typeArguments)
);
JetType receiverType =
extensionReceiver != null ? extensionReceiver.getType() : dispatchReceiver != null ? dispatchReceiver.getType() : null;
//noinspection ConstantConditions
JetType functionType = getBuiltIns(descriptor).getFunctionType(
@@ -139,6 +96,6 @@ public class JvmRuntimeTypes {
descriptor.getReturnType()
);
return Arrays.asList(functionImplType, kFunctionType, functionType);
return Arrays.asList(functionReference.getDefaultType(), functionType);
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.state;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.ReflectionTypes;
import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension;
@@ -35,7 +36,6 @@ import org.jetbrains.kotlin.psi.JetScript;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace;
import org.jetbrains.kotlin.builtins.ReflectionTypes;
import java.io.File;
import java.util.Collection;
@@ -211,7 +211,8 @@ public class GenerationState {
this.generateClassFilter = generateClassFilter;
this.reflectionTypes = new ReflectionTypes(module);
this.runtimeTypes = new JvmRuntimeTypes(reflectionTypes);
this.runtimeTypes = new JvmRuntimeTypes();
this.inlineCycleReporter = new InlineCycleReporter(diagnostics);
}
@@ -35,11 +35,18 @@ public class AsmTypes {
public static final Type PROPERTY_METADATA_IMPL_TYPE = Type.getObjectType("kotlin/PropertyMetadataImpl");
public static final Type LAMBDA = Type.getObjectType("kotlin/jvm/internal/Lambda");
public static final Type FUNCTION_REFERENCE = Type.getObjectType("kotlin/jvm/internal/FunctionReference");
public static final Type K_CLASS_TYPE = reflect("KClass");
public static final Type K_CLASS_ARRAY_TYPE = Type.getObjectType("[" + K_CLASS_TYPE.getDescriptor());
public static final Type K_PACKAGE_TYPE = reflect("KPackage");
public static final Type K_FUNCTION = reflect("KFunction");
public static final Type K_TOP_LEVEL_FUNCTION = reflect("KTopLevelFunction");
public static final Type K_MEMBER_FUNCTION = reflect("KMemberFunction");
public static final Type K_TOP_LEVEL_EXTENSION_FUNCTION = reflect("KTopLevelExtensionFunction");
public static final Type K_LOCAL_FUNCTION = reflect("KLocalFunction");
public static final Type K_MEMBER_PROPERTY_TYPE = reflect("KMemberProperty");
public static final Type K_MUTABLE_MEMBER_PROPERTY_TYPE = reflect("KMutableMemberProperty");
public static final Type K_TOP_LEVEL_VARIABLE_TYPE = reflect("KTopLevelVariable");
@@ -14,11 +14,11 @@
* limitations under the License.
*/
package kotlin.reflect.jvm.internal
import kotlin.jvm.internal.ExtensionFunctionImpl
package kotlin.reflect
/**
* @suppress
* Represents a local function.
*
* @param R the return type of the function.
*/
public abstract class KExtensionFunctionImpl<in T, out R> : ExtensionFunctionImpl<T, R>()
public interface KLocalFunction<out R> : KFunction<R>
@@ -16,6 +16,7 @@
package kotlin.reflect.jvm.internal;
import kotlin.jvm.internal.FunctionReference;
import kotlin.jvm.internal.ReflectionFactory;
import kotlin.reflect.*;
@@ -39,6 +40,15 @@ public class ReflectionFactoryImpl extends ReflectionFactory {
return InternalPackage.foreignKotlinClass(javaClass);
}
// Functions
@Override
public KFunction function(FunctionReference f) {
return f;
}
// Properties
@Override
public KMemberProperty memberProperty(String name, KClass owner) {
return ((KClassImpl) owner).memberProperty(name);
@@ -1,23 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.jvm.internal
import java.io.Serializable
public abstract class ExtensionFunctionImpl : Serializable {
override fun toString() = "${(this as Object).getClass().getGenericInterfaces()[0]}"
}
@@ -14,13 +14,14 @@
* limitations under the License.
*/
package kotlin.reflect.jvm.internal
package kotlin.jvm.internal;
import java.io.Serializable
import kotlin.reflect.*;
/**
* @suppress
*/
public abstract class KMemberFunctionImpl<in T, out R> : Serializable {
override fun toString() = "${javaClass.getGenericInterfaces().first()}"
public abstract class FunctionReference
extends FunctionImpl
implements KTopLevelFunction,
KMemberFunction,
KTopLevelExtensionFunction,
KLocalFunction {
}
@@ -1,23 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.jvm.internal
import java.io.Serializable
public abstract class MemberFunctionImpl : Serializable {
override fun toString() = "${(this as Object).getClass().getGenericInterfaces()[0]}"
}
@@ -59,6 +59,14 @@ public class Reflection {
return factory.foreignKotlinClass(javaClass);
}
// Functions
public static KFunction function(FunctionReference f) {
return factory.function(f);
}
// Properties
public static KMemberProperty memberProperty(String name, KClass owner) {
return factory.memberProperty(name, owner);
}
@@ -32,6 +32,14 @@ public class ReflectionFactory {
throw error();
}
// Functions
public KFunction function(FunctionReference f) {
return f;
}
// Properties
public KMemberProperty memberProperty(String name, KClass owner) {
throw error();
}