JS: replace declareFreshName with declareTemporaryName in inliner, get rid of scopes where possible
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user