diff --git a/js/js.dce/build.gradle.kts b/js/js.dce/build.gradle.kts index bd20caedd3e..d49789c44d2 100644 --- a/js/js.dce/build.gradle.kts +++ b/js/js.dce/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { compile(project(":js:js.ast")) compile(project(":js:js.translator")) compileOnly(intellijCoreDep()) { includeJars("intellij-core") } + compileOnly(intellijDep()) { includeJars("guava", rootProject = rootProject) } } sourceSets { diff --git a/js/js.dce/src/org/jetbrains/kotlin/js/dce/Context.kt b/js/js.dce/src/org/jetbrains/kotlin/js/dce/Context.kt index 4fa27f5e0e6..4a5fb3b23f1 100644 --- a/js/js.dce/src/org/jetbrains/kotlin/js/dce/Context.kt +++ b/js/js.dce/src/org/jetbrains/kotlin/js/dce/Context.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.js.dce +import com.google.common.collect.LinkedHashMultimap import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction import org.jetbrains.kotlin.js.backend.ast.metadata.specialFunction @@ -24,6 +25,12 @@ import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.array import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.index class Context { + // Collections per Node consumes too much RAM + private val nodeDependencies = LinkedHashMultimap.create() + private val nodeExpressions = LinkedHashMultimap.create() + private val nodeFunctions = LinkedHashMultimap.create() + private val nodeUsedByAstNodes = LinkedHashMultimap.create() + val globalScope = Node() val moduleExportsNode = globalScope.member("module").member("exports") var currentModule = globalScope @@ -134,36 +141,24 @@ class Context { fun visit(n: Node) = n.visit(currentColor) - class Node private constructor(val localName: JsName?, parent: Node?, val memberName: String?) { - private var _dependenciesImpl: MutableSet? = null - private var _expressionsImpl: MutableSet? = null - private var _functionsImpl: MutableSet? = null + inner class Node private constructor(val localName: JsName?, parent: Node?, val memberName: String?) { private var _membersImpl: MutableMap? = null - private var _usedByAstNodesImpl: MutableSet? = null - private val dependenciesImpl: MutableSet - get() = _dependenciesImpl ?: mutableSetOf().also { _dependenciesImpl = it } - private val expressionsImpl: MutableSet - get() = _expressionsImpl ?: mutableSetOf().also { _expressionsImpl = it } - private val functionsImpl: MutableSet - get() = _functionsImpl ?: mutableSetOf().also { _functionsImpl = it } private val membersImpl: MutableMap get() = _membersImpl ?: mutableMapOf().also { _membersImpl = it } - private val usedByAstNodesImpl: MutableSet - get() = _usedByAstNodesImpl ?: mutableSetOf().also { _usedByAstNodesImpl = it } private var rank = 0 private var hasSideEffectsImpl = false private var reachableImpl = false private var declarationReachableImpl = false - val dependencies: Set get() = original._dependenciesImpl ?: emptySet() + val dependencies: Set get() = nodeDependencies[original] - val expressions: Set get() = original._expressionsImpl ?: emptySet() + val expressions: Set get() = nodeExpressions[original] - val functions: Set get() = original._functionsImpl ?: emptySet() + val functions: Set get() = nodeFunctions[original] - val usedByAstNodes: Set get() = original._usedByAstNodesImpl ?: emptySet() + val usedByAstNodes: Set get() = nodeUsedByAstNodes[original] var hasSideEffects: Boolean get() = original.hasSideEffectsImpl @@ -210,19 +205,19 @@ class Context { val members: Map get() = original._membersImpl ?: emptyMap() fun addDependency(node: Node) { - original.dependenciesImpl += node + nodeDependencies.put(original, node) } fun addFunction(function: JsFunction) { - original.functionsImpl += function + nodeFunctions.put(original, function) } fun addExpression(expression: JsExpression) { - original.expressionsImpl += expression + nodeExpressions.put(original, expression) } fun addUsedByAstNode(node: JsNode) { - original.usedByAstNodesImpl += node + nodeUsedByAstNodes.put(original, node) } fun member(name: String): Node = original.membersImpl.getOrPut(name) { Node(null, this, name) }.original @@ -247,8 +242,8 @@ class Context { } private fun makeDependencies(other: Node) { - dependenciesImpl += other - other.dependenciesImpl += this + nodeDependencies.put(this, other) + nodeDependencies.put(other, this) } private fun evacuateFrom(other: Node) { @@ -267,23 +262,15 @@ class Context { other.membersImpl.clear() hasSideEffectsImpl = hasSideEffectsImpl || other.hasSideEffectsImpl - if (!other._expressionsImpl.isNullOrEmpty()) { - expressionsImpl += other.expressionsImpl - } - if (!other._functionsImpl.isNullOrEmpty()) { - functionsImpl += other.functionsImpl - } - if (!other._dependenciesImpl.isNullOrEmpty()) { - dependenciesImpl += other.dependenciesImpl - } - if (!other._usedByAstNodesImpl.isNullOrEmpty()) { - usedByAstNodesImpl += other.usedByAstNodesImpl - } + nodeExpressions.putAll(this, nodeExpressions[other]) + nodeFunctions.putAll(this, nodeFunctions[other]) + nodeDependencies.putAll(this, nodeDependencies[other]) + nodeUsedByAstNodes.putAll(this, nodeUsedByAstNodes[other]) - other._expressionsImpl = null - other._functionsImpl = null - other._dependenciesImpl = null - other._usedByAstNodesImpl = null + nodeExpressions.removeAll(other) + nodeFunctions.removeAll(other) + nodeDependencies.removeAll(other) + nodeUsedByAstNodes.removeAll(other) } private fun merge(other: Node) {