Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: lib/compiler/implementation/ssa/codegen.dart

Issue 10533128: Reapply "Simplify generated code for trivial bailout methods". (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class SsaCodeGeneratorTask extends CompilerTask { 5 class SsaCodeGeneratorTask extends CompilerTask {
6 final JavaScriptBackend backend; 6 final JavaScriptBackend backend;
7 SsaCodeGeneratorTask(JavaScriptBackend backend) 7 SsaCodeGeneratorTask(JavaScriptBackend backend)
8 : this.backend = backend, 8 : this.backend = backend,
9 super(backend.compiler); 9 super(backend.compiler);
10 String get name() => 'SSA code generator'; 10 String get name() => 'SSA code generator';
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 } else { 65 } else {
66 code = codegen.buffer.toString(); 66 code = codegen.buffer.toString();
67 } 67 }
68 return buildJavaScriptFunction(element, parameters, code); 68 return buildJavaScriptFunction(element, parameters, code);
69 }); 69 });
70 } 70 }
71 71
72 String generateBailoutMethod(WorkItem work, HGraph graph) { 72 String generateBailoutMethod(WorkItem work, HGraph graph) {
73 return measure(() { 73 return measure(() {
74 compiler.tracer.traceGraph("codegen-bailout", graph); 74 compiler.tracer.traceGraph("codegen-bailout", graph);
75 new SsaBailoutPropagator(compiler).visitGraph(graph);
76 75
77 Map<Element, String> parameterNames = getParameterNames(work); 76 Map<Element, String> parameterNames = getParameterNames(work);
78 String parameters = Strings.join(parameterNames.getValues(), ', '); 77 String parameters = Strings.join(parameterNames.getValues(), ', ');
79 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator( 78 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator(
80 backend, work, parameters, parameterNames); 79 backend, work, parameters, parameterNames);
81 codegen.visitGraph(graph); 80 codegen.visitGraph(graph);
82 81
83 StringBuffer newParameters = new StringBuffer();
84 if (!parameterNames.isEmpty()) newParameters.add('$parameters, ');
85 newParameters.add('state');
86
87 for (int i = 0; i < codegen.maxBailoutParameters; i++) {
88 newParameters.add(', env$i');
89 }
90
91 Element element = work.element;
92 String body = '${codegen.setup}${codegen.buffer}'; 82 String body = '${codegen.setup}${codegen.buffer}';
93 return buildJavaScriptFunction(element, newParameters.toString(), body); 83 return buildJavaScriptFunction(
84 work.element, codegen.newParameters.toString(), body);
94 }); 85 });
95 } 86 }
96 87
97 Map<Element, String> getParameterNames(WorkItem work) { 88 Map<Element, String> getParameterNames(WorkItem work) {
98 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>(); 89 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>();
99 FunctionElement function = work.element; 90 FunctionElement function = work.element;
100 91
101 // The dom/html libraries have inline JS code that reference 92 // The dom/html libraries have inline JS code that reference
102 // parameter names directly. Long-term such code will be rejected. 93 // parameter names directly. Long-term such code will be rejected.
103 // Now, just don't mangle the parameter name. 94 // Now, just don't mangle the parameter name.
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 parameterNames); 257 parameterNames);
267 allocator.visitGraph(graph); 258 allocator.visitGraph(graph);
268 variableNames = allocator.names; 259 variableNames = allocator.names;
269 } 260 }
270 261
271 visitGraph(HGraph graph) { 262 visitGraph(HGraph graph) {
272 preGenerateMethod(graph); 263 preGenerateMethod(graph);
273 currentGraph = graph; 264 currentGraph = graph;
274 indent++; // We are already inside a function. 265 indent++; // We are already inside a function.
275 subGraph = new SubGraph(graph.entry, graph.exit); 266 subGraph = new SubGraph(graph.entry, graph.exit);
276 beginGraph(graph); 267 HBasicBlock start = beginGraph(graph);
277 visitBasicBlock(graph.entry); 268 visitBasicBlock(start);
278 if (!delayedVariableDeclarations.isEmpty()) { 269 if (!delayedVariableDeclarations.isEmpty()) {
279 addIndented("var "); 270 addIndented("var ");
280 buffer.add(Strings.join( 271 buffer.add(Strings.join(
281 new List<String>.from(delayedVariableDeclarations), ', ')); 272 new List<String>.from(delayedVariableDeclarations), ', '));
282 buffer.add(";\n"); 273 buffer.add(";\n");
283 } 274 }
284 endGraph(graph); 275 endGraph(graph);
285 } 276 }
286 277
287 void visitSubGraph(SubGraph newSubGraph) { 278 void visitSubGraph(SubGraph newSubGraph) {
(...skipping 2168 matching lines...) Expand 10 before | Expand all | Expand 10 after
2456 } 2447 }
2457 } 2448 }
2458 } 2449 }
2459 2450
2460 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { 2451 class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
2461 SsaOptimizedCodeGenerator(backend, work, parameters, parameterNames) 2452 SsaOptimizedCodeGenerator(backend, work, parameters, parameterNames)
2462 : super(backend, work, parameters, parameterNames); 2453 : super(backend, work, parameters, parameterNames);
2463 2454
2464 int maxBailoutParameters; 2455 int maxBailoutParameters;
2465 2456
2466 void beginGraph(HGraph graph) {} 2457 HBasicBlock beginGraph(HGraph graph) => graph.entry;
2467 void endGraph(HGraph graph) {} 2458 void endGraph(HGraph graph) {}
2468 2459
2469 void bailout(HTypeGuard guard, String reason) { 2460 void bailout(HTypeGuard guard, String reason) {
2470 if (maxBailoutParameters === null) { 2461 if (maxBailoutParameters === null) {
2471 maxBailoutParameters = 0; 2462 maxBailoutParameters = 0;
2472 work.guards.forEach((HTypeGuard guard) { 2463 work.guards.forEach((HTypeGuard guard) {
2473 int inputLength = guard.inputs.length; 2464 int inputLength = guard.inputs.length;
2474 if (inputLength > maxBailoutParameters) { 2465 if (inputLength > maxBailoutParameters) {
2475 maxBailoutParameters = inputLength; 2466 maxBailoutParameters = inputLength;
2476 } 2467 }
2477 }); 2468 });
2478 } 2469 }
2479 HInstruction input = guard.guarded; 2470 HInstruction input = guard.guarded;
2480 Namer namer = compiler.namer; 2471 Namer namer = compiler.namer;
2481 Element element = work.element; 2472 Element element = work.element;
2482 buffer.add('return '); 2473 buffer.add('return ');
2483 if (element.isInstanceMember()) { 2474 if (element.isInstanceMember()) {
2484 // TODO(ngeoffray): This does not work in case we come from a 2475 // TODO(ngeoffray): This does not work in case we come from a
2485 // super call. We must make bailout names unique. 2476 // super call. We must make bailout names unique.
2486 buffer.add('this.${namer.getBailoutName(element)}'); 2477 buffer.add('this.${namer.getBailoutName(element)}');
2487 } else { 2478 } else {
2488 buffer.add(namer.isolateBailoutAccess(element)); 2479 buffer.add(namer.isolateBailoutAccess(element));
2489 } 2480 }
2490 int parametersCount = parameterNames.length; 2481 buffer.add('(${guard.state}');
2491 buffer.add('($parameters');
2492 if (parametersCount != 0) buffer.add(', ');
2493 buffer.add('${guard.state}');
2494 // TODO(ngeoffray): try to put a variable at a deterministic 2482 // TODO(ngeoffray): try to put a variable at a deterministic
2495 // location, so that multiple bailout calls put the variable at 2483 // location, so that multiple bailout calls put the variable at
2496 // the same parameter index. 2484 // the same parameter index.
2497 int i = 0; 2485 int i = 0;
2498 for (; i < guard.inputs.length; i++) { 2486 for (; i < guard.inputs.length; i++) {
2499 buffer.add(', '); 2487 buffer.add(', ');
2500 use(guard.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 2488 use(guard.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2501 } 2489 }
2502 // Make sure we call the bailout method with the number of 2490 // Make sure we call the bailout method with the number of
2503 // arguments it expects. This avoids having the underlying 2491 // arguments it expects. This avoids having the underlying
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2607 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2595 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2608 } 2596 }
2609 2597
2610 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2598 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2611 } 2599 }
2612 } 2600 }
2613 2601
2614 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { 2602 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator {
2615 2603
2616 final StringBuffer setup; 2604 final StringBuffer setup;
2605 final StringBuffer newParameters;
2617 final List<String> labels; 2606 final List<String> labels;
2618 int labelId = 0; 2607 int labelId = 0;
2619 int maxBailoutParameters = 0; 2608 int maxBailoutParameters = 0;
2620 2609
2610 SsaBailoutPropagator propagator;
2611 HInstruction savedFirstInstruction;
2612
2621 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames) 2613 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames)
2622 : super(backend, work, parameters, parameterNames), 2614 : super(backend, work, parameters, parameterNames),
2623 setup = new StringBuffer(), 2615 setup = new StringBuffer(),
2616 newParameters = new StringBuffer(),
2624 labels = <String>[]; 2617 labels = <String>[];
2625 2618
2626 String pushLabel() { 2619 String pushLabel() {
2627 String label = 'L${labelId++}'; 2620 String label = 'L${labelId++}';
2628 labels.addLast(label); 2621 labels.addLast(label);
2629 return label; 2622 return label;
2630 } 2623 }
2631 2624
2632 String popLabel() { 2625 String popLabel() {
2633 return labels.removeLast(); 2626 return labels.removeLast();
2634 } 2627 }
2635 2628
2636 String currentLabel() { 2629 String currentLabel() {
2637 return labels.last(); 2630 return labels.last();
2638 } 2631 }
2639 2632
2640 void beginGraph(HGraph graph) { 2633 HBasicBlock beginGraph(HGraph graph) {
2641 if (!graph.entry.hasGuards()) return; 2634 propagator = new SsaBailoutPropagator(compiler, generateAtUseSite);
2642 addIndented('switch (state) {\n'); 2635 propagator.visitGraph(graph);
2643 indent++;
2644 addIndented('case 0:\n');
2645 indent++;
2646 2636
2647 // The setup phase of a bailout function sets up the environment for 2637 if (propagator.hasComplexTypeGuards) {
2648 // each bailout target. Each bailout target will populate this 2638 startBailoutSwitch();
2649 // setup phase. It is put at the beginning of the function. 2639
2650 setup.add(' switch (state) {\n'); 2640 // The setup phase of a bailout function sets up the environment for
2641 // each bailout target. Each bailout target will populate this
2642 // setup phase. It is put at the beginning of the function.
2643 setup.add(' switch (state) {\n');
2644 return graph.entry;
2645 } else {
2646 // We change the first instruction of the first guard to be the
2647 // guard. We will change it back in the call to [endGraph].
2648 HBasicBlock block = propagator.firstTypeGuard.block;
2649 savedFirstInstruction = block.first;
2650 block.first = propagator.firstTypeGuard;
2651 return block;
2652 }
2651 } 2653 }
2652 2654
2653 void endGraph(HGraph graph) {
2654 if (!graph.entry.hasGuards()) return;
2655 indent--; // Close original case.
2656 indent--;
2657 addIndented('}\n'); // Close 'switch'.
2658 setup.add(' }\n');
2659 }
2660
2661 bool visitAndOrInfo(HAndOrBlockInformation info) => false;
2662 bool visitIfInfo(HIfBlockInformation info) => false;
2663 bool visitLoopInfo(HLoopBlockInformation info) => false;
2664 bool visitTryInfo(HTryBlockInformation info) => false;
2665 bool visitSequenceInfo(HStatementSequenceInformation info) => false;
2666
2667 // If argument is a [HCheck] and it does not have a name, we try to 2655 // If argument is a [HCheck] and it does not have a name, we try to
2668 // find the name of its checked input. Note that there must be a 2656 // find the name of its checked input. Note that there must be a
2669 // name, otherwise the instruction would not be in the live 2657 // name, otherwise the instruction would not be in the live
2670 // environment. 2658 // environment.
2671 HInstruction unwrap(argument) { 2659 HInstruction unwrap(HInstruction argument) {
2672 while (argument is HCheck && !variableNames.hasName(argument)) { 2660 while (argument is HCheck && !variableNames.hasName(argument)) {
2673 argument = argument.checkedInput; 2661 argument = argument.checkedInput;
2674 } 2662 }
2675 assert(variableNames.hasName(argument)); 2663 assert(variableNames.hasName(argument));
2676 return argument; 2664 return argument;
2677 } 2665 }
2678 2666
2667 void endGraph(HGraph graph) {
2668 // TODO(ngeoffray): We could avoid generating the state at the
2669 // call site for non-complex bailout methods.
2670 newParameters.add('state');
2671
2672 if (!propagator.hasComplexTypeGuards) {
2673 propagator.firstTypeGuard.block.first = savedFirstInstruction;
2674 for (HInstruction input in propagator.firstTypeGuard.inputs) {
2675 input = unwrap(input);
2676 newParameters.add(', ${variableNames.getName(input)}');
2677 }
2678 } else {
2679 for (int i = 0; i < maxBailoutParameters; i++) {
2680 newParameters.add(', env$i');
2681 }
2682 indent--; // Close original case.
2683 indent--;
2684 addIndented('}\n'); // Close 'switch'.
2685 setup.add(' }\n');
2686 }
2687 }
2688
2689 bool visitAndOrInfo(HAndOrBlockInformation info) => false;
2690
2691 bool visitIfInfo(HIfBlockInformation info) {
2692 if (info.thenGraph.start.hasGuards()) return false;
2693 if (info.elseGraph.start.hasGuards()) return false;
2694 return super.visitIfInfo(info);
2695 }
2696
2697 bool visitLoopInfo(HLoopBlockInformation info) {
2698 if (info.start.hasGuards()) return false;
2699 if (info.loopHeader.hasGuards()) return false;
2700 return super.visitLoopInfo(info);
2701 }
2702
2703 bool visitTryInfo(HTryBlockInformation info) => false;
2704 bool visitSequenceInfo(HStatementSequenceInformation info) => false;
2705
2679 void visitTypeGuard(HTypeGuard node) { 2706 void visitTypeGuard(HTypeGuard node) {
2707 if (!propagator.hasComplexTypeGuards) return;
2708
2680 indent--; 2709 indent--;
2681 addIndented('case ${node.state}:\n'); 2710 addIndented('case ${node.state}:\n');
2682 indent++; 2711 indent++;
2683 addIndented('state = 0;\n'); 2712 addIndented('state = 0;\n');
2684 2713
2685 setup.add(' case ${node.state}:\n'); 2714 setup.add(' case ${node.state}:\n');
2686 int i = 0; 2715 int i = 0;
2687 for (HInstruction input in node.inputs) { 2716 for (HInstruction input in node.inputs) {
2688 HInstruction instruction = unwrap(input); 2717 input = unwrap(input);
2689 setup.add(' ${variableNames.getName(instruction)} = env$i;\n'); 2718 String name = variableNames.getName(input);
2719 setup.add(' ');
2720 if (!isVariableDeclared(name)) {
2721 declaredVariables.add(name);
2722 setup.add('var ');
2723 }
2724 setup.add('$name = env$i;\n');
2690 i++; 2725 i++;
2691 } 2726 }
2692 if (i > maxBailoutParameters) maxBailoutParameters = i; 2727 if (i > maxBailoutParameters) maxBailoutParameters = i;
2693 setup.add(' break;\n'); 2728 setup.add(' break;\n');
2694 } 2729 }
2695 2730
2696 void startBailoutCase(List<HTypeGuard> bailouts1, 2731 void startBailoutCase(List<HTypeGuard> bailouts1,
2697 List<HTypeGuard> bailouts2) { 2732 List<HTypeGuard> bailouts2) {
2698 indent--; 2733 indent--;
2699 handleBailoutCase(bailouts1); 2734 handleBailoutCase(bailouts1);
(...skipping 14 matching lines...) Expand all
2714 indent++; 2749 indent++;
2715 } 2750 }
2716 2751
2717 void endBailoutSwitch() { 2752 void endBailoutSwitch() {
2718 indent--; // Close 'case'. 2753 indent--; // Close 'case'.
2719 indent--; 2754 indent--;
2720 addIndented('}\n'); // Close 'switch'. 2755 addIndented('}\n'); // Close 'switch'.
2721 } 2756 }
2722 2757
2723 void beginLoop(HBasicBlock block) { 2758 void beginLoop(HBasicBlock block) {
2724 // TODO(ngeoffray): Don't put labels on loops that don't bailout.
2725 String newLabel = pushLabel(); 2759 String newLabel = pushLabel();
2726 if (block.hasGuards()) { 2760 if (block.hasGuards()) {
2727 startBailoutCase(block.guards, const <HTypeGuard>[]); 2761 startBailoutCase(block.guards, const <HTypeGuard>[]);
2728 } 2762 }
2729 2763
2730 addIndentation(); 2764 addIndentation();
2731 HLoopInformation loopInformation = block.loopInformation; 2765 HLoopInformation loopInformation = block.loopInformation;
2732 for (LabelElement label in loopInformation.labels) { 2766 for (LabelElement label in loopInformation.labels) {
2733 writeLabel(label); 2767 writeLabel(label);
2734 buffer.add(":"); 2768 buffer.add(":");
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2823 startBailoutSwitch(); 2857 startBailoutSwitch();
2824 } 2858 }
2825 } 2859 }
2826 2860
2827 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2861 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2828 if (labeledBlockInfo.body.start.hasGuards()) { 2862 if (labeledBlockInfo.body.start.hasGuards()) {
2829 endBailoutSwitch(); 2863 endBailoutSwitch();
2830 } 2864 }
2831 } 2865 }
2832 } 2866 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/builder.dart ('k') | lib/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698