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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 2301293002: kernel -> ssa: implement if-statements (Closed)
Patch Set: Created 4 years, 3 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
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 import 'dart:collection'; 5 import 'dart:collection';
6 6
7 import 'package:compiler/src/ssa/ssa_branch_builder.dart';
7 import 'package:js_runtime/shared/embedded_names.dart'; 8 import 'package:js_runtime/shared/embedded_names.dart';
8 9
9 import '../closure.dart'; 10 import '../closure.dart';
10 import '../common.dart'; 11 import '../common.dart';
11 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 12 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
12 import '../common/names.dart' show Identifiers, Selectors; 13 import '../common/names.dart' show Identifiers, Selectors;
13 import '../common/tasks.dart' show CompilerTask; 14 import '../common/tasks.dart' show CompilerTask;
14 import '../compiler.dart' show Compiler; 15 import '../compiler.dart' show Compiler;
15 import '../constants/constant_system.dart'; 16 import '../constants/constant_system.dart';
16 import '../constants/expressions.dart'; 17 import '../constants/expressions.dart';
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 * account. 405 * account.
405 */ 406 */
406 int loopNesting = 0; 407 int loopNesting = 0;
407 408
408 /** 409 /**
409 * This stack contains declaration elements of the functions being built 410 * This stack contains declaration elements of the functions being built
410 * or inlined by this builder. 411 * or inlined by this builder.
411 */ 412 */
412 final List<Element> sourceElementStack = <Element>[]; 413 final List<Element> sourceElementStack = <Element>[];
413 414
414 LocalsHandler localsHandler;
415
416 HInstruction rethrowableException; 415 HInstruction rethrowableException;
417 416
418 Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{}; 417 Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
419 418
420 /// Returns `true` if the current element is an `async` function. 419 /// Returns `true` if the current element is an `async` function.
421 bool get isBuildingAsyncFunction { 420 bool get isBuildingAsyncFunction {
422 Element element = sourceElement; 421 Element element = sourceElement;
423 return (element is FunctionElement && 422 return (element is FunctionElement &&
424 element.asyncMarker == AsyncMarker.ASYNC); 423 element.asyncMarker == AsyncMarker.ASYNC);
425 } 424 }
(...skipping 1474 matching lines...) Expand 10 before | Expand all | Expand 10 after
1900 // TODO(kasperl): Make this goto an implicit return. 1899 // TODO(kasperl): Make this goto an implicit return.
1901 if (!isAborted()) closeAndGotoExit(new HGoto()); 1900 if (!isAborted()) closeAndGotoExit(new HGoto());
1902 graph.finalize(); 1901 graph.finalize();
1903 return graph; 1902 return graph;
1904 } 1903 }
1905 1904
1906 void pushWithPosition(HInstruction instruction, ast.Node node) { 1905 void pushWithPosition(HInstruction instruction, ast.Node node) {
1907 push(attachPosition(instruction, node)); 1906 push(attachPosition(instruction, node));
1908 } 1907 }
1909 1908
1910 HInstruction popBoolified() { 1909 @override
1910 HBoolify popBoolified() {
1911 HInstruction value = pop(); 1911 HInstruction value = pop();
1912 if (_checkOrTrustTypes) { 1912 if (_checkOrTrustTypes) {
1913 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType, 1913 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType,
1914 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 1914 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
1915 } 1915 }
1916 HInstruction result = new HBoolify(value, backend.boolType); 1916 HInstruction result = new HBoolify(value, backend.boolType);
1917 add(result); 1917 add(result);
1918 return result; 1918 return result;
1919 } 1919 }
1920 1920
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
2530 visitThen: () => visit(node.thenPart), 2530 visitThen: () => visit(node.thenPart),
2531 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, 2531 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null,
2532 sourceInformation: sourceInformationBuilder.buildIf(node)); 2532 sourceInformation: sourceInformationBuilder.buildIf(node));
2533 } 2533 }
2534 2534
2535 void handleIf(ast.Node diagnosticNode, 2535 void handleIf(ast.Node diagnosticNode,
2536 {void visitCondition(), 2536 {void visitCondition(),
2537 void visitThen(), 2537 void visitThen(),
2538 void visitElse(), 2538 void visitElse(),
2539 SourceInformation sourceInformation}) { 2539 SourceInformation sourceInformation}) {
2540 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); 2540 SsaBranchBuilder branchBuilder =
2541 new SsaBranchBuilder(this, compiler, diagnosticNode);
2541 branchBuilder.handleIf(visitCondition, visitThen, visitElse, 2542 branchBuilder.handleIf(visitCondition, visitThen, visitElse,
2542 sourceInformation: sourceInformation); 2543 sourceInformation: sourceInformation);
2543 } 2544 }
2544 2545
2545 @override 2546 @override
2546 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { 2547 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) {
2547 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 2548 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
2548 brancher.handleIfNull(() => visit(left), () => visit(right)); 2549 brancher.handleIfNull(() => visit(left), () => visit(right));
2549 } 2550 }
2550 2551
2551 @override 2552 @override
2552 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { 2553 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) {
2553 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); 2554 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler, node);
2554 branchBuilder.handleLogicalAndOrWithLeftNode(left, () { 2555
2555 visit(right); 2556 // This method is similar to [SsaBranchBuilder.handleLogicalAndOr] but
2556 }, isAnd: true); 2557 // optimizes the case where left is a logical "and".
2558 //
2559 // For example (x && y) && z is transformed into x && (y && z):
2560 // t0 = boolify(x);
2561 // if (t0) {
2562 // t1 = boolify(y);
2563 // if (t1) {
2564 // t2 = boolify(z);
2565 // }
2566 // t3 = phi(t2, false);
2567 // }
2568 // result = phi(t3, false);
2569 void handleLogicalAndWithLeftNode(ast.Node left, void visitRight()) {
2570 ast.Send send = left.asSend();
2571 if (send != null && send.isLogicalAnd) {
2572 ast.Node newLeft = send.receiver;
2573 Link<ast.Node> link = send.argumentsNode.nodes;
2574 assert(link.tail.isEmpty);
2575 ast.Node middle = link.head;
2576 handleLogicalAndWithLeftNode(
2577 newLeft, () => handleLogicalAndWithLeftNode(middle, visitRight));
2578 } else {
2579 branchBuilder.handleLogicalAndOr(() => visit(left), visitRight,
2580 isAnd: true);
2581 }
2582 }
2583
2584 handleLogicalAndWithLeftNode(left, () => visit(right));
2557 } 2585 }
2558 2586
2559 @override 2587 @override
2560 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) { 2588 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) {
2561 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); 2589 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler, node);
2562 branchBuilder.handleLogicalAndOrWithLeftNode(left, () { 2590
2563 visit(right); 2591 // This method is similar to [SsaBranchBuilder.handleLogicalAndOr] but
2564 }, isAnd: false); 2592 // optimizes the case where left is a logical "or".
2593 void handleLogicalOrWithLeftNode(ast.Node left, void visitRight()) {
Siggi Cherem (dart-lang) 2016/09/01 23:51:21 what if we keep the handleLogicalAndOrWithLeftNode
Harry Terkelsen 2016/09/02 17:52:27 Done.
2594 ast.Send send = left.asSend();
2595 if (send != null && send.isLogicalOr) {
2596 ast.Node newLeft = send.receiver;
2597 Link<ast.Node> link = send.argumentsNode.nodes;
2598 assert(link.tail.isEmpty);
2599 ast.Node middle = link.head;
2600 handleLogicalOrWithLeftNode(
2601 newLeft, () => handleLogicalOrWithLeftNode(middle, visitRight));
2602 } else {
2603 branchBuilder.handleLogicalAndOr(() => visit(left), visitRight,
2604 isAnd: true);
Siggi Cherem (dart-lang) 2016/09/01 23:51:21 shouldn't this be "false"?
Harry Terkelsen 2016/09/02 17:52:27 oops! good catch
2605 }
2606 }
2607
2608 handleLogicalOrWithLeftNode(left, () => visit(right));
2565 } 2609 }
2566 2610
2567 @override 2611 @override
2568 void visitNot(ast.Send node, ast.Node expression, _) { 2612 void visitNot(ast.Send node, ast.Node expression, _) {
2569 assert(node.argumentsNode is ast.Prefix); 2613 assert(node.argumentsNode is ast.Prefix);
2570 visit(expression); 2614 visit(expression);
2571 SourceInformation sourceInformation = 2615 SourceInformation sourceInformation =
2572 sourceInformationBuilder.buildGeneric(node); 2616 sourceInformationBuilder.buildGeneric(node);
2573 push(new HNot(popBoolified(), backend.boolType) 2617 push(new HNot(popBoolified(), backend.boolType)
2574 ..sourceInformation = sourceInformation); 2618 ..sourceInformation = sourceInformation);
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
2812 @override 2856 @override
2813 void visitIfNotNullDynamicPropertyGet( 2857 void visitIfNotNullDynamicPropertyGet(
2814 ast.Send node, ast.Node receiver, Name name, _) { 2858 ast.Send node, ast.Node receiver, Name name, _) {
2815 // exp?.x compiled as: 2859 // exp?.x compiled as:
2816 // t1 = exp; 2860 // t1 = exp;
2817 // result = t1 == null ? t1 : t1.x; 2861 // result = t1 == null ? t1 : t1.x;
2818 // This is equivalent to t1 == null ? null : t1.x, but in the current form 2862 // This is equivalent to t1 == null ? null : t1.x, but in the current form
2819 // we will be able to later compress it as: 2863 // we will be able to later compress it as:
2820 // t1 || t1.x 2864 // t1 || t1.x
2821 HInstruction expression; 2865 HInstruction expression;
2822 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 2866 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
2823 brancher.handleConditional( 2867 brancher.handleConditional(
2824 () { 2868 () {
2825 expression = visitAndPop(receiver); 2869 expression = visitAndPop(receiver);
2826 pushCheckNull(expression); 2870 pushCheckNull(expression);
2827 }, 2871 },
2828 () => stack.add(expression), 2872 () => stack.add(expression),
2829 () { 2873 () {
2830 generateInstanceGetterWithCompiledReceiver( 2874 generateInstanceGetterWithCompiledReceiver(
2831 node, 2875 node,
2832 elements.getSelector(node), 2876 elements.getSelector(node),
2833 elements.getTypeMask(node), 2877 elements.getTypeMask(node),
2834 expression); 2878 expression);
2835 }); 2879 });
2836 } 2880 }
2837 2881
2838 /// Pushes a boolean checking [expression] against null. 2882 @override
2839 pushCheckNull(HInstruction expression) { 2883 pushCheckNull(HInstruction expression) {
2840 push(new HIdentity( 2884 push(new HIdentity(
2841 expression, graph.addConstantNull(compiler), null, backend.boolType)); 2885 expression, graph.addConstantNull(compiler), null, backend.boolType));
2842 } 2886 }
2843 2887
2844 @override 2888 @override
2845 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { 2889 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) {
2846 handleLocalGet(node, variable); 2890 handleLocalGet(node, variable);
2847 } 2891 }
2848 2892
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
3195 visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver, 3239 visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver,
3196 ast.NodeList arguments, Selector selector, _) { 3240 ast.NodeList arguments, Selector selector, _) {
3197 generateDynamicSend(node); 3241 generateDynamicSend(node);
3198 } 3242 }
3199 3243
3200 @override 3244 @override
3201 visitIfNotNullDynamicPropertyInvoke(ast.Send node, ast.Node receiver, 3245 visitIfNotNullDynamicPropertyInvoke(ast.Send node, ast.Node receiver,
3202 ast.NodeList arguments, Selector selector, _) { 3246 ast.NodeList arguments, Selector selector, _) {
3203 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()` 3247 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()`
3204 HInstruction receiver; 3248 HInstruction receiver;
3205 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 3249 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
3206 brancher.handleConditional(() { 3250 brancher.handleConditional(() {
3207 receiver = generateInstanceSendReceiver(node); 3251 receiver = generateInstanceSendReceiver(node);
3208 pushCheckNull(receiver); 3252 pushCheckNull(receiver);
3209 }, () => stack.add(receiver), () => _generateDynamicSend(node, receiver)); 3253 }, () => stack.add(receiver), () => _generateDynamicSend(node, receiver));
3210 } 3254 }
3211 3255
3212 @override 3256 @override
3213 visitThisPropertyInvoke( 3257 visitThisPropertyInvoke(
3214 ast.Send node, ast.NodeList arguments, Selector selector, _) { 3258 ast.Send node, ast.NodeList arguments, Selector selector, _) {
3215 generateDynamicSend(node); 3259 generateDynamicSend(node);
(...skipping 1785 matching lines...) Expand 10 before | Expand all | Expand 10 after
5001 if (Elements.isUnresolved(getter)) { 5045 if (Elements.isUnresolved(getter)) {
5002 generateSuperNoSuchMethodSend(node, getterSelector, getterInputs); 5046 generateSuperNoSuchMethodSend(node, getterSelector, getterInputs);
5003 getterInstruction = pop(); 5047 getterInstruction = pop();
5004 } else { 5048 } else {
5005 getterInstruction = 5049 getterInstruction =
5006 buildInvokeSuper(getterSelector, getter, getterInputs); 5050 buildInvokeSuper(getterSelector, getter, getterInputs);
5007 add(getterInstruction); 5051 add(getterInstruction);
5008 } 5052 }
5009 5053
5010 if (node.isIfNullAssignment) { 5054 if (node.isIfNullAssignment) {
5011 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5055 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5012 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5056 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5013 addDynamicSendArgumentsToList(node, setterInputs); 5057 addDynamicSendArgumentsToList(node, setterInputs);
5014 generateSuperSendSet(); 5058 generateSuperSendSet();
5015 stack.add(setterInputs.last); 5059 stack.add(setterInputs.last);
5016 }); 5060 });
5017 } else { 5061 } else {
5018 handleComplexOperatorSend(node, getterInstruction, arguments); 5062 handleComplexOperatorSend(node, getterInstruction, arguments);
5019 setterInputs.add(pop()); 5063 setterInputs.add(pop());
5020 generateSuperSendSet(); 5064 generateSuperSendSet();
5021 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); 5065 stack.add(node.isPostfix ? getterInstruction : setterInputs.last);
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
5321 5365
5322 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node), 5366 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node),
5323 elements.getGetterTypeMaskInComplexSendSet(node), [receiver, index]); 5367 elements.getGetterTypeMaskInComplexSendSet(node), [receiver, index]);
5324 HInstruction getterInstruction = pop(); 5368 HInstruction getterInstruction = pop();
5325 if (node.isIfNullAssignment) { 5369 if (node.isIfNullAssignment) {
5326 // Compile x[i] ??= e as: 5370 // Compile x[i] ??= e as:
5327 // t1 = x[i] 5371 // t1 = x[i]
5328 // if (t1 == null) 5372 // if (t1 == null)
5329 // t1 = x[i] = e; 5373 // t1 = x[i] = e;
5330 // result = t1 5374 // result = t1
5331 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5375 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5332 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5376 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5333 visit(arguments.head); 5377 visit(arguments.head);
5334 HInstruction value = pop(); 5378 HInstruction value = pop();
5335 pushInvokeDynamic(node, elements.getSelector(node), 5379 pushInvokeDynamic(node, elements.getSelector(node),
5336 elements.getTypeMask(node), [receiver, index, value]); 5380 elements.getTypeMask(node), [receiver, index, value]);
5337 pop(); 5381 pop();
5338 stack.add(value); 5382 stack.add(value);
5339 }); 5383 });
5340 } else { 5384 } else {
5341 handleComplexOperatorSend(node, getterInstruction, arguments); 5385 handleComplexOperatorSend(node, getterInstruction, arguments);
(...skipping 27 matching lines...) Expand all
5369 void visitIfNotNullDynamicPropertySet( 5413 void visitIfNotNullDynamicPropertySet(
5370 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) { 5414 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) {
5371 // compile e?.x = e2 to: 5415 // compile e?.x = e2 to:
5372 // 5416 //
5373 // t1 = e 5417 // t1 = e
5374 // if (t1 == null) 5418 // if (t1 == null)
5375 // result = t1 // same as result = null 5419 // result = t1 // same as result = null
5376 // else 5420 // else
5377 // result = e.x = e2 5421 // result = e.x = e2
5378 HInstruction receiverInstruction; 5422 HInstruction receiverInstruction;
5379 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5423 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5380 brancher.handleConditional( 5424 brancher.handleConditional(
5381 () { 5425 () {
5382 receiverInstruction = generateInstanceSendReceiver(node); 5426 receiverInstruction = generateInstanceSendReceiver(node);
5383 pushCheckNull(receiverInstruction); 5427 pushCheckNull(receiverInstruction);
5384 }, 5428 },
5385 () => stack.add(receiverInstruction), 5429 () => stack.add(receiverInstruction),
5386 () { 5430 () {
5387 generateInstanceSetterWithCompiledReceiver( 5431 generateInstanceSetterWithCompiledReceiver(
5388 node, receiverInstruction, visitAndPop(rhs)); 5432 node, receiverInstruction, visitAndPop(rhs));
5389 }); 5433 });
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
5542 if (Elements.isInstanceSend(node, elements)) { 5586 if (Elements.isInstanceSend(node, elements)) {
5543 void generateAssignment(HInstruction receiver) { 5587 void generateAssignment(HInstruction receiver) {
5544 // desugars `e.x op= e2` to `e.x = e.x op e2` 5588 // desugars `e.x op= e2` to `e.x = e.x op e2`
5545 generateInstanceGetterWithCompiledReceiver( 5589 generateInstanceGetterWithCompiledReceiver(
5546 node, 5590 node,
5547 elements.getGetterSelectorInComplexSendSet(node), 5591 elements.getGetterSelectorInComplexSendSet(node),
5548 elements.getGetterTypeMaskInComplexSendSet(node), 5592 elements.getGetterTypeMaskInComplexSendSet(node),
5549 receiver); 5593 receiver);
5550 HInstruction getterInstruction = pop(); 5594 HInstruction getterInstruction = pop();
5551 if (node.isIfNullAssignment) { 5595 if (node.isIfNullAssignment) {
5552 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5596 SsaBranchBuilder brancher =
5597 new SsaBranchBuilder(this, compiler, node);
5553 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5598 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5554 visit(node.arguments.head); 5599 visit(node.arguments.head);
5555 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); 5600 generateInstanceSetterWithCompiledReceiver(node, receiver, pop());
5556 }); 5601 });
5557 } else { 5602 } else {
5558 handleComplexOperatorSend(node, getterInstruction, node.arguments); 5603 handleComplexOperatorSend(node, getterInstruction, node.arguments);
5559 HInstruction value = pop(); 5604 HInstruction value = pop();
5560 generateInstanceSetterWithCompiledReceiver(node, receiver, value); 5605 generateInstanceSetterWithCompiledReceiver(node, receiver, value);
5561 } 5606 }
5562 if (node.isPostfix) { 5607 if (node.isPostfix) {
5563 pop(); 5608 pop();
5564 stack.add(getterInstruction); 5609 stack.add(getterInstruction);
5565 } 5610 }
5566 } 5611 }
5567 5612
5568 if (node.isConditional) { 5613 if (node.isConditional) {
5569 // generate `e?.x op= e2` as: 5614 // generate `e?.x op= e2` as:
5570 // t1 = e 5615 // t1 = e
5571 // t1 == null ? t1 : (t1.x = t1.x op e2); 5616 // t1 == null ? t1 : (t1.x = t1.x op e2);
5572 HInstruction receiver; 5617 HInstruction receiver;
5573 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5618 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5574 brancher.handleConditional(() { 5619 brancher.handleConditional(() {
5575 receiver = generateInstanceSendReceiver(node); 5620 receiver = generateInstanceSendReceiver(node);
5576 pushCheckNull(receiver); 5621 pushCheckNull(receiver);
5577 }, () => stack.add(receiver), () => generateAssignment(receiver)); 5622 }, () => stack.add(receiver), () => generateAssignment(receiver));
5578 } else { 5623 } else {
5579 generateAssignment(generateInstanceSendReceiver(node)); 5624 generateAssignment(generateInstanceSendReceiver(node));
5580 } 5625 }
5581 return; 5626 return;
5582 } 5627 }
5583 5628
5584 if (getter.isMalformed) { 5629 if (getter.isMalformed) {
5585 generateStaticUnresolvedGet(node, getter); 5630 generateStaticUnresolvedGet(node, getter);
5586 } else if (getter.isField) { 5631 } else if (getter.isField) {
5587 generateStaticFieldGet(node, getter); 5632 generateStaticFieldGet(node, getter);
5588 } else if (getter.isGetter) { 5633 } else if (getter.isGetter) {
5589 generateStaticGetterGet(node, getter); 5634 generateStaticGetterGet(node, getter);
5590 } else if (getter.isFunction) { 5635 } else if (getter.isFunction) {
5591 generateStaticFunctionGet(node, getter); 5636 generateStaticFunctionGet(node, getter);
5592 } else if (getter.isLocal) { 5637 } else if (getter.isLocal) {
5593 handleLocalGet(node, getter); 5638 handleLocalGet(node, getter);
5594 } else { 5639 } else {
5595 internalError(node, "Unexpected getter: $getter"); 5640 internalError(node, "Unexpected getter: $getter");
5596 } 5641 }
5597 HInstruction getterInstruction = pop(); 5642 HInstruction getterInstruction = pop();
5598 if (node.isIfNullAssignment) { 5643 if (node.isIfNullAssignment) {
5599 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5644 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5600 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5645 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5601 visit(node.arguments.head); 5646 visit(node.arguments.head);
5602 generateNonInstanceSetter(node, element, pop()); 5647 generateNonInstanceSetter(node, element, pop());
5603 }); 5648 });
5604 } else { 5649 } else {
5605 handleComplexOperatorSend(node, getterInstruction, node.arguments); 5650 handleComplexOperatorSend(node, getterInstruction, node.arguments);
5606 HInstruction value = pop(); 5651 HInstruction value = pop();
5607 generateNonInstanceSetter(node, element, value); 5652 generateNonInstanceSetter(node, element, value);
5608 } 5653 }
5609 if (node.isPostfix) { 5654 if (node.isPostfix) {
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
5999 instruction = setRtiIfNeeded(instruction, node); 6044 instruction = setRtiIfNeeded(instruction, node);
6000 } 6045 }
6001 6046
6002 TypeMask type = 6047 TypeMask type =
6003 TypeMaskFactory.inferredForNode(sourceElement, node, compiler); 6048 TypeMaskFactory.inferredForNode(sourceElement, node, compiler);
6004 if (!type.containsAll(compiler.world)) instruction.instructionType = type; 6049 if (!type.containsAll(compiler.world)) instruction.instructionType = type;
6005 stack.add(instruction); 6050 stack.add(instruction);
6006 } 6051 }
6007 6052
6008 visitConditional(ast.Conditional node) { 6053 visitConditional(ast.Conditional node) {
6009 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6054 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
6010 brancher.handleConditional(() => visit(node.condition), 6055 brancher.handleConditional(() => visit(node.condition),
6011 () => visit(node.thenExpression), () => visit(node.elseExpression)); 6056 () => visit(node.thenExpression), () => visit(node.elseExpression));
6012 } 6057 }
6013 6058
6014 visitStringInterpolation(ast.StringInterpolation node) { 6059 visitStringInterpolation(ast.StringInterpolation node) {
6015 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); 6060 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
6016 stringBuilder.visit(node); 6061 stringBuilder.visit(node);
6017 stack.add(stringBuilder.result); 6062 stack.add(stringBuilder.result);
6018 } 6063 }
6019 6064
(...skipping 1451 matching lines...) Expand 10 before | Expand all | Expand 10 after
7471 this.oldReturnLocal, 7516 this.oldReturnLocal,
7472 this.oldReturnType, 7517 this.oldReturnType,
7473 this.oldResolvedAst, 7518 this.oldResolvedAst,
7474 this.oldStack, 7519 this.oldStack,
7475 this.oldLocalsHandler, 7520 this.oldLocalsHandler,
7476 this.inTryStatement, 7521 this.inTryStatement,
7477 this.allFunctionsCalledOnce) 7522 this.allFunctionsCalledOnce)
7478 : super(function); 7523 : super(function);
7479 } 7524 }
7480 7525
7481 class SsaBranch {
7482 final SsaBranchBuilder branchBuilder;
7483 final HBasicBlock block;
7484 LocalsHandler startLocals;
7485 LocalsHandler exitLocals;
7486 SubGraph graph;
7487
7488 SsaBranch(this.branchBuilder) : block = new HBasicBlock();
7489 }
7490
7491 class SsaBranchBuilder {
7492 final SsaBuilder builder;
7493 final ast.Node diagnosticNode;
7494
7495 SsaBranchBuilder(this.builder, [this.diagnosticNode]);
7496
7497 Compiler get compiler => builder.compiler;
7498
7499 void checkNotAborted() {
7500 if (builder.isAborted()) {
7501 compiler.unimplemented(diagnosticNode, "aborted control flow");
7502 }
7503 }
7504
7505 void buildCondition(
7506 void visitCondition(),
7507 SsaBranch conditionBranch,
7508 SsaBranch thenBranch,
7509 SsaBranch elseBranch,
7510 SourceInformation sourceInformation) {
7511 startBranch(conditionBranch);
7512 visitCondition();
7513 checkNotAborted();
7514 assert(identical(builder.current, builder.lastOpenedBlock));
7515 HInstruction conditionValue = builder.popBoolified();
7516 HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation;
7517 HBasicBlock conditionExitBlock = builder.current;
7518 builder.close(branch);
7519 conditionBranch.exitLocals = builder.localsHandler;
7520 conditionExitBlock.addSuccessor(thenBranch.block);
7521 conditionExitBlock.addSuccessor(elseBranch.block);
7522 bool conditionBranchLocalsCanBeReused =
7523 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true);
7524 mergeLocals(conditionBranch, elseBranch,
7525 mayReuseFromLocals: conditionBranchLocalsCanBeReused);
7526
7527 conditionBranch.graph =
7528 new SubExpression(conditionBranch.block, conditionExitBlock);
7529 }
7530
7531 /**
7532 * Returns true if the locals of the [fromBranch] may be reused. A [:true:]
7533 * return value implies that [mayReuseFromLocals] was set to [:true:].
7534 */
7535 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch,
7536 {bool mayReuseFromLocals}) {
7537 LocalsHandler fromLocals = fromBranch.exitLocals;
7538 if (toBranch.startLocals == null) {
7539 if (mayReuseFromLocals) {
7540 toBranch.startLocals = fromLocals;
7541 return false;
7542 } else {
7543 toBranch.startLocals = new LocalsHandler.from(fromLocals);
7544 return true;
7545 }
7546 } else {
7547 toBranch.startLocals.mergeWith(fromLocals, toBranch.block);
7548 return true;
7549 }
7550 }
7551
7552 void startBranch(SsaBranch branch) {
7553 builder.graph.addBlock(branch.block);
7554 builder.localsHandler = branch.startLocals;
7555 builder.open(branch.block);
7556 }
7557
7558 HInstruction buildBranch(SsaBranch branch, void visitBranch(),
7559 SsaBranch joinBranch, bool isExpression) {
7560 startBranch(branch);
7561 visitBranch();
7562 branch.graph = new SubGraph(branch.block, builder.lastOpenedBlock);
7563 branch.exitLocals = builder.localsHandler;
7564 if (!builder.isAborted()) {
7565 builder.goto(builder.current, joinBranch.block);
7566 mergeLocals(branch, joinBranch, mayReuseFromLocals: true);
7567 }
7568 if (isExpression) {
7569 checkNotAborted();
7570 return builder.pop();
7571 }
7572 return null;
7573 }
7574
7575 handleIf(void visitCondition(), void visitThen(), void visitElse(),
7576 {SourceInformation sourceInformation}) {
7577 if (visitElse == null) {
7578 // Make sure to have an else part to avoid a critical edge. A
7579 // critical edge is an edge that connects a block with multiple
7580 // successors to a block with multiple predecessors. We avoid
7581 // such edges because they prevent inserting copies during code
7582 // generation of phi instructions.
7583 visitElse = () {};
7584 }
7585
7586 _handleDiamondBranch(visitCondition, visitThen, visitElse,
7587 isExpression: false, sourceInformation: sourceInformation);
7588 }
7589
7590 handleConditional(void visitCondition(), void visitThen(), void visitElse()) {
7591 assert(visitElse != null);
7592 _handleDiamondBranch(visitCondition, visitThen, visitElse,
7593 isExpression: true);
7594 }
7595
7596 handleIfNull(void left(), void right()) {
7597 // x ?? y is transformed into: x == null ? y : x
7598 HInstruction leftExpression;
7599 handleConditional(() {
7600 left();
7601 leftExpression = builder.pop();
7602 builder.pushCheckNull(leftExpression);
7603 }, right, () => builder.stack.add(leftExpression));
7604 }
7605
7606 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) {
7607 // x && y is transformed into:
7608 // t0 = boolify(x);
7609 // if (t0) {
7610 // t1 = boolify(y);
7611 // }
7612 // result = phi(t1, false);
7613 //
7614 // x || y is transformed into:
7615 // t0 = boolify(x);
7616 // if (not(t0)) {
7617 // t1 = boolify(y);
7618 // }
7619 // result = phi(t1, true);
7620 HInstruction boolifiedLeft;
7621 HInstruction boolifiedRight;
7622
7623 void visitCondition() {
7624 left();
7625 boolifiedLeft = builder.popBoolified();
7626 builder.stack.add(boolifiedLeft);
7627 if (!isAnd) {
7628 builder.push(new HNot(builder.pop(), builder.backend.boolType));
7629 }
7630 }
7631
7632 void visitThen() {
7633 right();
7634 boolifiedRight = builder.popBoolified();
7635 }
7636
7637 handleIf(visitCondition, visitThen, null);
7638 HConstant notIsAnd =
7639 builder.graph.addConstantBool(!isAnd, builder.compiler);
7640 JavaScriptBackend backend = builder.backend;
7641 HPhi result = new HPhi.manyInputs(
7642 null, <HInstruction>[boolifiedRight, notIsAnd], backend.dynamicType);
7643 builder.current.addPhi(result);
7644 builder.stack.add(result);
7645 }
7646
7647 void handleLogicalAndOrWithLeftNode(ast.Node left, void visitRight(),
7648 {bool isAnd}) {
7649 // This method is similar to [handleLogicalAndOr] but optimizes the case
7650 // where left is a logical "and" or logical "or".
7651 //
7652 // For example (x && y) && z is transformed into x && (y && z):
7653 // t0 = boolify(x);
7654 // if (t0) {
7655 // t1 = boolify(y);
7656 // if (t1) {
7657 // t2 = boolify(z);
7658 // }
7659 // t3 = phi(t2, false);
7660 // }
7661 // result = phi(t3, false);
7662
7663 ast.Send send = left.asSend();
7664 if (send != null && (isAnd ? send.isLogicalAnd : send.isLogicalOr)) {
7665 ast.Node newLeft = send.receiver;
7666 Link<ast.Node> link = send.argumentsNode.nodes;
7667 assert(link.tail.isEmpty);
7668 ast.Node middle = link.head;
7669 handleLogicalAndOrWithLeftNode(
7670 newLeft,
7671 () =>
7672 handleLogicalAndOrWithLeftNode(middle, visitRight, isAnd: isAnd),
7673 isAnd: isAnd);
7674 } else {
7675 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd);
7676 }
7677 }
7678
7679 void _handleDiamondBranch(
7680 void visitCondition(), void visitThen(), void visitElse(),
7681 {bool isExpression, SourceInformation sourceInformation}) {
7682 SsaBranch conditionBranch = new SsaBranch(this);
7683 SsaBranch thenBranch = new SsaBranch(this);
7684 SsaBranch elseBranch = new SsaBranch(this);
7685 SsaBranch joinBranch = new SsaBranch(this);
7686
7687 conditionBranch.startLocals = builder.localsHandler;
7688 builder.goto(builder.current, conditionBranch.block);
7689
7690 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch,
7691 sourceInformation);
7692 HInstruction thenValue =
7693 buildBranch(thenBranch, visitThen, joinBranch, isExpression);
7694 HInstruction elseValue =
7695 buildBranch(elseBranch, visitElse, joinBranch, isExpression);
7696
7697 if (isExpression) {
7698 assert(thenValue != null && elseValue != null);
7699 JavaScriptBackend backend = builder.backend;
7700 HPhi phi = new HPhi.manyInputs(
7701 null, <HInstruction>[thenValue, elseValue], backend.dynamicType);
7702 joinBranch.block.addPhi(phi);
7703 builder.stack.add(phi);
7704 }
7705
7706 HBasicBlock joinBlock;
7707 // If at least one branch did not abort, open the joinBranch.
7708 if (!joinBranch.block.predecessors.isEmpty) {
7709 startBranch(joinBranch);
7710 joinBlock = joinBranch.block;
7711 }
7712
7713 HIfBlockInformation info = new HIfBlockInformation(
7714 new HSubExpressionBlockInformation(conditionBranch.graph),
7715 new HSubGraphBlockInformation(thenBranch.graph),
7716 new HSubGraphBlockInformation(elseBranch.graph));
7717
7718 HBasicBlock conditionStartBlock = conditionBranch.block;
7719 conditionStartBlock.setBlockFlow(info, joinBlock);
7720 SubGraph conditionGraph = conditionBranch.graph;
7721 HIf branch = conditionGraph.end.last;
7722 assert(branch is HIf);
7723 branch.blockInformation = conditionStartBlock.blockFlow;
7724 }
7725 }
7726
7727 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> { 7526 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
7728 final ClassWorld classWorld; 7527 final ClassWorld classWorld;
7729 7528
7730 TypeBuilder(this.classWorld); 7529 TypeBuilder(this.classWorld);
7731 7530
7732 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder); 7531 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder);
7733 7532
7734 void visitVoidType(VoidType type, SsaBuilder builder) { 7533 void visitVoidType(VoidType type, SsaBuilder builder) {
7735 ClassElement cls = builder.backend.helpers.VoidRuntimeType; 7534 ClassElement cls = builder.backend.helpers.VoidRuntimeType;
7736 builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld))); 7535 builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld)));
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
7823 const _LoopTypeVisitor(); 7622 const _LoopTypeVisitor();
7824 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; 7623 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
7825 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; 7624 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
7826 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; 7625 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
7827 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; 7626 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
7828 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 7627 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7829 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 7628 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7830 int visitSwitchStatement(ast.SwitchStatement node) => 7629 int visitSwitchStatement(ast.SwitchStatement node) =>
7831 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; 7630 HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
7832 } 7631 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698