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

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

Issue 10539106: 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2600 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2588 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2601 } 2589 }
2602 2590
2603 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2591 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2604 } 2592 }
2605 } 2593 }
2606 2594
2607 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { 2595 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator {
2608 2596
2609 final StringBuffer setup; 2597 final StringBuffer setup;
2598 final StringBuffer newParameters;
2610 final List<String> labels; 2599 final List<String> labels;
2611 int labelId = 0; 2600 int labelId = 0;
2612 int maxBailoutParameters = 0; 2601 int maxBailoutParameters = 0;
2613 2602
2603 SsaBailoutPropagator propagator;
2604 HInstruction savedFirstInstruction;
2605
2614 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames) 2606 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames)
2615 : super(backend, work, parameters, parameterNames), 2607 : super(backend, work, parameters, parameterNames),
2616 setup = new StringBuffer(), 2608 setup = new StringBuffer(),
2609 newParameters = new StringBuffer(),
2617 labels = <String>[]; 2610 labels = <String>[];
2618 2611
2619 String pushLabel() { 2612 String pushLabel() {
2620 String label = 'L${labelId++}'; 2613 String label = 'L${labelId++}';
2621 labels.addLast(label); 2614 labels.addLast(label);
2622 return label; 2615 return label;
2623 } 2616 }
2624 2617
2625 String popLabel() { 2618 String popLabel() {
2626 return labels.removeLast(); 2619 return labels.removeLast();
2627 } 2620 }
2628 2621
2629 String currentLabel() { 2622 String currentLabel() {
2630 return labels.last(); 2623 return labels.last();
2631 } 2624 }
2632 2625
2633 void beginGraph(HGraph graph) { 2626 HBasicBlock beginGraph(HGraph graph) {
2634 if (!graph.entry.hasGuards()) return; 2627 propagator = new SsaBailoutPropagator(compiler, generateAtUseSite);
2635 addIndented('switch (state) {\n'); 2628 propagator.visitGraph(graph);
2636 indent++;
2637 addIndented('case 0:\n');
2638 indent++;
2639 2629
2640 // The setup phase of a bailout function sets up the environment for 2630 if (propagator.hasComplexTypeGuards) {
2641 // each bailout target. Each bailout target will populate this 2631 startBailoutSwitch();
2642 // setup phase. It is put at the beginning of the function. 2632
2643 setup.add(' switch (state) {\n'); 2633 // The setup phase of a bailout function sets up the environment for
2634 // each bailout target. Each bailout target will populate this
2635 // setup phase. It is put at the beginning of the function.
2636 setup.add(' switch (state) {\n');
2637 return graph.entry;
2638 } else {
2639 // We change the first instruction of the first guard to be the
2640 // guard. We will change it back in the call to [endGraph].
2641 HBasicBlock block = propagator.firstTypeGuard.block;
2642 savedFirstInstruction = block.first;
2643 block.first = propagator.firstTypeGuard;
2644 return block;
2645 }
2644 } 2646 }
2645 2647
2646 void endGraph(HGraph graph) {
2647 if (!graph.entry.hasGuards()) return;
2648 indent--; // Close original case.
2649 indent--;
2650 addIndented('}\n'); // Close 'switch'.
2651 setup.add(' }\n');
2652 }
2653
2654 bool visitAndOrInfo(HAndOrBlockInformation info) => false;
2655 bool visitIfInfo(HIfBlockInformation info) => false;
2656 bool visitLoopInfo(HLoopBlockInformation info) => false;
2657 bool visitTryInfo(HTryBlockInformation info) => false;
2658 bool visitSequenceInfo(HStatementSequenceInformation info) => false;
2659
2660 // If argument is a [HCheck] and it does not have a name, we try to 2648 // If argument is a [HCheck] and it does not have a name, we try to
2661 // find the name of its checked input. Note that there must be a 2649 // find the name of its checked input. Note that there must be a
2662 // name, otherwise the instruction would not be in the live 2650 // name, otherwise the instruction would not be in the live
2663 // environment. 2651 // environment.
2664 HInstruction unwrap(argument) { 2652 HInstruction unwrap(HInstruction argument) {
2665 while (argument is HCheck && !variableNames.hasName(argument)) { 2653 while (argument is HCheck && !variableNames.hasName(argument)) {
2666 argument = argument.checkedInput; 2654 argument = argument.checkedInput;
2667 } 2655 }
2668 assert(variableNames.hasName(argument)); 2656 assert(variableNames.hasName(argument));
2669 return argument; 2657 return argument;
2670 } 2658 }
2671 2659
2660 void endGraph(HGraph graph) {
2661 // TODO(ngeoffray): We could avoid generating the state at the
2662 // call site for non-complex bailout methods.
2663 newParameters.add('state');
2664
2665 if (!propagator.hasComplexTypeGuards) {
2666 propagator.firstTypeGuard.block.first = savedFirstInstruction;
2667 for (HInstruction input in propagator.firstTypeGuard.inputs) {
2668 input = unwrap(input);
2669 newParameters.add(', ${variableNames.getName(input)}');
2670 }
2671 } else {
2672 for (int i = 0; i < maxBailoutParameters; i++) {
2673 newParameters.add(', env$i');
2674 }
2675 indent--; // Close original case.
2676 indent--;
2677 addIndented('}\n'); // Close 'switch'.
2678 setup.add(' }\n');
2679 }
2680 }
2681
2682 bool visitAndOrInfo(HAndOrBlockInformation info) => false;
2683
2684 bool visitIfInfo(HIfBlockInformation info) {
2685 if (info.thenGraph.start.hasGuards()) return false;
2686 if (info.elseGraph.start.hasGuards()) return false;
2687 return super.visitIfInfo(info);
2688 }
2689
2690 bool visitLoopInfo(HLoopBlockInformation info) {
2691 if (info.start.hasGuards()) return false;
2692 if (info.loopHeader.hasGuards()) return false;
2693 return super.visitLoopInfo(info);
2694 }
2695
2696 bool visitTryInfo(HTryBlockInformation info) => false;
2697 bool visitSequenceInfo(HStatementSequenceInformation info) => false;
2698
2672 void visitTypeGuard(HTypeGuard node) { 2699 void visitTypeGuard(HTypeGuard node) {
2700 if (!propagator.hasComplexTypeGuards) return;
2701
2673 indent--; 2702 indent--;
2674 addIndented('case ${node.state}:\n'); 2703 addIndented('case ${node.state}:\n');
2675 indent++; 2704 indent++;
2676 addIndented('state = 0;\n'); 2705 addIndented('state = 0;\n');
2677 2706
2678 setup.add(' case ${node.state}:\n'); 2707 setup.add(' case ${node.state}:\n');
2679 int i = 0; 2708 int i = 0;
2680 for (HInstruction input in node.inputs) { 2709 for (HInstruction input in node.inputs) {
2681 HInstruction instruction = unwrap(input); 2710 input = unwrap(input);
2682 setup.add(' ${variableNames.getName(instruction)} = env$i;\n'); 2711 String name = variableNames.getName(input);
2712 setup.add(' $name = env$i;\n');
2683 i++; 2713 i++;
2684 } 2714 }
2685 if (i > maxBailoutParameters) maxBailoutParameters = i; 2715 if (i > maxBailoutParameters) maxBailoutParameters = i;
2686 setup.add(' break;\n'); 2716 setup.add(' break;\n');
2687 } 2717 }
2688 2718
2689 void startBailoutCase(List<HTypeGuard> bailouts1, 2719 void startBailoutCase(List<HTypeGuard> bailouts1,
2690 List<HTypeGuard> bailouts2) { 2720 List<HTypeGuard> bailouts2) {
2691 indent--; 2721 indent--;
2692 handleBailoutCase(bailouts1); 2722 handleBailoutCase(bailouts1);
(...skipping 14 matching lines...) Expand all
2707 indent++; 2737 indent++;
2708 } 2738 }
2709 2739
2710 void endBailoutSwitch() { 2740 void endBailoutSwitch() {
2711 indent--; // Close 'case'. 2741 indent--; // Close 'case'.
2712 indent--; 2742 indent--;
2713 addIndented('}\n'); // Close 'switch'. 2743 addIndented('}\n'); // Close 'switch'.
2714 } 2744 }
2715 2745
2716 void beginLoop(HBasicBlock block) { 2746 void beginLoop(HBasicBlock block) {
2717 // TODO(ngeoffray): Don't put labels on loops that don't bailout.
2718 String newLabel = pushLabel(); 2747 String newLabel = pushLabel();
2719 if (block.hasGuards()) { 2748 if (block.hasGuards()) {
2720 startBailoutCase(block.guards, const <HTypeGuard>[]); 2749 startBailoutCase(block.guards, const <HTypeGuard>[]);
2721 } 2750 }
2722 2751
2723 addIndentation(); 2752 addIndentation();
2724 HLoopInformation loopInformation = block.loopInformation; 2753 HLoopInformation loopInformation = block.loopInformation;
2725 for (LabelElement label in loopInformation.labels) { 2754 for (LabelElement label in loopInformation.labels) {
2726 writeLabel(label); 2755 writeLabel(label);
2727 buffer.add(":"); 2756 buffer.add(":");
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2816 startBailoutSwitch(); 2845 startBailoutSwitch();
2817 } 2846 }
2818 } 2847 }
2819 2848
2820 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2849 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2821 if (labeledBlockInfo.body.start.hasGuards()) { 2850 if (labeledBlockInfo.body.start.hasGuards()) {
2822 endBailoutSwitch(); 2851 endBailoutSwitch();
2823 } 2852 }
2824 } 2853 }
2825 } 2854 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/bailout.dart ('k') | lib/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698