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

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
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | test/codegen/expect/notnull.js » ('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) 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 var jsFrom = _visit(fromExpr);
456 var from = getStaticType(fromExpr);
457
458 JS.Expression maybeCheckNull(JS.Expression jsExpr) {
459 if (checkNull && isNullable(fromExpr)) {
460 return js.call('dart.notNull(#)', jsExpr);
461 }
462 return jsExpr;
463 }
454 464
455 // Skip the cast if it's not needed. 465 // Skip the cast if it's not needed.
456 if (rules.isSubtypeOf(from, to)) return fromExpr; 466 if (to == null || rules.isSubtypeOf(from, to)) {
467 return maybeCheckNull(jsFrom);
468 }
457 469
458 // All Dart number types map to a JS double. 470 // All Dart number types map to a JS double.
459 if (_isNumberInJS(from) && _isNumberInJS(to)) { 471 if (_isNumberInJS(from) && _isNumberInJS(to)) {
460 // Make sure to check when converting to int. 472 // Make sure to check when converting to int.
461 if (from != types.intType && to == types.intType) { 473 if (from != types.intType && to == types.intType) {
462 return js.call('dart.asInt(#)', [fromExpr]); 474 // TODO(jmesserly): fuse this with notNull check.
475 return maybeCheckNull(js.call('dart.asInt(#)', [jsFrom]));
463 } 476 }
464 477
465 // A no-op in JavaScript. 478 // A no-op in JavaScript.
466 return fromExpr; 479 return maybeCheckNull(jsFrom);
467 } 480 }
468 481
469 return js.call('dart.as(#, #)', [fromExpr, _emitType(to)]); 482 if (to == types.boolType && checkNull) {
483 return js.call('dart.test(#)', _visit(fromExpr));
484 }
485
486 return maybeCheckNull(js.call('dart.as(#, #)', [jsFrom, _emitType(to)]));
470 } 487 }
471 488
472 @override 489 @override
473 visitIsExpression(IsExpression node) { 490 visitIsExpression(IsExpression node) {
474 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. 491 // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
475 JS.Expression result; 492 JS.Expression result;
476 var type = node.type.type; 493 var type = node.type.type;
477 var lhs = _visit(node.expression); 494 var lhs = _visit(node.expression);
478 var typeofName = _jsTypeofName(type); 495 var typeofName = _jsTypeofName(type);
479 if (typeofName != null) { 496 if (typeofName != null) {
(...skipping 2572 matching lines...) Expand 10 before | Expand all | Expand 10 after
3052 bool typeIsPrimitiveInJS(DartType t) => 3069 bool typeIsPrimitiveInJS(DartType t) =>
3053 _isNumberInJS(t) || t == types.boolType; 3070 _isNumberInJS(t) || t == types.boolType;
3054 3071
3055 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => 3072 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
3056 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); 3073 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT);
3057 3074
3058 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); 3075 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t);
3059 3076
3060 JS.Expression notNull(Expression expr) { 3077 JS.Expression notNull(Expression expr) {
3061 if (expr == null) return null; 3078 if (expr == null) return null;
3062 var jsExpr = _visit(expr); 3079 if (expr is AsExpression) {
3063 if (!isNullable(expr)) return jsExpr; 3080 return _emitCast(expr.expression, to: expr.type.type, checkNull: true);
3064 return js.call('dart.notNull(#)', jsExpr); 3081 }
3082 return _emitCast(expr, checkNull: true);
3065 } 3083 }
3066 3084
3067 @override 3085 @override
3068 JS.Expression visitBinaryExpression(BinaryExpression node) { 3086 JS.Expression visitBinaryExpression(BinaryExpression node) {
3069 var op = node.operator; 3087 var op = node.operator;
3070 var left = node.leftOperand; 3088 var left = node.leftOperand;
3071 var right = node.rightOperand; 3089 var right = node.rightOperand;
3072 3090
3073 var leftType = getStaticType(left); 3091 var leftType = getStaticType(left);
3074 var rightType = getStaticType(right); 3092 var rightType = getStaticType(right);
(...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after
4408 } 4426 }
4409 4427
4410 bool isLibraryPrefix(Expression node) => 4428 bool isLibraryPrefix(Expression node) =>
4411 node is SimpleIdentifier && node.staticElement is PrefixElement; 4429 node is SimpleIdentifier && node.staticElement is PrefixElement;
4412 4430
4413 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4431 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4414 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4432 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4415 4433
4416 bool _isDartRuntime(LibraryElement l) => 4434 bool _isDartRuntime(LibraryElement l) =>
4417 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4435 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | test/codegen/expect/notnull.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698