Skip to content

Commit

Permalink
Minor refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
dima74 committed Sep 16, 2020
1 parent bc18bf4 commit a736e96
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 48 deletions.
63 changes: 38 additions & 25 deletions src/main/kotlin/org/rust/lang/core/resolve2/AsyncDefMapBuilder.kt
Expand Up @@ -18,7 +18,7 @@ private const val PRINT_TIME_STATISTICS: Boolean = true

class AsyncDefMapBuilder(
private val defMapService: DefMapService,
private val crates: Set<Crate>,
private val crates: List<Crate>, // should be top sorted
defMaps: Map<Crate, CrateDefMap>,
private val indicator: ProgressIndicator,
private val pool: Executor,
Expand All @@ -29,14 +29,15 @@ class AsyncDefMapBuilder(
}

/** Values - number of dependencies for which [CrateDefMap] is not build yet */
private val remainingDependenciesCounts: MutableMap<Crate, AtomicInteger> =
private val remainingDependenciesCounts: MutableMap<Crate, AtomicInteger> = run {
val cratesSet = crates.toSet()
crates.associateWithTo(hashMapOf()) {
val remainingDependencies = it.dependencies
.filter { dep -> dep.crate in crates }
.filter { dep -> dep.crate in cratesSet }
.size
AtomicInteger(remainingDependencies)
}

}
private val builtDefMaps: MutableMap<Crate, CrateDefMap> = ConcurrentHashMap(defMaps)

/** We don't use [CountDownLatch] because [CompletableFuture] allows easier exception handling */
Expand All @@ -48,28 +49,42 @@ class AsyncDefMapBuilder(

fun build() {
val wallTime = measureTimeMillis {
buildImpl()
if (pool is SingleThreadExecutor) {
buildSync()
} else {
buildAsync()
}
}

timesBuildDefMaps += wallTime
if (PRINT_TIME_STATISTICS) printTimeStatistics(wallTime)
}

private fun buildImpl() {
// todo сначала заполнить все defMapFeature,
// чтобы в waitOrGetOrBuild не строились рекурсивно `defMap`ы
private fun buildAsync() {
remainingDependenciesCounts
.filterValues { it.get() == 0 }
.keys
.forEach { buildDefMapAsync(it) }
completableFuture.getWithRethrow()
}

private fun buildSync() {
ourRunReadAction(indicator) {
for (crate in crates) {
tasksTimes[crate] = measureTimeMillis {
doBuildDefMap(crate)
}
}
}
}

private fun buildDefMapAsync(crate: Crate) {
pool.execute {
try {
tasksTimes[crate] = measureTimeMillis {
doBuildDefMap(crate)
ourRunReadAction(indicator) {
doBuildDefMap(crate)
}
}
} catch (e: Throwable) {
completableFuture.completeExceptionally(e)
Expand All @@ -80,23 +95,21 @@ class AsyncDefMapBuilder(
}

private fun doBuildDefMap(crate: Crate) {
ourRunReadAction(indicator) {
val crateId = crate.id ?: return@ourRunReadAction
val dependenciesDefMaps = crate.flatDependencies
.mapNotNull {
// it can be null e.g. if dependency has null id
val dependencyDefMap = builtDefMaps[it] ?: return@mapNotNull null
it to dependencyDefMap
}
.toMap()
val defMap = buildDefMap(crate, dependenciesDefMaps, indicator)
val holder = defMapService.getDefMapHolder(crateId)
holder.defMap = defMap
holder.shouldRebuild = false
holder.setLatestStamp()
if (defMap != null) {
builtDefMaps[crate] = defMap
val crateId = crate.id ?: return
val dependenciesDefMaps = crate.flatDependencies
.mapNotNull {
// it can be null e.g. if dependency has null id
val dependencyDefMap = builtDefMaps[it] ?: return@mapNotNull null
it to dependencyDefMap
}
.toMap()
val defMap = buildDefMap(crate, dependenciesDefMaps, indicator)
val holder = defMapService.getDefMapHolder(crateId)
holder.defMap = defMap
holder.shouldRebuild = false
holder.setLatestStamp()
if (defMap != null) {
builtDefMaps[crate] = defMap
}
}

Expand Down
13 changes: 5 additions & 8 deletions src/main/kotlin/org/rust/lang/core/resolve2/DefCollector.kt
Expand Up @@ -61,11 +61,10 @@ class DefCollector(
private val macroExpanderShared: MacroExpansionShared = MacroExpansionShared.getInstance()

fun collect() {
var changed = true
while (changed) {
do {
resolveImports()
changed = expandMacros()
}
val changed = expandMacros()
} while (changed)
}

/**
Expand All @@ -74,8 +73,7 @@ class DefCollector(
* This is a fixed point algorithm. We resolve imports until no forward progress in resolving imports is made
*/
private fun resolveImports() {
var hasChangedImports = true
while (hasChangedImports) {
do {
var hasChangedIndeterminateImports = false
val hasResolvedImports = unresolvedImports.removeIf { import ->
context.indicator.checkCanceled()
Expand All @@ -102,8 +100,7 @@ class DefCollector(
Unresolved -> false
}
}
hasChangedImports = hasResolvedImports || hasChangedIndeterminateImports
}
} while (hasResolvedImports || hasChangedIndeterminateImports)
}

private fun resolveImport(import: Import): PartialResolvedImport {
Expand Down
5 changes: 4 additions & 1 deletion src/main/kotlin/org/rust/lang/core/resolve2/FacadeBuild.kt
Expand Up @@ -140,7 +140,7 @@ private class DefMapUpdater(
val cratesToUpdateAll = cratesToUpdate.withReversedDependencies()
val builtDefMaps = getBuiltDefMaps(cratesToUpdateAll)
val pool = getPool(cratesToUpdateAll.size)
AsyncDefMapBuilder(defMapService, cratesToUpdateAll, builtDefMaps, indicator, pool).build()
AsyncDefMapBuilder(defMapService, cratesToUpdateAll.topSort(topSortedCrates), builtDefMaps, indicator, pool).build()
}

private fun findCratesToCheck(): List<Pair<Crate, DefMapHolder>> {
Expand Down Expand Up @@ -201,6 +201,9 @@ private fun List<Crate>.withReversedDependencies(): Set<Crate> {
return result
}

private fun Set<Crate>.topSort(topSortedCrates: List<Crate>): List<Crate> =
topSortedCrates.filterTo(mutableListOf()) { it in this }

class SingleThreadExecutor : Executor {
override fun execute(action: Runnable) = action.run()
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/org/rust/lang/core/resolve2/ModCollector.kt
Expand Up @@ -39,12 +39,13 @@ class CollectorContext(
/** All explicit imports (not expanded from macros) */
val imports: MutableList<Import> = mutableListOf()

/** All explicit macro calls */
/** All explicit macro calls */
val macroCalls: MutableList<MacroCallInfo> = mutableListOf()
}

fun buildDefMapContainingExplicitItems(
context: CollectorContext,
// todo изменить на `Map<CrateId, CrateDefMap>`? чтобы не нужно было считать `allDependenciesDefMaps`
dependenciesDefMaps: Map<Crate, CrateDefMap>
): CrateDefMap? {
val crate = context.crate
Expand Down
Expand Up @@ -62,6 +62,7 @@ fun CrateDefMap.resolvePathFp(
// we still have path segments left, but the path so far
// didn't resolve in the types namespace => no resolution
val currentModAsVisItem = currentPerNs.types
// todo этого недостаточно - ещё нужно проверять что `it.visibility` видима в sourceMod
?.takeIf { withInvisibleItems || !it.visibility.isInvisible }
?: return ResolvePathResult.empty(reachedFixedPoint = false)

Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/org/rust/lang/core/resolve2/resolve.kt
Expand Up @@ -309,12 +309,14 @@ data class PerNs(
macros = merge(macros, other.macros)
}

fun or(other: PerNs): PerNs =
PerNs(
fun or(other: PerNs): PerNs {
if (other.isEmpty) return this
return PerNs(
types ?: other.types,
values ?: other.values,
macros ?: other.macros
)
}

fun mapItems(f: (VisItem) -> VisItem): PerNs =
PerNs(
Expand Down
22 changes: 11 additions & 11 deletions src/test/kotlin/org/rustPerformanceTests/RsBuildDefMapTest.kt
Expand Up @@ -12,18 +12,18 @@ import org.rust.lang.core.macros.macroExpansionManager
class RsBuildDefMapTest : RsRealProjectTestBase() {

/** Don't run it on Rustc! It's a kind of stress-test */
fun `test analyze rustc`() = doTest(RUSTC)
fun `test build rustc`() = doTest(RUSTC)

fun `test analyze empty`() = doTest(EMPTY)
fun `test analyze Cargo`() = doTest(CARGO)
fun `test analyze mysql_async`() = doTest(MYSQL_ASYNC)
fun `test analyze tokio`() = doTest(TOKIO)
fun `test analyze amethyst`() = doTest(AMETHYST)
fun `test analyze clap`() = doTest(CLAP)
fun `test analyze diesel`() = doTest(DIESEL)
fun `test analyze rust_analyzer`() = doTest(RUST_ANALYZER)
fun `test analyze xi_editor`() = doTest(XI_EDITOR)
fun `test analyze juniper`() = doTest(JUNIPER)
fun `test build empty`() = doTest(EMPTY)
fun `test build Cargo`() = doTest(CARGO)
fun `test build mysql_async`() = doTest(MYSQL_ASYNC)
fun `test build tokio`() = doTest(TOKIO)
fun `test build amethyst`() = doTest(AMETHYST)
fun `test build clap`() = doTest(CLAP)
fun `test build diesel`() = doTest(DIESEL)
fun `test build rust_analyzer`() = doTest(RUST_ANALYZER)
fun `test build xi_editor`() = doTest(XI_EDITOR)
fun `test build juniper`() = doTest(JUNIPER)

private fun doTest(info: RealProjectInfo) {
val disposable = project.macroExpansionManager.setUnitTestExpansionModeAndDirectory(MacroExpansionScope.ALL, name)
Expand Down

0 comments on commit a736e96

Please sign in to comment.