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

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/code_generator.dart

Issue 2944413002: optimize null safe ops by using DDC's let abstraction (Closed)
Patch Set: Created 3 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 2
3 // for details. All rights reserved. Use of this source code is governed by a 3 // for details. All rights reserved. Use of this source code is governed by a
4 // BSD-style license that can be found in the LICENSE file. 4 // BSD-style license that can be found in the LICENSE file.
5 5
6 import 'dart:collection' show HashMap, HashSet; 6 import 'dart:collection' show HashMap, HashSet;
7 import 'dart:math' show min, max; 7 import 'dart:math' show min, max;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 4677 matching lines...) Expand 10 before | Expand all | Expand 10 after
4688 4688
4689 @override 4689 @override
4690 visitPropertyAccess(PropertyAccess node) { 4690 visitPropertyAccess(PropertyAccess node) {
4691 if (node.operator.lexeme == '?.') { 4691 if (node.operator.lexeme == '?.') {
4692 return _emitNullSafe(node); 4692 return _emitNullSafe(node);
4693 } 4693 }
4694 return _emitAccess(_getTarget(node), node.propertyName, node.staticType); 4694 return _emitAccess(_getTarget(node), node.propertyName, node.staticType);
4695 } 4695 }
4696 4696
4697 JS.Expression _emitNullSafe(Expression node) { 4697 JS.Expression _emitNullSafe(Expression node) {
4698 // Desugar ?. sequence by passing a sequence of callbacks that applies 4698 // Desugar `obj?.name` as ((x) => x == null ? null : x.name)(obj)
4699 // each operation in sequence: 4699 var target = _getTarget(node);
4700 // 4700 var vars = <JS.MetaLetVariable, JS.Expression>{};
4701 // obj?.foo()?.bar 4701 var t = _bindValue(vars, 't', target, context: target);
4702 // --> 4702 return new JS.MetaLet(vars, [
4703 // nullSafe(obj, _ => _.foo(), _ => _.bar); 4703 js.call('# == null ? null : #',
4704 // 4704 [_visit(t), _visit(_stripNullAwareOp(node, t))])
4705 // This pattern has the benefit of preserving order, as well as minimizing 4705 ]);
4706 // code expansion: each `?.` becomes `, _ => _`, plus one helper call.
4707 //
4708 // TODO(jmesserly): we could desugar with MetaLet instead, which may
4709 // lead to higher performing code, but at the cost of readability.
4710 var tail = <JS.Expression>[];
4711 for (;;) {
4712 var op = _getOperator(node);
4713 if (op != null && op.lexeme == '?.') {
4714 var nodeTarget = _getTarget(node);
4715 if (!isNullable(nodeTarget)) {
4716 node = _stripNullAwareOp(node, nodeTarget);
4717 break;
4718 }
4719
4720 var param = _createTemporary('_', nodeTarget.staticType,
4721 nullable: false, dynamicInvoke: isDynamicInvoke(nodeTarget));
4722 var baseNode = _stripNullAwareOp(node, param);
4723 tail.add(
4724 new JS.ArrowFun(<JS.Parameter>[_visit(param)], _visit(baseNode)));
4725 node = nodeTarget;
4726 } else {
4727 break;
4728 }
4729 }
4730 if (tail.isEmpty) return _visit(node);
4731 return _callHelper(
4732 'nullSafe(#, #)', [_visit(node) as JS.Expression, tail.reversed]);
4733 } 4706 }
4734 4707
4735 static Token _getOperator(Expression node) { 4708 static Token _getOperator(Expression node) {
4736 if (node is PropertyAccess) return node.operator; 4709 if (node is PropertyAccess) return node.operator;
4737 if (node is MethodInvocation) return node.operator; 4710 if (node is MethodInvocation) return node.operator;
4738 return null; 4711 return null;
4739 } 4712 }
4740 4713
4741 // TODO(jmesserly): this is dropping source location. 4714 // TODO(jmesserly): this is dropping source location.
4742 Expression _stripNullAwareOp(Expression node, Expression newTarget) { 4715 Expression _stripNullAwareOp(Expression node, Expression newTarget) {
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after
5863 if (targetIdentifier.staticElement is! PrefixElement) return false; 5836 if (targetIdentifier.staticElement is! PrefixElement) return false;
5864 var prefix = targetIdentifier.staticElement as PrefixElement; 5837 var prefix = targetIdentifier.staticElement as PrefixElement;
5865 5838
5866 // The library the prefix is referring to must come from a deferred import. 5839 // The library the prefix is referring to must come from a deferred import.
5867 var containingLibrary = resolutionMap 5840 var containingLibrary = resolutionMap
5868 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 5841 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
5869 .library; 5842 .library;
5870 var imports = containingLibrary.getImportsWithPrefix(prefix); 5843 var imports = containingLibrary.getImportsWithPrefix(prefix);
5871 return imports.length == 1 && imports[0].isDeferred; 5844 return imports.length == 1 && imports[0].isDeferred;
5872 } 5845 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/sdk/ddc_sdk.sum ('k') | pkg/dev_compiler/lib/src/compiler/side_effect_analysis.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698