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

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

Issue 1998113004: Optimize const construction (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') | tool/input_sdk/private/ddc_runtime/operations.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) 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 811 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 822
823 // Create static fields for each enum value 823 // Create static fields for each enum value
824 for (var i = 0; i < fields.length; ++i) { 824 for (var i = 0; i < fields.length; ++i) {
825 result.add(js.statement('#.# = dart.const(new #(#));', 825 result.add(js.statement('#.# = dart.const(new #(#));',
826 [id, fields[i].name, id, js.number(i)])); 826 [id, fields[i].name, id, js.number(i)]));
827 } 827 }
828 828
829 // Create static values list 829 // Create static values list
830 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( 830 var values = new JS.ArrayInitializer(new List<JS.Expression>.from(
831 fields.map((f) => js.call('#.#', [id, f.name])))); 831 fields.map((f) => js.call('#.#', [id, f.name]))));
832 result.add(js.statement('#.values = dart.const(dart.list(#, #));', 832 result.add(js.statement('#.values = dart.constList(#, #);',
833 [id, values, _emitType(type)])); 833 [id, values, _emitType(type)]));
834 834
835 return _statement(result); 835 return _statement(result);
836 } 836 }
837 837
838 /// Wraps a possibly generic class in its type arguments. 838 /// Wraps a possibly generic class in its type arguments.
839 JS.Statement _defineClassTypeArguments(TypeDefiningElement element, 839 JS.Statement _defineClassTypeArguments(TypeDefiningElement element,
840 List<TypeParameterElement> formals, JS.Statement body) { 840 List<TypeParameterElement> formals, JS.Statement body) {
841 assert(formals.isNotEmpty); 841 assert(formals.isNotEmpty);
842 var genericCall = js.call('dart.generic((#) => { #; return #; })', 842 var genericCall = js.call('dart.generic((#) => { #; return #; })',
(...skipping 2583 matching lines...) Expand 10 before | Expand all | Expand 10 after
3426 3426
3427 variable ??= new JS.TemporaryId(name); 3427 variable ??= new JS.TemporaryId(name);
3428 3428
3429 id.staticElement = new TemporaryVariableElement.forNode(id, variable); 3429 id.staticElement = new TemporaryVariableElement.forNode(id, variable);
3430 id.staticType = type; 3430 id.staticType = type;
3431 DynamicInvoke.set(id, type.isDynamic); 3431 DynamicInvoke.set(id, type.isDynamic);
3432 addTemporaryVariable(id.staticElement, nullable: nullable); 3432 addTemporaryVariable(id.staticElement, nullable: nullable);
3433 return id; 3433 return id;
3434 } 3434 }
3435 3435
3436 JS.Expression _emitConst(JS.Expression expr()) { 3436 JS.Expression _cacheConst(JS.Expression expr()) {
3437 var savedTypeParams = _typeParamInConst; 3437 var savedTypeParams = _typeParamInConst;
3438 _typeParamInConst = []; 3438 _typeParamInConst = [];
3439 3439
3440 var jsExpr = js.call('dart.const(#)', expr()); 3440 var jsExpr = expr();
3441 3441
3442 bool usesTypeParams = _typeParamInConst.isNotEmpty; 3442 bool usesTypeParams = _typeParamInConst.isNotEmpty;
3443 _typeParamInConst = savedTypeParams; 3443 _typeParamInConst = savedTypeParams;
3444 3444
3445 // TODO(jmesserly): if it uses type params we can still hoist it up as far 3445 // TODO(jmesserly): if it uses type params we can still hoist it up as far
3446 // as it will go, e.g. at the level the generic class is defined where type 3446 // as it will go, e.g. at the level the generic class is defined where type
3447 // params are available. 3447 // params are available.
3448 if (_currentFunction == null || usesTypeParams) return jsExpr; 3448 if (_currentFunction == null || usesTypeParams) return jsExpr;
3449 3449
3450 var temp = new JS.TemporaryId('const'); 3450 var temp = new JS.TemporaryId('const');
3451 _moduleItems.add(js.statement('let #;', [temp])); 3451 _moduleItems.add(js.statement('let #;', [temp]));
3452 return js.call('# || (# = #)', [temp, temp, jsExpr]); 3452 return js.call('# || (# = #)', [temp, temp, jsExpr]);
3453 } 3453 }
3454
3455 JS.Expression _emitConst(JS.Expression expr()) =>
3456 _cacheConst(() => js.call('dart.const(#)', expr()));
3454 3457
3455 /// Returns a new expression, which can be be used safely *once* on the 3458 /// Returns a new expression, which can be be used safely *once* on the
3456 /// left hand side, and *once* on the right side of an assignment. 3459 /// left hand side, and *once* on the right side of an assignment.
3457 /// For example: `expr1[expr2] += y` can be compiled as 3460 /// For example: `expr1[expr2] += y` can be compiled as
3458 /// `expr1[expr2] = expr1[expr2] + y`. 3461 /// `expr1[expr2] = expr1[expr2] + y`.
3459 /// 3462 ///
3460 /// The temporary scope will ensure `expr1` and `expr2` are only evaluated 3463 /// The temporary scope will ensure `expr1` and `expr2` are only evaluated
3461 /// once: `((x1, x2) => x1[x2] = x1[x2] + y)(expr1, expr2)`. 3464 /// once: `((x1, x2) => x1[x2] = x1[x2] + y)(expr1, expr2)`.
3462 /// 3465 ///
3463 /// If the expression does not end up using `x1` or `x2` more than once, or 3466 /// If the expression does not end up using `x1` or `x2` more than once, or
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
4149 // TODO(vsm): When we canonicalize, we need to treat private symbols 4152 // TODO(vsm): When we canonicalize, we need to treat private symbols
4150 // correctly. 4153 // correctly.
4151 var name = js.string(node.components.join('.'), "'"); 4154 var name = js.string(node.components.join('.'), "'");
4152 return js.call('#.new(#)', [_emitType(types.symbolType), name]); 4155 return js.call('#.new(#)', [_emitType(types.symbolType), name]);
4153 } 4156 }
4154 return _emitConst(emitSymbol); 4157 return _emitConst(emitSymbol);
4155 } 4158 }
4156 4159
4157 @override 4160 @override
4158 visitListLiteral(ListLiteral node) { 4161 visitListLiteral(ListLiteral node) {
4162 var isConst = node.constKeyword != null;
4159 JS.Expression emitList() { 4163 JS.Expression emitList() {
4160 JS.Expression list = new JS.ArrayInitializer( 4164 JS.Expression list = new JS.ArrayInitializer(
4161 _visitList(node.elements) as List<JS.Expression>); 4165 _visitList(node.elements) as List<JS.Expression>);
4162 ParameterizedType type = node.staticType; 4166 ParameterizedType type = node.staticType;
4163 var elementType = type.typeArguments.single; 4167 var elementType = type.typeArguments.single;
4164 // TODO(jmesserly): analyzer will usually infer `List<Object>` because 4168 // TODO(jmesserly): analyzer will usually infer `List<Object>` because
4165 // that is the least upper bound of the element types. So we rarely 4169 // that is the least upper bound of the element types. So we rarely
4166 // generate a plain `List<dynamic>` anymore. 4170 // generate a plain `List<dynamic>` anymore.
4167 if (!elementType.isDynamic) { 4171 if (!elementType.isDynamic || isConst) {
4168 // dart.list helper internally depends on _interceptors.JSArray. 4172 // dart.list helper internally depends on _interceptors.JSArray.
4169 _declareBeforeUse(_jsArray); 4173 _declareBeforeUse(_jsArray);
4170 list = js.call('dart.list(#, #)', [list, _emitType(elementType)]); 4174 var typeRep = _emitType(elementType);
4175 var helper = (isConst) ? 'constList' : 'list';
4176 list = js.call('dart.${helper}(#, #)', [list, typeRep]);
4171 } 4177 }
4172 return list; 4178 return list;
4173 } 4179 }
4174 if (node.constKeyword != null) return _emitConst(emitList); 4180 if (isConst) return _cacheConst(emitList);
4175 return emitList(); 4181 return emitList();
4176 } 4182 }
4177 4183
4178 @override 4184 @override
4179 visitMapLiteral(MapLiteral node) { 4185 visitMapLiteral(MapLiteral node) {
4180 // TODO(jmesserly): we can likely make these faster. 4186 // TODO(jmesserly): we can likely make these faster.
4181 JS.Expression emitMap() { 4187 JS.Expression emitMap() {
4182 var entries = node.entries; 4188 var entries = node.entries;
4183 var mapArguments = null; 4189 var mapArguments = null;
4184 var typeArgs = node.typeArguments; 4190 var typeArgs = node.typeArguments;
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
4557 } 4563 }
4558 4564
4559 bool isLibraryPrefix(Expression node) => 4565 bool isLibraryPrefix(Expression node) =>
4560 node is SimpleIdentifier && node.staticElement is PrefixElement; 4566 node is SimpleIdentifier && node.staticElement is PrefixElement;
4561 4567
4562 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4568 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4563 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4569 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4564 4570
4565 bool _isDartRuntime(LibraryElement l) => 4571 bool _isDartRuntime(LibraryElement l) =>
4566 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4572 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | tool/input_sdk/private/ddc_runtime/operations.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698