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%
This commit is contained in:
Denis Zharkov
2016-03-09 14:07:06 +03:00
parent ee50aec734
commit 4bea054e4b
2 changed files with 59 additions and 49 deletions
@@ -116,12 +116,12 @@ class NewResolveOldInference(
Candidate(ResolutionCandidateStatus(diagnostics), resolvedCall) Candidate(ResolutionCandidateStatus(diagnostics), resolvedCall)
} }
if (basicCallContext.collectAllCandidates) { if (basicCallContext.collectAllCandidates) {
val allCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates), val allCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false) TowerResolver.AllCandidatesCollector { it.candidateStatus }, useOrder = false)
return allCandidatesResult(allCandidates) as OverloadResolutionResultsImpl<D> return allCandidatesResult(allCandidates) as OverloadResolutionResultsImpl<D>
} }
val processedCandidates = towerResolver.run(listOf(TowerData.Empty), KnownResultProcessor(resolvedCandidates), val processedCandidates = towerResolver.runWithEmptyTowerData(KnownResultProcessor(resolvedCandidates),
TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true) TowerResolver.SuccessfulResultCollector { it.candidateStatus }, useOrder = true)
return convertToOverloadResults(processedCandidates, tracing, basicCallContext) as OverloadResolutionResultsImpl<D> return convertToOverloadResults(processedCandidates, tracing, basicCallContext) as OverloadResolutionResultsImpl<D>
@@ -65,10 +65,10 @@ class TowerResolver {
context: TowerContext<C>, context: TowerContext<C>,
processor: ScopeTowerProcessor<C>, processor: ScopeTowerProcessor<C>,
useOrder: Boolean useOrder: Boolean
): Collection<C> = run(context.scopeTower.createTowerDataList(), processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder) ): Collection<C> = context.scopeTower.run(processor, SuccessfulResultCollector { context.getStatus(it) }, useOrder)
fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C> fun <C> collectAllCandidates(context: TowerContext<C>, processor: ScopeTowerProcessor<C>): Collection<C>
= run(context.scopeTower.createTowerDataList(), processor, AllCandidatesCollector { context.getStatus(it) }, false) = context.scopeTower.run(processor, AllCandidatesCollector { context.getStatus(it) }, false)
private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> { private fun ScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
val result = ArrayList<ScopeTowerLevel>() val result = ArrayList<ScopeTowerLevel>()
@@ -87,98 +87,108 @@ class TowerResolver {
return result return result
} }
private fun ScopeTower.createTowerDataList(): List<TowerData> { private fun <C> ScopeTower.run(
val result = ArrayList<TowerData>() processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
operator fun TowerData.unaryPlus() = result.add(this) useOrder: Boolean
): Collection<C> {
fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this)
val localLevels = lexicalScope.parentsWithSelf. val localLevels = lexicalScope.parentsWithSelf.
filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors }. filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors }.
map { ScopeBasedTowerLevel(this@createTowerDataList, it) } map { ScopeBasedTowerLevel(this@run, it) }
val nonLocalLevels = createNonLocalLevels() // Lazy calculation
var nonLocalLevels: Collection<ScopeTowerLevel>? = null
val hidesMembersLevel = HidesMembersTowerLevel(this) val hidesMembersLevel = HidesMembersTowerLevel(this)
val syntheticLevel = SyntheticScopeBasedTowerLevel(this, syntheticScopes) val syntheticLevel = SyntheticScopeBasedTowerLevel(this, syntheticScopes)
// hides members extensions for explicit receiver // hides members extensions for explicit receiver
+ TowerData.TowerLevel(hidesMembersLevel) TowerData.TowerLevel(hidesMembersLevel).process()?.let { return it }
// possibly there is explicit member // possibly there is explicit member
+ TowerData.Empty TowerData.Empty.process()?.let { return it }
// synthetic member for explicit receiver // synthetic member for explicit receiver
+ TowerData.TowerLevel(syntheticLevel) TowerData.TowerLevel(syntheticLevel).process()?.let { return it }
// local non-extensions or extension for explicit receiver // local non-extensions or extension for explicit receiver
for (localLevel in localLevels) { 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) { if (scope is LexicalScope) {
// statics // statics
if (!scope.kind.withLocalDescriptors) { if (!scope.kind.withLocalDescriptors) {
+ TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)) TowerData.TowerLevel(ScopeBasedTowerLevel(this, scope)).process()?.let { return it }
} }
val implicitReceiver = scope.implicitReceiver?.value val implicitReceiver = scope.implicitReceiver?.value
if (implicitReceiver != null) { if (implicitReceiver != null) {
// hides members extensions // 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 // 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 // synthetic members
+ TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver) TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it }
// invokeExtension on local variable // invokeExtension on local variable
+ TowerData.OnlyImplicitReceiver(implicitReceiver) TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it }
// local extensions for implicit receiver // local extensions for implicit receiver
for (localLevel in localLevels) { for (localLevel in localLevels) {
+ TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver) TowerData.BothTowerLevelAndImplicitReceiver(localLevel, implicitReceiver).process()?.let { return it }
} }
// extension for implicit receiver // extension for implicit receiver
if (nonLocalLevels == null) {
nonLocalLevels = createNonLocalLevels()
}
for (nonLocalLevel in nonLocalLevels) { for (nonLocalLevel in nonLocalLevels) {
+ TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver) TowerData.BothTowerLevelAndImplicitReceiver(nonLocalLevel, implicitReceiver).process()?.let { return it }
} }
} }
} }
else { else {
// functions with no receiver or extension for explicit receiver // functions with no receiver or extension for explicit receiver
+ TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)) TowerData.TowerLevel(ImportingScopeBasedTowerLevel(this, scope as ImportingScope)).process()?.let { return it }
}
}
return result
}
fun <C> run(
towerDataList: List<TowerData>,
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean
): Collection<C> {
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 }
} }
} }
return resultCollector.getFinalCandidates() return resultCollector.getFinalCandidates()
} }
fun <C> runWithEmptyTowerData(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean
): Collection<C> = processTowerData(processor, resultCollector, useOrder, TowerData.Empty) ?: resultCollector.getFinalCandidates()
private fun <C> processTowerData(
processor: ScopeTowerProcessor<C>,
resultCollector: ResultCollector<C>,
useOrder: Boolean,
towerData: TowerData
): Collection<C>? {
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<C>(protected val getStatus: (C) -> ResolutionCandidateStatus) { abstract class ResultCollector<C>(protected val getStatus: (C) -> ResolutionCandidateStatus) {
abstract fun getSuccessfulCandidates(): Collection<C>? abstract fun getSuccessfulCandidates(): Collection<C>?