Chromium Code Reviews| Index: lib/compiler/implementation/ssa/codegen.dart |
| =================================================================== |
| --- lib/compiler/implementation/ssa/codegen.dart (revision 8089) |
| +++ lib/compiler/implementation/ssa/codegen.dart (working copy) |
| @@ -141,23 +141,19 @@ |
| static final int TYPE_EXPRESSION = 1; |
| static final int TYPE_DECLARATION = 2; |
| - static final String TEMPORARY_PREFIX = 't'; |
| - |
| final JavaScriptBackend backend; |
| final WorkItem work; |
| final StringBuffer buffer; |
| final String parameters; |
| - final Map<Element, String> parameterNames; |
| - final Map<int, String> names; |
| - final Set<String> usedNames; |
| - final Set<HInstruction> declaredInstructions; |
| - final Map<String, int> prefixes; |
| + final Set<String> declaredVariables; |
|
Lasse Reichstein Nielsen
2012/05/31 08:24:56
Can you add a doc-comment describing what this mea
ngeoffray
2012/05/31 08:48:22
Done.
|
| final Set<HInstruction> generateAtUseSite; |
| final Map<HPhi, String> logicalOperations; |
| final Map<Element, ElementAction> breakAction; |
| final Map<Element, ElementAction> continueAction; |
| - final Equivalence<HPhi> phiEquivalence; |
| + final List<String> delayedVariablesDeclaration; |
| + final Map<Element, String> parameterNames; |
| + VariableNames variableNames; |
|
Lasse Reichstein Nielsen
2012/05/31 08:24:56
And this one too, to explain the difference from t
ngeoffray
2012/05/31 08:48:22
Done.
|
| Element equalsNullElement; |
| Element boolifiedEqualsNullElement; |
| @@ -174,7 +170,6 @@ |
| * While generating expressions, we can't insert variable declarations. |
| * Instead we declare them at the end of the function |
|
floitsch
2012/05/30 18:45:03
Move this comment too.
ngeoffray
2012/05/31 08:12:46
Done.
|
| */ |
| - Link<String> delayedVarDecl = const EmptyLink<String>(); |
| HBasicBlock currentBlock; |
| // Records a block-information that is being handled specially. |
| @@ -197,25 +192,15 @@ |
| this.work, |
| this.parameters, |
| this.parameterNames) |
| - : names = new Map<int, String>(), |
| - prefixes = new Map<String, int>(), |
| - usedNames = new Set<String>(), |
| - declaredInstructions = new Set<HInstruction>(), |
| + : declaredVariables = new Set<String>(), |
| + delayedVariablesDeclaration = new List<String>(), |
| buffer = new StringBuffer(), |
| generateAtUseSite = new Set<HInstruction>(), |
| logicalOperations = new Map<HPhi, String>(), |
| breakAction = new Map<Element, ElementAction>(), |
| continueAction = new Map<Element, ElementAction>(), |
| - phiEquivalence = new Equivalence<HPhi>(), |
| unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { |
| - for (final name in parameterNames.getValues()) { |
| - prefixes[name] = 0; |
| - } |
| - |
| - // Create a namespace for temporaries. |
| - prefixes[TEMPORARY_PREFIX] = 0; |
| - |
| Interceptors interceptors = backend.builder.interceptors; |
| equalsNullElement = interceptors.getEqualsNullInterceptor(); |
| boolifiedEqualsNullElement = |
| @@ -258,7 +243,16 @@ |
| new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); |
| new SsaConditionMerger(generateAtUseSite, |
| logicalOperations).visitGraph(graph); |
| - new PhiEquivalator(phiEquivalence, logicalOperations).analyzeGraph(graph); |
| + SsaLiveIntervalBuilder intervalBuilder = |
|
floitsch
2012/05/30 18:45:03
new SsaLiveIntervalBuilder(compiler).visitGraph(gr
ngeoffray
2012/05/31 08:12:46
No, I need the object to take its liveInstructions
Lasse Reichstein Nielsen
2012/05/31 08:24:56
It's also used below.
|
| + new SsaLiveIntervalBuilder(compiler); |
| + intervalBuilder.visitGraph(graph); |
| + SsaVariableAllocator allocator = new SsaVariableAllocator( |
| + compiler, |
| + intervalBuilder.liveInstructions, |
| + intervalBuilder.liveIntervals, |
| + generateAtUseSite); |
| + allocator.visitGraph(graph); |
| + variableNames = allocator.names; |
| } |
| visitGraph(HGraph graph) { |
| @@ -268,14 +262,9 @@ |
| subGraph = new SubGraph(graph.entry, graph.exit); |
| beginGraph(graph); |
| visitBasicBlock(graph.entry); |
| - if (!delayedVarDecl.isEmpty()) { |
| + if (!delayedVariablesDeclaration.isEmpty()) { |
| addIndented("var "); |
| - while (true) { |
| - buffer.add(delayedVarDecl.head); |
| - delayedVarDecl = delayedVarDecl.tail; |
| - if (delayedVarDecl.isEmpty()) break; |
| - buffer.add(", "); |
| - } |
| + buffer.add(Strings.join(delayedVariablesDeclaration, ', ')); |
| buffer.add(";\n"); |
| } |
| endGraph(graph); |
| @@ -413,60 +402,6 @@ |
| generateExpression(condition); |
| } |
| - String temporary(HInstruction instruction) { |
| - int id = instruction.id; |
| - String name = names[id]; |
| - if (name !== null) return name; |
| - |
| - String prefix = TEMPORARY_PREFIX; |
| - if (instruction.sourceElement !== null) { |
| - Element element = instruction.sourceElement; |
| - if (element !== null && !element.name.isEmpty()) { |
| - prefix = element.name.slowToString(); |
| - // Special case the variable named [TEMPORARY_PREFIX] to allow |
| - // keeping its name. |
| - if (prefix == TEMPORARY_PREFIX && !usedNames.contains(prefix)) { |
| - return newName(id, prefix); |
| - } |
| - // If we've never seen that prefix before, try to use it |
| - // directly. |
| - if (!prefixes.containsKey(prefix)) { |
| - // Make sure the variable name does not conflict with our mangling. |
| - while (usedNames.contains(prefix)) { |
| - prefix = '${prefix}_'; |
| - } |
| - prefixes[prefix] = 0; |
| - return newName(id, prefix); |
| - } |
| - } |
| - } |
| - |
| - name = '${prefix}${prefixes[prefix]++}'; |
| - while (usedNames.contains(name)) { |
| - name = '${prefix}${prefixes[prefix]++}'; |
| - } |
| - return newName(id, name); |
| - } |
| - |
| - // TODO(floitsch): share more code with [temporary]. |
| - String freshTemporary() { |
| - String prefix = TEMPORARY_PREFIX; |
| - String name = '${prefix}${prefixes[prefix]++}'; |
| - while (usedNames.contains(name)) { |
| - name = '${prefix}${prefixes[prefix]++}'; |
| - } |
| - String result = JsNames.getValid(name); |
| - usedNames.add(result); |
| - return result; |
| - } |
| - |
| - String newName(int id, String name) { |
| - String result = JsNames.getValid(name); |
| - names[id] = result; |
| - usedNames.add(result); |
| - return result; |
| - } |
| - |
| /** |
| * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET]. |
| */ |
| @@ -502,8 +437,7 @@ |
| */ |
| void addExpressionSeparator() { |
| if (generationState == STATE_FIRST_DECLARATION) { |
| - buffer.add("var "); |
| - generationState = STATE_DECLARATION; |
| + return; |
|
kasperl
2012/05/31 05:26:03
Maybe change the structure so that you check for S
ngeoffray
2012/05/31 08:12:46
Done.
Lasse Reichstein Nielsen
2012/05/31 08:24:56
Why this change?
Where do you change the state to
ngeoffray
2012/05/31 08:48:22
In declareVariable line 454. I need this change be
|
| } else if (generationState == STATE_FIRST_EXPRESSION) { |
| generationState = STATE_EXPRESSION; |
| } else { |
| @@ -511,59 +445,35 @@ |
| } |
| } |
| + bool isVariableDeclared(String variableName) { |
| + return declaredVariables.contains(variableName); |
| + } |
| + |
| void declareVariable(String variableName) { |
| if (isGeneratingExpression()) { |
| - buffer.add(variableName); |
| - if (!isGeneratingDeclaration()) { |
| - delayedVarDecl = delayedVarDecl.prepend(variableName); |
| + if (generationState == STATE_FIRST_DECLARATION) { |
| + generationState = STATE_DECLARATION; |
| + if (!isVariableDeclared(variableName)) { |
| + declaredVariables.add(variableName); |
| + buffer.add("var "); |
|
floitsch
2012/05/30 18:45:03
The 'var' is emitted conditionally. This means tha
ngeoffray
2012/05/31 08:12:46
After the first declaration we must go into STATE_
|
| + } |
| + } else if (!isGeneratingDeclaration() |
| + && !isVariableDeclared(variableName)) { |
| + delayedVariablesDeclaration.add(variableName); |
| } |
| - } else { |
| + } else if (!isVariableDeclared(variableName)) { |
| + declaredVariables.add(variableName); |
| buffer.add("var "); |
| - buffer.add(variableName); |
| } |
| + buffer.add(variableName); |
| } |
| void declareInstruction(HInstruction instruction) { |
| - declaredInstructions.add(instruction); |
| - String name = temporary(instruction); |
| - declareVariable(name); |
| + declareVariable(variableNames.getName(instruction)); |
| } |
| - bool needsNewVariable(HInstruction instruction) { |
| - bool needsVar = !instruction.usedBy.isEmpty(); |
| - if (needsVar && instruction is HCheck) { |
| - HCheck check = instruction; |
| - HInstruction input = check.checkedInput; |
| - // We only need a new var if [input] is generated at use site |
| - // but is not a trivial code motion invariant instruction like |
| - // for parameters or this. |
| - // |
| - // For example: |
| - // Foo a = this; |
| - // print(a); |
| - // print(a); |
| - // |
| - // In checked mode no new variable is needed. |
| - // FooTypeCheck(this); |
| - // print(this); |
| - // print(this); |
| - // |
| - // But for this example: |
| - // Foo a = foo(); |
| - // print(a); |
| - // print(a); |
| - // |
| - // We need a new variable: |
| - // var a = FooTypeCheck(foo()); |
| - // print(a); |
| - // print(a); |
| - needsVar = isGenerateAtUseSite(input) && !input.isCodeMotionInvariant(); |
| - } |
| - return needsVar; |
| - } |
| - |
| void define(HInstruction instruction) { |
| - if (needsNewVariable(instruction)) { |
| + if (instruction is !HCheck && variableNames.hasName(instruction)) { |
| declareInstruction(instruction); |
| buffer.add(" = "); |
| visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| @@ -573,70 +483,13 @@ |
| } |
| void use(HInstruction argument, int expectedPrecedenceForArgument) { |
| - if (argument is HCheck) { |
| - HCheck instruction = argument; |
| - HInstruction input = instruction.checkedInput; |
| - if (isGenerateAtUseSite(argument) && isGenerateAtUseSite(input)) { |
| - // If both instructions can be generated at use site, we can |
| - // just visit [argument]. |
| - // |
| - // For example: |
| - // Foo a = foo(); |
| - // print(a); |
| - // |
| - // In checked mode will turn into: |
| - // print(FooTypeCheck(foo())); |
| - visit(argument, expectedPrecedenceForArgument); |
| - } else if (isGenerateAtUseSite(input)) { |
| - // Get the real input of that checked instruction. |
| - while (input is HCheck) { |
| - HCheck check = input; |
| - input = check.checkedInput; |
| - } |
| - |
| - // If [argument] cannot be generated at use site, but [input] |
| - // can, use the temporary of [argument]. A code motion |
| - // invariant instruction does not have a temporary, so we just |
| - // |
| - // For example: |
| - // Foo a = foo(); |
| - // print(a); |
| - // print(a); |
| - // |
| - // In checked mode will turn into: |
| - // var a = FooTypeCheck(foo()); |
| - // print(a); |
| - // print(a); |
| - // |
| - // Note that in case the input is code motion invariant, like |
| - // for parameters or this, we just need to visit it, since |
| - // there is no temporary for such instruction. |
| - if (input.isCodeMotionInvariant()) { |
| - visit(input, expectedPrecedenceForArgument); |
| - } else { |
| - buffer.add(temporary(argument)); |
| - } |
| - } else { |
| - // Otherwise we just use [input]. [argument] has already been |
| - // emitted, and we just need the temporary of [input]. |
| - // |
| - // For example: |
| - // var a = foo(); |
| - // print(a); |
| - // Foo b = a; |
| - // print(b); |
| - // |
| - // In checked mode will turn into: |
| - // var a = foo(); |
| - // print(a); |
| - // FooTypeCheck(a); |
| - // print(a); |
| - use(input, expectedPrecedenceForArgument); |
| - } |
| - } else if (isGenerateAtUseSite(argument)) { |
| + if (isGenerateAtUseSite(argument)) { |
| visit(argument, expectedPrecedenceForArgument); |
| + } else if (argument is HCheck) { |
| + HCheck check = argument; |
| + use(argument.checkedInput, expectedPrecedenceForArgument); |
| } else { |
| - buffer.add(temporary(argument)); |
| + buffer.add(variableNames.getName(argument)); |
| } |
| } |
| @@ -724,7 +577,7 @@ |
| if (info.catchBlock !== null) { |
| // Printing the catch part. |
| HParameterValue exception = info.catchVariable; |
| - String name = temporary(exception); |
| + String name = variableNames.getName(exception); |
| parameterNames[exception.element] = name; |
| buffer.add(' catch ($name) {\n'); |
| indent++; |
| @@ -1025,135 +878,117 @@ |
| iterateBasicBlock(node); |
| } |
| - /** Generates the assignments for all phis of successors blocks. */ |
| - void assignPhisOfAllSuccessors(HBasicBlock node) { |
| - Map<HInstruction, String> temporaryNamesOfPhis = null; |
| + void emitAssignment(String source, String destination) { |
| + if (isGeneratingExpression()) { |
| + addExpressionSeparator(); |
| + } else { |
| + addIndentation(); |
| + } |
| + declareVariable(destination); |
| + buffer.add(' = $source'); |
| + if (!isGeneratingExpression()) { |
| + buffer.add(';\n'); |
| + } |
| + } |
| - /** |
| - * Generates the assignment [canonicalPhi] = [value]. |
| - * |
| - * If the [canonicalPhi] has a temporary name (in [temporaryNamesOfPhis]) |
| - * then the temporary is assigned instead of the [canonicalPhi]. However, |
| - * when the left and right-hand side are equal ([:canonicalPhi === value:]) |
| - * then the [canonicalPhi] is assigned with the temporary. |
| - */ |
| - void generateAssignment(HPhi canonicalPhi, HInstruction value) { |
| - if (isGeneratingExpression()) { |
| - addExpressionSeparator(); |
| - } else { |
| - addIndentation(); |
| + /** |
| + * Sequentialize a list of parallel copies. |
|
Lasse Reichstein Nielsen
2012/05/31 08:24:56
Describe which criteria are being used to do the o
ngeoffray
2012/05/31 08:48:22
Added the 'conceptually'. As discussed, kept the '
|
| + */ |
| + void sequentializeCopies(List<Copy> copies) { |
| + // Map to keep track of the current location of a variable. |
| + Map<String, String> currentLocation = new Map<String, String>(); |
|
Lasse Reichstein Nielsen
2012/05/31 08:24:56
What is a "location" here?
ngeoffray
2012/05/31 08:48:22
It is a variable. It really is "the variable that
|
| + |
| + // Map to keep track of the initial value of a variable. |
| + Map<String, String> initialValue = new Map<String, String>(); |
| + |
| + // List of variables to assign a value. |
| + List<String> todo = <String>[]; |
|
Lasse Reichstein Nielsen
2012/05/31 08:24:56
"todo" -> "worklist".
ngeoffray
2012/05/31 08:48:22
Done.
|
| + |
| + // List of variables that we can assign a value to (ie are not |
|
Lasse Reichstein Nielsen
2012/05/31 08:24:56
Describe which criteria are being used to do the o
ngeoffray
2012/05/31 08:48:22
Done.
|
| + // being used anymore). |
| + List<String> ready = <String>[]; |
| + |
| + // Prune [copies] by removing self-copies. |
| + List<Copy> prunedCopies = <Copy>[]; |
| + for (Copy copy in copies) { |
| + String sourceName = variableNames.getName(copy.source); |
| + String destinationName = variableNames.getName(copy.destination); |
| + if (sourceName != destinationName) { |
| + prunedCopies.add(new Copy(sourceName, destinationName)); |
| } |
| - if (temporaryNamesOfPhis !== null && |
| - canonicalPhi !== value && |
| - temporaryNamesOfPhis.containsKey(canonicalPhi)) { |
| - // This is the assignment to the temporary. |
| - declareVariable(temporaryNamesOfPhis[canonicalPhi]); |
| - } else if (!declaredInstructions.contains(canonicalPhi)) { |
| - declareInstruction(canonicalPhi); |
| - } else { |
| - buffer.add(temporary(canonicalPhi)); |
| - } |
| - buffer.add(" = "); |
| - bool isLogicalOperation = logicalOperations.containsKey(canonicalPhi); |
| - if (isLogicalOperation) { |
| - emitLogicalOperation(canonicalPhi, logicalOperations[canonicalPhi]); |
| - } else if (canonicalPhi === value) { |
| - buffer.add(temporaryNamesOfPhis[value]); |
| - } else { |
| - use(value, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| - } |
| - if (!isGeneratingExpression()) { |
| - buffer.add(';\n'); |
| - } |
| } |
| + copies = prunedCopies; |
| - // Assignments are delayed so that we don't overwrite phis that might |
| - // be used as inputs. |
| - // TODO(floitsch): improve phi assignments. Currently we introduce |
| - // way too many temporary variables. |
| - Map<HPhi, HInstruction> phiAssignments = new Map<HPhi, HInstruction>(); |
| - for (HBasicBlock successor in node.successors) { |
| - int index = successor.predecessors.indexOf(node); |
| - successor.forEachPhi((HPhi phi) { |
| - bool isLogicalOperation = logicalOperations.containsKey(phi); |
| - // In case the phi is being generated by another |
| - // instruction. |
| - if (isLogicalOperation && isGenerateAtUseSite(phi)) return; |
| - HPhi canonicalPhi = phiEquivalence.getRepresentative(phi); |
| - assert(!isLogicalOperation || canonicalPhi === phi); |
| - HInstruction input = phi.inputs[index]; |
| - if (input is HPhi) { |
| - input = phiEquivalence.getRepresentative(input); |
| - // If we use the same variable, we don't need to create an |
| - // assignment. |
| - if (input === canonicalPhi) { |
| - assert(!isLogicalOperation); |
| - return; |
| - } |
| - } |
| - phiAssignments[canonicalPhi] = input; |
| - }); |
| + // For each copy, set the current location of the source to |
| + // itself, and the initial value of the destination to the source. |
| + // Add the destination to the list of copies to make. |
| + for (Copy copy in copies) { |
| + currentLocation[copy.source] = copy.source; |
| + initialValue[copy.destination] = copy.source; |
| + todo.add(copy.destination); |
| } |
| - Set<HPhi> inputPhis = new Set<HPhi>(); |
| - List<HPhi> phis = <HPhi>[]; |
| + // For each copy, if the destination does not have a current |
| + // location, then we can safely assign to it. |
| + for (Copy copy in copies) { |
| + if (currentLocation[copy.destination] === null) { |
| + ready.add(copy.destination); |
| + } |
| + } |
| - /** |
| - * Transitively collects the phis that are used when emitting the [input] |
| - * and adds them to [inputPhis]. Does not add phis that are equal to the |
| - * [targetPhi] or are not in the [phiAssignments] map. |
| - */ |
| - void collectInputPhis(HInstruction input, HPhi targetPhi) { |
| - if (input is HPhi) { |
| - HPhi canonicalPhi = phiEquivalence.getRepresentative(input); |
| - // Self-updates are ok. |
| - if (canonicalPhi !== targetPhi && |
| - phiAssignments.containsKey(canonicalPhi)) { |
| - inputPhis.add(canonicalPhi); |
| + while (!todo.isEmpty()) { |
| + while (!ready.isEmpty()) { |
| + String destination = ready.removeLast(); |
| + String source = initialValue[destination]; |
| + // Since [source] might have been updated, use the current |
| + // location of [source] |
| + String copy = currentLocation[source]; |
| + emitAssignment(copy, destination); |
|
floitsch
2012/05/30 18:45:03
I find it easier to read if the arguments are inve
ngeoffray
2012/05/31 08:12:46
Done.
|
| + // Now [destination] is the current location of [source]. |
| + currentLocation[source] = destination; |
| + // If [source] hasn't been updated and needs to have a value, |
| + // add it to the list of variables that can be updated. Copies |
| + // of [source] will now use [destination]. |
| + if (source == copy && initialValue[source] !== null) { |
| + ready.add(source); |
| } |
| - } else if (isGenerateAtUseSite(input)) { |
| - for (HInstruction inputOfInput in input.inputs) { |
| - collectInputPhis(inputOfInput, targetPhi); |
| - } |
| } |
| + |
| + // Check if we have a cycle. |
| + String current = todo.removeLast(); |
| + // If [current] is the source of a copy, and the current |
| + // location of its initial value is not itself, then there is a |
| + // cycle that we break by using a temporary name. |
| + if (currentLocation[current] !== null |
|
floitsch
2012/05/30 18:45:03
Is this test necessary?
Clearly: current == curre
ngeoffray
2012/05/31 08:12:46
Yes, it is. Because I don't remove a variable that
|
| + && current != currentLocation[initialValue[current]]) { |
| + String tempName = VariableNames.SWAP_TEMP; |
| + emitAssignment(current, tempName); |
| + currentLocation[current] = tempName; |
| + // [current] can now be safely updated. Copies of [current] |
| + // will now use [tempName]. |
| + ready.add(current); |
| + } |
| } |
| + } |
| - phiAssignments.forEach((HPhi targetPhi, HInstruction input) { |
| - phis.add(targetPhi); |
| - collectInputPhis(input, targetPhi); |
| - }); |
| + void assignPhisOfSuccessors(HBasicBlock node) { |
| + CopyHandler handler = variableNames.getCopies(node); |
| + if (handler == null) return; |
| - if (inputPhis.isEmpty()) { |
| - phiAssignments.forEach(generateAssignment); |
| - } else { |
| - // Emit the phiX=phiY assignments, taking care to break cycles. |
| - // Example program: |
| - // var x = 499; |
| - // var y = 99; |
| - // while (x != 99) { |
| - // var tmp = x; // <=== The tmp variable is removed in Ssa-form. |
| - // x = y; |
| - // y = tmp; |
| - // } |
| - // |
| - temporaryNamesOfPhis = new HashMap<HInstruction, String>(); |
| - // For phis that are used as inputs simply *always* allocate a |
| - // temporary. |
| - for (HPhi phi in phis) { |
| - if (inputPhis.contains(phi)) { |
| - String temporaryPhi = freshTemporary(); |
| - temporaryNamesOfPhis[phi] = temporaryPhi; |
| - } |
| - // The assignPhi uses temporary variables for the left-hand side if |
| - // they exist. |
| - generateAssignment(phi, phiAssignments[phi]); |
| + sequentializeCopies(handler.copies); |
| + |
| + for (Copy copy in handler.assignments) { |
| + if (isGeneratingExpression()) { |
| + addExpressionSeparator(); |
| + } else { |
| + addIndentation(); |
| } |
| - // Finally assign the input phis. |
| - for (HPhi phi in inputPhis) { |
| - // The assignPhi special-cases phi assignments to itself and recognizes |
| - // it as assignment from the temporary variable to the actual phi. |
| - generateAssignment(phi, phi); |
| + declareVariable(variableNames.getName(copy.destination)); |
| + buffer.add(' = '); |
| + use(copy.source, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| + if (!isGeneratingExpression()) { |
| + buffer.add(';\n'); |
| } |
| } |
| } |
| @@ -1162,7 +997,7 @@ |
| HInstruction instruction = node.first; |
| while (instruction != null) { |
| if (instruction === node.last) { |
| - assignPhisOfAllSuccessors(node); |
| + assignPhisOfSuccessors(node); |
| } |
| if (isGenerateAtUseSite(instruction)) { |
| @@ -1591,11 +1426,6 @@ |
| buffer.add('.'); |
| buffer.add(name); |
| } else { |
| - // TODO(ngeoffray): Remove the 'var' once we don't globally box |
| - // variables used in a try/catch. |
| - if (!isGeneratingExpression()) { |
| - buffer.add('var '); |
| - } |
| use(node.receiver, JSPrecedence.EXPRESSION_PRECEDENCE); |
| } |
| buffer.add(' = '); |
| @@ -1744,11 +1574,7 @@ |
| visitParameterValue(HParameterValue node) { |
| assert(isGenerateAtUseSite(node)); |
| - if (parameterNames[node.element] == null) { |
| - buffer.add(temporary(node)); |
| - } else { |
| - buffer.add(parameterNames[node.element]); |
| - } |
| + buffer.add(variableNames.getName(node)); |
| } |
| visitPhi(HPhi node) { |
| @@ -1756,8 +1582,7 @@ |
| if (operation !== null) { |
| emitLogicalOperation(node, operation); |
| } else { |
| - HPhi canonicalPhi = phiEquivalence.getRepresentative(node); |
| - buffer.add('${temporary(canonicalPhi)}'); |
| + buffer.add('${variableNames.getName(node)}'); |
| } |
| } |
| @@ -2480,7 +2305,7 @@ |
| int i = 0; |
| for (HInstruction input in node.inputs) { |
| HInstruction instruction = unwrap(input); |
| - setup.add(' ${temporary(instruction)} = env$i;\n'); |
| + setup.add(' ${variableNames.getName(instruction)} = env$i;\n'); |
| i++; |
| } |
| if (i > maxBailoutParameters) maxBailoutParameters = i; |