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

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

Issue 2994203002: Optimize DDC private library files. (Closed)
Patch Set: Small tweaks Created 3 years, 4 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 26 matching lines...) Expand all
37 import '../js_ast/js_ast.dart' as JS; 37 import '../js_ast/js_ast.dart' as JS;
38 import '../js_ast/js_ast.dart' show js; 38 import '../js_ast/js_ast.dart' show js;
39 import 'ast_builder.dart' show AstBuilder; 39 import 'ast_builder.dart' show AstBuilder;
40 import 'compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile; 40 import 'compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile;
41 import 'element_helpers.dart'; 41 import 'element_helpers.dart';
42 import 'extension_types.dart' show ExtensionTypeSet; 42 import 'extension_types.dart' show ExtensionTypeSet;
43 import 'js_interop.dart'; 43 import 'js_interop.dart';
44 import 'js_metalet.dart' as JS; 44 import 'js_metalet.dart' as JS;
45 import 'js_names.dart' as JS; 45 import 'js_names.dart' as JS;
46 import 'js_typeref_codegen.dart' show JsTypeRefCodegen; 46 import 'js_typeref_codegen.dart' show JsTypeRefCodegen;
47 import 'js_typerep.dart' show JSTypeRep; 47 import 'js_typerep.dart' show JSTypeRep, JSType;
48 import 'module_builder.dart' show pathToJSIdentifier; 48 import 'module_builder.dart' show pathToJSIdentifier;
49 import 'nullable_type_inference.dart' show NullableTypeInference; 49 import 'nullable_type_inference.dart' show NullableTypeInference;
50 import 'property_model.dart'; 50 import 'property_model.dart';
51 import 'reify_coercions.dart' show CoercionReifier; 51 import 'reify_coercions.dart' show CoercionReifier;
52 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless; 52 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless;
53 import 'type_utilities.dart'; 53 import 'type_utilities.dart';
54 54
55 /// The code generator for Dart Dev Compiler. 55 /// The code generator for Dart Dev Compiler.
56 /// 56 ///
57 /// Takes as input resolved Dart ASTs for every compilation unit in every 57 /// Takes as input resolved Dart ASTs for every compilation unit in every
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 128
129 final LibraryElement dartCoreLibrary; 129 final LibraryElement dartCoreLibrary;
130 final LibraryElement dartJSLibrary; 130 final LibraryElement dartJSLibrary;
131 131
132 /// The dart:async `StreamIterator<>` type. 132 /// The dart:async `StreamIterator<>` type.
133 final InterfaceType _asyncStreamIterator; 133 final InterfaceType _asyncStreamIterator;
134 134
135 /// The dart:core `identical` element. 135 /// The dart:core `identical` element.
136 final FunctionElement _coreIdentical; 136 final FunctionElement _coreIdentical;
137 137
138 /// The dart:_interceptors JSArray element. 138 /// The dart:_interceptors implementation elements.
139 final ClassElement _jsArray; 139 final ClassElement _jsArray;
140 final ClassElement _jsBool;
141 final ClassElement _jsNumber;
142 final ClassElement _jsString;
140 143
141 final ClassElement boolClass; 144 final ClassElement boolClass;
142 final ClassElement intClass; 145 final ClassElement intClass;
143 final ClassElement interceptorClass; 146 final ClassElement interceptorClass;
144 final ClassElement nullClass; 147 final ClassElement nullClass;
145 final ClassElement numClass; 148 final ClassElement numClass;
146 final ClassElement objectClass; 149 final ClassElement objectClass;
147 final ClassElement stringClass; 150 final ClassElement stringClass;
148 final ClassElement functionClass; 151 final ClassElement functionClass;
149 final ClassElement privateSymbolClass; 152 final ClassElement privateSymbolClass;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 CodeGenerator( 201 CodeGenerator(
199 AnalysisContext c, this.summaryData, this.options, this._extensionTypes) 202 AnalysisContext c, this.summaryData, this.options, this._extensionTypes)
200 : context = c, 203 : context = c,
201 rules = new StrongTypeSystemImpl(c.typeProvider), 204 rules = new StrongTypeSystemImpl(c.typeProvider),
202 types = c.typeProvider, 205 types = c.typeProvider,
203 _asyncStreamIterator = 206 _asyncStreamIterator =
204 _getLibrary(c, 'dart:async').getType('StreamIterator').type, 207 _getLibrary(c, 'dart:async').getType('StreamIterator').type,
205 _coreIdentical = 208 _coreIdentical =
206 _getLibrary(c, 'dart:core').publicNamespace.get('identical'), 209 _getLibrary(c, 'dart:core').publicNamespace.get('identical'),
207 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'), 210 _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'),
211 _jsBool = _getLibrary(c, 'dart:_interceptors').getType('JSBool'),
212 _jsString = _getLibrary(c, 'dart:_interceptors').getType('JSString'),
213 _jsNumber = _getLibrary(c, 'dart:_interceptors').getType('JSNumber'),
208 interceptorClass = 214 interceptorClass =
209 _getLibrary(c, 'dart:_interceptors').getType('Interceptor'), 215 _getLibrary(c, 'dart:_interceptors').getType('Interceptor'),
210 dartCoreLibrary = _getLibrary(c, 'dart:core'), 216 dartCoreLibrary = _getLibrary(c, 'dart:core'),
211 boolClass = _getLibrary(c, 'dart:core').getType('bool'), 217 boolClass = _getLibrary(c, 'dart:core').getType('bool'),
212 intClass = _getLibrary(c, 'dart:core').getType('int'), 218 intClass = _getLibrary(c, 'dart:core').getType('int'),
213 numClass = _getLibrary(c, 'dart:core').getType('num'), 219 numClass = _getLibrary(c, 'dart:core').getType('num'),
214 nullClass = _getLibrary(c, 'dart:core').getType('Null'), 220 nullClass = _getLibrary(c, 'dart:core').getType('Null'),
215 objectClass = _getLibrary(c, 'dart:core').getType('Object'), 221 objectClass = _getLibrary(c, 'dart:core').getType('Object'),
216 stringClass = _getLibrary(c, 'dart:core').getType('String'), 222 stringClass = _getLibrary(c, 'dart:core').getType('String'),
217 functionClass = _getLibrary(c, 'dart:core').getType('Function'), 223 functionClass = _getLibrary(c, 'dart:core').getType('Function'),
(...skipping 2207 matching lines...) Expand 10 before | Expand all | Expand 10 after
2425 body.add(js.statement('if (# === void 0) # = #;', 2431 body.add(js.statement('if (# === void 0) # = #;',
2426 [jsParam, jsParam, _defaultParamValue(param)])); 2432 [jsParam, jsParam, _defaultParamValue(param)]));
2427 } 2433 }
2428 } 2434 }
2429 2435
2430 var paramElement = resolutionMap.elementDeclaredByFormalParameter(param); 2436 var paramElement = resolutionMap.elementDeclaredByFormalParameter(param);
2431 if (_isCovariant(paramElement)) { 2437 if (_isCovariant(paramElement)) {
2432 var castType = _emitType(paramElement.type); 2438 var castType = _emitType(paramElement.type);
2433 body.add(js.statement('#._check(#);', [castType, jsParam])); 2439 body.add(js.statement('#._check(#);', [castType, jsParam]));
2434 } 2440 }
2441 if (_annotatedNullCheck(paramElement)) {
2442 body.add(nullParameterCheck(jsParam));
2443 }
2435 } 2444 }
2436 return body.isEmpty ? null : _statement(body); 2445 return body.isEmpty ? null : _statement(body);
2437 } 2446 }
2438 2447
2439 bool _isCovariant(ParameterElement p) { 2448 bool _isCovariant(ParameterElement p) {
2440 if (p.isCovariant) return true; 2449 if (p.isCovariant) return true;
2441 var covariantParams = _classProperties?.covariantParameters; 2450 var covariantParams = _classProperties?.covariantParameters;
2442 return covariantParams != null && covariantParams.contains(p); 2451 return covariantParams != null && covariantParams.contains(p);
2443 } 2452 }
2444 2453
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after
3260 var t = _bindValue(vars, 't', x, context: x); 3269 var t = _bindValue(vars, 't', x, context: x);
3261 return new JS.MetaLet(vars, [ 3270 return new JS.MetaLet(vars, [
3262 js.call('# == null ? # : #', [_visit(t), _emitSet(x, right), _visit(t)]) 3271 js.call('# == null ? # : #', [_visit(t), _emitSet(x, right), _visit(t)])
3263 ]); 3272 ]);
3264 } 3273 }
3265 3274
3266 // Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions 3275 // Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions
3267 // (for example, x is IndexExpression) we evaluate those once. 3276 // (for example, x is IndexExpression) we evaluate those once.
3268 var vars = <JS.MetaLetVariable, JS.Expression>{}; 3277 var vars = <JS.MetaLetVariable, JS.Expression>{};
3269 var lhs = _bindLeftHandSide(vars, left, context: context); 3278 var lhs = _bindLeftHandSide(vars, left, context: context);
3279 // TODO(leafp): The element for lhs here will be the setter element
3280 // instead of the getter element if lhs is a property access. This
3281 // interferes with nullability analysis.
Jennifer Messerly 2017/08/22 21:54:41 FYI ... I think it would be safe to fix _bindLeftH
Leaf 2017/08/23 17:26:14 Not super high priority, but good to fix at some p
3270 Expression inc = AstBuilder.binaryExpression(lhs, op, right) 3282 Expression inc = AstBuilder.binaryExpression(lhs, op, right)
3271 ..staticElement = element 3283 ..staticElement = element
3272 ..staticType = getStaticType(lhs); 3284 ..staticType = getStaticType(lhs);
3273 3285
3274 var castTo = getImplicitOperationCast(left); 3286 var castTo = getImplicitOperationCast(left);
3275 if (castTo != null) inc = CoercionReifier.castExpression(inc, castTo); 3287 if (castTo != null) inc = CoercionReifier.castExpression(inc, castTo);
3276 return new JS.MetaLet(vars, [_emitSet(lhs, inc)]); 3288 return new JS.MetaLet(vars, [_emitSet(lhs, inc)]);
3277 } 3289 }
3278 3290
3279 JS.Expression _emitSet(Expression left, Expression right) { 3291 JS.Expression _emitSet(Expression left, Expression right) {
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
4043 JS.Statement visitVariableDeclarationStatement( 4055 JS.Statement visitVariableDeclarationStatement(
4044 VariableDeclarationStatement node) { 4056 VariableDeclarationStatement node) {
4045 // Special case a single variable with an initializer. 4057 // Special case a single variable with an initializer.
4046 // This helps emit cleaner code for things like: 4058 // This helps emit cleaner code for things like:
4047 // var result = []..add(1)..add(2); 4059 // var result = []..add(1)..add(2);
4048 var variables = node.variables.variables; 4060 var variables = node.variables.variables;
4049 if (variables.length == 1) { 4061 if (variables.length == 1) {
4050 var v = variables[0]; 4062 var v = variables[0];
4051 if (v.initializer != null) { 4063 if (v.initializer != null) {
4052 var name = new JS.Identifier(v.name.name); 4064 var name = new JS.Identifier(v.name.name);
4053 return _visit<JS.Expression>(v.initializer).toVariableDeclaration(name); 4065 var value = _annotatedNullCheck(v.element)
4066 ? notNull(v.initializer)
4067 : _visit<JS.Expression>(v.initializer);
4068 return value.toVariableDeclaration(name);
4054 } 4069 }
4055 } 4070 }
4056 return _visit<JS.Expression>(node.variables).toStatement(); 4071 return _visit<JS.Expression>(node.variables).toStatement();
4057 } 4072 }
4058 4073
4059 @override 4074 @override
4060 visitVariableDeclarationList(VariableDeclarationList node) { 4075 visitVariableDeclarationList(VariableDeclarationList node) {
4061 return new JS.VariableDeclarationList('let', _visitList(node.variables)); 4076 return new JS.VariableDeclarationList('let', _visitList(node.variables));
4062 } 4077 }
4063 4078
(...skipping 22 matching lines...) Expand all
4086 for (var field in fields) { 4101 for (var field in fields) {
4087 _moduleItems.add(annotate( 4102 _moduleItems.add(annotate(
4088 js.statement('# = #;', 4103 js.statement('# = #;',
4089 [_emitTopLevelName(field.element), _visitInitializer(field)]), 4104 [_emitTopLevelName(field.element), _visitInitializer(field)]),
4090 field, 4105 field,
4091 field.element)); 4106 field.element));
4092 } 4107 }
4093 } 4108 }
4094 4109
4095 JS.Expression _visitInitializer(VariableDeclaration node) { 4110 JS.Expression _visitInitializer(VariableDeclaration node) {
4096 var value = _visit(node.initializer); 4111 var value = _annotatedNullCheck(node.element)
4112 ? notNull(node.initializer)
4113 : _visit(node.initializer);
4097 // explicitly initialize to null, to avoid getting `undefined`. 4114 // explicitly initialize to null, to avoid getting `undefined`.
4098 // TODO(jmesserly): do this only for vars that aren't definitely assigned. 4115 // TODO(jmesserly): do this only for vars that aren't definitely assigned.
4099 return value ?? new JS.LiteralNull(); 4116 return value ?? new JS.LiteralNull();
4100 } 4117 }
4101 4118
4102 JS.Statement _emitLazyFields( 4119 JS.Statement _emitLazyFields(
4103 Element target, List<VariableDeclaration> fields) { 4120 Element target, List<VariableDeclaration> fields) {
4104 var methods = []; 4121 var methods = [];
4105 for (var node in fields) { 4122 for (var node in fields) {
4106 var name = node.name.name; 4123 var name = node.name.name;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
4247 : new JS.LiteralNull(); 4264 : new JS.LiteralNull();
4248 } 4265 }
4249 throw new StateError('failed to evaluate $node'); 4266 throw new StateError('failed to evaluate $node');
4250 } 4267 }
4251 return _emitInstanceCreationExpression( 4268 return _emitInstanceCreationExpression(
4252 element, type, name, node.argumentList, node.isConst); 4269 element, type, name, node.argumentList, node.isConst);
4253 } 4270 }
4254 4271
4255 bool isPrimitiveType(DartType t) => typeRep.isPrimitive(t); 4272 bool isPrimitiveType(DartType t) => typeRep.isPrimitive(t);
4256 4273
4274 InterfaceType getImplementationType(DartType t) {
Jennifer Messerly 2017/08/22 21:54:41 add a doc comment? /// Given a Dart type for `boo
Leaf 2017/08/23 17:26:14 Done.
4275 JSType rep = typeRep.typeFor(t);
4276 // Number, String, and Bool are final
4277 if (rep == JSType.jsNumber) return _jsNumber.type;
4278 if (rep == JSType.jsBoolean) return _jsBool.type;
4279 if (rep == JSType.jsString) return _jsString.type;
4280 return null;
4281 }
4282
4283 JS.Statement nullParameterCheck(JS.Expression param) {
4284 var call = _callHelper('throwArgumentErrorValue((#))', [param]);
Jennifer Messerly 2017/08/22 21:54:41 if these are really common, consider a shorter nam
Leaf 2017/08/23 17:26:13 Done.
4285 return js.statement('if (# == null) #;', [param, call]);
4286 }
4287
4257 JS.Expression notNull(Expression expr) { 4288 JS.Expression notNull(Expression expr) {
4258 if (expr == null) return null; 4289 if (expr == null) return null;
4259 var jsExpr = _visit(expr); 4290 var jsExpr = _visit(expr);
4260 if (!isNullable(expr)) return jsExpr; 4291 if (!isNullable(expr)) return jsExpr;
4261 return _callHelper('notNull(#)', jsExpr); 4292 return _callHelper('notNull(#)', jsExpr);
4262 } 4293 }
4263 4294
4264 JS.Expression _emitEqualityOperator(BinaryExpression node, Token op) { 4295 JS.Expression _emitEqualityOperator(BinaryExpression node, Token op) {
4265 var left = node.leftOperand; 4296 var left = node.leftOperand;
4266 var right = node.rightOperand; 4297 var right = node.rightOperand;
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after
5109 return new JS.Do(_visitScope(node.body), _visitTest(node.condition)); 5140 return new JS.Do(_visitScope(node.body), _visitTest(node.condition));
5110 } 5141 }
5111 5142
5112 @override 5143 @override
5113 JS.Statement visitForEachStatement(ForEachStatement node) { 5144 JS.Statement visitForEachStatement(ForEachStatement node) {
5114 if (node.awaitKeyword != null) { 5145 if (node.awaitKeyword != null) {
5115 return _emitAwaitFor(node); 5146 return _emitAwaitFor(node);
5116 } 5147 }
5117 5148
5118 var init = _visit(node.identifier); 5149 var init = _visit(node.identifier);
5150 var iterable = _visit(node.iterable);
5151 var body = _visitScope(node.body);
5119 if (init == null) { 5152 if (init == null) {
5120 init = js.call('let #', node.loopVariable.identifier.name); 5153 var name = node.loopVariable.identifier.name;
5154 init = js.call('let #', name);
5155 if (_annotatedNullCheck(node.loopVariable.element)) {
5156 body =
5157 new JS.Block([nullParameterCheck(new JS.Identifier(name)), body]);
5158 }
5121 } 5159 }
5122 return new JS.ForOf(init, _visit(node.iterable), _visitScope(node.body)); 5160 return new JS.ForOf(init, iterable, body);
5123 } 5161 }
5124 5162
5125 JS.Statement _emitAwaitFor(ForEachStatement node) { 5163 JS.Statement _emitAwaitFor(ForEachStatement node) {
5126 // Emits `await for (var value in stream) ...`, which desugars as: 5164 // Emits `await for (var value in stream) ...`, which desugars as:
5127 // 5165 //
5128 // var iter = new StreamIterator(stream); 5166 // var iter = new StreamIterator(stream);
5129 // try { 5167 // try {
5130 // while (await iter.moveNext()) { 5168 // while (await iter.moveNext()) {
5131 // var value = iter.current; 5169 // var value = iter.current;
5132 // ... 5170 // ...
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after
5992 if (targetIdentifier.staticElement is! PrefixElement) return false; 6030 if (targetIdentifier.staticElement is! PrefixElement) return false;
5993 var prefix = targetIdentifier.staticElement as PrefixElement; 6031 var prefix = targetIdentifier.staticElement as PrefixElement;
5994 6032
5995 // The library the prefix is referring to must come from a deferred import. 6033 // The library the prefix is referring to must come from a deferred import.
5996 var containingLibrary = resolutionMap 6034 var containingLibrary = resolutionMap
5997 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 6035 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
5998 .library; 6036 .library;
5999 var imports = containingLibrary.getImportsWithPrefix(prefix); 6037 var imports = containingLibrary.getImportsWithPrefix(prefix);
6000 return imports.length == 1 && imports[0].isDeferred; 6038 return imports.length == 1 && imports[0].isDeferred;
6001 } 6039 }
6040
6041 bool _annotatedNullCheck(Element e) =>
6042 (e != null) && (findAnnotation(e, isNullCheckAnnotation) != null);
Jennifer Messerly 2017/08/22 21:54:41 fyi, parens not necessary
Leaf 2017/08/23 17:26:14 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698