Introduce ReflectionTypes, use it in JVM back-end
Make FunctionTypesUtil a component
This commit is contained in:
@@ -69,8 +69,6 @@ import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.jet.codegen.FunctionTypesUtil.functionTypeToImpl;
|
||||
import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionImplType;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
|
||||
@@ -1312,7 +1310,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
FunctionDescriptor descriptor = bindingContext.get(FUNCTION, declaration);
|
||||
assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText();
|
||||
|
||||
Type closureSuperClass = samInterfaceClass == null ? getFunctionImplType(descriptor) : OBJECT_TYPE;
|
||||
String functionImplClassPrefix = descriptor.getReceiverParameter() != null ? "ExtensionFunctionImpl" : "FunctionImpl";
|
||||
Type closureSuperClass =
|
||||
samInterfaceClass == null ?
|
||||
Type.getObjectType("kotlin/" + functionImplClassPrefix + descriptor.getValueParameters().size()) :
|
||||
OBJECT_TYPE;
|
||||
|
||||
ClosureCodegen closureCodegen = new ClosureCodegen(state, declaration, descriptor, samInterfaceClass, closureSuperClass, context,
|
||||
kind, this, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), parentCodegen);
|
||||
@@ -2416,7 +2418,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
JetType kFunctionType = bindingContext.get(EXPRESSION_TYPE, expression);
|
||||
assert kFunctionType != null : "Callable reference is not type checked: " + expression.getText();
|
||||
ClassDescriptor kFunctionImpl = functionTypeToImpl(kFunctionType);
|
||||
ClassDescriptor kFunctionImpl = state.getFunctionTypesUtil().kFunctionTypeToImpl(kFunctionType);
|
||||
assert kFunctionImpl != null : "Impl type is not found for the function type: " + kFunctionType;
|
||||
|
||||
Type closureSuperClass = typeMapper.mapType(kFunctionImpl);
|
||||
|
||||
@@ -19,10 +19,10 @@ package org.jetbrains.jet.codegen;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
|
||||
import org.jetbrains.jet.lang.reflect.ReflectionTypes;
|
||||
import org.jetbrains.jet.lang.resolve.ImportPath;
|
||||
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
@@ -37,24 +37,22 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.lang.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
|
||||
|
||||
public class FunctionTypesUtil {
|
||||
private static final List<ClassDescriptor> FUNCTIONS;
|
||||
private static final List<ClassDescriptor> EXTENSION_FUNCTIONS;
|
||||
private static final List<ClassDescriptor> K_FUNCTIONS;
|
||||
private static final List<ClassDescriptor> K_MEMBER_FUNCTIONS;
|
||||
private static final List<ClassDescriptor> K_EXTENSION_FUNCTIONS;
|
||||
private final List<ClassDescriptor> functions;
|
||||
private final List<ClassDescriptor> extensionFunctions;
|
||||
private final List<ClassDescriptor> kFunctions;
|
||||
private final List<ClassDescriptor> kMemberFunctions;
|
||||
private final List<ClassDescriptor> kExtensionFunctions;
|
||||
|
||||
private static final ImmutableMap<ClassDescriptor, ClassDescriptor> FUNCTION_TO_IMPL;
|
||||
private final ImmutableMap<ClassDescriptor, ClassDescriptor> kFunctionToImpl;
|
||||
|
||||
static {
|
||||
public FunctionTypesUtil(@NotNull ReflectionTypes reflectionTypes) {
|
||||
int n = KotlinBuiltIns.FUNCTION_TRAIT_COUNT;
|
||||
FUNCTIONS = new ArrayList<ClassDescriptor>(n);
|
||||
EXTENSION_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
|
||||
K_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
|
||||
K_MEMBER_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
|
||||
K_EXTENSION_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
|
||||
functions = new ArrayList<ClassDescriptor>(n);
|
||||
extensionFunctions = new ArrayList<ClassDescriptor>(n);
|
||||
kFunctions = new ArrayList<ClassDescriptor>(n);
|
||||
kMemberFunctions = new ArrayList<ClassDescriptor>(n);
|
||||
kExtensionFunctions = new ArrayList<ClassDescriptor>(n);
|
||||
|
||||
ModuleDescriptor module = new ModuleDescriptorImpl(Name.special("<fake module for functions impl>"),
|
||||
Collections.<ImportPath>emptyList(), JavaToKotlinClassMap.getInstance());
|
||||
@@ -63,34 +61,31 @@ public class FunctionTypesUtil {
|
||||
|
||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||
for (int i = 0; i < n; i++) {
|
||||
createFunctionImpl(FUNCTIONS, kotlin, "FunctionImpl" + i, builtIns.getFunction(i));
|
||||
createFunctionImpl(EXTENSION_FUNCTIONS, kotlin, "ExtensionFunctionImpl" + i, builtIns.getExtensionFunction(i));
|
||||
createFunctionImpl(K_FUNCTIONS, reflect, "KFunctionImpl" + i, builtIns.getKFunction(i));
|
||||
createFunctionImpl(K_MEMBER_FUNCTIONS, reflect, "KMemberFunctionImpl" + i, builtIns.getKMemberFunction(i));
|
||||
createFunctionImpl(K_EXTENSION_FUNCTIONS, reflect, "KExtensionFunctionImpl" + i, builtIns.getKExtensionFunction(i));
|
||||
createFunctionImpl(functions, kotlin, "FunctionImpl" + i, builtIns.getFunction(i));
|
||||
createFunctionImpl(extensionFunctions, kotlin, "ExtensionFunctionImpl" + i, builtIns.getExtensionFunction(i));
|
||||
createFunctionImpl(kFunctions, reflect, "KFunctionImpl" + i, reflectionTypes.getKFunction(i));
|
||||
createFunctionImpl(kMemberFunctions, reflect, "KMemberFunctionImpl" + i, reflectionTypes.getKMemberFunction(i));
|
||||
createFunctionImpl(kExtensionFunctions, reflect, "KExtensionFunctionImpl" + i, reflectionTypes.getKExtensionFunction(i));
|
||||
}
|
||||
|
||||
ImmutableMap.Builder<ClassDescriptor, ClassDescriptor> builder = ImmutableMap.builder();
|
||||
for (int i = 0; i < n; i++) {
|
||||
builder.put(builtIns.getKFunction(i), K_FUNCTIONS.get(i));
|
||||
builder.put(builtIns.getKMemberFunction(i), K_MEMBER_FUNCTIONS.get(i));
|
||||
builder.put(builtIns.getKExtensionFunction(i), K_EXTENSION_FUNCTIONS.get(i));
|
||||
builder.put(reflectionTypes.getKFunction(i), kFunctions.get(i));
|
||||
builder.put(reflectionTypes.getKMemberFunction(i), kMemberFunctions.get(i));
|
||||
builder.put(reflectionTypes.getKExtensionFunction(i), kExtensionFunctions.get(i));
|
||||
}
|
||||
FUNCTION_TO_IMPL = builder.build();
|
||||
}
|
||||
|
||||
private FunctionTypesUtil() {
|
||||
kFunctionToImpl = builder.build();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static ClassDescriptor functionTypeToImpl(@NotNull JetType functionType) {
|
||||
public ClassDescriptor kFunctionTypeToImpl(@NotNull JetType functionType) {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
return FUNCTION_TO_IMPL.get(functionType.getConstructor().getDeclarationDescriptor());
|
||||
return kFunctionToImpl.get(functionType.getConstructor().getDeclarationDescriptor());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetType getSuperTypeForClosure(@NotNull FunctionDescriptor descriptor, boolean kFunction) {
|
||||
public JetType getSuperTypeForClosure(@NotNull FunctionDescriptor descriptor, boolean kFunction) {
|
||||
int arity = descriptor.getValueParameters().size();
|
||||
|
||||
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||
@@ -108,26 +103,27 @@ public class FunctionTypesUtil {
|
||||
typeArguments.add(new TypeProjectionImpl(parameter.getType()));
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
|
||||
|
||||
ClassDescriptor classDescriptor;
|
||||
if (kFunction) {
|
||||
if (expectedThisObject != null) {
|
||||
classDescriptor = K_MEMBER_FUNCTIONS.get(arity);
|
||||
classDescriptor = kMemberFunctions.get(arity);
|
||||
}
|
||||
else if (receiverParameter != null) {
|
||||
classDescriptor = K_EXTENSION_FUNCTIONS.get(arity);
|
||||
classDescriptor = kExtensionFunctions.get(arity);
|
||||
}
|
||||
else {
|
||||
classDescriptor = K_FUNCTIONS.get(arity);
|
||||
classDescriptor = kFunctions.get(arity);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (receiverParameter != null) {
|
||||
classDescriptor = EXTENSION_FUNCTIONS.get(arity);
|
||||
classDescriptor = extensionFunctions.get(arity);
|
||||
}
|
||||
else {
|
||||
classDescriptor = FUNCTIONS.get(arity);
|
||||
classDescriptor = functions.get(arity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,26 +156,4 @@ public class FunctionTypesUtil {
|
||||
|
||||
result.add(functionImpl);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type getFunctionTraitClassName(@NotNull FunctionDescriptor descriptor) {
|
||||
int paramCount = descriptor.getValueParameters().size();
|
||||
if (descriptor.getReceiverParameter() != null) {
|
||||
return Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/ExtensionFunction" + paramCount);
|
||||
}
|
||||
else {
|
||||
return Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/Function" + paramCount);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type getFunctionImplType(@NotNull FunctionDescriptor descriptor) {
|
||||
int paramCount = descriptor.getValueParameters().size();
|
||||
if (descriptor.getReceiverParameter() != null) {
|
||||
return Type.getObjectType("kotlin/ExtensionFunctionImpl" + paramCount);
|
||||
}
|
||||
else {
|
||||
return Type.getObjectType("kotlin/FunctionImpl" + paramCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-9
@@ -22,6 +22,7 @@ import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.FunctionTypesUtil;
|
||||
import org.jetbrains.jet.codegen.SamCodegenUtil;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -47,7 +48,6 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.codegen.JvmCodegenUtil.peekFromStack;
|
||||
import static org.jetbrains.jet.codegen.FunctionTypesUtil.getSuperTypeForClosure;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||
@@ -87,13 +87,14 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
|
||||
private final BindingTrace bindingTrace;
|
||||
private final BindingContext bindingContext;
|
||||
|
||||
private final GenerationState.GenerateClassFilter filter;
|
||||
private final FunctionTypesUtil functionTypesUtil;
|
||||
|
||||
public CodegenAnnotatingVisitor(BindingTrace bindingTrace, GenerationState.GenerateClassFilter filter) {
|
||||
this.bindingTrace = bindingTrace;
|
||||
this.filter = filter;
|
||||
this.bindingContext = bindingTrace.getBindingContext();
|
||||
public CodegenAnnotatingVisitor(@NotNull GenerationState state) {
|
||||
this.bindingTrace = state.getBindingTrace();
|
||||
this.bindingContext = state.getBindingContext();
|
||||
this.filter = state.getGenerateDeclaredClassFilter();
|
||||
this.functionTypesUtil = state.getFunctionTypesUtil();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -269,7 +270,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
if (functionDescriptor == null) return;
|
||||
|
||||
String name = inventAnonymousClassName(expression);
|
||||
JetType superType = getSuperTypeForClosure(functionDescriptor, false);
|
||||
JetType superType = functionTypesUtil.getSuperTypeForClosure(functionDescriptor, false);
|
||||
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, superType);
|
||||
recordClosure(functionLiteral, classDescriptor, name);
|
||||
|
||||
@@ -317,7 +318,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
|
||||
ResolvedCall<?> referencedFunction = bindingContext.get(RESOLVED_CALL, expression.getCallableReference());
|
||||
if (referencedFunction == null) return;
|
||||
JetType superType = getSuperTypeForClosure((FunctionDescriptor) referencedFunction.getResultingDescriptor(), true);
|
||||
JetType superType =
|
||||
functionTypesUtil.getSuperTypeForClosure((FunctionDescriptor) referencedFunction.getResultingDescriptor(), true);
|
||||
|
||||
String name = inventAnonymousClassName(expression);
|
||||
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, superType);
|
||||
@@ -371,7 +373,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
}
|
||||
else {
|
||||
String name = inventAnonymousClassName(function);
|
||||
JetType superType = getSuperTypeForClosure(functionDescriptor, false);
|
||||
JetType superType = functionTypesUtil.getSuperTypeForClosure(functionDescriptor, false);
|
||||
ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor, superType);
|
||||
recordClosure(function, classDescriptor, name);
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public class CodegenBinding {
|
||||
}
|
||||
|
||||
public static void initTrace(@NotNull GenerationState state) {
|
||||
CodegenAnnotatingVisitor visitor = new CodegenAnnotatingVisitor(state.getBindingTrace(), state.getGenerateDeclaredClassFilter());
|
||||
CodegenAnnotatingVisitor visitor = new CodegenAnnotatingVisitor(state);
|
||||
for (JetFile file : allFilesInPackages(state.getBindingContext(), state.getFiles())) {
|
||||
file.accept(visitor);
|
||||
}
|
||||
|
||||
@@ -19,19 +19,20 @@ package org.jetbrains.jet.codegen.state;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderMode;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.SamWrapperClasses;
|
||||
import org.jetbrains.jet.codegen.*;
|
||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.reflect.ReflectionTypes;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -97,6 +98,8 @@ public class GenerationState {
|
||||
@Nullable
|
||||
private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
|
||||
|
||||
private final FunctionTypesUtil functionTypesUtil;
|
||||
|
||||
public GenerationState(
|
||||
@NotNull Project project,
|
||||
@NotNull ClassBuilderFactory builderFactory,
|
||||
@@ -124,7 +127,7 @@ public class GenerationState {
|
||||
this.classBuilderMode = builderFactory.getClassBuilderMode();
|
||||
this.inlineEnabled = inlineEnabled;
|
||||
|
||||
bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState");
|
||||
this.bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState");
|
||||
this.bindingContext = bindingTrace.getBindingContext();
|
||||
|
||||
this.typeMapper = new JetTypeMapper(bindingTrace, classBuilderMode);
|
||||
@@ -136,6 +139,24 @@ public class GenerationState {
|
||||
this.generateNotNullAssertions = generateNotNullAssertions;
|
||||
this.generateNotNullParamAssertions = generateNotNullParamAssertions;
|
||||
this.generateClassFilter = generateClassFilter;
|
||||
|
||||
ReflectionTypes reflectionTypes = new ReflectionTypes(getAnyModule());
|
||||
this.functionTypesUtil = new FunctionTypesUtil(reflectionTypes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ModuleDescriptor getAnyModule() {
|
||||
// TODO: this shouldn't be happening once we have modules in the compiler (there simply will be a ModuleDescriptor instance here)
|
||||
|
||||
if (files.isEmpty()) {
|
||||
// This is a hackish workaround for this code not to fail when invoked for an empty file list. Technically it doesn't matter
|
||||
// which module we return here: if we're not compiling anything, we should never reach a point where we need this module
|
||||
return KotlinBuiltIns.getInstance().getBuiltInsModule();
|
||||
}
|
||||
|
||||
PackageFragmentDescriptor descriptor = bindingContext.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, files.get(0));
|
||||
assert descriptor != null : "File is not under any module: " + files.get(0);
|
||||
return descriptor.getContainingDeclaration();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -200,6 +221,11 @@ public class GenerationState {
|
||||
return generateClassFilter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FunctionTypesUtil getFunctionTypesUtil() {
|
||||
return functionTypesUtil;
|
||||
}
|
||||
|
||||
public boolean isInlineEnabled() {
|
||||
return inlineEnabled;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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 org.jetbrains.jet.lang.reflect
|
||||
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.jet.lang.descriptors.*
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
|
||||
public class ReflectionTypes(private val module: ModuleDescriptor) {
|
||||
// TODO: use module instead of built-ins
|
||||
public fun getKFunction(n: Int): ClassDescriptor = KotlinBuiltIns.getInstance().getKFunction(n)
|
||||
public fun getKExtensionFunction(n: Int): ClassDescriptor = KotlinBuiltIns.getInstance().getKExtensionFunction(n)
|
||||
public fun getKMemberFunction(n: Int): ClassDescriptor = KotlinBuiltIns.getInstance().getKMemberFunction(n)
|
||||
}
|
||||
Reference in New Issue
Block a user