diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt index 9140a79f361..88a3f904faa 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt @@ -339,7 +339,6 @@ internal class ExpressionDecomposer private constructor( fun assign(value: JsExpression): JsStatement { val statement = JsExpressionStatement(assignment(nameRef, value)).apply { synthetic = true } - name.staticRef = value return statement } } diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt index fc11ee06564..277e477193f 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.js.inline.util.rewriters.ReturnReplacingVisitor class FunctionInlineMutator private constructor( private val call: JsInvocation, - inliningContext: InliningContext + private val inliningContext: InliningContext ) { private val invokedFunction: JsFunction private val namingContext: NamingContext @@ -85,9 +85,7 @@ private constructor( } private fun applyCapturedArgs(call: JsInvocation, inner: JsFunction, outer: JsFunction) { - // We want statements that introduce temporary variables to be added immediately after applying renamings, - // so that further processing that involves detection of inlineable function had a chance to recognize them. - val namingContext = NamingContext(inner.scope) { inner.body.statements.addAll(0, it) } + val namingContext = inliningContext.newNamingContext() val arguments = call.arguments val parameters = outer.parameters aliasArgumentsIfNeeded(namingContext, arguments, parameters) @@ -108,11 +106,7 @@ private constructor( } private fun processReturns() { - val resultReference = getResultReference() - if (resultReference != null) { - resultExpr = resultReference - } - assert(resultExpr == null || resultExpr is JsNameRef) + resultExpr = getResultReference() val breakName = namingContext.getFreshName(getBreakLabel()) this.breakLabel = JsLabel(breakName).apply { synthetic = true } 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 59c79163d59..df26d1b2915 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 @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.inline; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties; import com.intellij.psi.PsiElement; -import kotlin.Unit; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -194,18 +193,7 @@ public class JsInliner extends JsVisitorWithContextImpl { return; } - resultExpression = accept(resultExpression); - JsStatement currentStatement = statementContext.getCurrentNode(); - - if (currentStatement instanceof JsExpressionStatement && - ((JsExpressionStatement) currentStatement).getExpression() == call && - resultExpression == null - ) { - statementContext.removeMe(); - } - else { - context.replaceMe(resultExpression); - } + context.replaceMe(accept(resultExpression)); } @NotNull @@ -267,13 +255,7 @@ public class JsInliner extends JsVisitorWithContextImpl { @Override public NamingContext newNamingContext() { JsScope scope = getFunctionContext().getScope(); - return new NamingContext(scope, new Function1, Unit>() { - @Override - public Unit invoke(List statements) { - getStatementContext().addPrevious(statements); - return null; - } - }); + return new NamingContext(scope, getStatementContext()); } @NotNull diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/ReferenceTracker.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/ReferenceTracker.kt index ffff4173614..f725fc57f22 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/ReferenceTracker.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/ReferenceTracker.kt @@ -34,14 +34,14 @@ internal class ReferenceTracker { } fun addCandidateForRemoval(reference: Reference, candidate: RemoveCandidate) { - assert(!isKnown(reference)) { "Candidate for removal cannot be reassigned: $candidate" } + assert(!isReferenceToRemovableCandidate(reference)) { "Candidate for removal cannot be reassigned: $candidate" } removableCandidates.put(reference, candidate) reachable.put(reference, false) } fun addRemovableReference(referrer: Reference, referenced: Reference) { - if (!isKnown(referenced)) return + if (!isReferenceToRemovableCandidate(referenced)) return getReferencedBy(referrer).add(referenced) @@ -51,12 +51,12 @@ internal class ReferenceTracker { } fun markReachable(reference: Reference) { - if (!isKnown(reference)) return + if (!isReferenceToRemovableCandidate(reference)) return visited.add(reference) getReferencedBy(reference) .filterNot { it in visited } - .filter { isKnown(it) && !isReachable(it) } + .filter { isReferenceToRemovableCandidate(it) && !isReachable(it) } .forEach { markReachable(it) } visited.remove(reference) @@ -67,7 +67,7 @@ internal class ReferenceTracker { return referenceFromTo.getOrPut(referrer, { IdentitySet() }) } - fun isKnown(ref: Reference): Boolean { + fun isReferenceToRemovableCandidate(ref: Reference): Boolean { return removableCandidates.containsKey(ref) } diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedLocalFunctionDeclarations.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedLocalFunctionDeclarations.kt index 4d478d0e426..97e7db0d874 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedLocalFunctionDeclarations.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedLocalFunctionDeclarations.kt @@ -78,7 +78,7 @@ private class UnusedInstanceCollector : JsVisitorWithContextImpl() { // For the case like this: `b = a; c = b;`, where `a` is a function. In this case we should remove both declaration, // although second one contains 'usage' of `b`. // see `inlineEvaluationOrder/cases/lambdaWithClosure.kt`. - if (expr is JsNameRef && (expr.name?.let { tracker.isKnown(it) } ?: false)) return true + if (expr is JsNameRef && (expr.name?.let { tracker.isReferenceToRemovableCandidate(it) } ?: false)) return true val staticRef = name?.staticRef return staticRef != null && staticRef == expr && isFunctionReference(expr) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/NamingContext.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/NamingContext.kt index c6383c2d7a0..008eed0a950 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/NamingContext.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/context/NamingContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. + * Copyright 2010-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.js.inline.util.replaceNames class NamingContext( private val scope: JsScope, - private val statementConsumer: (List) -> Unit + private val statementContext: JsContext ) { private val renamings = IdentityHashMap() private val declarations = ArrayList() @@ -35,7 +35,7 @@ class NamingContext( fun applyRenameTo(target: JsNode): JsNode { if (!addedDeclarations) { - statementConsumer(declarations) + statementContext.addPrevious(declarations) addedDeclarations = true } diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/invocationUtils.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/invocationUtils.kt index 78ce1e3c623..7f3ccdb51d7 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/invocationUtils.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/invocationUtils.kt @@ -132,8 +132,7 @@ val JsExpression.transitiveStaticRef: JsExpression get() { var qualifier = this while (qualifier is JsNameRef) { - val staticRef = qualifier.name?.staticRef as? JsExpression ?: break - qualifier = staticRef + qualifier = qualifier.name?.staticRef as? JsExpression ?: break } return qualifier } \ No newline at end of file diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/namingUtils.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/namingUtils.kt index 2a32ca76b28..6b2f004aba1 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/namingUtils.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/namingUtils.kt @@ -32,15 +32,10 @@ fun aliasArgumentsIfNeeded( for ((arg, param) in arguments.zip(parameters)) { val paramName = param.name - val replacement: JsExpression = if (arg is JsFunction && isFunctionCreator(arg)) { - arg - } - else { - val freshName = context.getFreshName(paramName).apply { staticRef = arg } - context.newVar(freshName, arg) - val freshNameRef = freshName.makeRef() - freshNameRef - } + val replacement = context.getFreshName(paramName).apply { + staticRef = arg + context.newVar(this, arg) + }.makeRef() context.replaceName(paramName, replacement) } diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/ReturnReplacingVisitor.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/ReturnReplacingVisitor.kt index 93003c1b32c..de8e913b760 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/ReturnReplacingVisitor.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/ReturnReplacingVisitor.kt @@ -55,12 +55,10 @@ class ReturnReplacingVisitor( private fun getReturnReplacement(returnExpression: JsExpression?): JsExpression? { return if (returnExpression != null) { - if (resultRef != null) { + val assignment = resultRef?.let { JsAstUtils.assignment(resultRef, returnExpression).apply { synthetic = true } } - else { - returnExpression - } + assignment ?: returnExpression } else { null diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt index ac57cc779cf..b8af2434035 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt @@ -28,8 +28,7 @@ fun JsExpression.canHaveOwnSideEffect(vars: Set) = when (this) { is JsConditional, is JsLiteral -> false is JsBinaryOperation -> operator.isAssignment - is JsNameRef -> !(qualifier == null && name in vars) && sideEffects - is JsInvocation -> !isFunctionCreatorInvocation(this) && sideEffects + is JsNameRef -> name !in vars && sideEffects is HasMetadata -> sideEffects else -> true }