From 07e067102baa12b8a8ba4ffd4fa2960a5391fa8d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 8 Oct 2019 13:25:15 +0300 Subject: [PATCH] FIR body resolve: use one scope session per module Gives significant (~5%) performance boost mainly due to use-site scope caching --- .../transformers/FirBodyResolveTransformer.kt | 18 +++++++++++-- .../fir/AbstractFirDiagnosticsSmokeTest.kt | 1 + .../fir/AbstractFirMultiModuleResolveTest.kt | 27 ++++++++++++++----- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt index b44d058221e..a711af3d13a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt @@ -1020,12 +1020,19 @@ class FirDesignatedBodyResolveTransformer( @Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer() { + private val scopeSession = ScopeSession() + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { return element.compose() } override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { - val transformer = FirBodyResolveTransformer(file.fileSession, phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, implicitTypeOnly = true) + val transformer = FirBodyResolveTransformer( + file.fileSession, + phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, + implicitTypeOnly = true, + scopeSession = scopeSession + ) return file.transform(transformer, null) } } @@ -1033,13 +1040,20 @@ class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer() @Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) class FirBodyResolveTransformerAdapter : FirTransformer() { + private val scopeSession = ScopeSession() + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { return element.compose() } override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { // Despite of real phase is EXPRESSIONS, we state IMPLICIT_TYPES here, because DECLARATIONS previous phase is OK for us - val transformer = FirBodyResolveTransformer(file.fileSession, phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, implicitTypeOnly = false) + val transformer = FirBodyResolveTransformer( + file.fileSession, + phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, + implicitTypeOnly = false, + scopeSession = scopeSession + ) return file.transform(transformer, null) } } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticsSmokeTest.kt b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticsSmokeTest.kt index 19703b20b22..95714835c17 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticsSmokeTest.kt +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticsSmokeTest.kt @@ -73,6 +73,7 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() { val firFiles = mutableListOf() + // TODO: make module/session/transformer handling like in AbstractFirMultiModuleTest (IDE) for ((testModule, testFilesInModule) in groupedByModule) { val ktFiles = getKtFiles(testFilesInModule, true) diff --git a/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt b/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt index 4ab420a428a..8ec1d505c06 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/fir/AbstractFirMultiModuleResolveTest.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.classId import org.jetbrains.kotlin.fir.dependenciesWithoutSelf import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession @@ -23,9 +24,9 @@ import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope -import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer @@ -76,7 +77,8 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() { } private fun doFirResolveTest(dirPath: String) { - val firFiles = mutableListOf() + val firFilesPerSession = mutableMapOf>() + val totalTransformerPerSession = mutableMapOf() val sessions = mutableListOf() val provider = FirProjectSessionProvider(project) for (module in project.allModules().drop(1)) { @@ -99,14 +101,17 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() { val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, contentScope) println("Got vfiles: ${files.size}") + val firFiles = mutableListOf() files.forEach { val file = psiManager.findFile(it) as? KtFile ?: return@forEach val firFile = builder.buildFirFile(file) (session.firProvider as FirProviderImpl).recordFile(firFile) firFiles += firFile } + firFilesPerSession[session] = firFiles + totalTransformerPerSession[session] = FirTotalResolveTransformer() } - println("Raw fir up, files: ${firFiles.size}") + println("Raw fir up, files: ${firFilesPerSession.values.flatten().size}") fun expectedTxtPath(virtualFile: VirtualFile): String { val virtualPath = virtualFile.path @@ -120,13 +125,23 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() { return result!! } - val transformer = FirTotalResolveTransformer() - transformer.processFiles(firFiles) - for (file in firFiles) { + // Start from 1 to miss raw FIR building + for (phaseIndex in 1 until FirResolvePhase.values().size) { + for (session in sessions) { + val firFiles = firFilesPerSession[session]!! + val transformer = totalTransformerPerSession[session]!! + for (file in firFiles) { + transformer.transformers[phaseIndex - 1].visitFile(file, null) + } + } + } + + for (file in firFilesPerSession.values.flatten()) { val firFileDump = StringBuilder().also { file.accept(FirRenderer(it), null) }.toString() val expectedPath = expectedTxtPath((file.psi as PsiFile).virtualFile) KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump) } + val processedJavaClasses = mutableSetOf() val javaFirDump = StringBuilder().also { builder -> val renderer = FirRenderer(builder)