~~ WIP: No symbolTable merging
diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt
index 151c452..b0dc4ab 100644
--- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt
+++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt
@@ -589,7 +589,7 @@
             session, scopeSession, firFiles + commonFirFiles,
             configuration.languageVersionSettings, signaturer,
             fir2IrExtensions,
-            FirJvmKotlinMangler(session), // TODO: replace with potentially simpler JS version
+            FirJvmKotlinMangler(), // TODO: replace with potentially simpler JS version
             JsManglerIr, IrFactoryImpl,
             Fir2IrVisibilityConverter.Default,
             Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation
diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
index 312ace2..1c3e5af 100644
--- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
+++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
@@ -77,29 +77,16 @@
     linkViaSignatures: Boolean,
     dependentComponents: List<Fir2IrComponents>
 ): Fir2IrResult {
-    if (linkViaSignatures) {
-        val signaturer = JvmIdSignatureDescriptor(mangler = JvmDescriptorMangler(mainDetector = null))
-        return Fir2IrConverter.createModuleFragmentWithSignaturesIfNeeded(
-            session, scopeSession, fir,
-            session.languageVersionSettings, signaturer, fir2IrExtensions,
-            FirJvmKotlinMangler(session),
-            JvmIrMangler, IrFactoryImpl, FirJvmVisibilityConverter,
-            Fir2IrJvmSpecialAnnotationSymbolProvider(),
-            irGeneratorExtensions,
-            kotlinBuiltIns = DefaultBuiltIns.Instance, // TODO: consider passing externally
-            generateSignatures = true,
-            dependentComponents = dependentComponents
-        )
-    } else {
-        return Fir2IrConverter.createModuleFragmentWithoutSignatures(
-            session, scopeSession, fir,
-            session.languageVersionSettings, fir2IrExtensions,
-            FirJvmKotlinMangler(session),
-            JvmIrMangler, IrFactoryImpl, FirJvmVisibilityConverter,
-            Fir2IrJvmSpecialAnnotationSymbolProvider(),
-            irGeneratorExtensions,
-            kotlinBuiltIns = DefaultBuiltIns.Instance, // TODO: consider passing externally,
-            dependentComponents = dependentComponents
-        )
-    }
+    val signaturer = JvmIdSignatureDescriptor(mangler = JvmDescriptorMangler(mainDetector = null))
+    return Fir2IrConverter.createModuleFragmentWithSignaturesIfNeeded(
+        session, scopeSession, fir,
+        session.languageVersionSettings, signaturer, fir2IrExtensions,
+        FirJvmKotlinMangler(),
+        JvmIrMangler, IrFactoryImpl, FirJvmVisibilityConverter,
+        Fir2IrJvmSpecialAnnotationSymbolProvider(),
+        irGeneratorExtensions,
+        kotlinBuiltIns = DefaultBuiltIns.Instance, // TODO: consider passing externally
+        generateSignatures = linkViaSignatures,
+        dependentComponents = dependentComponents
+    )
 }
diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmKotlinMangler.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmKotlinMangler.kt
index 19fc1f9..16258b5 100644
--- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmKotlinMangler.kt
+++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmKotlinMangler.kt
@@ -6,13 +6,12 @@
 package org.jetbrains.kotlin.fir.backend.jvm
 
 import org.jetbrains.kotlin.backend.common.serialization.mangle.*
-import org.jetbrains.kotlin.fir.FirSession
 import org.jetbrains.kotlin.fir.NoMutableState
 import org.jetbrains.kotlin.fir.declarations.FirDeclaration
 import org.jetbrains.kotlin.fir.signaturer.FirMangler
 
 @NoMutableState
-class FirJvmKotlinMangler(private val session: FirSession) : AbstractKotlinMangler<FirDeclaration>(), FirMangler {
+class FirJvmKotlinMangler : AbstractKotlinMangler<FirDeclaration>(), FirMangler {
 
     override fun FirDeclaration.mangleString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FULL, compatibleMode).computeMangle(this)
 
@@ -31,6 +30,6 @@
     }
 
     override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<FirDeclaration> {
-        return FirJvmMangleComputer(StringBuilder(256), mode, session)
+        return FirJvmMangleComputer(StringBuilder(256), mode)
     }
 }
diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt
index b528c60..ae51c28 100644
--- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt
+++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt
@@ -31,8 +31,7 @@
 
 open class FirJvmMangleComputer(
     private val builder: StringBuilder,
-    private val mode: MangleMode,
-    private val session: FirSession
+    private val mode: MangleMode
 ) : FirVisitor<Unit, Boolean>(), KotlinMangleComputer<FirDeclaration> {
 
     private val typeParameterContainer = ArrayList<FirMemberDeclaration>(4)
@@ -43,7 +42,7 @@
 
     open fun FirFunction.platformSpecificSuffix(): String? =
         if (this is FirSimpleFunction && name.asString() == "main")
-            this@FirJvmMangleComputer.session.firProvider.getFirCallableContainerFile(symbol)?.name
+            this.moduleData.session.firProvider.getFirCallableContainerFile(symbol)?.name
         else null
 
     open fun FirFunction.specialValueParamPrefix(param: FirValueParameter): String = ""
@@ -51,7 +50,7 @@
     private fun addReturnType(): Boolean = true
 
     override fun copy(newMode: MangleMode): FirJvmMangleComputer =
-        FirJvmMangleComputer(builder, newMode, session)
+        FirJvmMangleComputer(builder, newMode)
 
     private fun StringBuilder.appendName(s: String) {
         if (mode.fqn) {
@@ -90,7 +89,7 @@
             else -> return
         }
         if (parentClassId != null && !parentClassId.isLocal) {
-            val parentClassLike = this@FirJvmMangleComputer.session.symbolProvider.getClassLikeSymbolByClassId(parentClassId)?.fir
+            val parentClassLike = this.moduleData.session.symbolProvider.getClassLikeSymbolByClassId(parentClassId)?.fir
                 ?: error("Attempt to find parent ($parentClassId) for probably-local declaration!")
             if (parentClassLike is FirRegularClass || parentClassLike is FirTypeAlias) {
                 parentClassLike.accept(this@FirJvmMangleComputer, false)
@@ -151,13 +150,13 @@
 
         contextReceivers.forEach {
             builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
-            mangleType(builder, it.typeRef.coneType)
+            mangleType(builder, it.typeRef.coneType, moduleData.session)
         }
 
         val receiverType = receiverParameter?.typeRef ?: (this as? FirPropertyAccessor)?.propertySymbol?.fir?.receiverParameter?.typeRef
         receiverType?.let {
             builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
-            mangleType(builder, it.coneType)
+            mangleType(builder, it.coneType, moduleData.session)
         }
 
         valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
@@ -170,7 +169,7 @@
             }
 
         if (!isCtor && !returnTypeRef.isUnit && addReturnType()) {
-            mangleType(builder, returnTypeRef.coneType)
+            mangleType(builder, returnTypeRef.coneType, moduleData.session)
         }
     }
 
@@ -190,7 +189,7 @@
     }
 
     private fun mangleValueParameter(vpBuilder: StringBuilder, param: FirValueParameter) {
-        mangleType(vpBuilder, param.returnTypeRef.coneType)
+        mangleType(vpBuilder, param.returnTypeRef.coneType, param.moduleData.session)
 
         if (param.isVararg) {
             vpBuilder.appendSignature(MangleConstant.VAR_ARG_MARK)
@@ -202,7 +201,7 @@
         tpBuilder.appendSignature(MangleConstant.UPPER_BOUND_SEPARATOR)
 
         param.bounds.map { it.coneType }.collectForMangler(tpBuilder, MangleConstant.UPPER_BOUNDS) {
-            mangleType(this, it)
+            mangleType(this, it, param.moduleData.session)
         }
     }
 
@@ -215,12 +214,12 @@
         appendSignature(parent.typeParameters.indexOf(typeParameter))
     }
 
-    private fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType) {
+    private fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType, declarationSiteSession: FirSession) {
         when (type) {
             is ConeLookupTagBasedType -> {
-                when (val symbol = type.lookupTag.toSymbol(session)) {
+                when (val symbol = type.lookupTag.toSymbol(declarationSiteSession)) {
                     is FirTypeAliasSymbol -> {
-                        mangleType(tBuilder, type.fullyExpandedType(session))
+                        mangleType(tBuilder, type.fullyExpandedType(declarationSiteSession), declarationSiteSession)
                         return
                     }
 
@@ -242,7 +241,7 @@
                                     appendSignature(MangleConstant.VARIANCE_SEPARATOR)
                                 }
 
-                                mangleType(this, arg.type)
+                                mangleType(this, arg.type, declarationSiteSession)
                             }
                         }
                     }
@@ -258,11 +257,11 @@
             }
 
             is ConeRawType -> {
-                mangleType(tBuilder, type.lowerBound)
+                mangleType(tBuilder, type.lowerBound, declarationSiteSession)
             }
 
             is ConeFlexibleType -> {
-                with(session.typeContext) {
+                with(declarationSiteSession.typeContext) {
                     // Need to reproduce type approximation done for flexible types in TypeTranslator.
                     // For now, we replicate the current behaviour of Fir2IrTypeConverter and just take the upper bound
                     val upper = type.upperBound
@@ -272,23 +271,23 @@
                             lower.replaceArguments(upper.getArguments())
                         } else lower
                         val mixed = if (upper.isNullable) intermediate.makeNullable() else intermediate.makeDefinitelyNotNullOrNotNull()
-                        mangleType(tBuilder, mixed as ConeKotlinType)
-                    } else mangleType(tBuilder, upper)
+                        mangleType(tBuilder, mixed as ConeKotlinType, declarationSiteSession)
+                    } else mangleType(tBuilder, upper, declarationSiteSession)
                 }
             }
 
             is ConeDefinitelyNotNullType -> {
                 // E.g. not-null type parameter in Java
-                mangleType(tBuilder, type.original)
+                mangleType(tBuilder, type.original, declarationSiteSession)
             }
 
             is ConeCapturedType -> {
-                mangleType(tBuilder, type.lowerType ?: type.constructor.supertypes!!.first())
+                mangleType(tBuilder, type.lowerType ?: type.constructor.supertypes!!.first(), declarationSiteSession)
             }
 
             is ConeIntersectionType -> {
                 // TODO: add intersectionTypeApproximation
-                mangleType(tBuilder, type.intersectedTypes.first())
+                mangleType(tBuilder, type.intersectedTypes.first(), declarationSiteSession)
             }
 
             else -> error("Unexpected type $type")
@@ -319,7 +318,7 @@
 
         variable.receiverParameter?.typeRef?.let {
             builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
-            mangleType(builder, it.coneType)
+            mangleType(builder, it.coneType, variable.moduleData.session)
         }
 
         variable.typeParameters.withIndex().toList().collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt
index 5e05bda..294fe6c 100644
--- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt
+++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt
@@ -77,9 +77,6 @@
         with(typeConverter) { toIrType(typeContext) }
 
     fun preCacheBuiltinClasses() {
-        // dependentStorages are only actual for MPP scenario
-        // There is no need to precache them twice since the same library session is used and FIR and IR elements are the same
-        if (dependentStorages.isNotEmpty()) return
         for ((classId, irBuiltinSymbol) in typeConverter.classIdToSymbolMap) {
             val firClass = ConeClassLikeLookupTagImpl(classId).toSymbol(session)!!.fir as FirRegularClass
             val irClass = irBuiltinSymbol.owner
diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt
index 566fd93..8cb0281 100644
--- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt
+++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt
@@ -59,11 +59,14 @@
         irGenerationExtensions: Collection<IrGenerationExtension>,
         fir2irVisitor: Fir2IrVisitor,
         fir2IrExtensions: Fir2IrExtensions,
+        shouldPreCache: Boolean
     ) {
         for (firFile in allFirFiles) {
             registerFileAndClasses(firFile, irModuleFragment)
         }
-        classifierStorage.preCacheBuiltinClasses()
+        if (shouldPreCache) {
+            classifierStorage.preCacheBuiltinClasses()
+        }
         // The file processing is performed phase-to-phase:
         //   1. Creation of all non-local regular classes
         //   2. Class header processing (type parameters, supertypes, this receiver)
@@ -424,6 +427,20 @@
             }
         }
 
+        private fun createSymbolTable(
+            linkViaSignatures: Boolean,
+            signatureComposer: FirBasedSignatureComposer,
+            irFactory: IrFactory,
+            signaturer: IdSignatureComposer
+        ): SymbolTable {
+            return if (!linkViaSignatures) {
+                val stubSignaturer = DescriptorSignatureComposerStub()
+                SymbolTable(stubSignaturer, irFactory)
+            } else {
+                SymbolTable(WrappedDescriptorSignatureComposer(signaturer, signatureComposer), irFactory)
+            }
+        }
+
         fun createModuleFragmentWithSignaturesIfNeeded(
             session: FirSession,
             scopeSession: ScopeSession,
@@ -441,17 +458,11 @@
             kotlinBuiltIns: KotlinBuiltIns,
             dependentComponents: List<Fir2IrComponents>
         ): Fir2IrResult {
-            if (!generateSignatures) {
-                return createModuleFragmentWithoutSignatures(
-                    session, scopeSession, firFiles, languageVersionSettings,
-                    fir2IrExtensions, mangler, irMangler, irFactory,
-                    visibilityConverter, specialSymbolProvider, irGenerationExtensions,
-                    kotlinBuiltIns, dependentComponents
-                )
-            }
-            val signatureComposer = FirBasedSignatureComposer(mangler, dependentComposers = dependentComponents.map { it.signatureComposer as FirBasedSignatureComposer })
-            val wrappedSignaturer = WrappedDescriptorSignatureComposer(signaturer, signatureComposer)
-            val symbolTable = SymbolTable(wrappedSignaturer, irFactory, dependentTables = dependentComponents.map { it.symbolTable })
+            val otherComponents = dependentComponents.firstOrNull()
+            val signatureComposer = otherComponents?.signatureComposer as FirBasedSignatureComposer? ?: FirBasedSignatureComposer(mangler)
+            val symbolTable =
+                otherComponents?.symbolTable ?: createSymbolTable(generateSignatures, signatureComposer, irFactory, signaturer)
+
             return createModuleFragmentWithSymbolTable(
                 session, scopeSession, firFiles, languageVersionSettings,
                 fir2IrExtensions, irMangler, irFactory, visibilityConverter,
@@ -460,32 +471,6 @@
             )
         }
 
-        fun createModuleFragmentWithoutSignatures(
-            session: FirSession,
-            scopeSession: ScopeSession,
-            firFiles: List<FirFile>,
-            languageVersionSettings: LanguageVersionSettings,
-            fir2IrExtensions: Fir2IrExtensions,
-            mangler: FirMangler,
-            irMangler: KotlinMangler.IrMangler,
-            irFactory: IrFactory,
-            visibilityConverter: Fir2IrVisibilityConverter,
-            specialSymbolProvider: Fir2IrSpecialSymbolProvider,
-            irGenerationExtensions: Collection<IrGenerationExtension>,
-            kotlinBuiltIns: KotlinBuiltIns,
-            dependentComponents: List<Fir2IrComponents>
-        ): Fir2IrResult {
-            val signatureComposer = FirBasedSignatureComposer(mangler, dependentComposers = dependentComponents.map { it.signatureComposer as FirBasedSignatureComposer })
-            val signaturer = DescriptorSignatureComposerStub()
-            val symbolTable = SymbolTable(signaturer, irFactory, dependentTables = dependentComponents.map { it.symbolTable })
-            return createModuleFragmentWithSymbolTable(
-                session, scopeSession, firFiles, languageVersionSettings,
-                fir2IrExtensions, irMangler, irFactory, visibilityConverter,
-                specialSymbolProvider, irGenerationExtensions, signatureComposer,
-                symbolTable, generateSignatures = false, kotlinBuiltIns = kotlinBuiltIns, dependentComponents = dependentComponents
-            )
-        }
-
         private fun createModuleFragmentWithSymbolTable(
             session: FirSession,
             scopeSession: ScopeSession,
@@ -514,7 +499,8 @@
             val classifierStorage = Fir2IrClassifierStorage(components, dependentComponents.map { it.classifierStorage })
             components.classifierStorage = classifierStorage
             components.delegatedMemberGenerator = DelegatedMemberGenerator(components)
-            val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor, dependentComponents.map { it.declarationStorage })
+            val declarationStorage =
+                Fir2IrDeclarationStorage(components, moduleDescriptor, dependentComponents.map { it.declarationStorage })
             components.declarationStorage = declarationStorage
             components.visibilityConverter = visibilityConverter
             val typeConverter = Fir2IrTypeConverter(components)
@@ -547,7 +533,12 @@
             }
 
             converter.runSourcesConversion(
-                allFirFiles, irModuleFragment, irGenerationExtensions, fir2irVisitor, fir2IrExtensions
+                allFirFiles,
+                irModuleFragment,
+                irGenerationExtensions,
+                fir2irVisitor,
+                fir2IrExtensions,
+                shouldPreCache = dependentComponents.isEmpty()
             )
 
             return Fir2IrResult(irModuleFragment, components, moduleDescriptor)
diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt
index 57a99c2..3f1b20a 100644
--- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt
+++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt
@@ -120,7 +120,7 @@
         session, scopeSession, firFiles + commonFirFiles,
         languageVersionSettings, signaturer,
         fir2IrExtensions,
-        FirJvmKotlinMangler(session), // TODO: replace with potentially simpler JS version
+        FirJvmKotlinMangler(), // TODO: replace with potentially simpler JS version
         JsManglerIr, IrFactoryImpl,
         Fir2IrVisibilityConverter.Default,
         Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation
diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt
index 9577226..b641e00 100644
--- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt
+++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt
@@ -113,7 +113,7 @@
             session, _scopeSession!!, firFiles!!,
             languageVersionSettings, signaturer,
             fir2IrExtensions,
-            FirJvmKotlinMangler(session), JvmIrMangler, IrFactoryImpl,
+            FirJvmKotlinMangler(), JvmIrMangler, IrFactoryImpl,
             FirJvmVisibilityConverter,
             Fir2IrJvmSpecialAnnotationSymbolProvider(),
             irGeneratorExtensions,