| Index: lib/compiler/implementation/ssa/codegen.dart
|
| ===================================================================
|
| --- lib/compiler/implementation/ssa/codegen.dart (revision 8591)
|
| +++ 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(
|
| @@ -2463,7 +2454,7 @@
|
|
|
| int maxBailoutParameters;
|
|
|
| - void beginGraph(HGraph graph) {}
|
| + HBasicBlock beginGraph(HGraph graph) => graph.entry;
|
| void endGraph(HGraph graph) {}
|
|
|
| void bailout(HTypeGuard guard, String reason) {
|
| @@ -2487,10 +2478,7 @@
|
| } 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.
|
| @@ -2607,13 +2595,18 @@
|
| 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(),
|
| + newParameters = new StringBuffer(),
|
| labels = <String>[];
|
|
|
| String pushLabel() {
|
| @@ -2630,38 +2623,33 @@
|
| 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);
|
| + 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();
|
|
|
| - void endGraph(HGraph graph) {
|
| - if (!graph.entry.hasGuards()) return;
|
| - indent--; // Close original case.
|
| - indent--;
|
| - addIndented('}\n'); // Close 'switch'.
|
| - setup.add(' }\n');
|
| + // 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');
|
| + return graph.entry;
|
| + } else {
|
| + // 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;
|
| + }
|
| }
|
|
|
| - bool visitAndOrInfo(HAndOrBlockInformation info) => false;
|
| - bool visitIfInfo(HIfBlockInformation info) => false;
|
| - bool visitLoopInfo(HLoopBlockInformation info) => false;
|
| - 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) {
|
| + HInstruction unwrap(HInstruction argument) {
|
| while (argument is HCheck && !variableNames.hasName(argument)) {
|
| argument = argument.checkedInput;
|
| }
|
| @@ -2669,7 +2657,48 @@
|
| return argument;
|
| }
|
|
|
| + void endGraph(HGraph graph) {
|
| + // TODO(ngeoffray): We could avoid generating the state at the
|
| + // call site for non-complex bailout methods.
|
| + newParameters.add('state');
|
| +
|
| + if (!propagator.hasComplexTypeGuards) {
|
| + propagator.firstTypeGuard.block.first = savedFirstInstruction;
|
| + for (HInstruction input in propagator.firstTypeGuard.inputs) {
|
| + input = unwrap(input);
|
| + newParameters.add(', ${variableNames.getName(input)}');
|
| + }
|
| + } 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) {
|
| + 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;
|
| +
|
| void visitTypeGuard(HTypeGuard node) {
|
| + if (!propagator.hasComplexTypeGuards) return;
|
| +
|
| indent--;
|
| addIndented('case ${node.state}:\n');
|
| indent++;
|
| @@ -2678,8 +2707,9 @@
|
| 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');
|
| + input = unwrap(input);
|
| + String name = variableNames.getName(input);
|
| + setup.add(' $name = env$i;\n');
|
| i++;
|
| }
|
| if (i > maxBailoutParameters) maxBailoutParameters = i;
|
| @@ -2714,7 +2744,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>[]);
|
|
|