Introduce ReflectionTypes, use it in JVM back-end

Make FunctionTypesUtil a component
This commit is contained in:
Alexander Udalov
2014-05-06 17:46:54 +04:00
parent 3ac89030c7
commit 6004c6cefe
6 changed files with 111 additions and 76 deletions
@@ -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);
}
}
}
@@ -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)
}