Chromium Code Reviews| Index: lib/compiler/implementation/ssa/codegen.dart |
| =================================================================== |
| --- lib/compiler/implementation/ssa/codegen.dart (revision 8532) |
| +++ lib/compiler/implementation/ssa/codegen.dart (working copy) |
| @@ -72,7 +72,6 @@ |
| String generateBailoutMethod(WorkItem work, HGraph graph) { |
| return measure(() { |
| compiler.tracer.traceGraph("codegen-bailout", graph); |
| - new SsaBailoutPropagator(compiler).visitGraph(graph); |
| Map<Element, String> parameterNames = getParameterNames(work); |
| String parameters = Strings.join(parameterNames.getValues(), ', '); |
| @@ -80,17 +79,9 @@ |
| backend, work, parameters, parameterNames); |
| codegen.visitGraph(graph); |
| - StringBuffer newParameters = new StringBuffer(); |
| - if (!parameterNames.isEmpty()) newParameters.add('$parameters, '); |
| - newParameters.add('state'); |
| - |
| - for (int i = 0; i < codegen.maxBailoutParameters; i++) { |
| - newParameters.add(', env$i'); |
| - } |
| - |
| - Element element = work.element; |
| String body = '${codegen.setup}${codegen.buffer}'; |
| - return buildJavaScriptFunction(element, newParameters.toString(), body); |
| + return buildJavaScriptFunction( |
| + work.element, codegen.newParameters.toString(), body); |
| }); |
| } |
| @@ -273,8 +264,8 @@ |
| currentGraph = graph; |
| indent++; // We are already inside a function. |
| subGraph = new SubGraph(graph.entry, graph.exit); |
| - beginGraph(graph); |
| - visitBasicBlock(graph.entry); |
| + HBasicBlock start = beginGraph(graph); |
| + visitBasicBlock(start); |
| if (!delayedVariableDeclarations.isEmpty()) { |
| addIndented("var "); |
| buffer.add(Strings.join( |
| @@ -2447,7 +2438,7 @@ |
| int maxBailoutParameters; |
| - void beginGraph(HGraph graph) {} |
| + HBasicBlock beginGraph(HGraph graph) => graph.entry; |
| void endGraph(HGraph graph) {} |
| void bailout(HTypeGuard guard, String reason) { |
| @@ -2471,17 +2462,13 @@ |
| } else { |
| buffer.add(namer.isolateBailoutAccess(element)); |
| } |
| - int parametersCount = parameterNames.length; |
| - buffer.add('($parameters'); |
| - if (parametersCount != 0) buffer.add(', '); |
| - buffer.add('${guard.state}'); |
| + buffer.add('(${guard.state}'); |
| // TODO(ngeoffray): try to put a variable at a deterministic |
| // location, so that multiple bailout calls put the variable at |
| // the same parameter index. |
| int i = 0; |
| - for (; i < guard.inputs.length; i++) { |
| - buffer.add(', '); |
| - use(guard.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| + for (; i < guard.sortedVariableNames.length; i++) { |
| + buffer.add(', ${guard.sortedVariableNames[i]}'); |
| } |
| // Make sure we call the bailout method with the number of |
| // arguments it expects. This avoids having the underlying |
| @@ -2591,14 +2578,20 @@ |
| class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { |
| final StringBuffer setup; |
| + final StringBuffer newParameters; |
| final List<String> labels; |
| int labelId = 0; |
| int maxBailoutParameters = 0; |
| + SsaBailoutPropagator propagator; |
| + HInstruction savedFirstInstruction; |
| + |
| SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames) |
| : super(backend, work, parameters, parameterNames), |
| setup = new StringBuffer(), |
| - labels = <String>[]; |
| + newParameters = new StringBuffer(), |
| + labels = <String>[] { |
|
kasperl
2012/06/12 12:18:40
Keep ;
ngeoffray
2012/06/12 12:28:18
Done.
|
| + } |
| String pushLabel() { |
| String label = 'L${labelId++}'; |
| @@ -2614,46 +2607,77 @@ |
| return labels.last(); |
| } |
| - void beginGraph(HGraph graph) { |
| - if (!graph.entry.hasGuards()) return; |
| - addIndented('switch (state) {\n'); |
| - indent++; |
| - addIndented('case 0:\n'); |
| - indent++; |
| + HBasicBlock beginGraph(HGraph graph) { |
| + propagator = new SsaBailoutPropagator( |
| + compiler, generateAtUseSite, variableNames); |
| + propagator.visitGraph(graph); |
| - // The setup phase of a bailout function sets up the environment for |
| - // each bailout target. Each bailout target will populate this |
| - // setup phase. It is put at the beginning of the function. |
| - setup.add(' switch (state) {\n'); |
| + if (propagator.hasComplexTypeGuards) { |
| + startBailoutSwitch(); |
| + |
| + // The setup phase of a bailout function sets up the environment for |
| + // each bailout target. Each bailout target will populate this |
| + // setup phase. It is put at the beginning of the function. |
| + setup.add(' switch (state) {\n'); |
| + } |
| + |
| + if (propagator.startGeneratingAt !== null) { |
| + return propagator.startGeneratingAt; |
| + } |
| + |
| + // We change the first instruction of the first guard to be the |
| + // guard. We will change it back in the call to [endGraph]. |
| + HBasicBlock block = propagator.firstTypeGuard.block; |
| + savedFirstInstruction = block.first; |
| + block.first = propagator.firstTypeGuard; |
| + return block; |
| } |
| void endGraph(HGraph graph) { |
| - if (!graph.entry.hasGuards()) return; |
| - indent--; // Close original case. |
| - indent--; |
| - addIndented('}\n'); // Close 'switch'. |
| - setup.add(' }\n'); |
| + // Restore the first instruction of the first guard. |
| + if (propagator.startGeneratingAt === null) { |
| + propagator.firstTypeGuard.block.first = savedFirstInstruction; |
| + } |
| + |
| + // TODO(ngeoffray): We could avoid generating the state at the |
| + // call site for non-complex bailout methods. |
| + newParameters.add('state'); |
| + |
| + if (!propagator.hasComplexTypeGuards) { |
| + for (String name in propagator.firstTypeGuard.sortedVariableNames) { |
| + newParameters.add(', $name'); |
| + } |
| + } else { |
| + for (int i = 0; i < maxBailoutParameters; i++) { |
| + newParameters.add(', env$i'); |
| + } |
| + indent--; // Close original case. |
| + indent--; |
| + addIndented('}\n'); // Close 'switch'. |
| + setup.add(' }\n'); |
| + } |
| } |
| bool visitAndOrInfo(HAndOrBlockInformation info) => false; |
| - bool visitIfInfo(HIfBlockInformation info) => false; |
| - bool visitLoopInfo(HLoopBlockInformation info) => false; |
| + |
| + bool visitIfInfo(HIfBlockInformation info) { |
| + if (info.thenGraph.start.hasGuards()) return false; |
| + if (info.elseGraph.start.hasGuards()) return false; |
| + return super.visitIfInfo(info); |
| + } |
| + |
| + bool visitLoopInfo(HLoopBlockInformation info) { |
| + if (info.start.hasGuards()) return false; |
| + if (info.loopHeader.hasGuards()) return false; |
| + return super.visitLoopInfo(info); |
| + } |
| + |
| bool visitTryInfo(HTryBlockInformation info) => false; |
| bool visitSequenceInfo(HStatementSequenceInformation info) => false; |
| - // If argument is a [HCheck] and it does not have a name, we try to |
| - // find the name of its checked input. Note that there must be a |
| - // name, otherwise the instruction would not be in the live |
| - // environment. |
| - HInstruction unwrap(argument) { |
| - while (argument is HCheck && !variableNames.hasName(argument)) { |
| - argument = argument.checkedInput; |
| - } |
| - assert(variableNames.hasName(argument)); |
| - return argument; |
| - } |
| + void visitTypeGuard(HTypeGuard node) { |
| + if (!propagator.hasComplexTypeGuards) return; |
| - void visitTypeGuard(HTypeGuard node) { |
| indent--; |
| addIndented('case ${node.state}:\n'); |
| indent++; |
| @@ -2661,9 +2685,8 @@ |
| setup.add(' case ${node.state}:\n'); |
| int i = 0; |
| - for (HInstruction input in node.inputs) { |
| - HInstruction instruction = unwrap(input); |
| - setup.add(' ${variableNames.getName(instruction)} = env$i;\n'); |
| + for (String name in node.sortedVariableNames) { |
| + setup.add(' $name = env$i;\n'); |
| i++; |
| } |
| if (i > maxBailoutParameters) maxBailoutParameters = i; |
| @@ -2686,9 +2709,7 @@ |
| void startBailoutSwitch() { |
| addIndented('switch (state) {\n'); |
| - indent++; |
| - addIndented('case 0:\n'); |
| - indent++; |
| + indent += 2; |
| } |
| void endBailoutSwitch() { |
| @@ -2698,7 +2719,6 @@ |
| } |
| void beginLoop(HBasicBlock block) { |
| - // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
| String newLabel = pushLabel(); |
| if (block.hasGuards()) { |
| startBailoutCase(block.guards, const <HTypeGuard>[]); |