From 974df0ed8e2ed0e235427db6878e93151e84ad9d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 21 Mar 2013 20:39:01 +0400 Subject: [PATCH] Use FunctionImplN instead of FunctionN in codegen Superclass of closures should now be FunctionImplN instead of FunctionN. Since these -Impl classes are needed only in JVM, the corresponding descriptors and types are created in the back-end only. --- .../jetbrains/jet/codegen/CodegenUtil.java | 4 +- .../jet/codegen/ExpressionCodegen.java | 2 +- .../binding/CodegenAnnotatingVisitor.java | 56 +++++++++++++++++-- .../jet/lang/types/lang/KotlinBuiltIns.java | 2 +- .../testData/codegen/box/classes/kt1535.kt | 4 +- .../box/closures/closureOnTopLevel1.kt | 2 +- .../box/closures/closureOnTopLevel2.kt | 2 +- 7 files changed, 58 insertions(+), 14 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index f3ccf307616..a9560571c79 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -126,10 +126,10 @@ public class CodegenUtil { public static JvmClassName getInternalClassName(FunctionDescriptor descriptor) { int paramCount = descriptor.getValueParameters().size(); if (descriptor.getReceiverParameter() != null) { - return JvmClassName.byInternalName("jet/ExtensionFunction" + paramCount); + return JvmClassName.byInternalName("jet/ExtensionFunctionImpl" + paramCount); } else { - return JvmClassName.byInternalName("jet/Function" + paramCount); + return JvmClassName.byInternalName("jet/FunctionImpl" + paramCount); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 6b44447d97f..5e6fd2079d6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -3122,7 +3122,7 @@ public class ExpressionCodegen extends JetVisitor implem v.dup2(); v.load(indexIndex, Type.INT_TYPE); v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); - v.invokevirtual("jet/Function1", "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;"); + v.invokeinterface("jet/Function1", "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;"); v.load(indexIndex, Type.INT_TYPE); v.iinc(indexIndex, 1); v.swap(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java index ad58397a910..711fd369968 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; @@ -33,11 +34,10 @@ import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; 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.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import static org.jetbrains.jet.codegen.CodegenUtil.peekFromStack; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; @@ -56,6 +56,42 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { this.bindingContext = bindingTrace.getBindingContext(); } + private static final List FUNCTIONS; + private static final List EXTENSION_FUNCTIONS; + + static { + int n = KotlinBuiltIns.FUNCTION_TRAIT_COUNT; + FUNCTIONS = new ArrayList(n); + EXTENSION_FUNCTIONS = new ArrayList(n); + + KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + for (int i = 0; i < n; i++) { + Name functionImpl = Name.identifier("FunctionImpl" + i); + FUNCTIONS.add(createFunctionImplDescriptor(functionImpl, builtIns.getFunction(i))); + + Name extensionFunctionImpl = Name.identifier("ExtensionFunctionImpl" + i); + EXTENSION_FUNCTIONS.add(createFunctionImplDescriptor(extensionFunctionImpl, builtIns.getExtensionFunction(i))); + } + } + + private static ClassDescriptor createFunctionImplDescriptor(Name name, ClassDescriptor functionInterface) { + JetScope builtInsScope = KotlinBuiltIns.getInstance().getBuiltInsScope(); + + MutableClassDescriptor functionImpl = new MutableClassDescriptor( + builtInsScope.getContainingDeclaration(), + builtInsScope, + ClassKind.CLASS, + false, + name + ); + functionImpl.setModality(Modality.FINAL); + functionImpl.setVisibility(Visibilities.PUBLIC); + functionImpl.setTypeParameterDescriptors(functionInterface.getDefaultType().getConstructor().getParameters()); + functionImpl.createTypeConstructor(); + + return functionImpl; + } + @Override public void visitCallExpression(JetCallExpression expression) { super.visitCallExpression(expression); @@ -92,9 +128,8 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { ((ClassDescriptorImpl)classDescriptor).initialize( false, Collections.emptyList(), - Collections.singleton((funDescriptor.getReceiverParameter() != null - ? KotlinBuiltIns.getInstance().getExtensionFunction(arity) - : KotlinBuiltIns.getInstance().getFunction(arity)).getDefaultType()), JetScope.EMPTY, + Collections.singleton(getSuperTypeForClosure(funDescriptor, arity)), + JetScope.EMPTY, Collections.emptySet(), null, false); @@ -104,6 +139,15 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { return classDescriptor; } + private JetType getSuperTypeForClosure(FunctionDescriptor funDescriptor, int arity) { + if (funDescriptor.getReceiverParameter() != null) { + return EXTENSION_FUNCTIONS.get(arity).getDefaultType(); + } + else { + return FUNCTIONS.get(arity).getDefaultType(); + } + } + private String inventAnonymousClassName(JetElement declaration) { String top = peekFromStack(nameStack); Integer cnt = anonymousSubclassesCount.get(top); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index a92a4e02b6d..2a22edf52d2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -80,7 +80,7 @@ public class KotlinBuiltIns { BUILT_INS_DIR + "/Unit.jet" ); - private static final int FUNCTION_TRAIT_COUNT = 23; + public static final int FUNCTION_TRAIT_COUNT = 23; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/testData/codegen/box/classes/kt1535.kt b/compiler/testData/codegen/box/classes/kt1535.kt index 973a475c4f6..c93ff8f7ab3 100644 --- a/compiler/testData/codegen/box/classes/kt1535.kt +++ b/compiler/testData/codegen/box/classes/kt1535.kt @@ -1,9 +1,9 @@ -class Works() : jet.Function0() { +class Works() : jet.Function0 { public override fun invoke():Object { return "Works" as Object } } -class Broken() : jet.Function0() { +class Broken() : jet.Function0 { public override fun invoke():String { return "Broken" } diff --git a/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt b/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt index bc0a5f61a4b..516c5c110b1 100644 --- a/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt +++ b/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt @@ -7,7 +7,7 @@ val getter: String fun f() = { "OK" }() -val obj = object : Function0() { +val obj = object : Function0 { override fun invoke() = "OK" } diff --git a/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt b/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt index e86ec48df07..a92f366c0fa 100644 --- a/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt +++ b/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt @@ -5,7 +5,7 @@ val getter: String fun f() = { "OK" }() -val obj = object : Function0() { +val obj = object : Function0 { override fun invoke() = "OK" }