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

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 2152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2440 } 2431 }
2441 } 2432 }
2442 } 2433 }
2443 2434
2444 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { 2435 class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
2445 SsaOptimizedCodeGenerator(backend, work, parameters, parameterNames) 2436 SsaOptimizedCodeGenerator(backend, work, parameters, parameterNames)
2446 : super(backend, work, parameters, parameterNames); 2437 : super(backend, work, parameters, parameterNames);
2447 2438
2448 int maxBailoutParameters; 2439 int maxBailoutParameters;
2449 2440
2450 void beginGraph(HGraph graph) {} 2441 HBasicBlock beginGraph(HGraph graph) => graph.entry;
2451 void endGraph(HGraph graph) {} 2442 void endGraph(HGraph graph) {}
2452 2443
2453 void bailout(HTypeGuard guard, String reason) { 2444 void bailout(HTypeGuard guard, String reason) {
2454 if (maxBailoutParameters === null) { 2445 if (maxBailoutParameters === null) {
2455 maxBailoutParameters = 0; 2446 maxBailoutParameters = 0;
2456 work.guards.forEach((HTypeGuard guard) { 2447 work.guards.forEach((HTypeGuard guard) {
2457 int inputLength = guard.inputs.length; 2448 int inputLength = guard.inputs.length;
2458 if (inputLength > maxBailoutParameters) { 2449 if (inputLength > maxBailoutParameters) {
2459 maxBailoutParameters = inputLength; 2450 maxBailoutParameters = inputLength;
2460 } 2451 }
2461 }); 2452 });
2462 } 2453 }
2463 HInstruction input = guard.guarded; 2454 HInstruction input = guard.guarded;
2464 Namer namer = compiler.namer; 2455 Namer namer = compiler.namer;
2465 Element element = work.element; 2456 Element element = work.element;
2466 buffer.add('return '); 2457 buffer.add('return ');
2467 if (element.isInstanceMember()) { 2458 if (element.isInstanceMember()) {
2468 // TODO(ngeoffray): This does not work in case we come from a 2459 // TODO(ngeoffray): This does not work in case we come from a
2469 // super call. We must make bailout names unique. 2460 // super call. We must make bailout names unique.
2470 buffer.add('this.${namer.getBailoutName(element)}'); 2461 buffer.add('this.${namer.getBailoutName(element)}');
2471 } else { 2462 } else {
2472 buffer.add(namer.isolateBailoutAccess(element)); 2463 buffer.add(namer.isolateBailoutAccess(element));
2473 } 2464 }
2474 int parametersCount = parameterNames.length; 2465 buffer.add('(${guard.state}');
2475 buffer.add('($parameters');
2476 if (parametersCount != 0) buffer.add(', ');
2477 buffer.add('${guard.state}');
2478 // TODO(ngeoffray): try to put a variable at a deterministic 2466 // TODO(ngeoffray): try to put a variable at a deterministic
2479 // location, so that multiple bailout calls put the variable at 2467 // location, so that multiple bailout calls put the variable at
2480 // the same parameter index. 2468 // the same parameter index.
2481 int i = 0; 2469 int i = 0;
2482 for (; i < guard.inputs.length; i++) { 2470 for (; i < guard.sortedVariableNames.length; i++) {
2483 buffer.add(', '); 2471 buffer.add(', ${guard.sortedVariableNames[i]}');
2484 use(guard.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2485 } 2472 }
2486 // Make sure we call the bailout method with the number of 2473 // Make sure we call the bailout method with the number of
2487 // arguments it expects. This avoids having the underlying 2474 // arguments it expects. This avoids having the underlying
2488 // JS engine fill them in for us. 2475 // JS engine fill them in for us.
2489 for (; i < maxBailoutParameters; i++) { 2476 for (; i < maxBailoutParameters; i++) {
2490 buffer.add(', 0'); 2477 buffer.add(', 0');
2491 } 2478 }
2492 buffer.add(')'); 2479 buffer.add(')');
2493 } 2480 }
2494 2481
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
2584 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2571 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2585 } 2572 }
2586 2573
2587 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2574 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2588 } 2575 }
2589 } 2576 }
2590 2577
2591 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { 2578 class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator {
2592 2579
2593 final StringBuffer setup; 2580 final StringBuffer setup;
2581 final StringBuffer newParameters;
2594 final List<String> labels; 2582 final List<String> labels;
2595 int labelId = 0; 2583 int labelId = 0;
2596 int maxBailoutParameters = 0; 2584 int maxBailoutParameters = 0;
2597 2585
2586 SsaBailoutPropagator propagator;
2587 HInstruction savedFirstInstruction;
2588
2598 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames) 2589 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames)
2599 : super(backend, work, parameters, parameterNames), 2590 : super(backend, work, parameters, parameterNames),
2600 setup = new StringBuffer(), 2591 setup = new StringBuffer(),
2601 labels = <String>[]; 2592 newParameters = new StringBuffer(),
2593 labels = <String>[] {
kasperl 2012/06/12 12:18:40 Keep ;
ngeoffray 2012/06/12 12:28:18 Done.
2594 }
2602 2595
2603 String pushLabel() { 2596 String pushLabel() {
2604 String label = 'L${labelId++}'; 2597 String label = 'L${labelId++}';
2605 labels.addLast(label); 2598 labels.addLast(label);
2606 return label; 2599 return label;
2607 } 2600 }
2608 2601
2609 String popLabel() { 2602 String popLabel() {
2610 return labels.removeLast(); 2603 return labels.removeLast();
2611 } 2604 }
2612 2605
2613 String currentLabel() { 2606 String currentLabel() {
2614 return labels.last(); 2607 return labels.last();
2615 } 2608 }
2616 2609
2617 void beginGraph(HGraph graph) { 2610 HBasicBlock beginGraph(HGraph graph) {
2618 if (!graph.entry.hasGuards()) return; 2611 propagator = new SsaBailoutPropagator(
2619 addIndented('switch (state) {\n'); 2612 compiler, generateAtUseSite, variableNames);
2620 indent++; 2613 propagator.visitGraph(graph);
2621 addIndented('case 0:\n');
2622 indent++;
2623 2614
2624 // The setup phase of a bailout function sets up the environment for 2615 if (propagator.hasComplexTypeGuards) {
2625 // each bailout target. Each bailout target will populate this 2616 startBailoutSwitch();
2626 // setup phase. It is put at the beginning of the function. 2617
2627 setup.add(' switch (state) {\n'); 2618 // The setup phase of a bailout function sets up the environment for
2619 // each bailout target. Each bailout target will populate this
2620 // setup phase. It is put at the beginning of the function.
2621 setup.add(' switch (state) {\n');
2622 }
2623
2624 if (propagator.startGeneratingAt !== null) {
2625 return propagator.startGeneratingAt;
2626 }
2627
2628 // We change the first instruction of the first guard to be the
2629 // guard. We will change it back in the call to [endGraph].
2630 HBasicBlock block = propagator.firstTypeGuard.block;
2631 savedFirstInstruction = block.first;
2632 block.first = propagator.firstTypeGuard;
2633 return block;
2628 } 2634 }
2629 2635
2630 void endGraph(HGraph graph) { 2636 void endGraph(HGraph graph) {
2631 if (!graph.entry.hasGuards()) return; 2637 // Restore the first instruction of the first guard.
2632 indent--; // Close original case. 2638 if (propagator.startGeneratingAt === null) {
2633 indent--; 2639 propagator.firstTypeGuard.block.first = savedFirstInstruction;
2634 addIndented('}\n'); // Close 'switch'. 2640 }
2635 setup.add(' }\n'); 2641
2642 // TODO(ngeoffray): We could avoid generating the state at the
2643 // call site for non-complex bailout methods.
2644 newParameters.add('state');
2645
2646 if (!propagator.hasComplexTypeGuards) {
2647 for (String name in propagator.firstTypeGuard.sortedVariableNames) {
2648 newParameters.add(', $name');
2649 }
2650 } else {
2651 for (int i = 0; i < maxBailoutParameters; i++) {
2652 newParameters.add(', env$i');
2653 }
2654 indent--; // Close original case.
2655 indent--;
2656 addIndented('}\n'); // Close 'switch'.
2657 setup.add(' }\n');
2658 }
2636 } 2659 }
2637 2660
2638 bool visitAndOrInfo(HAndOrBlockInformation info) => false; 2661 bool visitAndOrInfo(HAndOrBlockInformation info) => false;
2639 bool visitIfInfo(HIfBlockInformation info) => false; 2662
2640 bool visitLoopInfo(HLoopBlockInformation info) => false; 2663 bool visitIfInfo(HIfBlockInformation info) {
2664 if (info.thenGraph.start.hasGuards()) return false;
2665 if (info.elseGraph.start.hasGuards()) return false;
2666 return super.visitIfInfo(info);
2667 }
2668
2669 bool visitLoopInfo(HLoopBlockInformation info) {
2670 if (info.start.hasGuards()) return false;
2671 if (info.loopHeader.hasGuards()) return false;
2672 return super.visitLoopInfo(info);
2673 }
2674
2641 bool visitTryInfo(HTryBlockInformation info) => false; 2675 bool visitTryInfo(HTryBlockInformation info) => false;
2642 bool visitSequenceInfo(HStatementSequenceInformation info) => false; 2676 bool visitSequenceInfo(HStatementSequenceInformation info) => false;
2643 2677
2644 // If argument is a [HCheck] and it does not have a name, we try to 2678 void visitTypeGuard(HTypeGuard node) {
2645 // find the name of its checked input. Note that there must be a 2679 if (!propagator.hasComplexTypeGuards) return;
2646 // name, otherwise the instruction would not be in the live
2647 // environment.
2648 HInstruction unwrap(argument) {»
2649 while (argument is HCheck && !variableNames.hasName(argument)) {
2650 argument = argument.checkedInput;
2651 }
2652 assert(variableNames.hasName(argument));
2653 return argument;»
2654 }
2655 2680
2656 void visitTypeGuard(HTypeGuard node) {
2657 indent--; 2681 indent--;
2658 addIndented('case ${node.state}:\n'); 2682 addIndented('case ${node.state}:\n');
2659 indent++; 2683 indent++;
2660 addIndented('state = 0;\n'); 2684 addIndented('state = 0;\n');
2661 2685
2662 setup.add(' case ${node.state}:\n'); 2686 setup.add(' case ${node.state}:\n');
2663 int i = 0; 2687 int i = 0;
2664 for (HInstruction input in node.inputs) { 2688 for (String name in node.sortedVariableNames) {
2665 HInstruction instruction = unwrap(input); 2689 setup.add(' $name = env$i;\n');
2666 setup.add(' ${variableNames.getName(instruction)} = env$i;\n');
2667 i++; 2690 i++;
2668 } 2691 }
2669 if (i > maxBailoutParameters) maxBailoutParameters = i; 2692 if (i > maxBailoutParameters) maxBailoutParameters = i;
2670 setup.add(' break;\n'); 2693 setup.add(' break;\n');
2671 } 2694 }
2672 2695
2673 void startBailoutCase(List<HTypeGuard> bailouts1, 2696 void startBailoutCase(List<HTypeGuard> bailouts1,
2674 List<HTypeGuard> bailouts2) { 2697 List<HTypeGuard> bailouts2) {
2675 indent--; 2698 indent--;
2676 handleBailoutCase(bailouts1); 2699 handleBailoutCase(bailouts1);
2677 handleBailoutCase(bailouts2); 2700 handleBailoutCase(bailouts2);
2678 indent++; 2701 indent++;
2679 } 2702 }
2680 2703
2681 void handleBailoutCase(List<HTypeGuard> guards) { 2704 void handleBailoutCase(List<HTypeGuard> guards) {
2682 for (int i = 0, len = guards.length; i < len; i++) { 2705 for (int i = 0, len = guards.length; i < len; i++) {
2683 addIndented('case ${guards[i].state}:\n'); 2706 addIndented('case ${guards[i].state}:\n');
2684 } 2707 }
2685 } 2708 }
2686 2709
2687 void startBailoutSwitch() { 2710 void startBailoutSwitch() {
2688 addIndented('switch (state) {\n'); 2711 addIndented('switch (state) {\n');
2689 indent++; 2712 indent += 2;
2690 addIndented('case 0:\n');
2691 indent++;
2692 } 2713 }
2693 2714
2694 void endBailoutSwitch() { 2715 void endBailoutSwitch() {
2695 indent--; // Close 'case'. 2716 indent--; // Close 'case'.
2696 indent--; 2717 indent--;
2697 addIndented('}\n'); // Close 'switch'. 2718 addIndented('}\n'); // Close 'switch'.
2698 } 2719 }
2699 2720
2700 void beginLoop(HBasicBlock block) { 2721 void beginLoop(HBasicBlock block) {
2701 // TODO(ngeoffray): Don't put labels on loops that don't bailout.
2702 String newLabel = pushLabel(); 2722 String newLabel = pushLabel();
2703 if (block.hasGuards()) { 2723 if (block.hasGuards()) {
2704 startBailoutCase(block.guards, const <HTypeGuard>[]); 2724 startBailoutCase(block.guards, const <HTypeGuard>[]);
2705 } 2725 }
2706 2726
2707 addIndentation(); 2727 addIndentation();
2708 HLoopInformation loopInformation = block.loopInformation; 2728 HLoopInformation loopInformation = block.loopInformation;
2709 for (LabelElement label in loopInformation.labels) { 2729 for (LabelElement label in loopInformation.labels) {
2710 writeLabel(label); 2730 writeLabel(label);
2711 buffer.add(":"); 2731 buffer.add(":");
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2800 startBailoutSwitch(); 2820 startBailoutSwitch();
2801 } 2821 }
2802 } 2822 }
2803 2823
2804 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2824 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2805 if (labeledBlockInfo.body.start.hasGuards()) { 2825 if (labeledBlockInfo.body.start.hasGuards()) {
2806 endBailoutSwitch(); 2826 endBailoutSwitch();
2807 } 2827 }
2808 } 2828 }
2809 } 2829 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698