FIR body resolve: use one scope session per module

Gives significant (~5%) performance boost mainly due to use-site scope caching
This commit is contained in:
Mikhail Glukhikh
2019-10-08 13:25:15 +03:00
parent c2c88a9ee6
commit 07e067102b
3 changed files with 38 additions and 8 deletions
@@ -1020,12 +1020,19 @@ class FirDesignatedBodyResolveTransformer(
@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) @Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")"))
class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer<Nothing?>() { class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer<Nothing?>() {
private val scopeSession = ScopeSession()
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> { override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose() return element.compose()
} }
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> { override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
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) return file.transform(transformer, null)
} }
} }
@@ -1033,13 +1040,20 @@ class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer<Nothing?>()
@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) @Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")"))
class FirBodyResolveTransformerAdapter : FirTransformer<Nothing?>() { class FirBodyResolveTransformerAdapter : FirTransformer<Nothing?>() {
private val scopeSession = ScopeSession()
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> { override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
return element.compose() return element.compose()
} }
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> { override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
// Despite of real phase is EXPRESSIONS, we state IMPLICIT_TYPES here, because DECLARATIONS previous phase is OK for us // 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) return file.transform(transformer, null)
} }
} }
@@ -73,6 +73,7 @@ abstract class AbstractFirDiagnosticsSmokeTest : BaseDiagnosticsTest() {
val firFiles = mutableListOf<FirFile>() val firFiles = mutableListOf<FirFile>()
// TODO: make module/session/transformer handling like in AbstractFirMultiModuleTest (IDE)
for ((testModule, testFilesInModule) in groupedByModule) { for ((testModule, testFilesInModule) in groupedByModule) {
val ktFiles = getKtFiles(testFilesInModule, true) val ktFiles = getKtFiles(testFilesInModule, true)
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile 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.declarations.classId
import org.jetbrains.kotlin.fir.dependenciesWithoutSelf import org.jetbrains.kotlin.fir.dependenciesWithoutSelf
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession 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.FirJavaClass
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope 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.firProvider
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider 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.FirCompositeSymbolProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
@@ -76,7 +77,8 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
} }
private fun doFirResolveTest(dirPath: String) { private fun doFirResolveTest(dirPath: String) {
val firFiles = mutableListOf<FirFile>() val firFilesPerSession = mutableMapOf<FirJavaModuleBasedSession, List<FirFile>>()
val totalTransformerPerSession = mutableMapOf<FirJavaModuleBasedSession, FirTotalResolveTransformer>()
val sessions = mutableListOf<FirJavaModuleBasedSession>() val sessions = mutableListOf<FirJavaModuleBasedSession>()
val provider = FirProjectSessionProvider(project) val provider = FirProjectSessionProvider(project)
for (module in project.allModules().drop(1)) { for (module in project.allModules().drop(1)) {
@@ -99,14 +101,17 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, contentScope) val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, contentScope)
println("Got vfiles: ${files.size}") println("Got vfiles: ${files.size}")
val firFiles = mutableListOf<FirFile>()
files.forEach { files.forEach {
val file = psiManager.findFile(it) as? KtFile ?: return@forEach val file = psiManager.findFile(it) as? KtFile ?: return@forEach
val firFile = builder.buildFirFile(file) val firFile = builder.buildFirFile(file)
(session.firProvider as FirProviderImpl).recordFile(firFile) (session.firProvider as FirProviderImpl).recordFile(firFile)
firFiles += 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 { fun expectedTxtPath(virtualFile: VirtualFile): String {
val virtualPath = virtualFile.path val virtualPath = virtualFile.path
@@ -120,13 +125,23 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
return result!! return result!!
} }
val transformer = FirTotalResolveTransformer() // Start from 1 to miss raw FIR building
transformer.processFiles(firFiles) for (phaseIndex in 1 until FirResolvePhase.values().size) {
for (file in firFiles) { 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 firFileDump = StringBuilder().also { file.accept(FirRenderer(it), null) }.toString()
val expectedPath = expectedTxtPath((file.psi as PsiFile).virtualFile) val expectedPath = expectedTxtPath((file.psi as PsiFile).virtualFile)
KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump) KotlinTestUtils.assertEqualsToFile(File(expectedPath), firFileDump)
} }
val processedJavaClasses = mutableSetOf<FirJavaClass>() val processedJavaClasses = mutableSetOf<FirJavaClass>()
val javaFirDump = StringBuilder().also { builder -> val javaFirDump = StringBuilder().also { builder ->
val renderer = FirRenderer(builder) val renderer = FirRenderer(builder)