JS/Inlining: minor simplifications after code review

This commit is contained in:
Alexey Andreev
2016-05-31 11:53:41 +03:00
parent a26c09ae81
commit 878e95e040
10 changed files with 22 additions and 56 deletions
@@ -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
}
}
@@ -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 }
@@ -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<List<? extends JsStatement>, Unit>() {
@Override
public Unit invoke(List<? extends JsStatement> statements) {
getStatementContext().addPrevious(statements);
return null;
}
});
return new NamingContext(scope, getStatementContext());
}
@NotNull
@@ -34,14 +34,14 @@ internal class ReferenceTracker<in Reference, RemoveCandidate : JsNode> {
}
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<in Reference, RemoveCandidate : JsNode> {
}
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<in Reference, RemoveCandidate : JsNode> {
return referenceFromTo.getOrPut(referrer, { IdentitySet<Reference>() })
}
fun isKnown(ref: Reference): Boolean {
fun isReferenceToRemovableCandidate(ref: Reference): Boolean {
return removableCandidates.containsKey(ref)
}
@@ -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)
@@ -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<JsStatement>) -> Unit
private val statementContext: JsContext<JsStatement>
) {
private val renamings = IdentityHashMap<JsName, JsExpression>()
private val declarations = ArrayList<JsVars>()
@@ -35,7 +35,7 @@ class NamingContext(
fun applyRenameTo(target: JsNode): JsNode {
if (!addedDeclarations) {
statementConsumer(declarations)
statementContext.addPrevious(declarations)
addedDeclarations = true
}
@@ -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
}
@@ -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)
}
@@ -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
@@ -28,8 +28,7 @@ fun JsExpression.canHaveOwnSideEffect(vars: Set<JsName>) = 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
}