| Index: lib/compiler/implementation/ssa/codegen.dart
|
| ===================================================================
|
| --- lib/compiler/implementation/ssa/codegen.dart (revision 8141)
|
| +++ lib/compiler/implementation/ssa/codegen.dart (working copy)
|
| @@ -141,24 +141,34 @@
|
| 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<HInstruction> generateAtUseSite;
|
| final Map<HPhi, String> logicalOperations;
|
| final Map<Element, ElementAction> breakAction;
|
| final Map<Element, ElementAction> continueAction;
|
| - final Equivalence<HPhi> phiEquivalence;
|
| + final Map<Element, String> parameterNames;
|
|
|
| + /**
|
| + * Contains the names of the instructions, as well as the parallel
|
| + * copies to perform on block transitioning.
|
| + */
|
| + VariableNames variableNames;
|
| +
|
| + /**
|
| + * While generating expressions, we can't insert variable declarations.
|
| + * Instead we declare them at the end of the function
|
| + */
|
| + final List<String> delayedVariablesDeclaration;
|
| +
|
| + /**
|
| + * Set of variables that have already been declared.
|
| + */
|
| + final Set<String> declaredVariables;
|
| +
|
| Element equalsNullElement;
|
| Element boolifiedEqualsNullElement;
|
| int indent = 0;
|
| @@ -170,11 +180,6 @@
|
| * instead of a sequence of statements.
|
| */
|
| int generationState = STATE_STATEMENT;
|
| - /**
|
| - * While generating expressions, we can't insert variable declarations.
|
| - * Instead we declare them at the end of the function
|
| - */
|
| - Link<String> delayedVarDecl = const EmptyLink<String>();
|
| HBasicBlock currentBlock;
|
|
|
| // Records a block-information that is being handled specially.
|
| @@ -197,25 +202,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 +253,16 @@
|
| new SsaInstructionMerger(generateAtUseSite).visitGraph(graph);
|
| new SsaConditionMerger(generateAtUseSite,
|
| logicalOperations).visitGraph(graph);
|
| - new PhiEquivalator(phiEquivalence, logicalOperations).analyzeGraph(graph);
|
| + SsaLiveIntervalBuilder intervalBuilder =
|
| + 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 +272,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 +412,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].
|
| */
|
| @@ -501,69 +446,44 @@
|
| * Ensures that expressions are comma spearated.
|
| */
|
| void addExpressionSeparator() {
|
| - if (generationState == STATE_FIRST_DECLARATION) {
|
| - buffer.add("var ");
|
| - generationState = STATE_DECLARATION;
|
| - } else if (generationState == STATE_FIRST_EXPRESSION) {
|
| + if (generationState == STATE_FIRST_EXPRESSION) {
|
| generationState = STATE_EXPRESSION;
|
| - } else {
|
| + } else if (generationState != STATE_FIRST_DECLARATION) {
|
| buffer.add(", ");
|
| }
|
| + // If the state is [STATE_FIRST_DECLARATION] the potential
|
| + // declaration of the variable will be done by the instruction.
|
| }
|
|
|
| + 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 ");
|
| + }
|
| + } 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 +493,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 +587,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 +888,119 @@
|
| iterateBasicBlock(node);
|
| }
|
|
|
| - /** Generates the assignments for all phis of successors blocks. */
|
| - void assignPhisOfAllSuccessors(HBasicBlock node) {
|
| - Map<HInstruction, String> temporaryNamesOfPhis = null;
|
| + void emitAssignment(String destination, String source) {
|
| + 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 conceptually parallel copies. Parallel
|
| + * copies may contain cycles, that this method breaks.
|
| + */
|
| + void sequentializeCopies(List<Copy> copies) {
|
| + // Map to keep track of the current location (ie the variable that
|
| + // holds the initial value) of a variable.
|
| + Map<String, String> currentLocation = new Map<String, String>();
|
| +
|
| + // 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> worklist = <String>[];
|
| +
|
| + // List of variables that we can assign a value to (ie are not
|
| + // 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;
|
| + worklist.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 (!worklist.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(destination, copy);
|
| + // 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 = worklist.removeLast();
|
| + // If [current] is used as a source, and the assignment has been
|
| + // done, we are done with this variable. Otherwise there is a
|
| + // cycle that we break by using a temporary name.
|
| + if (currentLocation[current] !== null
|
| + && current != currentLocation[initialValue[current]]) {
|
| + String tempName = VariableNames.SWAP_TEMP;
|
| + emitAssignment(tempName, current);
|
| + 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.getCopyHandler(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 +1009,7 @@
|
| HInstruction instruction = node.first;
|
| while (instruction != null) {
|
| if (instruction === node.last) {
|
| - assignPhisOfAllSuccessors(node);
|
| + assignPhisOfSuccessors(node);
|
| }
|
|
|
| if (isGenerateAtUseSite(instruction)) {
|
| @@ -1591,11 +1438,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 +1586,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 +1594,7 @@
|
| if (operation !== null) {
|
| emitLogicalOperation(node, operation);
|
| } else {
|
| - HPhi canonicalPhi = phiEquivalence.getRepresentative(node);
|
| - buffer.add('${temporary(canonicalPhi)}');
|
| + buffer.add('${variableNames.getName(node)}');
|
| }
|
| }
|
|
|
| @@ -2480,7 +2317,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;
|
|
|