From fb80e19b8824780ac7468bae28e8223e3ce3e1c0 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 15 Aug 2017 13:20:30 +0700 Subject: [PATCH] Filter out inapplicable local scopes in call resolution The idea is that resolution has an approximate complexity close to (n + n*m) * 3 Where n is a number of scopes, m is a number of receivers and 3-constant is used because each of these combinations runs through 3 processors for functions. And while call resolver seems to be a hot spot, it should be useful to decreate the value of n --- .../calls/tower/NewResolutionOldInference.kt | 6 ++-- .../resolve/calls/KotlinCallResolver.kt | 4 +-- .../components/CallableReferenceResolver.kt | 2 +- .../resolve/calls/tower/TowerResolver.kt | 36 ++++++++++++------- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt index 70e096bcf32..7a5f1174eba 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -168,10 +168,10 @@ class NewResolutionOldInference( val processor = kind.createTowerProcessor(this, nameToResolve, tracing, scopeTower, detailedReceiver, context) if (context.collectAllCandidates) { - return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor)) + return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor, nameToResolve)) } - var candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference) + var candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference, name = nameToResolve) // Temporary hack to resolve 'rem' as 'mod' if the first is do not present val emptyOrInapplicableCandidates = candidates.isEmpty() || @@ -179,7 +179,7 @@ class NewResolutionOldInference( if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) { val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name] val processorForDeprecatedName = kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context) - candidates = towerResolver.runResolve(scopeTower, processorForDeprecatedName, useOrder = kind != ResolutionKind.CallableReference) + candidates = towerResolver.runResolve(scopeTower, processorForDeprecatedName, useOrder = kind != ResolutionKind.CallableReference, name = deprecatedName) } if (candidates.isEmpty()) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt index 12d4457ddc9..3326fc6d30e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/KotlinCallResolver.kt @@ -55,11 +55,11 @@ class KotlinCallResolver( } if (collectAllCandidates) { - val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor) + val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor, kotlinCall.name) return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks) } - val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED) + val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED, name = kotlinCall.name) return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt index c53ca974002..35e5496f9d3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolver.kt @@ -115,7 +115,7 @@ class CallableReferenceResolver( ): Set { val factory = CallableReferencesCandidateFactory(callableReference, callComponents, scopeTower, compatibilityChecker, expectedType) val processor = createCallableReferenceProcessor(factory) - val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true) + val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true, name = callableReference.rhsName) return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates( candidates, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, 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 b97fac2e46b..d1051e918a4 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 @@ -16,12 +16,15 @@ package org.jetbrains.kotlin.resolve.calls.tower +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.scopes.ImportingScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.resolve.scopes.ResolutionScope import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf +import org.jetbrains.kotlin.util.OperatorNameConventions import java.util.* interface Candidate { @@ -74,14 +77,16 @@ class TowerResolver { fun runResolve( scopeTower: ImplicitScopeTower, processor: ScopeTowerProcessor, - useOrder: Boolean - ): Collection = scopeTower.run(processor, SuccessfulResultCollector(), useOrder) + useOrder: Boolean, + name: Name + ): Collection = scopeTower.run(processor, SuccessfulResultCollector(), useOrder, name) fun collectAllCandidates( scopeTower: ImplicitScopeTower, - processor: ScopeTowerProcessor + processor: ScopeTowerProcessor, + name: Name ): Collection - = scopeTower.run(processor, AllCandidatesCollector(), false) + = scopeTower.run(processor, AllCandidatesCollector(), false, name) private fun ImplicitScopeTower.createNonLocalLevels(): List { val result = ArrayList() @@ -103,14 +108,11 @@ class TowerResolver { private fun ImplicitScopeTower.run( processor: ScopeTowerProcessor, resultCollector: ResultCollector, - useOrder: Boolean + useOrder: Boolean, + name: Name ): Collection { fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this) - val localLevels = lexicalScope.parentsWithSelf. - filterIsInstance().filter { it.kind.withLocalDescriptors }. - map { ScopeBasedTowerLevel(this@run, it) } - // Lazy calculation var nonLocalLevels: Collection? = null val hidesMembersLevel = HidesMembersTowerLevel(this) @@ -123,6 +125,11 @@ class TowerResolver { // synthetic property for explicit receiver TowerData.TowerLevel(syntheticLevel).process()?.let { return it } + val localLevels = + lexicalScope.parentsWithSelf. + filterIsInstance().filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }. + map { ScopeBasedTowerLevel(this@run, it) }.toList() + // local non-extensions or extension for explicit receiver for (localLevel in localLevels) { TowerData.TowerLevel(localLevel).process()?.let { return it } @@ -173,6 +180,9 @@ class TowerResolver { return resultCollector.getFinalCandidates() } + private fun ResolutionScope.mayFitForName(name: Name) = + !definitelyDoesNotContainName(name) || !definitelyDoesNotContainName(OperatorNameConventions.INVOKE) + fun runWithEmptyTowerData( processor: ScopeTowerProcessor, resultCollector: ResultCollector, @@ -234,7 +244,7 @@ class TowerResolver { val firstGroupWithResolved = candidateGroups.firstOrNull { it.any { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED } } ?: return null - + return firstGroupWithResolved.filter { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED } } @@ -261,8 +271,8 @@ class TowerResolver { return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability } } - - private val Collection.groupApplicability get() = - minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN + + private val Collection.groupApplicability get() = + minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN } }