diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmFunctionImplTypes.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmFunctionImplTypes.java index daa50761e86..516cffbc1e2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JvmFunctionImplTypes.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmFunctionImplTypes.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.codegen; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,52 +37,107 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; public class JvmFunctionImplTypes { - private final List functions; - private final List extensionFunctions; - private final List kFunctions; - private final List kMemberFunctions; - private final List kExtensionFunctions; + private final ReflectionTypes reflectionTypes; + private final ModuleDescriptor fakeModule; - private final ImmutableMap kFunctionToImpl; + private volatile List functionsList; + private volatile List kFunctionsList; + private volatile Map kFunctionToImplMap; + + private static class Functions { + public final ClassDescriptor functionImpl; + public final ClassDescriptor extensionFunctionImpl; + + public Functions( + @NotNull ClassDescriptor functionImpl, + @NotNull ClassDescriptor extensionFunctionImpl + ) { + this.functionImpl = functionImpl; + this.extensionFunctionImpl = extensionFunctionImpl; + } + } + + private static class KFunctions { + public final ClassDescriptor kFunctionImpl; + public final ClassDescriptor kMemberFunctionImpl; + public final ClassDescriptor kExtensionFunctionImpl; + + public KFunctions( + @NotNull ClassDescriptor kFunctionImpl, + @NotNull ClassDescriptor kMemberFunctionImpl, + @NotNull ClassDescriptor kExtensionFunctionImpl + ) { + this.kFunctionImpl = kFunctionImpl; + this.kMemberFunctionImpl = kMemberFunctionImpl; + this.kExtensionFunctionImpl = kExtensionFunctionImpl; + } + } public JvmFunctionImplTypes(@NotNull ReflectionTypes reflectionTypes) { - int n = KotlinBuiltIns.FUNCTION_TRAIT_COUNT; - functions = new ArrayList(n); - extensionFunctions = new ArrayList(n); - kFunctions = new ArrayList(n); - kMemberFunctions = new ArrayList(n); - kExtensionFunctions = new ArrayList(n); + this.reflectionTypes = reflectionTypes; + this.fakeModule = new ModuleDescriptorImpl(Name.special(""), Collections.emptyList(), + JavaToKotlinClassMap.getInstance()); + } - ModuleDescriptor module = new ModuleDescriptorImpl(Name.special(""), - Collections.emptyList(), JavaToKotlinClassMap.getInstance()); - MutablePackageFragmentDescriptor kotlin = new MutablePackageFragmentDescriptor(module, new FqName("kotlin")); - MutablePackageFragmentDescriptor reflect = new MutablePackageFragmentDescriptor(module, new FqName("kotlin.reflect")); + @NotNull + private List getFunctionsImplList() { + if (functionsList == null) { + MutablePackageFragmentDescriptor kotlin = new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin")); + KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); - KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); - for (int i = 0; i < n; 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)); + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < KotlinBuiltIns.FUNCTION_TRAIT_COUNT; i++) { + builder.add(new Functions( + createFunctionImpl(kotlin, "FunctionImpl" + i, builtIns.getFunction(i)), + createFunctionImpl(kotlin, "ExtensionFunctionImpl" + i, builtIns.getExtensionFunction(i)) + )); + } + functionsList = builder.build(); } + return functionsList; + } - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (int i = 0; i < n; 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)); + @NotNull + private List getKFunctionsImplList() { + if (kFunctionsList == null) { + MutablePackageFragmentDescriptor reflect = new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin.reflect")); + + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < KotlinBuiltIns.FUNCTION_TRAIT_COUNT; i++) { + builder.add(new KFunctions( + createFunctionImpl(reflect, "KFunctionImpl" + i, reflectionTypes.getKFunction(i)), + createFunctionImpl(reflect, "KMemberFunctionImpl" + i, reflectionTypes.getKMemberFunction(i)), + createFunctionImpl(reflect, "KExtensionFunctionImpl" + i, reflectionTypes.getKExtensionFunction(i)) + )); + } + kFunctionsList = builder.build(); } - kFunctionToImpl = builder.build(); + return kFunctionsList; + } + + @NotNull + private Map getKFunctionToImplMap() { + if (kFunctionToImplMap == null) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (int i = 0; i < KotlinBuiltIns.FUNCTION_TRAIT_COUNT; i++) { + KFunctions kFunctions = getKFunctionsImplList().get(i); + builder.put(reflectionTypes.getKFunction(i), kFunctions.kFunctionImpl); + builder.put(reflectionTypes.getKMemberFunction(i), kFunctions.kMemberFunctionImpl); + builder.put(reflectionTypes.getKExtensionFunction(i), kFunctions.kExtensionFunctionImpl); + } + kFunctionToImplMap = builder.build(); + } + return kFunctionToImplMap; } @Nullable public ClassDescriptor kFunctionTypeToImpl(@NotNull JetType functionType) { //noinspection SuspiciousMethodCalls - return kFunctionToImpl.get(functionType.getConstructor().getDeclarationDescriptor()); + return getKFunctionToImplMap().get(functionType.getConstructor().getDeclarationDescriptor()); } @NotNull @@ -108,22 +164,24 @@ public class JvmFunctionImplTypes { ClassDescriptor classDescriptor; if (kFunction) { + KFunctions kFunctions = getKFunctionsImplList().get(arity); if (expectedThisObject != null) { - classDescriptor = kMemberFunctions.get(arity); + classDescriptor = kFunctions.kMemberFunctionImpl; } else if (receiverParameter != null) { - classDescriptor = kExtensionFunctions.get(arity); + classDescriptor = kFunctions.kExtensionFunctionImpl; } else { - classDescriptor = kFunctions.get(arity); + classDescriptor = kFunctions.kFunctionImpl; } } else { + Functions functions = getFunctionsImplList().get(arity); if (receiverParameter != null) { - classDescriptor = extensionFunctions.get(arity); + classDescriptor = functions.extensionFunctionImpl; } else { - classDescriptor = functions.get(arity); + classDescriptor = functions.functionImpl; } } @@ -136,8 +194,8 @@ public class JvmFunctionImplTypes { ); } - private static void createFunctionImpl( - @NotNull List result, + @NotNull + private static ClassDescriptor createFunctionImpl( @NotNull PackageFragmentDescriptor containingDeclaration, @NotNull String name, @NotNull ClassDescriptor functionInterface @@ -154,6 +212,6 @@ public class JvmFunctionImplTypes { functionImpl.setTypeParameterDescriptors(functionInterface.getDefaultType().getConstructor().getParameters()); functionImpl.createTypeConstructor(); - result.add(functionImpl); + return functionImpl; } }