JS: during translation of expression mark assignment to temporary variables as synthetic statement.
This helps optimizer to find and eliminate temporary variables.
This commit is contained in:
@@ -133,7 +133,7 @@ public class JsFor extends SourceInfoAwareJsNode implements JsStatement {
|
||||
if (initVars != null) {
|
||||
result = new JsFor(initVars.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy);
|
||||
} else {
|
||||
result = new JsFor(initExpression.deepCopy(), conditionCopy, incrementExpression, bodyCopy);
|
||||
result = new JsFor(initExpression.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy);
|
||||
}
|
||||
|
||||
return result.withMetadataFrom(this);
|
||||
|
||||
+10
@@ -121,6 +121,16 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) {
|
||||
override fun visitBreak(x: JsBreak) { }
|
||||
|
||||
override fun visitContinue(x: JsContinue) { }
|
||||
|
||||
override fun visitFor(x: JsFor) {
|
||||
x.initVars?.let { it.vars.forEach { it.initExpression?.let { accept(it) } } }
|
||||
x.initExpression?.let { accept(it) }
|
||||
x.condition?.let { accept(it) }
|
||||
x.body?.let { accept(it) }
|
||||
x.incrementExpression?.let { accept(it) }
|
||||
|
||||
super.visitFor(x)
|
||||
}
|
||||
}.accept(root)
|
||||
|
||||
usages.keys.retainAll(syntheticNames)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.js.translate.context;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -57,11 +58,14 @@ public final class DynamicContext {
|
||||
public TemporaryVariable declareTemporary(@Nullable JsExpression initExpression) {
|
||||
if (vars == null) {
|
||||
vars = new JsVars();
|
||||
MetadataProperties.setSynthetic(vars, true);
|
||||
currentBlock.getStatements().add(vars);
|
||||
}
|
||||
|
||||
JsName temporaryName = currentScope.declareTemporary();
|
||||
vars.add(new JsVar(temporaryName, null));
|
||||
JsVar var = new JsVar(temporaryName, null);
|
||||
MetadataProperties.setSynthetic(var, true);
|
||||
vars.add(var);
|
||||
return TemporaryVariable.create(temporaryName, initExpression);
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -16,9 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.context;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsName;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
@@ -26,7 +28,12 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
public class TemporaryVariable {
|
||||
|
||||
/*package*/ static TemporaryVariable create(@NotNull JsName temporaryName, @Nullable JsExpression initExpression) {
|
||||
return new TemporaryVariable(temporaryName, initExpression == null ? null : JsAstUtils.assignment(temporaryName.makeRef(), initExpression));
|
||||
JsBinaryOperation rhs = null;
|
||||
if (initExpression != null) {
|
||||
rhs = JsAstUtils.assignment(temporaryName.makeRef(), initExpression);
|
||||
MetadataProperties.setSynthetic(rhs, true);
|
||||
}
|
||||
return new TemporaryVariable(temporaryName, rhs);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+1
-2
@@ -29,9 +29,8 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer;
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.declaration.ClassTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt;
|
||||
import org.jetbrains.kotlin.js.translate.expression.loopTranslator.LoopTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.general.Translation;
|
||||
import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt;
|
||||
import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
|
||||
import org.jetbrains.kotlin.js.translate.operation.BinaryOperationTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.operation.UnaryOperationTranslator;
|
||||
|
||||
+32
-18
@@ -16,14 +16,13 @@
|
||||
|
||||
@file:JvmName("LoopTranslator")
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.expression.loopTranslator
|
||||
package org.jetbrains.kotlin.js.translate.expression
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
||||
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.expression.DestructuringDeclarationTranslator
|
||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.CompositeFIF
|
||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getHasNextCallable
|
||||
@@ -33,7 +32,6 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getTypeForExpression
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
|
||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopParameter
|
||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopRange
|
||||
import org.jetbrains.kotlin.js.translate.utils.TemporariesUtils.temporariesInitialization
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
@@ -117,16 +115,16 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
|
||||
|
||||
val destructuringParameter: KtDestructuringDeclaration? = expression.destructuringParameter
|
||||
|
||||
fun declareParameter(): JsName {
|
||||
fun declareParameter(): Pair<JsName, Boolean> {
|
||||
val loopParameter = getLoopParameter(expression)
|
||||
if (loopParameter != null) {
|
||||
return context.getNameForElement(loopParameter)
|
||||
return Pair(context.getNameForElement(loopParameter), false)
|
||||
}
|
||||
assert(destructuringParameter != null) { "If loopParameter is null, multi parameter must be not null ${expression.text}" }
|
||||
return context.scope().declareTemporary()
|
||||
return Pair(context.scope().declareTemporary(), true)
|
||||
}
|
||||
|
||||
val parameterName: JsName = declareParameter()
|
||||
val (parameterName, parameterIsTemporary) = declareParameter()
|
||||
|
||||
fun translateBody(itemValue: JsExpression?): JsStatement? {
|
||||
val realBody = expression.body?.let { Translation.translateAsStatementAndMergeInBlockIfNeeded(it, context) }
|
||||
@@ -135,10 +133,12 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
|
||||
}
|
||||
else {
|
||||
val currentVarInit =
|
||||
if (destructuringParameter == null)
|
||||
if (destructuringParameter == null) {
|
||||
newVar(parameterName, itemValue)
|
||||
else
|
||||
}
|
||||
else {
|
||||
DestructuringDeclarationTranslator.translate(destructuringParameter, parameterName, itemValue, context)
|
||||
}
|
||||
|
||||
if (realBody == null) return JsBlock(currentVarInit)
|
||||
|
||||
@@ -170,12 +170,16 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
|
||||
val rangeEnd = context.declareTemporary(rightExpression)
|
||||
|
||||
val body = translateBody(null)
|
||||
val initExpression = newVar(parameterName, rangeStart)
|
||||
val conditionExpression = lessThanEq(parameterName.makeRef(), rangeEnd.reference())
|
||||
val incrementExpression = JsPostfixOperation(JsUnaryOperator.INC, parameterName.makeRef())
|
||||
|
||||
context.addStatementToCurrentBlock(temporariesInitialization(rangeEnd).makeStmt())
|
||||
return JsFor(initExpression, conditionExpression, incrementExpression, body)
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(rangeEnd.assignmentExpression()))
|
||||
return if (parameterIsTemporary) {
|
||||
JsFor(assignment(parameterName.makeRef(), rangeStart), conditionExpression, incrementExpression, body)
|
||||
}
|
||||
else {
|
||||
JsFor(newVar(parameterName, rangeStart), conditionExpression, incrementExpression, body)
|
||||
}
|
||||
}
|
||||
|
||||
fun translateForOverRange(): JsStatement {
|
||||
@@ -188,12 +192,21 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
|
||||
val increment = context.declareTemporary(getProperty("step"))
|
||||
|
||||
val body = translateBody(null)
|
||||
val initExpression = newVar(parameterName, start.reference())
|
||||
val conditionExpression = lessThanEq(parameterName.makeRef(), end.reference())
|
||||
|
||||
val conditionExpression = lessThanEq(parameterName.makeRef(), end.reference())
|
||||
val incrementExpression = addAssign(parameterName.makeRef(), increment.reference())
|
||||
|
||||
context.addStatementToCurrentBlock(temporariesInitialization(rangeExpression, start, end, increment).makeStmt())
|
||||
return JsFor(initExpression, conditionExpression, incrementExpression, body)
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(rangeExpression.assignmentExpression()))
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(start.assignmentExpression()))
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(end.assignmentExpression()))
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(increment.assignmentExpression()))
|
||||
|
||||
return if (parameterIsTemporary) {
|
||||
JsFor(assignment(parameterName.makeRef(), start.reference()), conditionExpression, incrementExpression, body)
|
||||
}
|
||||
else {
|
||||
JsFor(newVar(parameterName, start.reference()), conditionExpression, incrementExpression, body)
|
||||
}
|
||||
}
|
||||
|
||||
fun translateForOverArray(): JsStatement {
|
||||
@@ -204,11 +217,12 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
|
||||
|
||||
val arrayAccess = JsArrayAccess(rangeExpression.reference(), index.reference())
|
||||
val body = translateBody(arrayAccess)
|
||||
val initExpression = newVar(index.name(), context.program().getNumberLiteral(0))
|
||||
val initExpression = assignment(index.name().makeRef(), context.program().getNumberLiteral(0))
|
||||
val conditionExpression = inequality(index.reference(), end.reference())
|
||||
val incrementExpression = JsPrefixOperation(JsUnaryOperator.INC, index.reference())
|
||||
|
||||
context.addStatementToCurrentBlock(temporariesInitialization(rangeExpression, end).makeStmt())
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(rangeExpression.assignmentExpression()))
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(end.assignmentExpression()))
|
||||
return JsFor(initExpression, conditionExpression, incrementExpression, body)
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.js.translate.expression;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*;
|
||||
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
|
||||
@@ -57,9 +58,12 @@ public final class WhenTranslator extends AbstractTranslator {
|
||||
KtExpression subject = expression.getSubjectExpression();
|
||||
if (subject != null) {
|
||||
JsExpression subjectExpression = Translation.translateAsExpression(subject, context);
|
||||
if (TranslationUtils.isCacheNeeded(subjectExpression)) {
|
||||
if (!JsAstUtils.isEmptyExpression(subjectExpression)) {
|
||||
TemporaryVariable subjectVar = context.declareTemporary(null);
|
||||
context.addStatementToCurrentBlock(JsAstUtils.assignment(subjectVar.reference(), subjectExpression).makeStmt());
|
||||
JsExpressionStatement subjectAssignment = new JsExpressionStatement(
|
||||
JsAstUtils.assignment(subjectVar.reference(), subjectExpression));
|
||||
MetadataProperties.setSynthetic(subjectAssignment, true);
|
||||
context.addStatementToCurrentBlock(subjectAssignment);
|
||||
subjectExpression = subjectVar.reference();
|
||||
}
|
||||
expressionToMatch = subjectExpression;
|
||||
|
||||
@@ -302,6 +302,12 @@ public final class JsAstUtils {
|
||||
return new JsBinaryOperation(JsBinaryOperator.ASG, left, right);
|
||||
}
|
||||
|
||||
public static JsStatement asSyntheticStatement(@NotNull JsExpression expression) {
|
||||
JsExpressionStatement statement = new JsExpressionStatement(expression);
|
||||
MetadataProperties.setSynthetic(statement, true);
|
||||
return statement;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Pair<JsExpression, JsExpression> decomposeAssignment(@NotNull JsExpression expr) {
|
||||
if (!(expr instanceof JsBinaryOperation)) return null;
|
||||
|
||||
Reference in New Issue
Block a user