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

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

Issue 2301293002: kernel -> ssa: implement if-statements (Closed)
Patch Set: add visitNot 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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:js_runtime/shared/embedded_names.dart'; 7 import 'package:js_runtime/shared/embedded_names.dart';
8 8
9 import '../closure.dart'; 9 import '../closure.dart';
10 import '../common.dart'; 10 import '../common.dart';
(...skipping 20 matching lines...) Expand all
31 import '../resolution/semantic_visitor.dart'; 31 import '../resolution/semantic_visitor.dart';
32 import '../resolution/tree_elements.dart' show TreeElements; 32 import '../resolution/tree_elements.dart' show TreeElements;
33 import '../tree/tree.dart' as ast; 33 import '../tree/tree.dart' as ast;
34 import '../types/types.dart'; 34 import '../types/types.dart';
35 import '../universe/call_structure.dart' show CallStructure; 35 import '../universe/call_structure.dart' show CallStructure;
36 import '../universe/selector.dart' show Selector; 36 import '../universe/selector.dart' show Selector;
37 import '../universe/side_effects.dart' show SideEffects; 37 import '../universe/side_effects.dart' show SideEffects;
38 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse; 38 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
39 import '../util/util.dart'; 39 import '../util/util.dart';
40 import '../world.dart' show ClassWorld; 40 import '../world.dart' show ClassWorld;
41
41 import 'graph_builder.dart'; 42 import 'graph_builder.dart';
42 import 'locals_handler.dart'; 43 import 'locals_handler.dart';
43 import 'nodes.dart'; 44 import 'nodes.dart';
44 import 'optimize.dart'; 45 import 'optimize.dart';
46 import 'ssa_branch_builder.dart';
45 import 'types.dart'; 47 import 'types.dart';
46 48
47 /// A synthetic local variable only used with the SSA graph. 49 /// A synthetic local variable only used with the SSA graph.
48 /// 50 ///
49 /// For instance used for holding return value of function or the exception of a 51 /// For instance used for holding return value of function or the exception of a
50 /// try-catch statement. 52 /// try-catch statement.
51 class SyntheticLocal extends Local { 53 class SyntheticLocal extends Local {
52 final String name; 54 final String name;
53 final ExecutableElement executableContext; 55 final ExecutableElement executableContext;
54 56
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 * account. 406 * account.
405 */ 407 */
406 int loopNesting = 0; 408 int loopNesting = 0;
407 409
408 /** 410 /**
409 * This stack contains declaration elements of the functions being built 411 * This stack contains declaration elements of the functions being built
410 * or inlined by this builder. 412 * or inlined by this builder.
411 */ 413 */
412 final List<Element> sourceElementStack = <Element>[]; 414 final List<Element> sourceElementStack = <Element>[];
413 415
414 LocalsHandler localsHandler;
415
416 HInstruction rethrowableException; 416 HInstruction rethrowableException;
417 417
418 Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{}; 418 Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
419 419
420 /// Returns `true` if the current element is an `async` function. 420 /// Returns `true` if the current element is an `async` function.
421 bool get isBuildingAsyncFunction { 421 bool get isBuildingAsyncFunction {
422 Element element = sourceElement; 422 Element element = sourceElement;
423 return (element is FunctionElement && 423 return (element is FunctionElement &&
424 element.asyncMarker == AsyncMarker.ASYNC); 424 element.asyncMarker == AsyncMarker.ASYNC);
425 } 425 }
(...skipping 1474 matching lines...) Expand 10 before | Expand all | Expand 10 after
1900 // TODO(kasperl): Make this goto an implicit return. 1900 // TODO(kasperl): Make this goto an implicit return.
1901 if (!isAborted()) closeAndGotoExit(new HGoto()); 1901 if (!isAborted()) closeAndGotoExit(new HGoto());
1902 graph.finalize(); 1902 graph.finalize();
1903 return graph; 1903 return graph;
1904 } 1904 }
1905 1905
1906 void pushWithPosition(HInstruction instruction, ast.Node node) { 1906 void pushWithPosition(HInstruction instruction, ast.Node node) {
1907 push(attachPosition(instruction, node)); 1907 push(attachPosition(instruction, node));
1908 } 1908 }
1909 1909
1910 @override
1910 HInstruction popBoolified() { 1911 HInstruction popBoolified() {
1911 HInstruction value = pop(); 1912 HInstruction value = pop();
1912 if (_checkOrTrustTypes) { 1913 if (_checkOrTrustTypes) {
1913 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType, 1914 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType,
1914 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 1915 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
1915 } 1916 }
1916 HInstruction result = new HBoolify(value, backend.boolType); 1917 HInstruction result = new HBoolify(value, backend.boolType);
1917 add(result); 1918 add(result);
1918 return result; 1919 return result;
1919 } 1920 }
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after
2530 visitThen: () => visit(node.thenPart), 2531 visitThen: () => visit(node.thenPart),
2531 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, 2532 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null,
2532 sourceInformation: sourceInformationBuilder.buildIf(node)); 2533 sourceInformation: sourceInformationBuilder.buildIf(node));
2533 } 2534 }
2534 2535
2535 void handleIf(ast.Node diagnosticNode, 2536 void handleIf(ast.Node diagnosticNode,
2536 {void visitCondition(), 2537 {void visitCondition(),
2537 void visitThen(), 2538 void visitThen(),
2538 void visitElse(), 2539 void visitElse(),
2539 SourceInformation sourceInformation}) { 2540 SourceInformation sourceInformation}) {
2540 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); 2541 SsaBranchBuilder branchBuilder =
2542 new SsaBranchBuilder(this, compiler, diagnosticNode);
2541 branchBuilder.handleIf(visitCondition, visitThen, visitElse, 2543 branchBuilder.handleIf(visitCondition, visitThen, visitElse,
2542 sourceInformation: sourceInformation); 2544 sourceInformation: sourceInformation);
2543 } 2545 }
2544 2546
2545 @override 2547 @override
2546 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { 2548 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) {
2547 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 2549 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
2548 brancher.handleIfNull(() => visit(left), () => visit(right)); 2550 brancher.handleIfNull(() => visit(left), () => visit(right));
2549 } 2551 }
2550 2552
2553 /// Optimizes logical binary where the left is also a logical binary.
2554 ///
2555 /// This method transforms the operator by optimizing the case where [left] is
2556 /// a logical "and" or logical "or". Then it uses [branchBuilder] to build the
2557 /// graph for the optimized expression.
2558 ///
2559 /// For example, `(x && y) && z` is transformed into `x && (y && z)`:
2560 ///
2561 /// t0 = boolify(x);
2562 /// if (t0) {
2563 /// t1 = boolify(y);
2564 /// if (t1) {
2565 /// t2 = boolify(z);
2566 /// }
2567 /// t3 = phi(t2, false);
2568 /// }
2569 /// result = phi(t3, false);
2570 void handleLogicalBinaryWithLeftNode(
2571 ast.Node left, void visitRight(), SsaBranchBuilder branchBuilder,
2572 {bool isAnd}) {
2573 ast.Send send = left.asSend();
2574 if (send != null && (isAnd ? send.isLogicalAnd : send.isLogicalOr)) {
2575 ast.Node newLeft = send.receiver;
2576 Link<ast.Node> link = send.argumentsNode.nodes;
2577 assert(link.tail.isEmpty);
2578 ast.Node middle = link.head;
2579 handleLogicalBinaryWithLeftNode(
2580 newLeft,
2581 () => handleLogicalBinaryWithLeftNode(
2582 middle, visitRight, branchBuilder,
2583 isAnd: isAnd),
2584 branchBuilder,
2585 isAnd: isAnd);
2586 } else {
2587 branchBuilder.handleLogicalBinary(() => visit(left), visitRight,
2588 isAnd: isAnd);
2589 }
2590 }
2591
2551 @override 2592 @override
2552 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { 2593 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) {
2553 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); 2594 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler, node);
2554 branchBuilder.handleLogicalAndOrWithLeftNode(left, () { 2595 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder,
2555 visit(right); 2596 isAnd: true);
2556 }, isAnd: true);
2557 } 2597 }
2558 2598
2559 @override 2599 @override
2560 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) { 2600 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) {
2561 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); 2601 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, compiler, node);
2562 branchBuilder.handleLogicalAndOrWithLeftNode(left, () { 2602 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder,
2563 visit(right); 2603 isAnd: false);
2564 }, isAnd: false);
2565 } 2604 }
2566 2605
2567 @override 2606 @override
2568 void visitNot(ast.Send node, ast.Node expression, _) { 2607 void visitNot(ast.Send node, ast.Node expression, _) {
2569 assert(node.argumentsNode is ast.Prefix); 2608 assert(node.argumentsNode is ast.Prefix);
2570 visit(expression); 2609 visit(expression);
2571 SourceInformation sourceInformation = 2610 SourceInformation sourceInformation =
2572 sourceInformationBuilder.buildGeneric(node); 2611 sourceInformationBuilder.buildGeneric(node);
2573 push(new HNot(popBoolified(), backend.boolType) 2612 push(new HNot(popBoolified(), backend.boolType)
2574 ..sourceInformation = sourceInformation); 2613 ..sourceInformation = sourceInformation);
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
2812 @override 2851 @override
2813 void visitIfNotNullDynamicPropertyGet( 2852 void visitIfNotNullDynamicPropertyGet(
2814 ast.Send node, ast.Node receiver, Name name, _) { 2853 ast.Send node, ast.Node receiver, Name name, _) {
2815 // exp?.x compiled as: 2854 // exp?.x compiled as:
2816 // t1 = exp; 2855 // t1 = exp;
2817 // result = t1 == null ? t1 : t1.x; 2856 // result = t1 == null ? t1 : t1.x;
2818 // This is equivalent to t1 == null ? null : t1.x, but in the current form 2857 // This is equivalent to t1 == null ? null : t1.x, but in the current form
2819 // we will be able to later compress it as: 2858 // we will be able to later compress it as:
2820 // t1 || t1.x 2859 // t1 || t1.x
2821 HInstruction expression; 2860 HInstruction expression;
2822 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 2861 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
2823 brancher.handleConditional( 2862 brancher.handleConditional(
2824 () { 2863 () {
2825 expression = visitAndPop(receiver); 2864 expression = visitAndPop(receiver);
2826 pushCheckNull(expression); 2865 pushCheckNull(expression);
2827 }, 2866 },
2828 () => stack.add(expression), 2867 () => stack.add(expression),
2829 () { 2868 () {
2830 generateInstanceGetterWithCompiledReceiver( 2869 generateInstanceGetterWithCompiledReceiver(
2831 node, 2870 node,
2832 elements.getSelector(node), 2871 elements.getSelector(node),
2833 elements.getTypeMask(node), 2872 elements.getTypeMask(node),
2834 expression); 2873 expression);
2835 }); 2874 });
2836 } 2875 }
2837 2876
2838 /// Pushes a boolean checking [expression] against null. 2877 @override
2839 pushCheckNull(HInstruction expression) { 2878 pushCheckNull(HInstruction expression) {
2840 push(new HIdentity( 2879 push(new HIdentity(
2841 expression, graph.addConstantNull(compiler), null, backend.boolType)); 2880 expression, graph.addConstantNull(compiler), null, backend.boolType));
2842 } 2881 }
2843 2882
2844 @override 2883 @override
2845 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { 2884 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) {
2846 handleLocalGet(node, variable); 2885 handleLocalGet(node, variable);
2847 } 2886 }
2848 2887
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
3195 visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver, 3234 visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver,
3196 ast.NodeList arguments, Selector selector, _) { 3235 ast.NodeList arguments, Selector selector, _) {
3197 generateDynamicSend(node); 3236 generateDynamicSend(node);
3198 } 3237 }
3199 3238
3200 @override 3239 @override
3201 visitIfNotNullDynamicPropertyInvoke(ast.Send node, ast.Node receiver, 3240 visitIfNotNullDynamicPropertyInvoke(ast.Send node, ast.Node receiver,
3202 ast.NodeList arguments, Selector selector, _) { 3241 ast.NodeList arguments, Selector selector, _) {
3203 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()` 3242 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()`
3204 HInstruction receiver; 3243 HInstruction receiver;
3205 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 3244 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
3206 brancher.handleConditional(() { 3245 brancher.handleConditional(() {
3207 receiver = generateInstanceSendReceiver(node); 3246 receiver = generateInstanceSendReceiver(node);
3208 pushCheckNull(receiver); 3247 pushCheckNull(receiver);
3209 }, () => stack.add(receiver), () => _generateDynamicSend(node, receiver)); 3248 }, () => stack.add(receiver), () => _generateDynamicSend(node, receiver));
3210 } 3249 }
3211 3250
3212 @override 3251 @override
3213 visitThisPropertyInvoke( 3252 visitThisPropertyInvoke(
3214 ast.Send node, ast.NodeList arguments, Selector selector, _) { 3253 ast.Send node, ast.NodeList arguments, Selector selector, _) {
3215 generateDynamicSend(node); 3254 generateDynamicSend(node);
(...skipping 1785 matching lines...) Expand 10 before | Expand all | Expand 10 after
5001 if (Elements.isUnresolved(getter)) { 5040 if (Elements.isUnresolved(getter)) {
5002 generateSuperNoSuchMethodSend(node, getterSelector, getterInputs); 5041 generateSuperNoSuchMethodSend(node, getterSelector, getterInputs);
5003 getterInstruction = pop(); 5042 getterInstruction = pop();
5004 } else { 5043 } else {
5005 getterInstruction = 5044 getterInstruction =
5006 buildInvokeSuper(getterSelector, getter, getterInputs); 5045 buildInvokeSuper(getterSelector, getter, getterInputs);
5007 add(getterInstruction); 5046 add(getterInstruction);
5008 } 5047 }
5009 5048
5010 if (node.isIfNullAssignment) { 5049 if (node.isIfNullAssignment) {
5011 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5050 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5012 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5051 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5013 addDynamicSendArgumentsToList(node, setterInputs); 5052 addDynamicSendArgumentsToList(node, setterInputs);
5014 generateSuperSendSet(); 5053 generateSuperSendSet();
5015 stack.add(setterInputs.last); 5054 stack.add(setterInputs.last);
5016 }); 5055 });
5017 } else { 5056 } else {
5018 handleComplexOperatorSend(node, getterInstruction, arguments); 5057 handleComplexOperatorSend(node, getterInstruction, arguments);
5019 setterInputs.add(pop()); 5058 setterInputs.add(pop());
5020 generateSuperSendSet(); 5059 generateSuperSendSet();
5021 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); 5060 stack.add(node.isPostfix ? getterInstruction : setterInputs.last);
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
5321 5360
5322 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node), 5361 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node),
5323 elements.getGetterTypeMaskInComplexSendSet(node), [receiver, index]); 5362 elements.getGetterTypeMaskInComplexSendSet(node), [receiver, index]);
5324 HInstruction getterInstruction = pop(); 5363 HInstruction getterInstruction = pop();
5325 if (node.isIfNullAssignment) { 5364 if (node.isIfNullAssignment) {
5326 // Compile x[i] ??= e as: 5365 // Compile x[i] ??= e as:
5327 // t1 = x[i] 5366 // t1 = x[i]
5328 // if (t1 == null) 5367 // if (t1 == null)
5329 // t1 = x[i] = e; 5368 // t1 = x[i] = e;
5330 // result = t1 5369 // result = t1
5331 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5370 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5332 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5371 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5333 visit(arguments.head); 5372 visit(arguments.head);
5334 HInstruction value = pop(); 5373 HInstruction value = pop();
5335 pushInvokeDynamic(node, elements.getSelector(node), 5374 pushInvokeDynamic(node, elements.getSelector(node),
5336 elements.getTypeMask(node), [receiver, index, value]); 5375 elements.getTypeMask(node), [receiver, index, value]);
5337 pop(); 5376 pop();
5338 stack.add(value); 5377 stack.add(value);
5339 }); 5378 });
5340 } else { 5379 } else {
5341 handleComplexOperatorSend(node, getterInstruction, arguments); 5380 handleComplexOperatorSend(node, getterInstruction, arguments);
(...skipping 27 matching lines...) Expand all
5369 void visitIfNotNullDynamicPropertySet( 5408 void visitIfNotNullDynamicPropertySet(
5370 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) { 5409 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) {
5371 // compile e?.x = e2 to: 5410 // compile e?.x = e2 to:
5372 // 5411 //
5373 // t1 = e 5412 // t1 = e
5374 // if (t1 == null) 5413 // if (t1 == null)
5375 // result = t1 // same as result = null 5414 // result = t1 // same as result = null
5376 // else 5415 // else
5377 // result = e.x = e2 5416 // result = e.x = e2
5378 HInstruction receiverInstruction; 5417 HInstruction receiverInstruction;
5379 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5418 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5380 brancher.handleConditional( 5419 brancher.handleConditional(
5381 () { 5420 () {
5382 receiverInstruction = generateInstanceSendReceiver(node); 5421 receiverInstruction = generateInstanceSendReceiver(node);
5383 pushCheckNull(receiverInstruction); 5422 pushCheckNull(receiverInstruction);
5384 }, 5423 },
5385 () => stack.add(receiverInstruction), 5424 () => stack.add(receiverInstruction),
5386 () { 5425 () {
5387 generateInstanceSetterWithCompiledReceiver( 5426 generateInstanceSetterWithCompiledReceiver(
5388 node, receiverInstruction, visitAndPop(rhs)); 5427 node, receiverInstruction, visitAndPop(rhs));
5389 }); 5428 });
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
5542 if (Elements.isInstanceSend(node, elements)) { 5581 if (Elements.isInstanceSend(node, elements)) {
5543 void generateAssignment(HInstruction receiver) { 5582 void generateAssignment(HInstruction receiver) {
5544 // desugars `e.x op= e2` to `e.x = e.x op e2` 5583 // desugars `e.x op= e2` to `e.x = e.x op e2`
5545 generateInstanceGetterWithCompiledReceiver( 5584 generateInstanceGetterWithCompiledReceiver(
5546 node, 5585 node,
5547 elements.getGetterSelectorInComplexSendSet(node), 5586 elements.getGetterSelectorInComplexSendSet(node),
5548 elements.getGetterTypeMaskInComplexSendSet(node), 5587 elements.getGetterTypeMaskInComplexSendSet(node),
5549 receiver); 5588 receiver);
5550 HInstruction getterInstruction = pop(); 5589 HInstruction getterInstruction = pop();
5551 if (node.isIfNullAssignment) { 5590 if (node.isIfNullAssignment) {
5552 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5591 SsaBranchBuilder brancher =
5592 new SsaBranchBuilder(this, compiler, node);
5553 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5593 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5554 visit(node.arguments.head); 5594 visit(node.arguments.head);
5555 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); 5595 generateInstanceSetterWithCompiledReceiver(node, receiver, pop());
5556 }); 5596 });
5557 } else { 5597 } else {
5558 handleComplexOperatorSend(node, getterInstruction, node.arguments); 5598 handleComplexOperatorSend(node, getterInstruction, node.arguments);
5559 HInstruction value = pop(); 5599 HInstruction value = pop();
5560 generateInstanceSetterWithCompiledReceiver(node, receiver, value); 5600 generateInstanceSetterWithCompiledReceiver(node, receiver, value);
5561 } 5601 }
5562 if (node.isPostfix) { 5602 if (node.isPostfix) {
5563 pop(); 5603 pop();
5564 stack.add(getterInstruction); 5604 stack.add(getterInstruction);
5565 } 5605 }
5566 } 5606 }
5567 5607
5568 if (node.isConditional) { 5608 if (node.isConditional) {
5569 // generate `e?.x op= e2` as: 5609 // generate `e?.x op= e2` as:
5570 // t1 = e 5610 // t1 = e
5571 // t1 == null ? t1 : (t1.x = t1.x op e2); 5611 // t1 == null ? t1 : (t1.x = t1.x op e2);
5572 HInstruction receiver; 5612 HInstruction receiver;
5573 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5613 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5574 brancher.handleConditional(() { 5614 brancher.handleConditional(() {
5575 receiver = generateInstanceSendReceiver(node); 5615 receiver = generateInstanceSendReceiver(node);
5576 pushCheckNull(receiver); 5616 pushCheckNull(receiver);
5577 }, () => stack.add(receiver), () => generateAssignment(receiver)); 5617 }, () => stack.add(receiver), () => generateAssignment(receiver));
5578 } else { 5618 } else {
5579 generateAssignment(generateInstanceSendReceiver(node)); 5619 generateAssignment(generateInstanceSendReceiver(node));
5580 } 5620 }
5581 return; 5621 return;
5582 } 5622 }
5583 5623
5584 if (getter.isMalformed) { 5624 if (getter.isMalformed) {
5585 generateStaticUnresolvedGet(node, getter); 5625 generateStaticUnresolvedGet(node, getter);
5586 } else if (getter.isField) { 5626 } else if (getter.isField) {
5587 generateStaticFieldGet(node, getter); 5627 generateStaticFieldGet(node, getter);
5588 } else if (getter.isGetter) { 5628 } else if (getter.isGetter) {
5589 generateStaticGetterGet(node, getter); 5629 generateStaticGetterGet(node, getter);
5590 } else if (getter.isFunction) { 5630 } else if (getter.isFunction) {
5591 generateStaticFunctionGet(node, getter); 5631 generateStaticFunctionGet(node, getter);
5592 } else if (getter.isLocal) { 5632 } else if (getter.isLocal) {
5593 handleLocalGet(node, getter); 5633 handleLocalGet(node, getter);
5594 } else { 5634 } else {
5595 internalError(node, "Unexpected getter: $getter"); 5635 internalError(node, "Unexpected getter: $getter");
5596 } 5636 }
5597 HInstruction getterInstruction = pop(); 5637 HInstruction getterInstruction = pop();
5598 if (node.isIfNullAssignment) { 5638 if (node.isIfNullAssignment) {
5599 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5639 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5600 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5640 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5601 visit(node.arguments.head); 5641 visit(node.arguments.head);
5602 generateNonInstanceSetter(node, element, pop()); 5642 generateNonInstanceSetter(node, element, pop());
5603 }); 5643 });
5604 } else { 5644 } else {
5605 handleComplexOperatorSend(node, getterInstruction, node.arguments); 5645 handleComplexOperatorSend(node, getterInstruction, node.arguments);
5606 HInstruction value = pop(); 5646 HInstruction value = pop();
5607 generateNonInstanceSetter(node, element, value); 5647 generateNonInstanceSetter(node, element, value);
5608 } 5648 }
5609 if (node.isPostfix) { 5649 if (node.isPostfix) {
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
5999 instruction = setRtiIfNeeded(instruction, node); 6039 instruction = setRtiIfNeeded(instruction, node);
6000 } 6040 }
6001 6041
6002 TypeMask type = 6042 TypeMask type =
6003 TypeMaskFactory.inferredForNode(sourceElement, node, compiler); 6043 TypeMaskFactory.inferredForNode(sourceElement, node, compiler);
6004 if (!type.containsAll(compiler.world)) instruction.instructionType = type; 6044 if (!type.containsAll(compiler.world)) instruction.instructionType = type;
6005 stack.add(instruction); 6045 stack.add(instruction);
6006 } 6046 }
6007 6047
6008 visitConditional(ast.Conditional node) { 6048 visitConditional(ast.Conditional node) {
6009 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6049 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
6010 brancher.handleConditional(() => visit(node.condition), 6050 brancher.handleConditional(() => visit(node.condition),
6011 () => visit(node.thenExpression), () => visit(node.elseExpression)); 6051 () => visit(node.thenExpression), () => visit(node.elseExpression));
6012 } 6052 }
6013 6053
6014 visitStringInterpolation(ast.StringInterpolation node) { 6054 visitStringInterpolation(ast.StringInterpolation node) {
6015 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); 6055 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
6016 stringBuilder.visit(node); 6056 stringBuilder.visit(node);
6017 stack.add(stringBuilder.result); 6057 stack.add(stringBuilder.result);
6018 } 6058 }
6019 6059
(...skipping 1451 matching lines...) Expand 10 before | Expand all | Expand 10 after
7471 this.oldReturnLocal, 7511 this.oldReturnLocal,
7472 this.oldReturnType, 7512 this.oldReturnType,
7473 this.oldResolvedAst, 7513 this.oldResolvedAst,
7474 this.oldStack, 7514 this.oldStack,
7475 this.oldLocalsHandler, 7515 this.oldLocalsHandler,
7476 this.inTryStatement, 7516 this.inTryStatement,
7477 this.allFunctionsCalledOnce) 7517 this.allFunctionsCalledOnce)
7478 : super(function); 7518 : super(function);
7479 } 7519 }
7480 7520
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> { 7521 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
7728 final ClassWorld classWorld; 7522 final ClassWorld classWorld;
7729 7523
7730 TypeBuilder(this.classWorld); 7524 TypeBuilder(this.classWorld);
7731 7525
7732 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder); 7526 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder);
7733 7527
7734 void visitVoidType(VoidType type, SsaBuilder builder) { 7528 void visitVoidType(VoidType type, SsaBuilder builder) {
7735 ClassElement cls = builder.backend.helpers.VoidRuntimeType; 7529 ClassElement cls = builder.backend.helpers.VoidRuntimeType;
7736 builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld))); 7530 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(); 7617 const _LoopTypeVisitor();
7824 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; 7618 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
7825 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; 7619 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
7826 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; 7620 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
7827 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; 7621 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
7828 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 7622 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7829 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 7623 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7830 int visitSwitchStatement(ast.SwitchStatement node) => 7624 int visitSwitchStatement(ast.SwitchStatement node) =>
7831 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; 7625 HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
7832 } 7626 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698