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

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

Issue 1964263002: fuse some null checks with type checks, introduce a special bool variant (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 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 // 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' show HashMap, HashSet; 5 import 'dart:collection' show HashMap, HashSet;
6 import 'dart:math' show min, max; 6 import 'dart:math' show min, max;
7 7
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 if (export is ClassElement && export.typeParameters.isNotEmpty) { 439 if (export is ClassElement && export.typeParameters.isNotEmpty) {
440 // Export the generic name as well. 440 // Export the generic name as well.
441 // TODO(jmesserly): revisit generic classes 441 // TODO(jmesserly): revisit generic classes
442 emitExport(export, suffix: r'$'); 442 emitExport(export, suffix: r'$');
443 } 443 }
444 emitExport(export); 444 emitExport(export);
445 } 445 }
446 } 446 }
447 447
448 @override 448 @override
449 visitAsExpression(AsExpression node) { 449 visitAsExpression(AsExpression node) =>
450 var from = getStaticType(node.expression); 450 _emitCast(node.expression, to: node.type.type);
451 var to = node.type.type;
452 451
453 var fromExpr = _visit(node.expression); 452 /// Emits a cast and/or a null check (i.e. a cast to a non-null type).
453 JS.Expression _emitCast(Expression fromExpr,
454 {DartType to, bool checkNull: false}) {
455
456 var jsFrom = _visit(fromExpr);
457 var from = getStaticType(fromExpr);
458
459 JS.Expression maybeCheckNull(JS.Expression jsExpr) {
Jennifer Messerly 2016/05/10 23:42:12 aside: it might be a better architecture to fuse t
460 if (checkNull && isNullable(fromExpr)) {
461 return js.call('dart.notNull(#)', jsExpr);
462 }
463 return jsExpr;
464 }
454 465
455 // Skip the cast if it's not needed. 466 // Skip the cast if it's not needed.
456 if (rules.isSubtypeOf(from, to)) return fromExpr; 467 if (to == null || rules.isSubtypeOf(from, to)) {
468 return maybeCheckNull(jsFrom);
469 }
457 470
458 // All Dart number types map to a JS double. 471 // All Dart number types map to a JS double.
459 if (_isNumberInJS(from) && _isNumberInJS(to)) { 472 if (_isNumberInJS(from) && _isNumberInJS(to)) {
460 // Make sure to check when converting to int. 473 // Make sure to check when converting to int.
461 if (from != types.intType && to == types.intType) { 474 if (from != types.intType && to == types.intType) {
462 return js.call('dart.asInt(#)', [fromExpr]); 475 // TODO(jmesserly): fuse this with notNull check.
476 return maybeCheckNull(js.call('dart.asInt(#)', [jsFrom]));
463 } 477 }
464 478
465 // A no-op in JavaScript. 479 // A no-op in JavaScript.
466 return fromExpr; 480 return maybeCheckNull(jsFrom);
467 } 481 }
468 482
469 return js.call('dart.as(#, #)', [fromExpr, _emitType(to)]); 483 if (to == types.boolType && checkNull) {
484 return js.call('dart.test(#)', _visit(fromExpr));
485 }
486
487 if (checkNull && isNullable(fromExpr)) {
488 return js.call('dart.asNotNull(#, #)', [jsFrom, _emitType(to)]);
489 } else {
490 return js.call('dart.as(#, #)', [jsFrom, _emitType(to)]);
491 }
470 } 492 }
471 493
472 @override 494 @override
473 visitIsExpression(IsExpression node) { 495 visitIsExpression(IsExpression node) {
474 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. 496 // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
475 JS.Expression result; 497 JS.Expression result;
476 var type = node.type.type; 498 var type = node.type.type;
477 var lhs = _visit(node.expression); 499 var lhs = _visit(node.expression);
478 var typeofName = _jsTypeofName(type); 500 var typeofName = _jsTypeofName(type);
479 if (typeofName != null) { 501 if (typeofName != null) {
(...skipping 2572 matching lines...) Expand 10 before | Expand all | Expand 10 after
3052 bool typeIsPrimitiveInJS(DartType t) => 3074 bool typeIsPrimitiveInJS(DartType t) =>
3053 _isNumberInJS(t) || t == types.boolType; 3075 _isNumberInJS(t) || t == types.boolType;
3054 3076
3055 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => 3077 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
3056 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); 3078 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT);
3057 3079
3058 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); 3080 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t);
3059 3081
3060 JS.Expression notNull(Expression expr) { 3082 JS.Expression notNull(Expression expr) {
3061 if (expr == null) return null; 3083 if (expr == null) return null;
3062 var jsExpr = _visit(expr); 3084 if (expr is AsExpression) {
3063 if (!isNullable(expr)) return jsExpr; 3085 return _emitCast(expr.expression, to: expr.type.type, checkNull: true);
3064 return js.call('dart.notNull(#)', jsExpr); 3086 }
3087 return _emitCast(expr, checkNull: true);
3065 } 3088 }
3066 3089
3067 @override 3090 @override
3068 JS.Expression visitBinaryExpression(BinaryExpression node) { 3091 JS.Expression visitBinaryExpression(BinaryExpression node) {
3069 var op = node.operator; 3092 var op = node.operator;
3070 var left = node.leftOperand; 3093 var left = node.leftOperand;
3071 var right = node.rightOperand; 3094 var right = node.rightOperand;
3072 3095
3073 var leftType = getStaticType(left); 3096 var leftType = getStaticType(left);
3074 var rightType = getStaticType(right); 3097 var rightType = getStaticType(right);
(...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after
4408 } 4431 }
4409 4432
4410 bool isLibraryPrefix(Expression node) => 4433 bool isLibraryPrefix(Expression node) =>
4411 node is SimpleIdentifier && node.staticElement is PrefixElement; 4434 node is SimpleIdentifier && node.staticElement is PrefixElement;
4412 4435
4413 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4436 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4414 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4437 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4415 4438
4416 bool _isDartRuntime(LibraryElement l) => 4439 bool _isDartRuntime(LibraryElement l) =>
4417 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4440 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698