JS: replace declareFreshName with declareTemporaryName in inliner, get rid of scopes where possible

This commit is contained in:
Alexey Andreev
2017-02-28 12:17:59 +03:00
parent 22f24d13b9
commit dc1ce0e8b5
5 changed files with 14 additions and 31 deletions
@@ -52,7 +52,6 @@ import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.*
* and precedes inline call (in JavaScript evaluation order).
*/
internal class ExpressionDecomposer private constructor(
private val scope: JsScope,
private val containsExtractable: Set<JsNode>,
private val containsNodeWithSideEffect: Set<JsNode>
) : JsExpressionVisitor() {
@@ -60,16 +59,14 @@ internal class ExpressionDecomposer private constructor(
private var additionalStatements: MutableList<JsStatement> = SmartList()
companion object {
@JvmStatic fun preserveEvaluationOrder(
scope: JsScope, statement: JsStatement, canBeExtractedByInliner: (JsNode)->Boolean
): List<JsStatement> {
@JvmStatic fun preserveEvaluationOrder(statement: JsStatement, canBeExtractedByInliner: (JsNode) -> Boolean): List<JsStatement> {
val decomposer = with (statement) {
val extractable = match(canBeExtractedByInliner)
val containsExtractable = withParentsOfNodes(extractable)
val nodesWithSideEffect = match { it !is JsLiteral.JsValueLiteral }
val containsNodeWithSideEffect = withParentsOfNodes(nodesWithSideEffect)
ExpressionDecomposer(scope, containsExtractable, containsNodeWithSideEffect)
ExpressionDecomposer(containsExtractable, containsNodeWithSideEffect)
}
decomposer.accept(statement)
@@ -132,7 +129,7 @@ internal class ExpressionDecomposer private constructor(
}
else {
// See KT-12275
val guardName = scope.declareFreshName("guard\$${(loopLabel?.ident.orEmpty())}")
val guardName = JsScope.declareTemporaryName("guard\$${(loopLabel?.ident.orEmpty())}")
val label = JsLabel(guardName).apply { synthetic = true }
label.statement = JsBlock(bodyStatements)
addStatements(0, listOf(label))
@@ -99,7 +99,7 @@ private constructor(
var thisReplacement = getThisReplacement(call)
if (thisReplacement == null || thisReplacement is JsLiteral.JsThisRef) return
val thisName = namingContext.getFreshName(getThisAlias())
val thisName = JsScope.declareTemporaryName(getThisAlias())
namingContext.newVar(thisName, thisReplacement)
thisReplacement = thisName.makeRef()
@@ -109,7 +109,7 @@ private constructor(
private fun processReturns() {
resultExpr = getResultReference()
val breakName = namingContext.getFreshName(getBreakLabel())
val breakName = JsScope.declareTemporaryName(getBreakLabel())
this.breakLabel = JsLabel(breakName).apply { synthetic = true }
val visitor = ReturnReplacingVisitor(resultExpr as? JsNameRef, breakName.makeRef(), invokedFunction, call.isSuspend)
@@ -119,7 +119,7 @@ private constructor(
private fun getResultReference(): JsNameRef? {
if (!isResultNeeded(call)) return null
val resultName = namingContext.getFreshName(getResultLabel())
val resultName = JsScope.declareTemporaryName(getResultLabel())
this.resultName = resultName
namingContext.newVar(resultName, null)
return resultName.makeRef()
@@ -79,7 +79,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
FunctionReader functionReader = new FunctionReader((LibrarySourcesConfig) config, currentModuleName, fragments);
JsInliner inliner = new JsInliner(functions, accessors, functionReader, trace);
for (JsProgramFragment fragment : fragmentsToProcess) {
inliner.inliningContexts.push(inliner.new JsInliningContext(null, fragment.getScope()));
inliner.inliningContexts.push(inliner.new JsInliningContext());
inliner.accept(fragment.getDeclarationBlock());
// There can be inlined function in top-level initializers, we need to optimize them as well
@@ -106,7 +106,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
@Override
public boolean visit(@NotNull JsFunction function, @NotNull JsContext context) {
inliningContexts.push(new JsInliningContext(function, function.getScope()));
inliningContexts.push(new JsInliningContext());
assert !inProcessFunctions.contains(function): "Inliner has revisited function";
inProcessFunctions.add(function);
@@ -181,12 +181,11 @@ public class JsInliner extends JsVisitorWithContextImpl {
// at top level of js ast, contexts stack can be empty,
// but there is no inline calls anyway
if(!inliningContexts.isEmpty()) {
JsScope scope = getFunctionContext().getScope();
int i = 0;
while (i < statements.size()) {
List<JsStatement> additionalStatements =
ExpressionDecomposer.preserveEvaluationOrder(scope, statements.get(i), canBeExtractedByInliner);
ExpressionDecomposer.preserveEvaluationOrder(statements.get(i), canBeExtractedByInliner);
statements.addAll(i, additionalStatements);
i += additionalStatements.size() + 1;
}
@@ -286,8 +285,8 @@ public class JsInliner extends JsVisitorWithContextImpl {
private class JsInliningContext implements InliningContext {
private final FunctionContext functionContext;
JsInliningContext(@NotNull JsScope scope) {
functionContext = new FunctionContext(scope) {
JsInliningContext() {
functionContext = new FunctionContext(functionReader) {
@Nullable
@Override
protected JsFunction lookUpStaticFunction(@Nullable JsName functionName) {
@@ -305,8 +304,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
@NotNull
@Override
public NamingContext newNamingContext() {
JsScope scope = getFunctionContext().getScope();
return new NamingContext(scope, getStatementContext());
return new NamingContext(getStatementContext());
}
@NotNull
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.js.inline.FunctionReader
import org.jetbrains.kotlin.js.inline.util.*
import org.jetbrains.kotlin.js.translate.context.Namer
abstract class FunctionContext(
private val scope: JsScope,
private val functionReader: FunctionReader
) {
abstract class FunctionContext(private val functionReader: FunctionReader) {
protected abstract fun lookUpStaticFunction(functionName: JsName?): JsFunction?
protected abstract fun lookUpStaticFunctionByTag(functionTag: String): JsFunction?
@@ -39,10 +36,6 @@ abstract class FunctionContext(
return getFunctionDefinitionImpl(call) != null
}
fun getScope(): JsScope {
return scope
}
/**
* Gets function definition by invocation.
*
@@ -25,10 +25,7 @@ import java.util.IdentityHashMap
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.inline.util.replaceNames
class NamingContext(
private val scope: JsScope,
private val statementContext: JsContext<JsStatement>
) {
class NamingContext(private val statementContext: JsContext<JsStatement>) {
private val renamings = IdentityHashMap<JsName, JsExpression>()
private val declarations = ArrayList<JsVars>()
private var addedDeclarations = false
@@ -48,8 +45,6 @@ class NamingContext(
renamings.put(name, replacement)
}
fun getFreshName(candidate: String): JsName = scope.declareFreshName(candidate)
fun newVar(name: JsName, value: JsExpression? = null) {
val vars = JsAstUtils.newVar(name, value)
vars.synthetic = true