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:
@@ -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");
|
||||
|
||||
+5
-5
@@ -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]}"
|
||||
}
|
||||
+8
-7
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user