From a9788f950697e88bd185e1af21199e1538746b9e Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Mon, 16 Mar 2020 17:19:51 +0300 Subject: [PATCH] [KLIB] Create an abstract class for module deserializer - Introduce Ir-based Functional interface factory - Switch from LazyIr to pure - Use kotlin library to access raw bytes - Link dirty files against IC cache and dependencies instead of LazyIr - Move `DescriptorByIdSignatureFinder` from K/N to common - Support inline-bodies only MODE --- .../extensions/IrGenerationExtension.kt | 5 +- .../kotlin/ir/backend/js/compiler.kt | 18 +- .../kotlin/backend/jvm/JvmBackendFacade.kt | 32 +- .../jetbrains/kotlin/backend/wasm/compiler.kt | 2 +- .../kotlin/psi2ir/Psi2IrTranslator.kt | 16 +- .../ir/descriptors/IrFunctionFactory.kt | 457 +++++++++ .../ir/util/ExternalDependenciesGenerator.kt | 2 - .../jetbrains/kotlin/ir/util/SymbolTable.kt | 25 +- .../DescriptorByIdSignatureFinder.kt | 63 ++ .../IncrementalCompilationSupport.kt | 137 +++ .../serialization/IrFakeOverrideUtils.kt | 76 -- .../serialization/IrFileDeserializer.kt | 139 ++- .../serialization/IrModuleDeserializer.kt | 276 ++++++ .../common/serialization/KotlinIrLinker.kt | 899 +++++++----------- .../jetbrains/kotlin/ir/backend/js/klib.kt | 62 +- .../js/lower/serialization/ir/JsIrLinker.kt | 57 +- .../backend/jvm/serialization/JvmIrLinker.kt | 171 +++- .../repl/js/JsCoreScriptingCompiler.kt | 6 +- .../repl/js/JsScriptDependencyCompiler.kt | 5 +- 19 files changed, 1647 insertions(+), 801 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrFunctionFactory.kt create mode 100644 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt create mode 100644 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt delete mode 100644 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFakeOverrideUtils.kt create mode 100644 compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt index bae5e9943d7..8f38a853305 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/extensions/IrGenerationExtension.kt @@ -10,8 +10,11 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.ir.builders.IrGeneratorContext +import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.IrExtensionGenerator import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.resolve.BindingContext @@ -26,7 +29,7 @@ class IrPluginContext( val symbols: BuiltinSymbolsBase = BuiltinSymbolsBase(irBuiltIns.builtIns, symbolTable) ) : IrGeneratorContext() -interface IrGenerationExtension { +interface IrGenerationExtension : IrExtensionGenerator { companion object : ProjectExtensionDescriptor("org.jetbrains.kotlin.irGenerationExtension", IrGenerationExtension::class.java) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index e0e6185c348..65a403f36f5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.NameTables import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.StageController import org.jetbrains.kotlin.ir.declarations.stageController +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList import org.jetbrains.kotlin.ir.util.patchDeclarationParents @@ -58,11 +59,8 @@ fun compile( val context = JsIrBackendContext(moduleDescriptor, irBuiltIns, symbolTable, moduleFragment, exportedDeclarations, configuration) // Load declarations referenced during `context` initialization - dependencyModules.forEach { - val irProviders = generateTypicalIrProviderList(it.descriptor, irBuiltIns, symbolTable, deserializer) - ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings) - .generateUnboundSymbolsAsDependencies() - } + val irProviders = listOf(deserializer) + ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings).generateUnboundSymbolsAsDependencies() val allModules = when (mainModule) { is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment) @@ -71,16 +69,12 @@ fun compile( val irFiles = allModules.flatMap { it.files } + deserializer.postProcess() + moduleFragment.files.clear() moduleFragment.files += irFiles - val irProvidersWithoutDeserializer = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable) - // Create stubs - ExternalDependenciesGenerator(symbolTable, irProvidersWithoutDeserializer, configuration.languageVersionSettings) - .generateUnboundSymbolsAsDependencies() - moduleFragment.patchDeclarationParents() - - deserializer.finalizeExpectActualLinker() + symbolTable.lazyWrapper.stubGenerator = DeclarationStubGenerator(moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings) moveBodilessDeclarationsToSeparatePlace(context, moduleFragment) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt index 22603f6dc75..19150afacf6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt @@ -13,8 +13,11 @@ import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.idea.MainFunctionDetector +import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary +import org.jetbrains.kotlin.idea.MainFunctionDetector import org.jetbrains.kotlin.ir.backend.jvm.serialization.EmptyLoggingContext import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrLinker import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmManglerDesc @@ -33,8 +36,9 @@ object JvmBackendFacade { val signaturer = JvmIdSignatureDescriptor(mangler) val psi2ir = Psi2IrTranslator(state.languageVersionSettings, signaturer = signaturer) val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext, extensions = extensions) + val pluginExtensions = IrGenerationExtension.getInstances(state.project) - for (extension in IrGenerationExtension.getInstances(state.project)) { + for (extension in pluginExtensions) { psi2ir.addPostprocessingStep { module -> extension.generate( module, @@ -53,22 +57,22 @@ object JvmBackendFacade { val stubGenerator = DeclarationStubGenerator( psi2irContext.moduleDescriptor, psi2irContext.symbolTable, psi2irContext.irBuiltIns.languageVersionSettings, extensions ) - val deserializer = JvmIrLinker( - EmptyLoggingContext, psi2irContext.irBuiltIns, psi2irContext.symbolTable - ) - psi2irContext.moduleDescriptor.allDependencyModules.filter { it.getCapability(KlibModuleOrigin.CAPABILITY) != null }.forEach { - deserializer.deserializeIrModuleHeader(it) + val irLinker = JvmIrLinker(psi2irContext.moduleDescriptor, EmptyLoggingContext, psi2irContext.irBuiltIns, psi2irContext.symbolTable, stubGenerator, mangler) + val dependencies = psi2irContext.moduleDescriptor.allDependencyModules.map { + val kotlinLibrary = (it.getCapability(KlibModuleOrigin.CAPABILITY) as? DeserializedKlibModuleOrigin)?.library + irLinker.deserializeIrModuleHeader(it, kotlinLibrary) } - val irProviders = listOf(deserializer, stubGenerator) + val irProviders = listOf(irLinker) + stubGenerator.setIrProviders(irProviders) - val irModuleFragment = psi2ir.generateModuleFragment( - psi2irContext, files, - irProviders = irProviders, - expectDescriptorToSymbol = null - ) + val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, irProviders, expectDescriptorToSymbol = null, pluginExtensions) + irLinker.postProcess() + + stubGenerator.unboundSymbolGeneration = true + // We need to compile all files we reference in Klibs - irModuleFragment.files.addAll(deserializer.getAllIrFiles()) + irModuleFragment.files.addAll(dependencies.flatMap { it.files }) doGenerateFilesInternal( state, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, irProviders, extensions diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt index dc3bd82804b..b88bc933805 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt @@ -56,7 +56,7 @@ fun compileWasm( val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer) ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings).generateUnboundSymbolsAsDependencies() moduleFragment.patchDeclarationParents() - deserializer.finalizeExpectActualLinker() + deserializer.postProcess() wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index 09caccc93f6..e9fdae4d636 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -43,6 +43,7 @@ class Psi2IrTranslator( postprocessingSteps.add(step) } + // NOTE: used only for test purpose fun generateModule( moduleDescriptor: ModuleDescriptor, ktFiles: Collection, @@ -68,7 +69,8 @@ class Psi2IrTranslator( context: GeneratorContext, ktFiles: Collection, irProviders: List, - expectDescriptorToSymbol: MutableMap? = null + expectDescriptorToSymbol: MutableMap? = null, + pluginExtensions: Collection = emptyList() ): IrModuleFragment { val moduleGenerator = ModuleGenerator(context) val irModule = moduleGenerator.generateModuleFragmentWithoutDependencies(ktFiles) @@ -76,8 +78,14 @@ class Psi2IrTranslator( irModule.patchDeclarationParents() expectDescriptorToSymbol?.let { referenceExpectsForUsedActuals(it, context.symbolTable, irModule) } postprocess(context, irModule) - // do not generate unbound symbols before postprocessing, - // since plugins must work with non-lazy IR + + irProviders.filterIsInstance().forEach { it.init(irModule, pluginExtensions) } + + moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders) + + postprocessingSteps.forEach { it.invoke(irModule) } + + // TODO: remove it once plugin API improved moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders) return irModule @@ -87,8 +95,6 @@ class Psi2IrTranslator( insertImplicitCasts(irElement, context) generateAnnotationsForDeclarations(context, irElement) - postprocessingSteps.forEach { it(irElement) } - irElement.patchDeclarationParents() } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrFunctionFactory.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrFunctionFactory.kt new file mode 100644 index 00000000000..55914026bd0 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrFunctionFactory.kt @@ -0,0 +1,457 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.descriptors + +import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.impl.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.Variance + +abstract class IrAbstractFunctionFactory { + + abstract fun functionClassDescriptor(arity: Int): FunctionClassDescriptor + abstract fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor + abstract fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor + abstract fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor + + abstract fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass + abstract fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass + abstract fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass + abstract fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass + + fun functionN(n: Int) = functionN(n) { callback -> + val descriptor = functionClassDescriptor(n) + declareClass(offset, offset, classOrigin, descriptor) { symbol -> + callback(symbol) + } + } + + fun kFunctionN(n: Int): IrClass { + return kFunctionN(n) { callback -> + val descriptor = kFunctionClassDescriptor(n) + declareClass(offset, offset, classOrigin, descriptor) { symbol -> + callback(symbol) + } + } + } + + fun suspendFunctionN(n: Int): IrClass = suspendFunctionN(n) { callback -> + val descriptor = suspendFunctionClassDescriptor(n) + declareClass(offset, offset, classOrigin, descriptor) { symbol -> + callback(symbol) + } + } + + fun kSuspendFunctionN(n: Int): IrClass = kSuspendFunctionN(n) { callback -> + val descriptor = kSuspendFunctionClassDescriptor(n) + declareClass(offset, offset, classOrigin, descriptor) { symbol -> + callback(symbol) + } + } + + companion object { + val classOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_CLASS") {} + val memberOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_MEMBER") {} + const val offset = SYNTHETIC_OFFSET + } +} + +class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTable: SymbolTable) : IrAbstractFunctionFactory() { + + // TODO: Lazieness + + private val functionNMap = mutableMapOf() + private val kFunctionNMap = mutableMapOf() + private val suspendFunctionNMap = mutableMapOf() + private val kSuspendFunctionNMap = mutableMapOf() + + override fun functionClassDescriptor(arity: Int): FunctionClassDescriptor = + irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor + + override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass { + return functionNMap.getOrPut(arity) { + symbolTable.declarator { symbol -> + val descriptor = symbol.descriptor as FunctionClassDescriptor + val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable) + createFunctionClass(symbol, false, false, arity, irBuiltIns.functionClass, kotlinPackageFragment, descriptorFactory) + } + } + } + + override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor = + irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor + + override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass { + return suspendFunctionNMap.getOrPut(arity) { + symbolTable.declarator { symbol -> + val descriptor = symbol.descriptor as FunctionClassDescriptor + val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable) + createFunctionClass(symbol, false, true, arity, irBuiltIns.functionClass, kotlinCoroutinesPackageFragment, descriptorFactory) + } + } + } + + override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor { + val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity)) + return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor + } + + override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass { + return kFunctionNMap.getOrPut(arity) { + symbolTable.declarator { symbol -> + val descriptor = symbol.descriptor as FunctionClassDescriptor + val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable) + createFunctionClass(symbol, true, false, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory) + } + } + } + + override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor { + val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(true, arity)) + return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor + } + + override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass { + return kSuspendFunctionNMap.getOrPut(arity) { + symbolTable.declarator { symbol -> + val descriptor = symbol.descriptor as FunctionClassDescriptor + val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable) + createFunctionClass(symbol, true, true, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory) + } + } + } + + companion object { + private fun reflectFunctionClassFqn(shortName: Name): FqName = KOTLIN_REFLECT_FQ_NAME.child(shortName) + private fun reflectionFunctionClassName(isSuspend: Boolean, arity: Int): Name = + Name.identifier("K${if (isSuspend) "Suspend" else ""}Function$arity") + + private fun functionClassName(isK: Boolean, isSuspend: Boolean, arity: Int): String = + "${if (isK) "K" else ""}${if (isSuspend) "Suspend" else ""}Function$arity" + } + + private sealed class FunctionDescriptorFactory(protected val symbolTable: SymbolTable) { + abstract fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol + abstract fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor + abstract fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol + abstract fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor + abstract fun FunctionDescriptor.memberReceiverParameterDescriptor(): ReceiverParameterDescriptor + + class RealDescriptorFactory(private val classDescriptor: FunctionClassDescriptor, symbolTable: SymbolTable) : + FunctionDescriptorFactory(symbolTable) { + override fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol { + val descriptor = classDescriptor.unsubstitutedMemberScope.run { + if (name[0] == '<') { + val propertyName = name.drop(5).dropLast(1) + val property = getContributedVariables(Name.identifier(propertyName), NoLookupLocation.FROM_BACKEND).single() + property.accessors.first { it.name.asString() == name } + } else { + getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first() + } + } + return symbolTable.declareSimpleFunction(offset, offset, memberOrigin, descriptor, factory).symbol + } + + override fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor { + assert(containingDeclaration === classDescriptor) + return valueParameters[index] + } + + override fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol { + val descriptor = classDescriptor.declaredTypeParameters[index] + return symbolTable.declareGlobalTypeParameter(offset, offset, classOrigin, descriptor, factory).symbol + } + + override fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor { + return classDescriptor.thisAsReceiverParameter + } + + override fun FunctionDescriptor.memberReceiverParameterDescriptor(): ReceiverParameterDescriptor { + assert(containingDeclaration === classDescriptor) + return dispatchReceiverParameter ?: error("Expected dispatch receiver at $this") + } + } + } + + private fun IrTypeParametersContainer.createTypeParameters(n: Int, descriptorFactory: FunctionDescriptorFactory): IrTypeParameter { + + var index = 0 + + val typeParametersArray = ArrayList(n + 1) + + for (i in 1 until (n + 1)) { + val pName = Name.identifier("P$i") + + val pSymbol = descriptorFactory.typeParameterDescriptor(index) { + IrTypeParameterImpl(offset, offset, classOrigin, it, pName, index++, false, Variance.IN_VARIANCE) + } + val pDeclaration = pSymbol.owner + + pDeclaration.superTypes += irBuiltIns.anyNType + pDeclaration.parent = this + typeParametersArray.add(pDeclaration) + } + + val rSymbol = descriptorFactory.typeParameterDescriptor(index) { + IrTypeParameterImpl(offset, offset, classOrigin, it, Name.identifier("R"), index, false, Variance.OUT_VARIANCE) + } + val rDeclaration = rSymbol.owner + + rDeclaration.superTypes += irBuiltIns.anyNType + rDeclaration.parent = this + typeParametersArray.add(rDeclaration) + + typeParameters = typeParametersArray + + return rDeclaration + } + + private val kotlinPackageFragment: IrPackageFragment by lazy { + irBuiltIns.builtIns.getFunction(0).let { + symbolTable.declareExternalPackageFragment(it.containingDeclaration as PackageFragmentDescriptor) + } + } + private val kotlinCoroutinesPackageFragment: IrPackageFragment by lazy { + irBuiltIns.builtIns.getSuspendFunction(0).let { + symbolTable.declareExternalPackageFragment(it.containingDeclaration as PackageFragmentDescriptor) + } + } + + private val kotlinReflectPackageFragment: IrPackageFragment by lazy { + irBuiltIns.kPropertyClass.descriptor.let { + symbolTable.declareExternalPackageFragment(it.containingDeclaration as PackageFragmentDescriptor) + } + } + + private fun IrClass.createThisReceiver(descriptorFactory: FunctionDescriptorFactory): IrValueParameter { + val vDescriptor = descriptorFactory.classReceiverParameterDescriptor() + val vSymbol = IrValueParameterSymbolImpl(vDescriptor) + val type = with(IrSimpleTypeBuilder()) { + classifier = symbol + arguments = typeParameters.run { + val builder = IrSimpleTypeBuilder() + mapTo(ArrayList(size)) { + builder.classifier = it.symbol + buildTypeProjection() + } + } + buildSimpleType() + } + val vDeclaration = IrValueParameterImpl( + offset, offset, classOrigin, vSymbol, Name.special(""), -1, type, null, + isCrossinline = false, + isNoinline = false + ) + + if (vDescriptor is WrappedReceiverParameterDescriptor) vDescriptor.bind(vDeclaration) + + return vDeclaration + } + + private fun FunctionClassDescriptor.createFunctionClass(): IrClass { + val s = symbolTable.referenceClass(this) + if (s.isBound) return s.owner + return symbolTable.declareClass(offset, offset, classOrigin, this, modality) { + val factory = FunctionDescriptorFactory.RealDescriptorFactory(this, symbolTable) + when (functionKind) { + FunctionClassDescriptor.Kind.Function -> + createFunctionClass(it, false, false, arity, irBuiltIns.functionClass, kotlinPackageFragment, factory) + FunctionClassDescriptor.Kind.SuspendFunction -> + createFunctionClass(it, false, true, arity, irBuiltIns.functionClass, kotlinCoroutinesPackageFragment, factory) + FunctionClassDescriptor.Kind.KFunction -> + createFunctionClass(it, true, false, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, factory) + FunctionClassDescriptor.Kind.KSuspendFunction -> + createFunctionClass(it, true, true, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, factory) + } + } + } + + private fun IrClass.createMembers(isK: Boolean, isSuspend: Boolean, arity: Int, name: String, descriptorFactory: FunctionDescriptorFactory) { + if (!isK) { + val invokeSymbol = descriptorFactory.memberDescriptor("invoke") { + val returnType = with(IrSimpleTypeBuilder()) { + classifier = typeParameters.last().symbol + buildSimpleType() + } + + IrFunctionImpl(offset, offset, memberOrigin, it, Name.identifier("invoke"), Visibilities.PUBLIC, Modality.ABSTRACT, + returnType, + isInline = false, + isExternal = false, + isTailrec = false, + isSuspend = isSuspend, + isOperator = true, + isExpect = false, + isFakeOverride = false + ) + } + + val fDeclaration = invokeSymbol.owner + + fDeclaration.dispatchReceiverParameter = createThisReceiver(descriptorFactory).also { it.parent = fDeclaration } + + val typeBuilder = IrSimpleTypeBuilder() + for (i in 1 until typeParameters.size) { + val vTypeParam = typeParameters[i - 1] + val vDescriptor = with(descriptorFactory) { invokeSymbol.descriptor.valueParameterDescriptor(i - 1) } + val vSymbol = IrValueParameterSymbolImpl(vDescriptor) + val vType = with(typeBuilder) { + classifier = vTypeParam.symbol + buildSimpleType() + } + val vDeclaration = IrValueParameterImpl( + offset, offset, memberOrigin, vSymbol, Name.identifier("p$i"), i - 1, vType, null, + isCrossinline = false, + isNoinline = false + ) + vDeclaration.parent = fDeclaration + if (vDescriptor is WrappedValueParameterDescriptor) vDescriptor.bind(vDeclaration) + fDeclaration.valueParameters += vDeclaration + } + + fDeclaration.parent = this + declarations += fDeclaration + } + + addFakeOverrides() + } + + private fun toIrType(wrapped: KotlinType): IrType { + val kotlinType = wrapped.unwrap() + return with(IrSimpleTypeBuilder()) { + classifier = + symbolTable.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType")) + hasQuestionMark = kotlinType.isMarkedNullable + arguments = kotlinType.arguments.map { + if (it.isStarProjection) IrStarProjectionImpl + else makeTypeProjection(toIrType(it.type), it.projectionKind) + } + buildSimpleType() + } + } + + private fun IrFunction.createValueParameter(descriptor: ParameterDescriptor): IrValueParameter { + val symbol = IrValueParameterSymbolImpl(descriptor) + val varargType = if (descriptor is ValueParameterDescriptor) descriptor.varargElementType else null + return IrValueParameterImpl( + offset, + offset, + memberOrigin, + symbol, + toIrType(descriptor.type), + varargType?.let { toIrType(it) }).also { + it.parent = this + } + } + + private fun IrClass.addFakeOverrides() { + + val fakeOverrideDescriptors = descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES) + .filterIsInstance().filter { it.kind === CallableMemberDescriptor.Kind.FAKE_OVERRIDE } + + fun createFakeOverrideFunction(descriptor: FunctionDescriptor, property: IrPropertySymbol?): IrSimpleFunction { + val returnType = descriptor.returnType?.let { toIrType(it) } ?: error("No return type for $descriptor") + val newFunction = symbolTable.declareSimpleFunction(offset, offset, memberOrigin, descriptor) { + descriptor.run { + IrFunctionImpl( + offset, offset, memberOrigin, it, name, visibility, modality, returnType, + isInline, isExternal, isTailrec, isSuspend, isOperator, isExpect, true + ) + } + } + + newFunction.parent = this + newFunction.overriddenSymbols = descriptor.overriddenDescriptors.map { symbolTable.referenceSimpleFunction(it.original) } + newFunction.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { newFunction.createValueParameter(it) } + newFunction.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { newFunction.createValueParameter(it) } + newFunction.valueParameters = descriptor.valueParameters.map { newFunction.createValueParameter(it) } + newFunction.correspondingPropertySymbol = property + + return newFunction + } + + fun createFakeOverrideProperty(descriptor: PropertyDescriptor): IrProperty { + return symbolTable.declareProperty(offset, offset, memberOrigin, descriptor) { + IrPropertyImpl(offset, offset, memberOrigin, it, descriptor.name).apply { + parent = this@addFakeOverrides + getter = descriptor.getter?.let { g -> createFakeOverrideFunction(g, symbol) } + setter = descriptor.setter?.let { s -> createFakeOverrideFunction(s, symbol) } + } + } + } + + + fun createFakeOverride(descriptor: CallableMemberDescriptor): IrDeclaration { + return when (descriptor) { + is FunctionDescriptor -> createFakeOverrideFunction(descriptor, null) + is PropertyDescriptor -> createFakeOverrideProperty(descriptor) + else -> error("Unexpected member $descriptor") + } + } + + declarations += fakeOverrideDescriptors.map { createFakeOverride(it) } + } + + private fun createFunctionClass( + symbol: IrClassSymbol, + isK: Boolean, + isSuspend: Boolean, + n: Int, + baseClass: IrClassSymbol, + packageFragment: IrPackageFragment, + descriptorFactory: FunctionDescriptorFactory + ): IrClass { + val name = functionClassName(isK, isSuspend, n) + val klass = IrClassImpl( + offset, offset, classOrigin, symbol, Name.identifier(name), ClassKind.INTERFACE, Visibilities.PUBLIC, Modality.ABSTRACT, + isCompanion = false, + isInner = false, + isData = false, + isExternal = false, + isInline = false, + isExpect = false, + isFun = false + ) + + val r = klass.createTypeParameters(n, descriptorFactory) + + klass.thisReceiver = klass.createThisReceiver(descriptorFactory).also { it.parent = klass } + + klass.superTypes = listOf(with(IrSimpleTypeBuilder()) { + classifier = baseClass + arguments = listOf( + with(IrSimpleTypeBuilder()) { + classifier = r.symbol + buildTypeProjection() + }, + ) + buildSimpleType() + }) + + klass.createMembers(isK, isSuspend, n, klass.name.identifier, descriptorFactory) + + klass.parent = packageFragment + packageFragment.declarations += klass + + return klass + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index fcf298ca343..293b5eb9c98 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -52,8 +52,6 @@ class ExternalDependenciesGenerator( assert(symbol.isBound) { "$symbol unbound even after deserialization attempt" } } } while (unbound.isNotEmpty()) - - irProviders.forEach { (it as? IrDeserializer)?.declareForwardDeclarations() } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 7f183e6e349..a50629e95de 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -46,8 +46,12 @@ interface LazyIrProvider : IrProvider { override fun getDeclaration(symbol: IrSymbol): IrLazyDeclarationBase? } +interface IrExtensionGenerator { + fun declare(symbol: IrSymbol): IrDeclaration? = null +} + interface IrDeserializer : IrProvider { - fun declareForwardDeclarations() + fun init(moduleFragment: IrModuleFragment?, extensions: Collection) {} } interface ReferenceSymbolTable { @@ -846,6 +850,25 @@ open class SymbolTable(val signaturer: IdSignatureComposer) : ReferenceSymbolTab } return result } + + private inline fun > FlatSymbolTable.forEachPublicSymbolImpl( + block: (IrSymbol) -> Unit + ) { + idSigToSymbol.forEach { (_, sym) -> + assert(sym.isPublicApi) + block(sym) + } + } + + fun forEachPublicSymbol(block: (IrSymbol) -> Unit) { + classSymbolTable.forEachPublicSymbolImpl { block(it) } + constructorSymbolTable.forEachPublicSymbolImpl { block(it) } + simpleFunctionSymbolTable.forEachPublicSymbolImpl { block(it) } + propertySymbolTable.forEachPublicSymbolImpl { block(it) } + enumEntrySymbolTable.forEachPublicSymbolImpl { block(it) } + typeAliasSymbolTable.forEachPublicSymbolImpl { block(it) } + fieldSymbolTable.forEachPublicSymbolImpl { block(it) } + } } inline fun SymbolTable.withScope(owner: D, block: SymbolTable.(D) -> T): T { diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt new file mode 100644 index 00000000000..4b50acd5f36 --- /dev/null +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/DescriptorByIdSignatureFinder.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.common.serialization + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.ir.util.KotlinMangler + +class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescriptor, private val mangler: KotlinMangler.DescriptorMangler) { + fun findDescriptorBySignature(signature: IdSignature): DeclarationDescriptor? = when (signature) { + is IdSignature.AccessorSignature -> findDescriptorForAccessorSignature(signature) + is IdSignature.PublicSignature -> findDescriptorForPublicSignature(signature) + else -> error("only PublicSignature or AccessorSignature should reach this point, got $signature") + } + + private fun findDescriptorForAccessorSignature(signature: IdSignature.AccessorSignature): DeclarationDescriptor? { + val propertyDescriptor = findDescriptorBySignature(signature.propertySignature) as? PropertyDescriptor + ?: return null + return propertyDescriptor.accessors.singleOrNull { + it.name == signature.accessorSignature.declarationFqn.shortName() + } + } + + private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? { + val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName()) + val pathSegments = signature.declarationFqn.pathSegments() + val toplevelDescriptors = packageDescriptor.memberScope.getContributedDescriptors { name -> name == pathSegments.first() } + .filter { it.name == pathSegments.first() } + val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current -> + acc.flatMap { container -> + val classDescriptor = container as? ClassDescriptor + ?: return@flatMap emptyList() + val nextStepCandidates = classDescriptor.constructors + + classDescriptor.unsubstitutedMemberScope.getContributedDescriptors { name -> name == current } + + // Static scope is required only for Enum.values() and Enum.valueOf(). + classDescriptor.staticScope.getContributedDescriptors { name -> name == current } + nextStepCandidates.filter { it.name == current } + } + } + + return when (candidates.size) { + 1 -> candidates.first() + else -> { + findDescriptorByHash(candidates, signature.id) + ?: error("No descriptor found for $signature") + } + } + } + + private fun findDescriptorByHash(candidates: List, id: Long?): DeclarationDescriptor? = + candidates.firstOrNull { candidate -> + if (id == null) { + // We don't compute id for typealiases and classes. + candidate is ClassDescriptor || candidate is TypeAliasDescriptor + } else { + val candidateHash = with(mangler) { candidate.signatureMangle } + candidateHash == id + } + } +} \ No newline at end of file diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt new file mode 100644 index 00000000000..e534713c68f --- /dev/null +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IncrementalCompilationSupport.kt @@ -0,0 +1,137 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.common.serialization + +import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.DeserializedDescriptor +import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.library.IrLibrary +import org.jetbrains.kotlin.library.SerializedIrFile +import org.jetbrains.kotlin.library.impl.* + + +class ICKotlinLibrary(private val icData: List) : IrLibrary { + override val dataFlowGraph: ByteArray? = null + + private inline fun > Array.itemBytes(fileIndex: Int, key: K, factory: () -> R): ByteArray { + val reader = this[fileIndex] ?: factory().also { this[fileIndex] = it } + + return reader.tableItemBytes(key) + } + + private inline fun Array.itemBytes(fileIndex: Int, index: Int, factory: () -> R): ByteArray { + val reader = this[fileIndex] ?: factory().also { this[fileIndex] = it } + + return reader.tableItemBytes(index) + } + + private val indexedDeclarations = arrayOfNulls(icData.size) + private val indexedTypes = arrayOfNulls(icData.size) + private val indexedSignatures = arrayOfNulls(icData.size) + private val indexedStrings = arrayOfNulls(icData.size) + private val indexedBodies = arrayOfNulls(icData.size) + + override fun irDeclaration(index: Int, fileIndex: Int): ByteArray = + indexedDeclarations.itemBytes(fileIndex, DeclarationId(index)) { + DeclarationIrTableMemoryReader(icData[fileIndex].declarations) + } + + override fun type(index: Int, fileIndex: Int): ByteArray = + indexedTypes.itemBytes(fileIndex, index) { + IrArrayMemoryReader(icData[fileIndex].types) + } + + override fun signature(index: Int, fileIndex: Int): ByteArray = + indexedSignatures.itemBytes(fileIndex, index) { + IrArrayMemoryReader(icData[fileIndex].signatures) + } + + override fun string(index: Int, fileIndex: Int): ByteArray = + indexedStrings.itemBytes(fileIndex, index) { + IrArrayMemoryReader(icData[fileIndex].strings) + } + + override fun body(index: Int, fileIndex: Int): ByteArray = + indexedBodies.itemBytes(fileIndex, index) { + IrArrayMemoryReader(icData[fileIndex].bodies) + } + + override fun file(index: Int): ByteArray = icData[index].fileData + + override fun fileCount(): Int = icData.size +} + +class CurrentModuleWithICDeserializer( + private val delegate: IrModuleDeserializer, + private val symbolTable: SymbolTable, + private val irBuiltIns: IrBuiltIns, + icData: List, + icReaderFactory: (IrLibrary) -> IrModuleDeserializer) : + IrModuleDeserializer(delegate.moduleDescriptor) { + + private val dirtyDeclarations = mutableMapOf() + private val icKlib = ICKotlinLibrary(icData) + + private val icDeserializer: IrModuleDeserializer = icReaderFactory(icKlib) + + override fun contains(idSig: IdSignature): Boolean { + return idSig in dirtyDeclarations || idSig.topLevelSignature() in icDeserializer || idSig in delegate + } + + override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + dirtyDeclarations[idSig]?.let { return it } + + if (idSig.topLevelSignature() in icDeserializer) return icDeserializer.deserializeIrSymbol(idSig, symbolKind) + + return delegate.deserializeIrSymbol(idSig, symbolKind) + } + + override fun addModuleReachableTopLevel(idSig: IdSignature) { + assert(idSig in icDeserializer) + icDeserializer.addModuleReachableTopLevel(idSig) + } + + override fun deserializeReachableDeclarations() { + icDeserializer.deserializeReachableDeclarations() + } + + override fun postProcess() { + icDeserializer.postProcess() + } + + private fun DeclarationDescriptor.isDirtyDescriptor(): Boolean { + if (this is PropertyAccessorDescriptor) return correspondingProperty.isDirtyDescriptor() + return this !is DeserializedDescriptor + } + + override fun init() { + val knownBuiltIns = irBuiltIns.knownBuiltins.map { (it as IrSymbolOwner).symbol }.toSet() + symbolTable.forEachPublicSymbol { + if (it.descriptor.isDirtyDescriptor()) { // public && non-deserialized should be dirty symbol + if (it !in knownBuiltIns) { + dirtyDeclarations[it.signature] = it + } + } + } + + icDeserializer.init(this) + } + + override val klib: IrLibrary + get() = icDeserializer.klib + + override val moduleFragment: IrModuleFragment + get() = delegate.moduleFragment + override val moduleDependencies: Collection + get() = delegate.moduleDependencies +} \ No newline at end of file diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFakeOverrideUtils.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFakeOverrideUtils.kt deleted file mode 100644 index d66b17ae1d5..00000000000 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFakeOverrideUtils.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.backend.common.serialization - -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol -import org.jetbrains.kotlin.ir.util.isReal -import org.jetbrains.kotlin.ir.util.original - -// We may get several real supers here (e.g. see the code snippet from KT-33034). -// TODO: Consider reworking the resolution algorithm to get a determined super declaration. -private fun , D: IrOverridableDeclaration> D.getRealSupers(): Set { - if (this.isReal) { - return setOf(this) - } - - val visited = mutableSetOf() - val realSupers = mutableSetOf() - - fun findRealSupers(declaration: D) { - if (declaration in visited) return - visited += declaration - if (declaration.isReal) { - realSupers += declaration - } else { - declaration.overriddenSymbols.forEach { findRealSupers(it.owner) } - } - } - - findRealSupers(this) - - if (realSupers.size > 1) { - visited.clear() - - fun excludeOverridden(declaration: D) { - if (declaration in visited) return - visited += declaration - declaration.overriddenSymbols.forEach { - realSupers.remove(it.owner) - excludeOverridden(it.owner) - } - } - - realSupers.toList().forEach { excludeOverridden(it) } - } - - return realSupers -} - -/** - * Implementation of given method. - * - * TODO: this method is actually a part of resolve and probably duplicates another one - */ -fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimpleFunction { - val realSupers = getRealSupers() - - return if (allowAbstract) { - realSupers.first() - } else { - realSupers.single { it.modality != Modality.ABSTRACT } - } -} - -val IrSimpleFunction.target: IrSimpleFunction - get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original - -val IrFunction.target: IrFunction get() = when (this) { - is IrSimpleFunction -> this.target - is IrConstructor -> this - else -> error(this) -} diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt index 091cb5844cf..f6fc17f70af 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileDeserializer.kt @@ -104,7 +104,7 @@ import org.jetbrains.kotlin.backend.common.serialization.proto.PublicIdSignature import org.jetbrains.kotlin.backend.common.serialization.proto.AccessorIdSignature as ProtoAccessorIdSignature import org.jetbrains.kotlin.backend.common.serialization.proto.FileLocalIdSignature as ProtoFileLocalIdSignature -abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBuiltIns, val symbolTable: SymbolTable) { +abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBuiltIns, val symbolTable: SymbolTable, protected var deserializeBodies: Boolean) { abstract fun deserializeIrSymbolToDeclare(code: Long): Pair abstract fun deserializeIrSymbol(code: Long): IrSymbol @@ -118,6 +118,9 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu abstract fun referenceIrSymbol(symbol: IrSymbol, signature: IdSignature) private val parentsStack = mutableListOf() + private val delegatedSymbolMap = mutableMapOf() + + abstract val deserializeInlineFunctions: Boolean fun deserializeFqName(fqn: List): FqName { return fqn.run { @@ -125,6 +128,13 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu } } + private fun deserializeIrSymbolAndRemap(code: Long): IrSymbol { + // TODO: could be simplified + return deserializeIrSymbol(code).let { + delegatedSymbolMap[it] ?: it + } + } + private fun deserializeName(index: Int): Name { val name = deserializeString(index) return Name.guessByFirstCharacter(name) @@ -145,7 +155,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu } private fun deserializeSimpleType(proto: ProtoSimpleType): IrSimpleType { - val symbol = deserializeIrSymbol(proto.classifier) as? IrClassifierSymbol + val symbol = deserializeIrSymbolAndRemap(proto.classifier) as? IrClassifierSymbol ?: error("could not convert sym to ClassifierSymbol") logger.log { "deserializeSimpleType: symbol=$symbol" } @@ -167,7 +177,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu private fun deserializeTypeAbbreviation(proto: ProtoTypeAbbreviation): IrTypeAbbreviation = IrTypeAbbreviationImpl( - deserializeIrSymbol(proto.typeAlias).let { + deserializeIrSymbolAndRemap(proto.typeAlias).let { it as? IrTypeAliasSymbol ?: error("IrTypeAliasSymbol expected: $it") }, @@ -344,14 +354,14 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu end: Int, type: IrType ): IrClassReference { - val symbol = deserializeIrSymbol(proto.classSymbol) as IrClassifierSymbol + val symbol = deserializeIrSymbolAndRemap(proto.classSymbol) as IrClassifierSymbol val classType = deserializeIrType(proto.classType) /** TODO: [createClassifierSymbolForClassReference] is internal function */ return IrClassReferenceImpl(start, end, type, symbol, classType) } private fun deserializeConstructorCall(proto: ProtoConstructorCall, start: Int, end: Int, type: IrType): IrConstructorCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol return IrConstructorCallImpl( start, end, type, symbol, typeArgumentsCount = proto.memberAccess.typeArgumentCount, @@ -363,10 +373,10 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu } private fun deserializeCall(proto: ProtoCall, start: Int, end: Int, type: IrType): IrCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrFunctionSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrFunctionSymbol val superSymbol = if (proto.hasSuper()) { - deserializeIrSymbol(proto.`super`) as IrClassSymbol + deserializeIrSymbolAndRemap(proto.`super`) as IrClassSymbol } else null val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null @@ -400,7 +410,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu start: Int, end: Int ): IrDelegatingConstructorCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol val call = IrDelegatingConstructorCallImpl( start, end, @@ -421,7 +431,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu end: Int, type: IrType ): IrEnumConstructorCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrConstructorSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrConstructorSymbol val call = IrEnumConstructorCallImpl( start, end, @@ -451,10 +461,10 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu start: Int, end: Int, type: IrType ): IrFunctionReference { - val symbol = deserializeIrSymbol(proto.symbol) as IrFunctionSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrFunctionSymbol val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null val reflectionTarget = - if (proto.hasReflectionTargetSymbol()) deserializeIrSymbol(proto.reflectionTargetSymbol) as IrFunctionSymbol else null + if (proto.hasReflectionTargetSymbol()) deserializeIrSymbolAndRemap(proto.reflectionTargetSymbol) as IrFunctionSymbol else null val callable = IrFunctionReferenceImpl( start, end, @@ -477,11 +487,11 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu private fun deserializeGetField(proto: ProtoGetField, start: Int, end: Int, type: IrType): IrGetField { val access = proto.fieldAccess - val symbol = deserializeIrSymbol(access.symbol) as IrFieldSymbol + val symbol = deserializeIrSymbolAndRemap(access.symbol) as IrFieldSymbol val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null val superQualifier = if (access.hasSuper()) { - deserializeIrSymbol(access.symbol) as IrClassSymbol + deserializeIrSymbolAndRemap(access.symbol) as IrClassSymbol } else null val receiver = if (access.hasReceiver()) { deserializeExpression(access.receiver) @@ -491,7 +501,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu } private fun deserializeGetValue(proto: ProtoGetValue, start: Int, end: Int, type: IrType): IrGetValue { - val symbol = deserializeIrSymbol(proto.symbol) as IrValueSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrValueSymbol val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null // TODO: origin! return IrGetValueImpl(start, end, type, symbol, origin) @@ -503,7 +513,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu end: Int, type: IrType ): IrGetEnumValue { - val symbol = deserializeIrSymbol(proto.symbol) as IrEnumEntrySymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrEnumEntrySymbol return IrGetEnumValueImpl(start, end, type, symbol) } @@ -513,7 +523,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu end: Int, type: IrType ): IrGetObjectValue { - val symbol = deserializeIrSymbol(proto.symbol) as IrClassSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrClassSymbol return IrGetObjectValueImpl(start, end, type, symbol) } @@ -522,7 +532,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu start: Int, end: Int ): IrInstanceInitializerCall { - val symbol = deserializeIrSymbol(proto.symbol) as IrClassSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrClassSymbol return IrInstanceInitializerCallImpl(start, end, symbol, builtIns.unitType) } @@ -533,10 +543,10 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu type: IrType ): IrLocalDelegatedPropertyReference { - val delegate = deserializeIrSymbol(proto.delegate) as IrVariableSymbol - val getter = deserializeIrSymbol(proto.getter) as IrSimpleFunctionSymbol - val setter = if (proto.hasSetter()) deserializeIrSymbol(proto.setter) as IrSimpleFunctionSymbol else null - val symbol = deserializeIrSymbol(proto.symbol) as IrLocalDelegatedPropertySymbol + val delegate = deserializeIrSymbolAndRemap(proto.delegate) as IrVariableSymbol + val getter = deserializeIrSymbolAndRemap(proto.getter) as IrSimpleFunctionSymbol + val setter = if (proto.hasSetter()) deserializeIrSymbolAndRemap(proto.setter) as IrSimpleFunctionSymbol else null + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrLocalDelegatedPropertySymbol val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null return IrLocalDelegatedPropertyReferenceImpl( @@ -551,11 +561,11 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu private fun deserializePropertyReference(proto: ProtoPropertyReference, start: Int, end: Int, type: IrType): IrPropertyReference { - val symbol = deserializeIrSymbol(proto.symbol) as IrPropertySymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrPropertySymbol - val field = if (proto.hasField()) deserializeIrSymbol(proto.field) as IrFieldSymbol else null - val getter = if (proto.hasGetter()) deserializeIrSymbol(proto.getter) as IrSimpleFunctionSymbol else null - val setter = if (proto.hasSetter()) deserializeIrSymbol(proto.setter) as IrSimpleFunctionSymbol else null + val field = if (proto.hasField()) deserializeIrSymbolAndRemap(proto.field) as IrFieldSymbol else null + val getter = if (proto.hasGetter()) deserializeIrSymbolAndRemap(proto.getter) as IrSimpleFunctionSymbol else null + val setter = if (proto.hasSetter()) deserializeIrSymbolAndRemap(proto.setter) as IrSimpleFunctionSymbol else null val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null val callable = IrPropertyReferenceImpl( @@ -572,16 +582,16 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu } private fun deserializeReturn(proto: ProtoReturn, start: Int, end: Int, type: IrType): IrReturn { - val symbol = deserializeIrSymbol(proto.returnTarget) as IrReturnTargetSymbol + val symbol = deserializeIrSymbolAndRemap(proto.returnTarget) as IrReturnTargetSymbol val value = deserializeExpression(proto.value) return IrReturnImpl(start, end, builtIns.nothingType, symbol, value) } private fun deserializeSetField(proto: ProtoSetField, start: Int, end: Int): IrSetField { val access = proto.fieldAccess - val symbol = deserializeIrSymbol(access.symbol) as IrFieldSymbol + val symbol = deserializeIrSymbolAndRemap(access.symbol) as IrFieldSymbol val superQualifier = if (access.hasSuper()) { - deserializeIrSymbol(access.symbol) as IrClassSymbol + deserializeIrSymbolAndRemap(access.symbol) as IrClassSymbol } else null val receiver = if (access.hasReceiver()) { deserializeExpression(access.receiver) @@ -593,7 +603,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu } private fun deserializeSetVariable(proto: ProtoSetVariable, start: Int, end: Int): IrSetVariable { - val symbol = deserializeIrSymbol(proto.symbol) as IrVariableSymbol + val symbol = deserializeIrSymbolAndRemap(proto.symbol) as IrVariableSymbol val value = deserializeExpression(proto.value) val origin = if (proto.hasOriginName()) deserializeIrStatementOrigin(proto.originName) else null return IrSetVariableImpl(start, end, builtIns.unitType, symbol, value, origin) @@ -902,6 +912,16 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu } } + private fun recordDelegatedSymbol(symbol: IrSymbol) { + if (symbol is IrDelegatingSymbol<*, *, *>) { + delegatedSymbolMap[symbol] = symbol.delegate + } + } + + private fun eraseDelegatedSymbol(symbol: IrSymbol) { + delegatedSymbolMap.remove(symbol) + } + private inline fun T.usingParent(block: T.() -> Unit): T = this.apply { usingParent(this) { block(it) } } @@ -911,15 +931,20 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu ): T where T : IrDeclaration, T : IrSymbolOwner { val (s, uid) = deserializeIrSymbolToDeclare(proto.symbol) val coordinates = BinaryCoordinates.decode(proto.coordinates) - val result = block( - s, - uid, - coordinates.startOffset, coordinates.endOffset, - deserializeIrDeclarationOrigin(proto.originName), proto.flags - ) - result.annotations += deserializeAnnotations(proto.annotationList) - result.parent = parentsStack.peek()!! - return result + try { + recordDelegatedSymbol(s) + val result = block( + s, + uid, + coordinates.startOffset, coordinates.endOffset, + deserializeIrDeclarationOrigin(proto.originName), proto.flags + ) + result.annotations += deserializeAnnotations(proto.annotationList) + result.parent = parentsStack.peek()!! + return result + } finally { + eraseDelegatedSymbol(s) + } } private fun deserializeIrTypeParameter(proto: ProtoTypeParameter, index: Int, isGlobal: Boolean): IrTypeParameter { @@ -1067,24 +1092,36 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu return result } + private inline fun T.withInlineGuard(block: T.() -> Unit) { + val oldInline = deserializeBodies + try { + deserializeBodies = oldInline || (deserializeInlineFunctions && this is IrSimpleFunction && isInline) + block() + } finally { + deserializeBodies = oldInline + } + } + private inline fun withDeserializedIrFunctionBase( proto: ProtoFunctionBase, block: (IrFunctionSymbol, IdSignature, Int, Int, IrDeclarationOrigin, Long) -> T ) = withDeserializedIrDeclarationBase(proto.base) { symbol, idSig, startOffset, endOffset, origin, fcode -> symbolTable.withScope(symbol.descriptor) { block(symbol as IrFunctionSymbol, idSig, startOffset, endOffset, origin, fcode).usingParent { - typeParameters = deserializeTypeParameters(proto.typeParameterList, false) - valueParameters = deserializeValueParameters(proto.valueParameterList) + withInlineGuard { + typeParameters = deserializeTypeParameters(proto.typeParameterList, false) + valueParameters = deserializeValueParameters(proto.valueParameterList) - val nameType = BinaryNameAndType.decode(proto.nameType) - returnType = deserializeIrType(nameType.typeIndex) + val nameType = BinaryNameAndType.decode(proto.nameType) + returnType = deserializeIrType(nameType.typeIndex) - if (proto.hasDispatchReceiver()) - dispatchReceiverParameter = deserializeIrValueParameter(proto.dispatchReceiver, -1) - if (proto.hasExtensionReceiver()) - extensionReceiverParameter = deserializeIrValueParameter(proto.extensionReceiver, -1) - if (proto.hasBody()) { - body = deserializeStatementBody(proto.body) as IrBody + if (proto.hasDispatchReceiver()) + dispatchReceiverParameter = deserializeIrValueParameter(proto.dispatchReceiver, -1) + if (proto.hasExtensionReceiver()) + extensionReceiverParameter = deserializeIrValueParameter(proto.extensionReceiver, -1) + if (proto.hasBody()) { + body = deserializeStatementBody(proto.body) as IrBody + } } } } @@ -1111,7 +1148,7 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu flags.isFakeOverride ) }.apply { - overriddenSymbols = proto.overriddenList.map { deserializeIrSymbol(it) as IrSimpleFunctionSymbol } + overriddenSymbols = proto.overriddenList.map { deserializeIrSymbolAndRemap(it) as IrSimpleFunctionSymbol } (descriptor as? WrappedSimpleFunctionDescriptor)?.bind(this) } @@ -1328,6 +1365,4 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu usingParent(parent) { deserializeDeclaration(proto) } -} - -val irrelevantOrigin = object : IrDeclarationOriginImpl("irrelevant") {} +} \ No newline at end of file diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt new file mode 100644 index 00000000000..62bd310e984 --- /dev/null +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrModuleDeserializer.kt @@ -0,0 +1,276 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.common.serialization + +import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData +import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.descriptors.WrappedDeclarationDescriptor +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.ir.util.IrExtensionGenerator +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.library.IrLibrary +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +internal fun IrSymbol.kind(): BinarySymbolData.SymbolKind { + return when (this) { + is IrClassSymbol -> BinarySymbolData.SymbolKind.CLASS_SYMBOL + is IrConstructorSymbol -> BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL + is IrSimpleFunctionSymbol -> BinarySymbolData.SymbolKind.FUNCTION_SYMBOL + is IrPropertySymbol -> BinarySymbolData.SymbolKind.PROPERTY_SYMBOL + is IrEnumEntrySymbol -> BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL + is IrTypeAliasSymbol -> BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL + else -> error("Unexpected symbol kind $this") + } +} + +abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor) { + abstract operator fun contains(idSig: IdSignature): Boolean + abstract fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol + + open fun declareIrSymbol(symbol: IrSymbol) { + assert(symbol.isPublicApi) + assert(symbol.descriptor !is WrappedDeclarationDescriptor<*>) + deserializeIrSymbol(symbol.signature, symbol.kind()) + } + + open val klib: IrLibrary get() = error("Unsupported operation") + + open fun init() = init(this) + + open fun init(delegate: IrModuleDeserializer) {} + + open fun addModuleReachableTopLevel(idSig: IdSignature) { error("Unsupported Operation (sig: $idSig") } + + open fun deserializeReachableDeclarations() { error("Unsupported Operation") } + + open fun postProcess() {} + + abstract val moduleFragment: IrModuleFragment + + abstract val moduleDependencies: Collection + + open val strategy: DeserializationStrategy = DeserializationStrategy.ONLY_DECLARATION_HEADERS +} + +// Used to resolve built in symbols like `kotlin.ir.internal.*` or `kotlin.FunctionN` +class IrModuleDeserializerWithBuiltIns( + private val builtIns: IrBuiltIns, + private val functionFactory: IrAbstractFunctionFactory, + private val delegate: IrModuleDeserializer +) : IrModuleDeserializer(delegate.moduleDescriptor) { + + init { + // TODO: figure out how it should work for K/N +// assert(builtIns.builtIns.builtInsModule === delegate.moduleDescriptor) + } + + private val irBuiltInsMap = builtIns.knownBuiltins.map { + val symbol = (it as IrSymbolOwner).symbol + symbol.signature to symbol + }.toMap() + + private fun checkIsFunctionInterface(idSig: IdSignature): Boolean { + val publicSig = idSig.asPublic() ?: return false + + if (publicSig.packageFqn !in functionalPackages) return false + + val declarationFqn = publicSig.declarationFqn + + if (declarationFqn.isRoot) return false + + val fqnParts = declarationFqn.pathSegments() + + val className = fqnParts.first() + + return functionPattern.matcher(className.asString()).find() + } + + override operator fun contains(idSig: IdSignature): Boolean { + if (idSig in irBuiltInsMap) return true + + return checkIsFunctionInterface(idSig) || idSig in delegate + } + + override fun deserializeReachableDeclarations() { + delegate.deserializeReachableDeclarations() + } + + private fun computeFunctionDescriptor(className: Name): FunctionClassDescriptor { + val nameString = className.asString() + val isK = nameString[0] == 'K' + val isSuspend = (if (isK) nameString[1] else nameString[0]) == 'S' + val arity = nameString.run { substring(indexOfFirst { it.isDigit() }).toInt(10) } + return functionFactory.run { + when { + isK && isSuspend -> kSuspendFunctionClassDescriptor(arity) + isK -> kFunctionClassDescriptor(arity) + isSuspend -> suspendFunctionClassDescriptor(arity) + else -> functionClassDescriptor(arity) + } + } + } + + private fun resolveFunctionalInterface(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + val publicSig = idSig.asPublic() ?: error("$idSig has to be public") + + val fqnParts = publicSig.declarationFqn.pathSegments() + val className = fqnParts.firstOrNull() ?: error("Expected class name for $idSig") + + val functionDescriptor = computeFunctionDescriptor(className) + val topLevelSignature = IdSignature.PublicSignature(publicSig.packageFqn, FqName(className.asString()), null, publicSig.mask) + + val functionClass = when (functionDescriptor.functionKind) { + FunctionClassDescriptor.Kind.KSuspendFunction -> functionFactory.kSuspendFunctionN(functionDescriptor.arity) { callback -> + declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) } + } + FunctionClassDescriptor.Kind.KFunction -> functionFactory.kFunctionN(functionDescriptor.arity) { callback -> + declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) } + } + FunctionClassDescriptor.Kind.SuspendFunction -> functionFactory.suspendFunctionN(functionDescriptor.arity) { callback -> + declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) } + } + FunctionClassDescriptor.Kind.Function -> functionFactory.functionN(functionDescriptor.arity) { callback -> + declareClassFromLinker(functionDescriptor, topLevelSignature) { callback(it) } + } + } + + return when (fqnParts.size) { + 1 -> functionClass.symbol.also { assert(symbolKind == BinarySymbolData.SymbolKind.CLASS_SYMBOL) } + 2 -> { + val memberName = fqnParts[1]!! + functionClass.declarations.single { it is IrDeclarationWithName && it.name == memberName }.let { + (it as IrSymbolOwner).symbol + } + } + 3 -> { + assert(idSig is IdSignature.AccessorSignature) + assert(symbolKind == BinarySymbolData.SymbolKind.FUNCTION_SYMBOL) + val propertyName = fqnParts[1]!! + val accessorName = fqnParts[2]!! + functionClass.declarations.filterIsInstance().single { it.name == propertyName }.let { p -> + p.getter?.let { g -> if (g.name == accessorName) return g.symbol } + p.setter?.let { s -> if (s.name == accessorName) return s.symbol } + error("No accessor found for signature $idSig") + } + } + else -> error("No member found for signature $idSig") + } + } + + override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + irBuiltInsMap[idSig]?.let { return it } + + if (checkIsFunctionInterface(idSig)) return resolveFunctionalInterface(idSig, symbolKind) + + return delegate.deserializeIrSymbol(idSig, symbolKind) + } + + override fun postProcess() { + delegate.postProcess() + } + + override fun init() { + delegate.init(this) + } + + override val klib: IrLibrary + get() = delegate.klib + + override val strategy: DeserializationStrategy + get() = delegate.strategy + + override fun addModuleReachableTopLevel(idSig: IdSignature) { + delegate.addModuleReachableTopLevel(idSig) + } + + override val moduleFragment: IrModuleFragment get() = delegate.moduleFragment + override val moduleDependencies: Collection get() = delegate.moduleDependencies +} + +open class CurrentModuleDeserializer( + override val moduleFragment: IrModuleFragment, + override val moduleDependencies: Collection, + private val symbolTable: SymbolTable, + private val extensions: Collection +) : IrModuleDeserializer(moduleFragment.descriptor) { + override fun contains(idSig: IdSignature): Boolean = false // TODO: + + override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + error("Unreachable execution: there could not be back-links") + } + + override fun declareIrSymbol(symbol: IrSymbol) { + declareIrSymbolImpl(symbol) + } + + private fun referenceParentDescriptor(descriptor: DeclarationDescriptor): IrSymbol { + return when (descriptor) { + is ClassDescriptor -> symbolTable.referenceClass(descriptor) + is PropertyDescriptor -> symbolTable.referenceProperty(descriptor) + is PackageFragmentDescriptor -> moduleFragment.files.single { it.symbol.descriptor === descriptor }.symbol + else -> error("Unexpected declaration parent $descriptor") + } + } + + private fun declareIrDeclaration(symbol: IrSymbol): IrDeclaration { + for (extension in extensions) { + extension.declare(symbol)?.let { return it } + } + + return declareIrDeclarationDefault(symbol) + } + + private fun declareIrDeclarationDefault(symbol: IrSymbol): IrDeclaration { + return when (symbol) { + is IrClassSymbol -> symbolTable.declareClass(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor) + is IrConstructorSymbol -> symbolTable.declareConstructor(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor) + is IrSimpleFunctionSymbol -> symbolTable.declareSimpleFunction(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor) + is IrPropertySymbol -> symbolTable.declareProperty(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor) + is IrTypeAliasSymbol -> TODO("Implement type alias $symbol") + is IrEnumEntrySymbol -> symbolTable.declareEnumEntry(offset, offset, IrDeclarationOrigin.DEFINED, symbol.descriptor) + else -> error("Unexpected symbol $symbol") + } + } + + private fun declareIrSymbolImpl(symbol: IrSymbol): IrSymbolOwner { + if (symbol.isBound) return symbol.owner + val descriptor = symbol.descriptor + + assert(descriptor !is WrappedDeclarationDescriptor<*>) + + val accessor = descriptor as? PropertyAccessorDescriptor + + val parent = descriptor.containingDeclaration ?: error("Expect non-root declaration $descriptor") + val parentDeclaration = declareIrSymbolImpl(referenceParentDescriptor(parent)) as IrDeclarationContainer + + val declaredDeclaration = declareIrDeclaration(symbol).also { + it.parent = parentDeclaration + if (accessor != null) { + val property = accessor.correspondingProperty + val irProperty = declareIrSymbolImpl(referenceParentDescriptor(property)) as IrProperty + val irAccessor = it as IrSimpleFunction + irAccessor.correspondingPropertySymbol = irProperty.symbol + if (accessor === property.getter) irProperty.getter = irAccessor + if (accessor === property.setter) irProperty.setter = irAccessor + } else { + parentDeclaration.declarations.add(it) + } + } + + return declaredDeclaration as IrSymbolOwner + } + + companion object { + private const val offset = UNDEFINED_OFFSET + } +} \ No newline at end of file diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt index c09436896b3..fa8685d978c 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/KotlinIrLinker.kt @@ -7,13 +7,12 @@ package org.jetbrains.kotlin.backend.common.serialization import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData -import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl import org.jetbrains.kotlin.ir.descriptors.* @@ -26,416 +25,127 @@ import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.library.IrLibrary +import org.jetbrains.kotlin.library.KotlinLibrary +import org.jetbrains.kotlin.protobuf.CodedInputStream import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite.newInstance import org.jetbrains.kotlin.resolve.descriptorUtil.module -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration -import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile -import org.jetbrains.kotlin.backend.common.serialization.proto.IrType as ProtoType -import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement -import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression -import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructorCall as ProtoConstructorCall import org.jetbrains.kotlin.backend.common.serialization.proto.Actual as ProtoActual import org.jetbrains.kotlin.backend.common.serialization.proto.IdSignature as ProtoIdSignature +import org.jetbrains.kotlin.backend.common.serialization.proto.IrConstructorCall as ProtoConstructorCall +import org.jetbrains.kotlin.backend.common.serialization.proto.IrDeclaration as ProtoDeclaration +import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression +import org.jetbrains.kotlin.backend.common.serialization.proto.IrFile as ProtoFile +import org.jetbrains.kotlin.backend.common.serialization.proto.IrStatement as ProtoStatement +import org.jetbrains.kotlin.backend.common.serialization.proto.IrType as ProtoType abstract class KotlinIrLinker( + private val currentModule: ModuleDescriptor?, val logger: LoggingContext, val builtIns: IrBuiltIns, val symbolTable: SymbolTable, - private val exportedDependencies: List, - private val forwardModuleDescriptor: ModuleDescriptor? + private val exportedDependencies: List ) : IrDeserializer { + // Kotlin-MPP related data. Consider some refactoring private val expectUniqIdToActualUniqId = mutableMapOf() private val topLevelActualUniqItToDeserializer = mutableMapOf() private val expectSymbols = mutableMapOf() private val actualSymbols = mutableMapOf() - sealed class DeserializationState { - val deserializedSymbols = mutableMapOf() + private val modulesWithReachableTopLevels = mutableSetOf() - operator fun contains(key: IdSignature) = key in deserializedSymbols - operator fun get(key: IdSignature): IrSymbol = deserializedSymbols[key] ?: error("No deserialized symbol found for $key") + protected val deserializersForModules = mutableMapOf() - abstract fun addIdSignature(key: IdSignature) - abstract fun processPendingDeclarations(processor: (T) -> Unit) + abstract inner class BasicIrModuleDeserializer(moduleDescriptor: ModuleDescriptor, override val klib: IrLibrary, override val strategy: DeserializationStrategy) : + IrModuleDeserializer(moduleDescriptor) { - class ModuleDeserializationState(val module: IrModuleDeserializer) : - DeserializationState() { - private val filesWithPendingTopLevels = mutableSetOf() + private val fileToDeserializerMap = mutableMapOf() - fun enqueueFile(fileDeserializer: IrModuleDeserializer.IrDeserializerForFile) { + private inner class ModuleDeserializationState { + private val filesWithPendingTopLevels = mutableSetOf() + + fun enqueueFile(fileDeserializer: IrDeserializerForFile) { filesWithPendingTopLevels.add(fileDeserializer) - module.enqueueModule() + enqueueModule() } - override fun addIdSignature(key: IdSignature) { - val fileDeserializer = module.moduleReversedFileIndex[key] ?: error("No file found for key $key") + fun addIdSignature(key: IdSignature) { + val fileDeserializer = moduleReversedFileIndex[key] ?: error("No file found for key $key") fileDeserializer.fileLocalDeserializationState.addIdSignature(key) enqueueFile(fileDeserializer) } - override fun processPendingDeclarations(processor: (IrModuleDeserializer.IrDeserializerForFile) -> Unit) { + fun processPendingDeclarations() { while (filesWithPendingTopLevels.isNotEmpty()) { val pendingDeserializer = filesWithPendingTopLevels.first() - processor(pendingDeserializer) + pendingDeserializer.deserializeFileImplicitDataIfFirstUse() + pendingDeserializer.deserializeAllFileReachableTopLevel() filesWithPendingTopLevels.remove(pendingDeserializer) } } } - class SimpleDeserializationState(private val checker: (IdSignature) -> Boolean) : DeserializationState() { - private val reachableTopLevels = LinkedHashSet() - - private fun shouldBeProcessed(idSig: IdSignature): Boolean = checker(idSig) - - override fun addIdSignature(key: IdSignature) { - reachableTopLevels.add(key) - } - - override fun processPendingDeclarations(processor: (IdSignature) -> Unit) { - while (reachableTopLevels.isNotEmpty()) { - val reachableKey = reachableTopLevels.first() - - if (shouldBeProcessed(reachableKey)) { - val existedSymbol = deserializedSymbols[reachableKey] - if (existedSymbol == null || !existedSymbol.isBound) { - processor(reachableKey) - } - } - - reachableTopLevels.remove(reachableKey) - } - } - } - } - - protected val globalDeserializationState = DeserializationState.SimpleDeserializationState { true } - private val modulesWithReachableTopLevels = mutableSetOf() - - //TODO: This is Native specific. Eliminate me. - private val forwardDeclarations = mutableSetOf() - - protected val deserializersForModules = mutableMapOf() - - abstract inner class IrModuleDeserializer( - private val moduleDescriptor: ModuleDescriptor, - private val strategy: DeserializationStrategy) { - - val fileToDeserializerMap = mutableMapOf() - - private val moduleDeserializationState = DeserializationState.ModuleDeserializationState(this) - val moduleReversedFileIndex = mutableMapOf() - private val moduleDependencies by lazy { - moduleDescriptor.allDependencyModules.filter { it != moduleDescriptor }.mapNotNull { resolveModuleDeserializer(it) } + private val moduleDeserializationState = ModuleDeserializationState() + private val moduleReversedFileIndex = mutableMapOf() + override val moduleDependencies by lazy { + moduleDescriptor.allDependencyModules.filter { it != moduleDescriptor }.map { resolveModuleDeserializer(it) } } - protected open fun containsIdSignature(idSig: IdSignature): Boolean = idSig in moduleReversedFileIndex + override fun init(delegate: IrModuleDeserializer) { + val fileCount = klib.fileCount() - // This is a heavy initializer - val module = deserializeIrModuleHeader() + val files = ArrayList(fileCount) - inner class IrDeserializerForFile( - private var annotations: List?, - private val actuals: List, - private val fileIndex: Int, - onlyHeaders: Boolean - ) : IrFileDeserializer(logger, builtIns, symbolTable) { - - private var fileLoops = mutableMapOf() - - lateinit var file: IrFile - - private val deserializeBodies: Boolean = !onlyHeaders - - private val irTypeCache = mutableMapOf() - - var reversedSignatureIndex = emptyMap() - - val fileLocalDeserializationState = DeserializationState.SimpleDeserializationState { - moduleDeserializationState.deserializedSymbols[it]?.isBound != true + for (i in 0 until fileCount) { + val fileStream = klib.file(i).codedInputStream + files.add(deserializeIrFile(ProtoFile.parseFrom(fileStream, newInstance()), i, delegate)) } - fun deserializeDeclaration(idSig: IdSignature): IrDeclaration { - return deserializeDeclaration(loadTopLevelDeclarationProto(idSig), file) - } + moduleFragment.files.addAll(files) - fun deserializeExpectActualMapping() { - actuals.forEach { - val expectSymbol = parseSymbolData(it.expectSymbol) - val actualSymbol = parseSymbolData(it.actualSymbol) + fileToDeserializerMap.values.forEach { it.deserializeExpectActualMapping() } + } - val expect = deserializeIdSignature(expectSymbol.signatureId) - val actual = deserializeIdSignature(actualSymbol.signatureId) + // TODO: fix to topLevel checker + override fun contains(idSig: IdSignature): Boolean = idSig in moduleReversedFileIndex - assert(expectUniqIdToActualUniqId[expect] == null) { - "Expect signature $expect is already actualized by ${expectUniqIdToActualUniqId[expect]}, while we try to record $actual" - } - expectUniqIdToActualUniqId[expect] = actual - // Non-null only for topLevel declarations. - getModuleForTopLevelId(actual)?.let { md -> topLevelActualUniqItToDeserializer[actual] = md } - } - } + override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + assert(idSig.isPublic) - private fun resolveSignatureIndex(idSig: IdSignature): Int { - return reversedSignatureIndex[idSig] ?: error("Not found Idx for $idSig") - } + val topLevelSignature = idSig.topLevelSignature() + val fileDeserializer = moduleReversedFileIndex[topLevelSignature] + ?: error("No file for $topLevelSignature (@ $idSig) in module $moduleDescriptor") - private fun loadTopLevelDeclarationProto(idSig: IdSignature): ProtoDeclaration { - val idSigIndex = resolveSignatureIndex(idSig) - val stream = reader(moduleDescriptor, fileIndex, idSigIndex).codedInputStream - return ProtoDeclaration.parseFrom(stream, newInstance()) - } + val fileDeserializationState = fileDeserializer.fileLocalDeserializationState - private fun loadTypeProto(index: Int): ProtoType { - val stream = readType(moduleDescriptor, fileIndex, index).codedInputStream - return ProtoType.parseFrom(stream, newInstance()) - } + fileDeserializationState.addIdSignature(topLevelSignature) + moduleDeserializationState.enqueueFile(fileDeserializer) - private fun loadSignatureProto(index: Int): ProtoIdSignature { - val stream = readSignature(moduleDescriptor, fileIndex, index).codedInputStream - return ProtoIdSignature.parseFrom(stream, newInstance()) - } + return fileDeserializationState.deserializedSymbols.getOrPut(idSig) { +// val descriptor = resolveSpecialSignature(idSig) + val symbol = referenceDeserializedSymbol(symbolKind, idSig) - private fun loadStatementBodyProto(index: Int): ProtoStatement { - val stream = readBody(moduleDescriptor, fileIndex, index).codedInputStream - return ProtoStatement.parseFrom(stream, newInstance()) - } - - private fun loadExpressionBodyProto(index: Int): ProtoExpression { - val stream = readBody(moduleDescriptor, fileIndex, index).codedInputStream - return ProtoExpression.parseFrom(stream, newInstance()) - } - - private fun loadStringProto(index: Int): String { - return String(readString(moduleDescriptor, fileIndex, index)) - } - // TODO: this function allows passing descriptor for all kinds of symbols. - // It is incorrect. - private fun referenceDeserializedSymbol( - symbolKind: BinarySymbolData.SymbolKind, - idSignature: IdSignature, - descriptor: DeclarationDescriptor? - ): IrSymbol { - fun checkDescriptorIsNull(symbolKind: BinarySymbolData.SymbolKind) { - assert(descriptor == null) { "Symbol with kind $symbolKind should not have non-wrapped descriptor" } - } - - return symbolTable.run { - when (symbolKind) { - BinarySymbolData.SymbolKind.ANONYMOUS_INIT_SYMBOL -> { - checkDescriptorIsNull(symbolKind) - IrAnonymousInitializerSymbolImpl(WrappedClassDescriptor()) - .also { require(idSignature.isLocal) } - } - // TODO: FunctionInterfaces - BinarySymbolData.SymbolKind.CLASS_SYMBOL -> referenceClassFromLinker( - descriptor as? ClassDescriptor ?: WrappedClassDescriptor(), idSignature - ) - BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL -> referenceConstructorFromLinker( - descriptor as? ClassConstructorDescriptor ?: WrappedClassConstructorDescriptor(), idSignature - ) - BinarySymbolData.SymbolKind.TYPE_PARAMETER_SYMBOL -> { - checkDescriptorIsNull(symbolKind) - referenceTypeParameterFromLinker(WrappedTypeParameterDescriptor(), idSignature) - } - BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> referenceEnumEntryFromLinker( - descriptor as? ClassDescriptor ?: WrappedEnumEntryDescriptor(), idSignature - ) - BinarySymbolData.SymbolKind.STANDALONE_FIELD_SYMBOL -> { - checkDescriptorIsNull(symbolKind) - referenceFieldFromLinker(WrappedFieldDescriptor(), idSignature) - } - BinarySymbolData.SymbolKind.FIELD_SYMBOL -> { - checkDescriptorIsNull(symbolKind) - referenceFieldFromLinker(WrappedPropertyDescriptor(), idSignature) - } - //TODO: FunctionInterfaces - BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> referenceSimpleFunctionFromLinker( - descriptor as? FunctionDescriptor ?: WrappedSimpleFunctionDescriptor(), idSignature - ) - BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL -> referenceTypeAliasFromLinker( - descriptor as? TypeAliasDescriptor ?: WrappedTypeAliasDescriptor(), idSignature - ) - BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> referencePropertyFromLinker( - descriptor as? PropertyDescriptor ?: WrappedPropertyDescriptor(), idSignature - ) - BinarySymbolData.SymbolKind.VARIABLE_SYMBOL -> { - checkDescriptorIsNull(symbolKind) - IrVariableSymbolImpl(WrappedVariableDescriptor()) - } - BinarySymbolData.SymbolKind.VALUE_PARAMETER_SYMBOL -> { - checkDescriptorIsNull(symbolKind) - IrValueParameterSymbolImpl(WrappedValueParameterDescriptor()) - } - BinarySymbolData.SymbolKind.RECEIVER_PARAMETER_SYMBOL -> IrValueParameterSymbolImpl( - descriptor as? ReceiverParameterDescriptor ?: WrappedReceiverParameterDescriptor() - ) - BinarySymbolData.SymbolKind.LOCAL_DELEGATED_PROPERTY_SYMBOL -> { - checkDescriptorIsNull(symbolKind) - IrLocalDelegatedPropertySymbolImpl(WrappedVariableDescriptorWithAccessor()) - } - else -> error("Unexpected classifier symbol kind: $symbolKind") - } - } - } - - private fun isGlobalIdSignature(isSignature: IdSignature): Boolean { - return isSignature in globalDeserializationState || isSpecialSignature(isSignature) - } - - private fun getModuleForTopLevelId(idSignature: IdSignature): IrModuleDeserializer? { - if (containsIdSignature(idSignature)) return this@IrModuleDeserializer - return moduleDependencies.firstOrNull { it.containsIdSignature(idSignature) } - } - - private fun getStateForID(isSignature: IdSignature): DeserializationState<*> { - if (isSignature.isLocal) return fileLocalDeserializationState - if (isGlobalIdSignature(isSignature)) return globalDeserializationState - return getModuleForTopLevelId(isSignature)?.moduleDeserializationState ?: handleNoModuleDeserializerFound(isSignature) - } - - private fun findDeserializationState(idSignature: IdSignature): DeserializationState<*> { - if (idSignature.hasTopLevel) { - val topLevelSignature = idSignature.topLevelSignature() - - val topLevelDeserializationState = getStateForID(topLevelSignature) - - if (topLevelSignature !in topLevelDeserializationState) { - topLevelDeserializationState.addIdSignature(topLevelSignature) - } - - // If topLevel declaration is module-public and current declaration iы not (e.g. value parameter) - // they should be processed via different tables - if (idSignature.isLocal) return fileLocalDeserializationState - - return topLevelDeserializationState - } - - assert(idSignature.isLocal) - return fileLocalDeserializationState - } - - private fun referenceIrSymbolData(symbol: IrSymbol, signature: IdSignature) { - val deserializationState = findDeserializationState(signature) - deserializationState.deserializedSymbols.putIfAbsent(signature, symbol) - } - - private fun deserializeIrSymbolData(idSignature: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { - val deserializationState = findDeserializationState(idSignature) - - val symbol = deserializationState.deserializedSymbols.getOrPut(idSignature) { - val descriptor = resolveSpecialSignature(idSignature) - - // TODO: move this logic out there - postProcessPlatformSpecificDeclaration(idSignature, descriptor) { - val fdState = getStateForID(it) - assert(it.isPublic && it.topLevelSignature() == it) - if (it !in fdState) fdState.addIdSignature(it) - } - - val symbol = referenceDeserializedSymbol(symbolKind, idSignature, descriptor).let { - if (expectUniqIdToActualUniqId[idSignature] != null) wrapInDelegatedSymbol(it) else it - } - - if (idSignature in expectUniqIdToActualUniqId.keys) expectSymbols[idSignature] = symbol - if (idSignature in expectUniqIdToActualUniqId.values) actualSymbols[idSignature] = symbol - - symbol - } - if (symbol.descriptor is ClassDescriptor && - symbol.descriptor !is WrappedDeclarationDescriptor<*> && - symbol.descriptor.module.isForwardDeclarationModule - ) { - forwardDeclarations.add(symbol) - } - - return symbol - } - - override fun deserializeIrSymbolToDeclare(code: Long): Pair { - val symbolData = parseSymbolData(code) - val signature = deserializeIdSignature(symbolData.signatureId) - return Pair(deserializeIrSymbolData(signature, symbolData.kind), signature) - } - - fun parseSymbolData(code: Long): BinarySymbolData = BinarySymbolData.decode(code) - - override fun deserializeIrSymbol(code: Long): IrSymbol { - val symbolData = parseSymbolData(code) - val signature = deserializeIdSignature(symbolData.signatureId) - return deserializeIrSymbolData(signature, symbolData.kind) - } - - override fun deserializeIrType(index: Int): IrType { - return irTypeCache.getOrPut(index) { - val typeData = loadTypeProto(index) - deserializeIrTypeData(typeData) - } - } - - override fun deserializeIdSignature(index: Int): IdSignature { - val sigData = loadSignatureProto(index) - return deserializeSignatureData(sigData) - } - - override fun deserializeString(index: Int): String = - loadStringProto(index) - - override fun deserializeLoopHeader(loopIndex: Int, loopBuilder: () -> IrLoopBase) = - fileLoops.getOrPut(loopIndex, loopBuilder) - - override fun deserializeExpressionBody(index: Int): IrExpression { - return if (deserializeBodies) { - val bodyData = loadExpressionBodyProto(index) - deserializeExpression(bodyData) - } else { - val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT) - IrErrorExpressionImpl(-1, -1, errorType, "Expression body is not deserialized yet") - } - } - - override fun deserializeStatementBody(index: Int): IrElement { - if (deserializeBodies) { - val bodyData = loadStatementBodyProto(index) - return deserializeStatement(bodyData) - } else { - val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT) - return IrBlockBodyImpl(-1, -1, listOf(IrErrorExpressionImpl(-1, -1, errorType, "Statement body is not deserialized yet"))) - } - } - - override fun referenceIrSymbol(symbol: IrSymbol, signature: IdSignature) { - referenceIrSymbolData(symbol, signature) - } - - fun deserializeFileImplicitDataIfFirstUse() { - annotations?.let { - file.annotations += deserializeAnnotations(it) - annotations = null - } - } - - fun deserializeAllFileReachableTopLevel() { - fileLocalDeserializationState.processPendingDeclarations { - val declaration = deserializeDeclaration(it) - file.declarations.add(declaration) - } + handleExpectActualMapping(idSig, symbol) } } - private fun deserializeIrFile(fileProto: ProtoFile, fileIndex: Int): IrFile { + override fun postProcess() {} + + override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList()) + + private fun deserializeIrFile(fileProto: ProtoFile, fileIndex: Int, moduleDeserializer: IrModuleDeserializer): IrFile { val fileName = fileProto.fileEntry.name val fileEntry = NaiveSourceBasedFileEntryImpl(fileName, fileProto.fileEntry.lineStartOffsetsList.toIntArray()) val fileDeserializer = - IrDeserializerForFile(fileProto.annotationList, fileProto.actualsList, fileIndex, !strategy.needBodies).apply { + IrDeserializerForFile(fileProto.annotationList, fileProto.actualsList, fileIndex, !strategy.needBodies, strategy.inlineBodies, moduleDeserializer).apply { // Explicitly exported declarations (e.g. top-level initializers) must be deserialized before all other declarations. // Thus we schedule their deserialization in deserializer's constructor. @@ -477,185 +187,325 @@ abstract class KotlinIrLinker( return file } - private fun deserializeIrModuleHeader(): IrModuleFragment { - val fileCount = readFileCount(moduleDescriptor) - - val files = ArrayList(fileCount) - - for (i in 0 until fileCount) { - files.add(deserializeIrFile(ProtoFile.parseFrom(readFile(moduleDescriptor, i), newInstance()), i)) - } - - return IrModuleFragmentImpl(moduleDescriptor, builtIns, files) + override fun deserializeReachableDeclarations() { + moduleDeserializationState.processPendingDeclarations() } - fun deserializeAllModuleReachableTopLevels() { - moduleDeserializationState.processPendingDeclarations { fileDeserializer -> - fileDeserializer.deserializeFileImplicitDataIfFirstUse() - fileDeserializer.deserializeAllFileReachableTopLevel() - } - } - - fun enqueueModule() { + private fun enqueueModule() { modulesWithReachableTopLevels.add(this) } - fun addModuleReachableTopLevel(idSig: IdSignature) { + override fun addModuleReachableTopLevel(idSig: IdSignature) { moduleDeserializationState.addIdSignature(idSig) } } - private fun loadKnownBuiltinSymbols() { - val globalDeserializedSymbols = globalDeserializationState.deserializedSymbols - builtIns.knownBuiltins.forEach { - val symbol = (it as IrSymbolOwner).symbol - val signature = symbol.signature - globalDeserializedSymbols[signature] = symbol + inner class IrDeserializerForFile( + private var annotations: List?, + private val actuals: List, + private val fileIndex: Int, + onlyHeaders: Boolean, + inlineBodies: Boolean, + private val moduleDeserializer: IrModuleDeserializer + ) : IrFileDeserializer(logger, builtIns, symbolTable, !onlyHeaders) { + + private var fileLoops = mutableMapOf() + + lateinit var file: IrFile + + private val irTypeCache = mutableMapOf() + + override val deserializeInlineFunctions: Boolean = inlineBodies + + var reversedSignatureIndex = emptyMap() + + inner class FileDeserializationState { + private val reachableTopLevels = LinkedHashSet() + val deserializedSymbols = mutableMapOf() + + fun addIdSignature(key: IdSignature) { + reachableTopLevels.add(key) + } + + fun processPendingDeclarations() { + while (reachableTopLevels.isNotEmpty()) { + val reachableKey = reachableTopLevels.first() + + val existedSymbol = deserializedSymbols[reachableKey] + if (existedSymbol == null || !existedSymbol.isBound) { + val declaration = deserializeDeclaration(reachableKey) + file.declarations.add(declaration) + } + + reachableTopLevels.remove(reachableKey) + } + } + } + + val fileLocalDeserializationState = FileDeserializationState() + + fun deserializeDeclaration(idSig: IdSignature): IrDeclaration { + return deserializeDeclaration(loadTopLevelDeclarationProto(idSig), file) + } + + fun deserializeExpectActualMapping() { + actuals.forEach { + val expectSymbol = parseSymbolData(it.expectSymbol) + val actualSymbol = parseSymbolData(it.actualSymbol) + + val expect = deserializeIdSignature(expectSymbol.signatureId) + val actual = deserializeIdSignature(actualSymbol.signatureId) + + assert(expectUniqIdToActualUniqId[expect] == null) { + "Expect signature $expect is already actualized by ${expectUniqIdToActualUniqId[expect]}, while we try to record $actual" + } + expectUniqIdToActualUniqId[expect] = actual + // Non-null only for topLevel declarations. + getModuleForTopLevelId(actual)?.let { md -> topLevelActualUniqItToDeserializer[actual] = md } + } + } + + private fun resolveSignatureIndex(idSig: IdSignature): Int { + return reversedSignatureIndex[idSig] ?: error("Not found Idx for $idSig") + } + + private fun readDeclaration(index: Int): CodedInputStream = + moduleDeserializer.klib.irDeclaration(index, fileIndex).codedInputStream + + private fun loadTopLevelDeclarationProto(idSig: IdSignature): ProtoDeclaration { + val idSigIndex = resolveSignatureIndex(idSig) + return ProtoDeclaration.parseFrom(readDeclaration(idSigIndex), newInstance()) + } + + private fun readType(index: Int): CodedInputStream = + moduleDeserializer.klib.type(index, fileIndex).codedInputStream + + private fun loadTypeProto(index: Int): ProtoType { + return ProtoType.parseFrom(readType(index), newInstance()) + } + + private fun readSignature(index: Int): CodedInputStream = + moduleDeserializer.klib.signature(index, fileIndex).codedInputStream + + private fun loadSignatureProto(index: Int): ProtoIdSignature { + return ProtoIdSignature.parseFrom(readSignature(index), newInstance()) + } + + private fun readBody(index: Int): CodedInputStream = + moduleDeserializer.klib.body(index, fileIndex).codedInputStream + + private fun loadStatementBodyProto(index: Int): ProtoStatement { + return ProtoStatement.parseFrom(readBody(index), newInstance()) + } + + private fun loadExpressionBodyProto(index: Int): ProtoExpression { + return ProtoExpression.parseFrom(readBody(index), newInstance()) + } + + private fun loadStringProto(index: Int): String { + return String(moduleDeserializer.klib.string(index, fileIndex)) + } + + private fun getModuleForTopLevelId(idSignature: IdSignature): IrModuleDeserializer? { + if (idSignature in moduleDeserializer) return moduleDeserializer + return moduleDeserializer.moduleDependencies.firstOrNull { idSignature in it } + } + + private fun findModuleDeserializer(idSig: IdSignature): IrModuleDeserializer { + assert(idSig.isPublic) + + val topLevelSig = idSig.topLevelSignature() + if (topLevelSig in moduleDeserializer) return moduleDeserializer + return moduleDeserializer.moduleDependencies.firstOrNull { topLevelSig in it } ?: handleNoModuleDeserializerFound(idSig) + } + + private fun referenceIrSymbolData(symbol: IrSymbol, signature: IdSignature) { + assert(signature.isLocal) + fileLocalDeserializationState.deserializedSymbols.putIfAbsent(signature, symbol) + } + + private fun deserializeIrLocalSymbolData(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + assert(idSig.isLocal) + + if (idSig.hasTopLevel) { + fileLocalDeserializationState.addIdSignature(idSig.topLevelSignature()) + } + + return fileLocalDeserializationState.deserializedSymbols.getOrPut(idSig) { + referenceDeserializedSymbol(symbolKind, idSig) + } + } + + private fun deserializeIrSymbolData(idSignature: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + if (idSignature.isLocal) return deserializeIrLocalSymbolData(idSignature, symbolKind) + + return findModuleDeserializer(idSignature).deserializeIrSymbol(idSignature, symbolKind) + } + + override fun deserializeIrSymbolToDeclare(code: Long): Pair { + val symbolData = parseSymbolData(code) + val signature = deserializeIdSignature(symbolData.signatureId) + return Pair(deserializeIrSymbolData(signature, symbolData.kind), signature) + } + + fun parseSymbolData(code: Long): BinarySymbolData = BinarySymbolData.decode(code) + + override fun deserializeIrSymbol(code: Long): IrSymbol { + val symbolData = parseSymbolData(code) + val signature = deserializeIdSignature(symbolData.signatureId) + return deserializeIrSymbolData(signature, symbolData.kind) + } + + override fun deserializeIrType(index: Int): IrType { + return irTypeCache.getOrPut(index) { + val typeData = loadTypeProto(index) + deserializeIrTypeData(typeData) + } + } + + override fun deserializeIdSignature(index: Int): IdSignature { + val sigData = loadSignatureProto(index) + return deserializeSignatureData(sigData) + } + + override fun deserializeString(index: Int): String = + loadStringProto(index) + + override fun deserializeLoopHeader(loopIndex: Int, loopBuilder: () -> IrLoopBase) = + fileLoops.getOrPut(loopIndex, loopBuilder) + + override fun deserializeExpressionBody(index: Int): IrExpression { + return if (deserializeBodies) { + val bodyData = loadExpressionBodyProto(index) + deserializeExpression(bodyData) + } else { + val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT) + IrErrorExpressionImpl(-1, -1, errorType, "Expression body is not deserialized yet") + } + } + + override fun deserializeStatementBody(index: Int): IrElement { + return if (deserializeBodies) { + val bodyData = loadStatementBodyProto(index) + deserializeStatement(bodyData) + } else { + val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT) + IrBlockBodyImpl(-1, -1, listOf(IrErrorExpressionImpl(-1, -1, errorType, "Statement body is not deserialized yet"))) + } + } + + override fun referenceIrSymbol(symbol: IrSymbol, signature: IdSignature) { + referenceIrSymbolData(symbol, signature) + } + + fun deserializeFileImplicitDataIfFirstUse() { + annotations?.let { + file.annotations += deserializeAnnotations(it) + annotations = null + } + } + + fun deserializeAllFileReachableTopLevel() { + fileLocalDeserializationState.processPendingDeclarations() } } - init { - loadKnownBuiltinSymbols() - } - - private val ByteArray.codedInputStream: org.jetbrains.kotlin.protobuf.CodedInputStream + private val ByteArray.codedInputStream: CodedInputStream get() { - val codedInputStream = org.jetbrains.kotlin.protobuf.CodedInputStream.newInstance(this) + val codedInputStream = CodedInputStream.newInstance(this) codedInputStream.setRecursionLimit(65535) // The default 64 is blatantly not enough for IR. return codedInputStream } - protected abstract fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int): ByteArray - protected abstract fun readType(moduleDescriptor: ModuleDescriptor, fileIndex: Int, typeIndex: Int): ByteArray - protected abstract fun readSignature(moduleDescriptor: ModuleDescriptor, fileIndex: Int, signatureIndex: Int): ByteArray - protected abstract fun readString(moduleDescriptor: ModuleDescriptor, fileIndex: Int, stringIndex: Int): ByteArray - protected abstract fun readBody(moduleDescriptor: ModuleDescriptor, fileIndex: Int, bodyIndex: Int): ByteArray - protected abstract fun readFile(moduleDescriptor: ModuleDescriptor, fileIndex: Int): ByteArray - protected abstract fun readFileCount(moduleDescriptor: ModuleDescriptor): Int - - protected open fun handleNoModuleDeserializerFound(idSignature: IdSignature): DeserializationState<*> { + protected open fun handleNoModuleDeserializerFound(idSignature: IdSignature): IrModuleDeserializer { error("Deserializer for declaration $idSignature is not found") } - protected open fun resolveModuleDeserializer(moduleDescriptor: ModuleDescriptor): IrModuleDeserializer? { - return deserializersForModules[moduleDescriptor] ?: error("No module deserializer found for $moduleDescriptor") + protected open fun resolveModuleDeserializer(moduleDescriptor: ModuleDescriptor): IrModuleDeserializer { + return deserializersForModules[moduleDescriptor] ?: + error("No module deserializer found for $moduleDescriptor") } protected abstract fun createModuleDeserializer( moduleDescriptor: ModuleDescriptor, + klib: IrLibrary?, strategy: DeserializationStrategy, ): IrModuleDeserializer - // TODO: the following code worths some refactoring in the nearest future + protected abstract val functionalInteraceFactory: IrAbstractFunctionFactory - private fun isSpecialSignature(idSig: IdSignature): Boolean { - return isSpecialPlatformSignature(idSig) || isSpecialFunctionDescriptor(idSig) - } - private fun resolveSpecialSignature(idSig: IdSignature): DeclarationDescriptor? { - return resolvePlatformDescriptor(idSig) ?: resolveFunctionDescriptor(idSig) - } + protected abstract fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean - protected open fun resolvePlatformDescriptor(idSig: IdSignature): DeclarationDescriptor? = null - protected open fun isSpecialPlatformSignature(idSig: IdSignature): Boolean = false + // TODO: the following code worth some refactoring in the nearest future - protected open fun postProcessPlatformSpecificDeclaration(idSig: IdSignature, descriptor: DeclarationDescriptor?, block: (IdSignature) -> Unit) { + private fun handleExpectActualMapping(idSig: IdSignature, rawSymbol: IrSymbol): IrSymbol { + val referencingSymbol = if (idSig in expectUniqIdToActualUniqId.keys) { + assert(idSig.run { IdSignature.Flags.IS_EXPECT.test() }) + wrapInDelegatedSymbol(rawSymbol).also { expectSymbols[idSig] = it } + } else rawSymbol - } - - private fun isSpecialFunctionDescriptor(idSig: IdSignature): Boolean { - - val publicSig = idSig.asPublic() ?: return false - - if (publicSig.packageFqn !in functionalPackages) return false - - val declarationFqn = publicSig.declarationFqn - - if (declarationFqn.isRoot) return false - - val fqnParts = declarationFqn.pathSegments() - - val className = fqnParts.first() - - return functionPattern.matcher(className.asString()).find() - } - - private fun resolveFunctionDescriptor(idSig: IdSignature): DeclarationDescriptor? { - if (isSpecialFunctionDescriptor(idSig)) { - val publicSig = idSig.asPublic() ?: error("$idSig has to be public") - - val fqnParts = publicSig.declarationFqn.pathSegments() - val className = fqnParts.first() - val classDescriptor = builtIns.builtIns.getBuiltInClassByFqName(publicSig.packageFqn.child(className)) - - fun findMemberDescriptor(): DeclarationDescriptor { - val memberName = fqnParts[1]!! - val memberDescriptors = classDescriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES).filter { d -> d.name == memberName } - - return memberDescriptors.single() - } - return when (fqnParts.size) { - 1 -> classDescriptor - 2 -> findMemberDescriptor() - 3 -> { - assert(idSig is IdSignature.AccessorSignature) - val propertyDescriptor = findMemberDescriptor() as PropertyDescriptor - val accessorName = fqnParts[2] - propertyDescriptor.accessors.single { it.name == accessorName } - } - else -> error("No member found for signature $idSig") - } + if (idSig in expectUniqIdToActualUniqId.values) { + actualSymbols[idSig] = rawSymbol } - return null + return referencingSymbol } - /** - * Check that descriptor shouldn't be processed by some backend-specific logic. - * For example, it is the case for Native interop libraries where there is no IR in libraries. - */ - protected open fun IdSignature.shouldBeDeserialized(): Boolean = true + private fun referenceDeserializedSymbol(symbolKind: BinarySymbolData.SymbolKind, idSig: IdSignature): IrSymbol = symbolTable.run { + when (symbolKind) { + BinarySymbolData.SymbolKind.ANONYMOUS_INIT_SYMBOL -> IrAnonymousInitializerSymbolImpl(WrappedClassDescriptor()) + BinarySymbolData.SymbolKind.CLASS_SYMBOL -> referenceClassFromLinker(WrappedClassDescriptor(), idSig) + BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL -> referenceConstructorFromLinker(WrappedClassConstructorDescriptor(), idSig) + BinarySymbolData.SymbolKind.TYPE_PARAMETER_SYMBOL -> referenceTypeParameterFromLinker(WrappedTypeParameterDescriptor(), idSig) + BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> referenceEnumEntryFromLinker(WrappedEnumEntryDescriptor(), idSig) + BinarySymbolData.SymbolKind.STANDALONE_FIELD_SYMBOL -> referenceFieldFromLinker(WrappedFieldDescriptor(), idSig) + BinarySymbolData.SymbolKind.FIELD_SYMBOL -> referenceFieldFromLinker(WrappedPropertyDescriptor(), idSig) + BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> referenceSimpleFunctionFromLinker(WrappedSimpleFunctionDescriptor(), idSig) + BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL -> referenceTypeAliasFromLinker(WrappedTypeAliasDescriptor(), idSig) + BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> referencePropertyFromLinker(WrappedPropertyDescriptor(), idSig) + BinarySymbolData.SymbolKind.VARIABLE_SYMBOL -> IrVariableSymbolImpl(WrappedVariableDescriptor()) + BinarySymbolData.SymbolKind.VALUE_PARAMETER_SYMBOL -> IrValueParameterSymbolImpl(WrappedValueParameterDescriptor()) + BinarySymbolData.SymbolKind.RECEIVER_PARAMETER_SYMBOL -> IrValueParameterSymbolImpl(WrappedReceiverParameterDescriptor()) + BinarySymbolData.SymbolKind.LOCAL_DELEGATED_PROPERTY_SYMBOL -> + IrLocalDelegatedPropertySymbolImpl(WrappedVariableDescriptorWithAccessor()) + else -> error("Unexpected classifier symbol kind: $symbolKind for signature $idSig") + } + } private fun deserializeAllReachableTopLevels() { - do { + while (modulesWithReachableTopLevels.isNotEmpty()) { val moduleDeserializer = modulesWithReachableTopLevels.first() modulesWithReachableTopLevels.remove(moduleDeserializer) - moduleDeserializer.deserializeAllModuleReachableTopLevels() - } while (modulesWithReachableTopLevels.isNotEmpty()) + moduleDeserializer.deserializeReachableDeclarations() + } } private fun findDeserializedDeclarationForSymbol(symbol: IrSymbol): DeclarationDescriptor? { - require(symbol.isPublicApi) - - val signature = symbol.signature - - // This is Native specific. Try to eliminate. - if (!signature.shouldBeDeserialized()) return null + assert(symbol.isPublicApi || symbol.descriptor.module === currentModule || platformSpecificSymbol(symbol)) val descriptor = symbol.descriptor - /* - Wrapped descriptors come from inside IrLinker. If a symbol with such a descriptor ends up here, this means we - have already looked for it in IrLinker and failed. - */ - if (descriptor is WrappedDeclarationDescriptor<*>) return null + val moduleDeserializer = resolveModuleDeserializer(descriptor.module) - if (descriptor is FunctionClassDescriptor || (descriptor.containingDeclaration is FunctionClassDescriptor)) { - return null - } - - val topLevelSignature = signature.topLevelSignature() - val moduleDeserializer = resolveModuleDeserializer(descriptor.module) ?: return null - - moduleDeserializer.addModuleReachableTopLevel(topLevelSignature) +// moduleDeserializer.deserializeIrSymbol(signature, symbol.kind()) + moduleDeserializer.declareIrSymbol(symbol) deserializeAllReachableTopLevels() return descriptor } + protected open fun platformSpecificSymbol(symbol: IrSymbol): Boolean = false + override fun getDeclaration(symbol: IrSymbol): IrDeclaration? { - if (!symbol.isPublicApi) return null + if (!symbol.isPublicApi) { + val descriptor = symbol.descriptor + if (descriptor is WrappedDeclarationDescriptor<*>) return null + if (!platformSpecificSymbol(symbol)) { + if (descriptor.module !== currentModule) return null + } + } if (!symbol.isBound) { findDeserializedDeclarationForSymbol(symbol) ?: return null @@ -672,54 +522,31 @@ abstract class KotlinIrLinker( return symbol.owner as IrDeclaration } - // TODO: This is Native specific. Eliminate me. - override fun declareForwardDeclarations() { - if (forwardModuleDescriptor == null) return - - val packageFragments = forwardDeclarations.map { it.descriptor.findPackage() }.distinct() - - // We don't bother making a real IR module here, as we have no need in it any later. - // All we need is just to declare forward declarations in the symbol table - // In case you need a full fledged module, turn the forEach into a map and collect - // produced files into an IrModuleFragment. - - packageFragments.forEach { packageFragment -> - val symbol = IrFileSymbolImpl(packageFragment) - val file = IrFileImpl(NaiveSourceBasedFileEntryImpl("forward declarations pseudo-file"), symbol) - val symbols = forwardDeclarations - .filter { !it.isBound } - .filter { it.descriptor.findPackage() == packageFragment } - val declarations = symbols.map { - - val classDescriptor = it.descriptor as ClassDescriptor - val declaration = symbolTable.declareClass( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, - classDescriptor, - classDescriptor.modality - ) { symbol: IrClassSymbol -> IrClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, symbol) } - .also { - it.parent = file - } - declaration + protected open fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection, extensions: Collection): IrModuleDeserializer = + CurrentModuleDeserializer(moduleFragment, dependencies, symbolTable, extensions) + override fun init(moduleFragment: IrModuleFragment?, extensions: Collection) { + if (moduleFragment != null) { + val currentModuleDependencies = moduleFragment.descriptor.allDependencyModules.map { + deserializersForModules[it] ?: error("No deserializer found for $it") } - file.declarations.addAll(declarations) + val currentModuleDeserializer = createCurrentModuleDeserializer(moduleFragment, currentModuleDependencies, extensions) + deserializersForModules[moduleFragment.descriptor] = + maybeWrapWithBuiltInAndInit(moduleFragment.descriptor, currentModuleDeserializer) } + deserializersForModules.values.forEach { it.init() } } - fun initializeExpectActualLinker() { - deserializersForModules.values.forEach { - it.fileToDeserializerMap.values.forEach { - it.deserializeExpectActualMapping() - } - } + fun postProcess() { + deserializersForModules.values.forEach { it.postProcess() } + finalizeExpectActualLinker() } // The issue here is that an expect can not trigger its actual deserialization by reachability // because the expect can not see the actual higher in the module dependency dag. // So we force deserialization of actuals for all deserialized expect symbols here. - fun finalizeExpectActualLinker() { - expectUniqIdToActualUniqId.filter{ topLevelActualUniqItToDeserializer[it.value] != null}.forEach { + private fun finalizeExpectActualLinker() { + expectUniqIdToActualUniqId.filter { topLevelActualUniqItToDeserializer[it.value] != null }.forEach { val expectSymbol = expectSymbols[it.key] val actualSymbol = actualSymbols[it.value] if (expectSymbol != null && (actualSymbol == null || !actualSymbol.isBound)) { @@ -752,16 +579,24 @@ abstract class KotlinIrLinker( fun deserializeIrModuleHeader( moduleDescriptor: ModuleDescriptor, + kotlinLibrary: KotlinLibrary?, deserializationStrategy: DeserializationStrategy = DeserializationStrategy.ONLY_REFERENCED ): IrModuleFragment { val deserializerForModule = deserializersForModules.getOrPut(moduleDescriptor) { - createModuleDeserializer(moduleDescriptor, deserializationStrategy) + maybeWrapWithBuiltInAndInit(moduleDescriptor, createModuleDeserializer(moduleDescriptor, kotlinLibrary, deserializationStrategy)) } // The IrModule and its IrFiles have been created during module initialization. - return deserializerForModule.module + return deserializerForModule.moduleFragment } - fun deserializeIrModuleHeader(moduleDescriptor: ModuleDescriptor): IrModuleFragment? { + private fun maybeWrapWithBuiltInAndInit( + moduleDescriptor: ModuleDescriptor, + moduleDeserializer: IrModuleDeserializer + ): IrModuleDeserializer = + if (isBuiltInModule(moduleDescriptor)) IrModuleDeserializerWithBuiltIns(builtIns, functionalInteraceFactory, moduleDeserializer) + else moduleDeserializer + + fun deserializeIrModuleHeader(moduleDescriptor: ModuleDescriptor, kotlinLibrary: KotlinLibrary?): IrModuleFragment { // TODO: consider skip deserializing explicitly exported declarations for libraries. // Now it's not valid because of all dependencies that must be computed. val deserializationStrategy = @@ -770,23 +605,23 @@ abstract class KotlinIrLinker( } else { DeserializationStrategy.EXPLICITLY_EXPORTED } - return deserializeIrModuleHeader(moduleDescriptor, deserializationStrategy) + return deserializeIrModuleHeader(moduleDescriptor, kotlinLibrary, deserializationStrategy) } - fun deserializeFullModule(moduleDescriptor: ModuleDescriptor): IrModuleFragment = - deserializeIrModuleHeader(moduleDescriptor, DeserializationStrategy.ALL) + fun deserializeFullModule(moduleDescriptor: ModuleDescriptor, kotlinLibrary: KotlinLibrary?): IrModuleFragment = + deserializeIrModuleHeader(moduleDescriptor, kotlinLibrary, DeserializationStrategy.ALL) - fun deserializeOnlyHeaderModule(moduleDescriptor: ModuleDescriptor): IrModuleFragment = - deserializeIrModuleHeader(moduleDescriptor, DeserializationStrategy.ONLY_DECLARATION_HEADERS) + fun deserializeOnlyHeaderModule(moduleDescriptor: ModuleDescriptor, kotlinLibrary: KotlinLibrary?): IrModuleFragment = + deserializeIrModuleHeader(moduleDescriptor, kotlinLibrary, DeserializationStrategy.ONLY_DECLARATION_HEADERS) - fun getAllIrFiles(): List { - return deserializersForModules.values.flatMap { it.module.files } - } + fun deserializeHeadersWithInlineBodies(moduleDescriptor: ModuleDescriptor, kotlinLibrary: KotlinLibrary?): IrModuleFragment = + deserializeIrModuleHeader(moduleDescriptor, kotlinLibrary, DeserializationStrategy.WITH_INLINE_BODIES) } -enum class DeserializationStrategy(val needBodies: Boolean, val explicitlyExported: Boolean, val theWholeWorld: Boolean) { - ONLY_REFERENCED(true, false, false), - ALL(true, true, true), - EXPLICITLY_EXPORTED(true, true, false), - ONLY_DECLARATION_HEADERS(false, false, false) +enum class DeserializationStrategy(val needBodies: Boolean, val explicitlyExported: Boolean, val theWholeWorld: Boolean, val inlineBodies: Boolean) { + ONLY_REFERENCED(true, false, false, true), + ALL(true, true, true, true), + EXPLICITLY_EXPORTED(true, true, false, true), + ONLY_DECLARATION_HEADERS(false, false, false, false), + WITH_INLINE_BODIES(false, false, false, true) } diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 30e0bf498c3..d813934b5be 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -102,6 +102,7 @@ fun generateKLib( val incrementalDataProvider = configuration.get(JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER) val icData: List + val serializedIrFiles: List? if (incrementalDataProvider != null) { val nonCompiledSources = files.map { VfsUtilCore.virtualToIoFile(it.virtualFile) to it }.toMap() @@ -124,8 +125,10 @@ fun generateKLib( } icData = storage + serializedIrFiles = storage.map { it.irData } } else { icData = emptyList() + serializedIrFiles = null } val depsDescriptors = @@ -135,8 +138,13 @@ fun generateKLib( val expectDescriptorToSymbol = mutableMapOf() - val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files, - deserializer = null, expectDescriptorToSymbol = expectDescriptorToSymbol) + val irLinker = JsIrLinker(psi2IrContext.moduleDescriptor, emptyLoggingContext, psi2IrContext.irBuiltIns, psi2IrContext.symbolTable, serializedIrFiles) + + val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map { + irLinker.deserializeOnlyHeaderModule(depsDescriptors.getModuleDescriptor(it), it) + } + + val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files, irLinker, expectDescriptorToSymbol) moduleFragment.acceptVoid(ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc))) @@ -193,22 +201,20 @@ fun loadIr( val irBuiltIns = psi2IrContext.irBuiltIns val symbolTable = psi2IrContext.symbolTable - val deserializer = JsIrLinker(emptyLoggingContext, irBuiltIns, symbolTable) + val irLinker = JsIrLinker(psi2IrContext.moduleDescriptor, emptyLoggingContext, irBuiltIns, symbolTable, null) val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map { - deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it))!! + irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), it) } - deserializer.initializeExpectActualLinker() - - val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, mainModule.files, deserializer) + val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, mainModule.files, irLinker) // TODO: not sure whether this check should be enabled by default. Add configuration key for it. val mangleChecker = ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc)) moduleFragment.acceptVoid(mangleChecker) irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) } - return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, deserializer) + return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker) } is MainModule.Klib -> { val moduleDescriptor = depsDescriptors.getModuleDescriptor(mainModule.lib) @@ -224,7 +230,7 @@ fun loadIr( typeTranslator.constantValueGenerator = constantValueGenerator constantValueGenerator.typeTranslator = typeTranslator val irBuiltIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable) - val deserializer = JsIrLinker(emptyLoggingContext, irBuiltIns, symbolTable) + val irLinker = JsIrLinker(null, emptyLoggingContext, irBuiltIns, symbolTable, null) val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map { val strategy = @@ -233,16 +239,16 @@ fun loadIr( else DeserializationStrategy.EXPLICITLY_EXPORTED - deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), strategy) + irLinker.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it), it, strategy) } - deserializer.initializeExpectActualLinker() + val moduleFragment = deserializedModuleFragments.last() - val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer) - ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings) - .generateUnboundSymbolsAsDependencies() + irLinker.init(null, emptyList()) + ExternalDependenciesGenerator(symbolTable, listOf(irLinker), configuration.languageVersionSettings).generateUnboundSymbolsAsDependencies() + irLinker.postProcess() - return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, deserializer) + return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker) } } } @@ -266,14 +272,15 @@ private fun runAnalysisAndPreparePsi2Ir(depsDescriptors: ModulesStructure): Gene fun GeneratorContext.generateModuleFragmentWithPlugins( project: Project, files: List, - deserializer: IrDeserializer? = null, + irLinker: IrDeserializer, expectDescriptorToSymbol: MutableMap? = null ): IrModuleFragment { - val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer) val signaturer = IdSignatureDescriptor(JsManglerDesc) val psi2Ir = Psi2IrTranslator(languageVersionSettings, configuration, signaturer) - for (extension in IrGenerationExtension.getInstances(project)) { + val extensions = IrGenerationExtension.getInstances(project) + + for (extension in extensions) { psi2Ir.addPostprocessingStep { module -> extension.generate( module, @@ -289,26 +296,9 @@ fun GeneratorContext.generateModuleFragmentWithPlugins( } } - val moduleFragment = - psi2Ir.generateModuleFragment( - this, - files, - irProviders, - expectDescriptorToSymbol - ) - return moduleFragment + return psi2Ir.generateModuleFragment(this, files, listOf(irLinker), expectDescriptorToSymbol, extensions) } -fun GeneratorContext.generateModuleFragment(files: List, deserializer: IrDeserializer? = null, expectDescriptorToSymbol: MutableMap? = null): IrModuleFragment { - val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer) - val mangler = JsManglerDesc - val signaturer = IdSignatureDescriptor(mangler) - return Psi2IrTranslator( - languageVersionSettings, configuration, signaturer - ).generateModuleFragment(this, files, irProviders, expectDescriptorToSymbol) -} - - private fun createBuiltIns(storageManager: StorageManager) = object : KotlinBuiltIns(storageManager) {} internal val JsFactories = KlibMetadataFactories(::createBuiltIns, DynamicTypeDeserializer) diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt index bf7aea44272..6589211cba9 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/JsIrLinker.kt @@ -6,40 +6,45 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.serialization.CurrentModuleWithICDeserializer import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy +import org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.descriptors.IrFunctionFactory +import org.jetbrains.kotlin.ir.util.IrExtensionGenerator import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.library.IrLibrary +import org.jetbrains.kotlin.library.SerializedIrFile -class JsIrLinker(logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable) : - KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null) { +class JsIrLinker(currentModule: ModuleDescriptor?, logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable, private val icData: List? = null) : + KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList()) { - override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) = - moduleDescriptor.kotlinLibrary.irDeclaration(idSigIndex, fileIndex) + override val functionalInteraceFactory: IrAbstractFunctionFactory = IrFunctionFactory(builtIns, symbolTable) - override fun readType(moduleDescriptor: ModuleDescriptor, fileIndex: Int, typeIndex: Int) = - moduleDescriptor.kotlinLibrary.type(typeIndex, fileIndex) + override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean = + moduleDescriptor === moduleDescriptor.builtIns.builtInsModule - override fun readSignature(moduleDescriptor: ModuleDescriptor, fileIndex: Int, signatureIndex: Int) = - moduleDescriptor.kotlinLibrary.signature(signatureIndex, fileIndex) + override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer = + JsModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy) - override fun readString(moduleDescriptor: ModuleDescriptor, fileIndex: Int, stringIndex: Int) = - moduleDescriptor.kotlinLibrary.string(stringIndex, fileIndex) + private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) : + KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy) - override fun readBody(moduleDescriptor: ModuleDescriptor, fileIndex: Int, bodyIndex: Int) = - moduleDescriptor.kotlinLibrary.body(bodyIndex, fileIndex) - - override fun readFile(moduleDescriptor: ModuleDescriptor, fileIndex: Int) = - moduleDescriptor.kotlinLibrary.file(fileIndex) - - override fun readFileCount(moduleDescriptor: ModuleDescriptor) = - moduleDescriptor.kotlinLibrary.fileCount() - - override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy): IrModuleDeserializer = - JsModuleDeserializer(moduleDescriptor, strategy) - - private inner class JsModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy) : - KotlinIrLinker.IrModuleDeserializer(moduleDescriptor, strategy) -} \ No newline at end of file + override fun createCurrentModuleDeserializer( + moduleFragment: IrModuleFragment, + dependencies: Collection, + extensions: Collection + ): IrModuleDeserializer { + val currentModuleDeserializer = super.createCurrentModuleDeserializer(moduleFragment, dependencies, extensions) + icData?.let { + return CurrentModuleWithICDeserializer(currentModuleDeserializer, symbolTable, builtIns, it) { lib -> + JsModuleDeserializer(currentModuleDeserializer.moduleDescriptor, lib, currentModuleDeserializer.strategy) + } + } + return currentModuleDeserializer + } +} diff --git a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt index 0609840a22c..e77b522bb67 100644 --- a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt +++ b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/ir/backend/jvm/serialization/JvmIrLinker.kt @@ -6,51 +6,146 @@ package org.jetbrains.kotlin.ir.backend.jvm.serialization import org.jetbrains.kotlin.backend.common.LoggingContext -import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy -import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary -import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.backend.common.serialization.* +import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl +import org.jetbrains.kotlin.ir.descriptors.* +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.ir.util.IrExtensionGenerator import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.library.IrLibrary +import org.jetbrains.kotlin.load.java.descriptors.* +import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment +import org.jetbrains.kotlin.name.Name -class JvmIrLinker(logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable) : - KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null) { +class JvmIrLinker(currentModule: ModuleDescriptor?, logger: LoggingContext, builtIns: IrBuiltIns, symbolTable: SymbolTable, private val stubGenerator: DeclarationStubGenerator, private val manglerDesc: JvmManglerDesc) : + KotlinIrLinker(currentModule, logger, builtIns, symbolTable, emptyList()) { - override fun handleNoModuleDeserializerFound(idSignature: IdSignature): DeserializationState<*> { - // TODO: Implement special java-module deserializer instead of this hack - return globalDeserializationState // !!!!!! Wrong, as external references will all have UniqId.NONE - } + override val functionalInteraceFactory: IrAbstractFunctionFactory = IrFunctionFactory(builtIns, symbolTable) - override fun reader(moduleDescriptor: ModuleDescriptor, fileIndex: Int, idSigIndex: Int) = - moduleDescriptor.kotlinLibrary.irDeclaration(idSigIndex, fileIndex) + private val javaName = Name.identifier("java") - override fun readType(moduleDescriptor: ModuleDescriptor, fileIndex: Int, typeIndex: Int) = - moduleDescriptor.kotlinLibrary.type(typeIndex, fileIndex) - - override fun readSignature(moduleDescriptor: ModuleDescriptor, fileIndex: Int, signatureIndex: Int) = - moduleDescriptor.kotlinLibrary.signature(signatureIndex, fileIndex) - - override fun readString(moduleDescriptor: ModuleDescriptor, fileIndex: Int, stringIndex: Int) = - moduleDescriptor.kotlinLibrary.string(stringIndex, fileIndex) - - override fun readBody(moduleDescriptor: ModuleDescriptor, fileIndex: Int, bodyIndex: Int) = - moduleDescriptor.kotlinLibrary.body(bodyIndex, fileIndex) - - override fun readFile(moduleDescriptor: ModuleDescriptor, fileIndex: Int) = - moduleDescriptor.kotlinLibrary.file(fileIndex) - - override fun readFileCount(moduleDescriptor: ModuleDescriptor) = - moduleDescriptor.kotlinLibrary.fileCount() - - override fun resolveModuleDeserializer(moduleDescriptor: ModuleDescriptor): IrModuleDeserializer? { - return deserializersForModules[moduleDescriptor] - } + override fun isBuiltInModule(moduleDescriptor: ModuleDescriptor): Boolean = + moduleDescriptor.name.asString() == "" // TODO: implement special Java deserializer - override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy): IrModuleDeserializer = - JvmModuleDeserializer(moduleDescriptor, strategy) + override fun createModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary?, strategy: DeserializationStrategy): IrModuleDeserializer { + if (klib != null) { + assert(moduleDescriptor.getCapability(KlibModuleOrigin.CAPABILITY) != null) + return JvmModuleDeserializer(moduleDescriptor, klib, strategy) + } - private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, strategy: DeserializationStrategy) : - KotlinIrLinker.IrModuleDeserializer(moduleDescriptor, strategy) + return MetadataJVMModuleDeserializer(moduleDescriptor, emptyList()) + } + + private inner class JvmModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy) : + KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy) + + private fun DeclarationDescriptor.isJavaDescriptor(): Boolean { + if (this is PackageFragmentDescriptor) { + return this is LazyJavaPackageFragment || fqName.startsWith(javaName) + } + + return this is JavaClassDescriptor || this is JavaCallableMemberDescriptor || (containingDeclaration?.isJavaDescriptor() == true) + } + + private fun DeclarationDescriptor.isCleanDescriptor(): Boolean { + if (this is PropertyAccessorDescriptor) return correspondingProperty.isCleanDescriptor() + return this is DeserializedDescriptor + } + + override fun platformSpecificSymbol(symbol: IrSymbol): Boolean { + return symbol.descriptor.isJavaDescriptor() + } + + private fun declareJavaFieldStub(symbol: IrFieldSymbol): IrField { + return with(stubGenerator) { + val old = stubGenerator.unboundSymbolGeneration + try { + stubGenerator.unboundSymbolGeneration = true + generateFieldStub(symbol.descriptor) + } finally { + stubGenerator.unboundSymbolGeneration = old + } + } + } + + + override fun createCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection, extensions: Collection): IrModuleDeserializer = + JvmCurrentModuleDeserializer(moduleFragment, dependencies, extensions) + + private inner class JvmCurrentModuleDeserializer(moduleFragment: IrModuleFragment, dependencies: Collection, extensions: Collection) : + CurrentModuleDeserializer(moduleFragment, dependencies, symbolTable, extensions) { + override fun declareIrSymbol(symbol: IrSymbol) { + val descriptor = symbol.descriptor + + if (descriptor.isJavaDescriptor()) { + // Wrap java declaration with lazy ir + if (symbol is IrFieldSymbol) { + declareJavaFieldStub(symbol) + } else { + stubGenerator.generateMemberStub(descriptor) + } + return + } + + if (descriptor.isCleanDescriptor()) { + stubGenerator.generateMemberStub(descriptor) + return + } + + super.declareIrSymbol(symbol) + } + } + + private inner class MetadataJVMModuleDeserializer(moduleDescriptor: ModuleDescriptor, dependencies: List) : + IrModuleDeserializer(moduleDescriptor) { + + // TODO: implement proper check whether `idSig` belongs to this module + override fun contains(idSig: IdSignature): Boolean = true + + private val descriptorFinder = DescriptorByIdSignatureFinder(moduleDescriptor, manglerDesc) + + private fun resolveDescriptor(idSig: IdSignature): DeclarationDescriptor { + return descriptorFinder.findDescriptorBySignature(idSig) ?: error("No descriptor found for $idSig") + } + + override fun deserializeIrSymbol(idSig: IdSignature, symbolKind: BinarySymbolData.SymbolKind): IrSymbol { + val descriptor = resolveDescriptor(idSig) + + val declaration = stubGenerator.run { + when (symbolKind) { + BinarySymbolData.SymbolKind.CLASS_SYMBOL -> generateClassStub(descriptor as ClassDescriptor) + BinarySymbolData.SymbolKind.PROPERTY_SYMBOL -> generatePropertyStub(descriptor as PropertyDescriptor) + BinarySymbolData.SymbolKind.FUNCTION_SYMBOL -> generateFunctionStub(descriptor as FunctionDescriptor) + BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL -> generateConstructorStub(descriptor as ClassConstructorDescriptor) + BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL -> generateEnumEntryStub(descriptor as ClassDescriptor) + BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL -> generateTypeAliasStub(descriptor as TypeAliasDescriptor) + else -> error("Unexpected type $symbolKind for sig $idSig") + } + } + + return declaration.symbol + } + + override fun declareIrSymbol(symbol: IrSymbol) { + assert(symbol.isPublicApi || symbol.descriptor.isJavaDescriptor()) + if (symbol is IrFieldSymbol) { + declareJavaFieldStub(symbol) + } else { + stubGenerator.generateMemberStub(symbol.descriptor) + } + } + + override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList()) + override val moduleDependencies: Collection = dependencies + + } } \ No newline at end of file diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt index 8a4158cc7f4..5fcc069d7dc 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsCoreScriptingCompiler.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.generateJsCode -import org.jetbrains.kotlin.ir.backend.js.generateModuleFragment import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc import org.jetbrains.kotlin.ir.backend.js.utils.NameTables import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator @@ -58,14 +57,15 @@ class JsCoreScriptingCompiler( if (messageCollector.hasErrors()) return ReplCompileResult.Error("Error while analysis") } + val files = listOf(snippetKtFile) val module = analysisResult.moduleDescriptor val bindingContext = analysisResult.bindingContext val mangler = JsManglerDesc val signaturer = IdSignatureDescriptor(mangler) val psi2ir = Psi2IrTranslator(environment.configuration.languageVersionSettings, signaturer = signaturer) val psi2irContext = psi2ir.createGeneratorContext(module, bindingContext, symbolTable) - - val irModuleFragment = psi2irContext.generateModuleFragment(listOf(snippetKtFile)) + val providers = generateTypicalIrProviderList(module, psi2irContext.irBuiltIns, psi2irContext.symbolTable) + val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files, providers, null) // TODO: deserializer val context = JsIrBackendContext( irModuleFragment.descriptor, diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt index 39809b9b011..9f76ba1ffd2 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/repl/js/JsScriptDependencyCompiler.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.emptyLoggingContext import org.jetbrains.kotlin.ir.backend.js.generateJsCode @@ -49,10 +50,10 @@ class JsScriptDependencyCompiler( val signaturer = IdSignatureDescriptor(JsManglerDesc) val irBuiltIns = IrBuiltIns(builtIns, typeTranslator, signaturer, symbolTable) - val jsLinker = JsIrLinker(emptyLoggingContext, irBuiltIns, symbolTable) + val jsLinker = JsIrLinker(null, emptyLoggingContext, irBuiltIns, symbolTable, null) val moduleFragment = IrModuleFragmentImpl(moduleDescriptor, irBuiltIns) - val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it) } + val irDependencies = dependencies.map { jsLinker.deserializeFullModule(it, it.kotlinLibrary) } val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer = jsLinker) ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings)