From 4bea054e4baec1c249cd2daa486d78dbfefdb28f Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 9 Mar 2016 14:07:06 +0300 Subject: [PATCH] Optimize TowerResolver.run implementation - run `processor` at each level instead of list construction - make it as lazy as possible Speed up analysis time nearly for 2-5% --- .../calls/tower/NewResolveOldInference.kt | 4 +- .../resolve/calls/tower/TowerResolver.kt | 104 ++++++++++-------- 2 files changed, 59 insertions(+), 49 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt index 7a8514c88bf..de32e6fb676 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt @@ -116,12 +116,12 @@ class NewResolveOldInference( Candidate(ResolutionCandidateStatus(diagnostics), resolvedCall) } if (basicCallContext.collectAllCandidates) { - val allCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates), + val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates), TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false) return allCandidatesResult(allCandidates) as OverloadResolutionResultsImpl } - val processedCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates), + val processedCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates), TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true) return convertToOverloadResults(processedCandidates, tracing, basicCallContext) as OverloadResolutionResultsImpl diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index bf6238a058e..d54c6add883 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -65,10 +65,10 @@ class TowerResolver { context: TowerContext, processor: ScopeTowerProcessor, useOrder: Boolean - ): Collection = run(context.scopeTower.createTowerDataList(), processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder) + ): Collection = context.scopeTower.run(processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder) fun collectAllCandidates(context: TowerContext, processor: ScopeTowerProcessor): Collection - = run(context.scopeTower.createTowerDataList(), processor, AllCandidatesCollector { context.getStatus(it) }, false) + = context.scopeTower.run(processor, AllCandidatesCollector { context.getStatus(it) }, false) private fun ScopeTower.createNonLocalLevels(): List { val result = ArrayList() @@ -87,98 +87,108 @@ class TowerResolver { return result } - private fun ScopeTower.createTowerDataList(): List { - val result = ArrayList() - - operator fun TowerData.unaryPlus() = result.add(this) + private fun ScopeTower.run( + processor: ScopeTowerProcessor, + resultCollector: ResultCollector, + useOrder: Boolean + ): Collection { + fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this) val localLevels = lexicalScope.parentsWithSelf. filterIsInstance().filter { it.kind.withLocalDescriptors }. - map { ScopeBasedTowerLevel(this@createTowerDataList, it) } + map { ScopeBasedTowerLevel(this@run, it) } - val nonLocalLevels = createNonLocalLevels() + // Lazy calculation + var nonLocalLevels: Collection? = null val hidesMembersLevel = HidesMembersTowerLevel(this) val syntheticLevel = SyntheticScopeBasedTowerLevel(this, syntheticScopes) // hides members extensions for explicit receiver - + TowerData.TowerLevel(hidesMembersLevel) + TowerData.TowerLevel(hidesMembersLevel).process()?.let { return it } // possibly there is explicit member - + TowerData.Empty + TowerData.Empty.process()?.let { return it } // synthetic member for explicit receiver - + TowerData.TowerLevel(syntheticLevel) + TowerData.TowerLevel(syntheticLevel).process()?.let { return it } // local non-extensions or extension for explicit receiver for (localLevel in localLevels) { - + TowerData.TowerLevel(localLevel) + TowerData.TowerLevel(localLevel).process()?.let { return it } } - for (scope in this.lexicalScope.parentsWithSelf) { + for (scope in lexicalScope.parentsWithSelf) { if (scope is LexicalScope) { // statics if (!scope.kind.withLocalDescriptors) { - + TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)) + TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)).process()?.let { return it } } val implicitReceiver = scope.implicitReceiver?.value if (implicitReceiver != null) { // hides members extensions - + TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver) + TowerData.BothTowerLevelAndImplicitReceiver(hidesMembersLevel, implicitReceiver).process()?.let { return it } // members of implicit receiver or member extension for explicit receiver - + TowerData.TowerLevel(ReceiverScopeTowerLevel(this, implicitReceiver)) + TowerData.TowerLevel(ReceiverScopeTowerLevel(this, implicitReceiver)).process()?.let { return it } // synthetic members - + TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver) + TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it } // invokeExtension on local variable - + TowerData.OnlyImplicitReceiver(implicitReceiver) + TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it } // local extensions for implicit receiver for (localLevel in localLevels) { - + TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver) + TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver).process()?.let { return it } } // extension for implicit receiver + if (nonLocalLevels == null) { + nonLocalLevels = createNonLocalLevels() + } + for (nonLocalLevel in nonLocalLevels) { - + TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver) + TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver).process()?.let { return it } } } } else { // functions with no receiver or extension for explicit receiver - + TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)) - } - } - - return result - } - - fun run( - towerDataList: List, - processor: ScopeTowerProcessor, - resultCollector: ResultCollector, - useOrder: Boolean - ): Collection { - - for (towerData in towerDataList) { - ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() - - val candidatesGroups = if (useOrder) { - processor.process(towerData) - } - else { - listOf(processor.process(towerData).flatMap { it }) - } - - for (candidatesGroup in candidatesGroups) { - resultCollector.pushCandidates(candidatesGroup) - resultCollector.getSuccessfulCandidates()?.let { return it } + TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)).process()?.let { return it } } } return resultCollector.getFinalCandidates() } + fun runWithEmptyTowerData( + processor: ScopeTowerProcessor, + resultCollector: ResultCollector, + useOrder: Boolean + ): Collection = processTowerData(processor, resultCollector, useOrder, TowerData.Empty) ?: resultCollector.getFinalCandidates() + + private fun processTowerData( + processor: ScopeTowerProcessor, + resultCollector: ResultCollector, + useOrder: Boolean, + towerData: TowerData + ): Collection? { + ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() + + val candidatesGroups = if (useOrder) { + processor.process(towerData) + } + else { + listOf(processor.process(towerData).flatMap { it }) + } + + for (candidatesGroup in candidatesGroups) { + resultCollector.pushCandidates(candidatesGroup) + resultCollector.getSuccessfulCandidates()?.let { return it } + } + + return null + } + abstract class ResultCollector(protected val getStatus: (C) -> ResolutionCandidateStatus) { abstract fun getSuccessfulCandidates(): Collection?