From f6964b18db5ae25b99f5288fe3692e922f5b234c Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 27 Jun 2017 11:21:04 +0300 Subject: [PATCH] Fix performance issue in JS inliner See KT-18679 --- .../jetbrains/kotlin/js/inline/JsInliner.java | 5 ++++- .../clean/removeUnusedFunctionDefinitions.kt | 17 +++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java index a19a425eaf8..4f3e8396af2 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/JsInliner.java @@ -79,6 +79,7 @@ public class JsInliner extends JsVisitorWithContextImpl { } FunctionReader functionReader = new FunctionReader(reporter, config, currentModuleName, fragments); JsInliner inliner = new JsInliner(config, functions, accessors, functionReader, trace); + List nodesToPostProcess = new ArrayList<>(); for (JsProgramFragment fragment : fragmentsToProcess) { inliner.inliningContexts.push(inliner.new JsInliningContext()); inliner.accept(fragment.getDeclarationBlock()); @@ -89,8 +90,10 @@ public class JsInliner extends JsVisitorWithContextImpl { inliner.inliningContexts.pop(); JsBlock block = new JsBlock(fragment.getDeclarationBlock(), fragment.getInitializerBlock(), fragment.getExportBlock()); - RemoveUnusedFunctionDefinitionsKt.removeUnusedFunctionDefinitions(block, functions); + nodesToPostProcess.add(block); } + + RemoveUnusedFunctionDefinitionsKt.removeUnusedFunctionDefinitions(nodesToPostProcess, functions); } private JsInliner( diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedFunctionDefinitions.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedFunctionDefinitions.kt index 4a39aa36bc2..ceead209a81 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedFunctionDefinitions.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedFunctionDefinitions.kt @@ -17,9 +17,8 @@ package org.jetbrains.kotlin.js.inline.clean import org.jetbrains.kotlin.js.backend.ast.* -import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef import org.jetbrains.kotlin.js.backend.ast.metadata.isLocal - +import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef import org.jetbrains.kotlin.js.inline.util.IdentitySet import org.jetbrains.kotlin.js.inline.util.collectFunctionReferencesInside @@ -30,21 +29,23 @@ import org.jetbrains.kotlin.js.inline.util.collectFunctionReferencesInside * At now, it only removes unused local functions and function literals, * because named functions can be referenced from another module. */ -fun removeUnusedFunctionDefinitions(root: JsNode, functions: Map) { +fun removeUnusedFunctionDefinitions(roots: List, functions: Map) { val removable = with(UnusedLocalFunctionsCollector(functions)) { process() - accept(root) - removableFunctions.toSet() - } + roots.forEach { accept(it) } + removableFunctions + }.toSet() - NodeRemover(JsStatement::class.java) { statement -> + val remover = NodeRemover(JsStatement::class.java) { statement -> val expression = when (statement) { is JsExpressionStatement -> statement.expression is JsVars -> if (statement.vars.size == 1) statement.vars[0].initExpression else null else -> null } expression is JsFunction && expression in removable - }.accept(root) + } + + roots.forEach { remover.accept(it) } } private class UnusedLocalFunctionsCollector(private val functions: Map) : JsVisitorWithContextImpl() {