Introduced the cache of temporary variables and expressions.

Used the cached temporary variables in SafeCall and SureCall instead create a new temporary variable.
This commit is contained in:
Zalim Bashorov
2013-06-15 15:55:10 +04:00
parent ee5c7c8f5c
commit a69744e6fb
7 changed files with 52 additions and 12 deletions
@@ -63,7 +63,7 @@ public final class DynamicContext {
JsName temporaryName = currentScope.declareTemporary();
vars.add(new JsVar(temporaryName, null));
return new TemporaryVariable(temporaryName, initExpression);
return TemporaryVariable.create(temporaryName, initExpression);
}
@NotNull
@@ -24,14 +24,19 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.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));
}
@Nullable
private final JsExpression assignmentExpression;
@NotNull
private final JsName variableName;
/*package*/ TemporaryVariable(@NotNull JsName temporaryName, @Nullable JsExpression initExpression) {
protected TemporaryVariable(@NotNull JsName temporaryName, @Nullable JsExpression assignmentExpression) {
this.variableName = temporaryName;
this.assignmentExpression = initExpression == null ? null : JsAstUtils.assignment(variableName.makeRef(), initExpression);
this.assignmentExpression = assignmentExpression;
}
@NotNull
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.translate.expression.LiteralFunctionTranslator;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
import java.util.HashMap;
import java.util.Map;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForElement;
@@ -53,6 +54,8 @@ public class TranslationContext {
rootDynamicContext, rootAliasingContext);
}
private final HashMap<JsExpression, TemporaryConstVariable> expressionToTempConstVariableCache = new HashMap<JsExpression, TemporaryConstVariable>();
public boolean isEcma5() {
return staticContext.isEcma5();
}
@@ -177,6 +180,27 @@ public class TranslationContext {
return dynamicContext.declareTemporary(initExpression);
}
@NotNull
public TemporaryConstVariable getOrDeclareTemporaryConstVariable(@NotNull JsExpression expression) {
TemporaryConstVariable tempVar = expressionToTempConstVariableCache.get(expression);
if (tempVar == null) {
TemporaryVariable tmpVar = declareTemporary(expression);
tempVar = new TemporaryConstVariable(tmpVar.name(), tmpVar.assignmentExpression());
expressionToTempConstVariableCache.put(expression, tempVar);
expressionToTempConstVariableCache.put(tmpVar.assignmentExpression(), tempVar);
}
return tempVar;
}
public void associateExpressionToLazyValue(JsExpression expression, TemporaryConstVariable temporaryConstVariable) {
assert expression == temporaryConstVariable.assignmentExpression();
expressionToTempConstVariableCache.put(expression, temporaryConstVariable);
}
@NotNull
public Namer namer() {
return staticContext.getNamer();
@@ -21,7 +21,7 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import org.jetbrains.k2js.translate.reference.CallType;
@@ -58,8 +58,14 @@ public final class UnaryOperationTranslator {
@NotNull
private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) {
TemporaryVariable cachedValue = context.declareTemporary(translateAsExpression(getBaseExpression(expression), context));
return new JsConditional(isNotNullCheck(cachedValue.assignmentExpression()), cachedValue.reference(), context.namer().throwNPEFunctionCall());
JsExpression translatedExpression = translateAsExpression(getBaseExpression(expression), context);
TemporaryConstVariable tempVar = context.getOrDeclareTemporaryConstVariable(translatedExpression);
JsConditional ensureNotNull = new JsConditional(isNotNullCheck(tempVar.value()), tempVar.value(), context.namer().throwNPEFunctionCall());
// associate (cache) ensureNotNull expression to new LazyValue with same name.
context.associateExpressionToLazyValue(ensureNotNull, new TemporaryConstVariable(tempVar.name(), ensureNotNull));
return ensureNotNull;
}
@NotNull
@@ -31,7 +31,7 @@ import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.calls.model.VarargValueArgument;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
@@ -57,7 +57,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
private final boolean isNativeFunctionCall;
private boolean hasSpreadOperator = false;
private TemporaryVariable cachedReceiver = null;
private TemporaryConstVariable cachedReceiver = null;
private List<JsExpression> translatedArguments = null;
private JsExpression translatedReceiver = null;
private JsExpression translatedCallee = null;
@@ -172,7 +172,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
}
if (receiver != null) {
cachedReceiver = context().declareTemporary(receiver);
cachedReceiver = context().getOrDeclareTemporaryConstVariable(receiver);
result.add(0, cachedReceiver.reference());
}
else {
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNotNullCheck;
@@ -36,8 +36,9 @@ public enum CallType {
JsExpression constructCall(@Nullable JsExpression receiver, @NotNull CallConstructor constructor,
@NotNull TranslationContext context) {
assert receiver != null;
TemporaryVariable cachedValue = context.declareTemporary(receiver);
return new JsConditional(isNotNullCheck(cachedValue.assignmentExpression()), constructor.construct(cachedValue.reference()), JsLiteral.NULL);
TemporaryConstVariable tempVar = context.getOrDeclareTemporaryConstVariable(receiver);
return new JsConditional(isNotNullCheck(tempVar.value()), constructor.construct(tempVar.value()), JsLiteral.NULL);
}
},
//TODO: bang qualifier is not implemented in frontend for now
@@ -85,5 +85,9 @@ fun box(): String {
if (!(testCallOrder(1, 2, 3, 4)))
return "failed when test calling order when using spread operator without args"
val baz: Bar? = Bar(1)
if (!(baz!!)?.test(0, 1, 1))
return "failed when combined SureCall and SafeCall, maybe we lost cached expression"
return "OK"
}