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

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

Issue 2503803004: fix #27784 and fix #27785, fromEnvironment constants in DDC (Closed)
Patch Set: allow trailing opts Created 4 years, 1 month 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 final ClassElement _jsArray; 118 final ClassElement _jsArray;
119 119
120 final ClassElement boolClass; 120 final ClassElement boolClass;
121 final ClassElement intClass; 121 final ClassElement intClass;
122 final ClassElement interceptorClass; 122 final ClassElement interceptorClass;
123 final ClassElement nullClass; 123 final ClassElement nullClass;
124 final ClassElement numClass; 124 final ClassElement numClass;
125 final ClassElement objectClass; 125 final ClassElement objectClass;
126 final ClassElement stringClass; 126 final ClassElement stringClass;
127 127
128 ConstFieldVisitor _constField; 128 ConstFieldVisitor _constants;
129 129
130 /// The current function body being compiled. 130 /// The current function body being compiled.
131 FunctionBody _currentFunction; 131 FunctionBody _currentFunction;
132 132
133 /// Helper class for emitting elements in the proper order to allow 133 /// Helper class for emitting elements in the proper order to allow
134 /// JS to load the module. 134 /// JS to load the module.
135 ElementLoader _loader; 135 ElementLoader _loader;
136 136
137 BuildUnit _buildUnit; 137 BuildUnit _buildUnit;
138 138
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 var nodes = new HashMap<Element, AstNode>.identity(); 269 var nodes = new HashMap<Element, AstNode>.identity();
270 var sdkBootstrappingFns = new List<FunctionElement>(); 270 var sdkBootstrappingFns = new List<FunctionElement>();
271 for (var unit in compilationUnits) { 271 for (var unit in compilationUnits) {
272 if (_isDartRuntime(unit.element.library)) { 272 if (_isDartRuntime(unit.element.library)) {
273 sdkBootstrappingFns.addAll(unit.element.functions); 273 sdkBootstrappingFns.addAll(unit.element.functions);
274 } 274 }
275 _collectElements(unit, nodes); 275 _collectElements(unit, nodes);
276 } 276 }
277 _loader = new ElementLoader(nodes); 277 _loader = new ElementLoader(nodes);
278 if (compilationUnits.isNotEmpty) { 278 if (compilationUnits.isNotEmpty) {
279 _constField = new ConstFieldVisitor(types, 279 _constants = new ConstFieldVisitor(context,
280 dummySource: compilationUnits.first.element.source); 280 dummySource: compilationUnits.first.element.source);
281 } 281 }
282 282
283 // Add implicit dart:core dependency so it is first. 283 // Add implicit dart:core dependency so it is first.
284 emitLibraryName(dartCoreLibrary); 284 emitLibraryName(dartCoreLibrary);
285 285
286 // Emit SDK bootstrapping functions first, if any. 286 // Emit SDK bootstrapping functions first, if any.
287 sdkBootstrappingFns.forEach(_emitDeclaration); 287 sdkBootstrappingFns.forEach(_emitDeclaration);
288 288
289 // Visit each compilation unit and emit its code. 289 // Visit each compilation unit and emit its code.
(...skipping 1823 matching lines...) Expand 10 before | Expand all | Expand 10 after
2113 [ConstructorDeclaration ctor]) { 2113 [ConstructorDeclaration ctor]) {
2114 bool isConst = ctor != null && ctor.constKeyword != null; 2114 bool isConst = ctor != null && ctor.constKeyword != null;
2115 if (isConst) _loader.startTopLevel(cls.element); 2115 if (isConst) _loader.startTopLevel(cls.element);
2116 2116
2117 // Run field initializers if they can have side-effects. 2117 // Run field initializers if they can have side-effects.
2118 var fields = new Map<FieldElement, JS.Expression>(); 2118 var fields = new Map<FieldElement, JS.Expression>();
2119 var unsetFields = new Map<FieldElement, VariableDeclaration>(); 2119 var unsetFields = new Map<FieldElement, VariableDeclaration>();
2120 for (var declaration in fieldDecls) { 2120 for (var declaration in fieldDecls) {
2121 for (var fieldNode in declaration.fields.variables) { 2121 for (var fieldNode in declaration.fields.variables) {
2122 var element = fieldNode.element; 2122 var element = fieldNode.element;
2123 if (_constField.isFieldInitConstant(fieldNode)) { 2123 if (_constants.isFieldInitConstant(fieldNode)) {
2124 unsetFields[element as FieldElement] = fieldNode; 2124 unsetFields[element as FieldElement] = fieldNode;
2125 } else { 2125 } else {
2126 fields[element as FieldElement] = _visitInitializer(fieldNode); 2126 fields[element as FieldElement] = _visitInitializer(fieldNode);
2127 } 2127 }
2128 } 2128 }
2129 } 2129 }
2130 2130
2131 // Initialize fields from `this.fieldName` parameters. 2131 // Initialize fields from `this.fieldName` parameters.
2132 if (ctor != null) { 2132 if (ctor != null) {
2133 for (var p in ctor.parameters.parameters) { 2133 for (var p in ctor.parameters.parameters) {
(...skipping 1626 matching lines...) Expand 10 before | Expand all | Expand 10 after
3760 JS.Statement _emitConstantStaticField(ClassElement classElem, 3760 JS.Statement _emitConstantStaticField(ClassElement classElem,
3761 VariableDeclaration field, Set<FieldElement> staticFieldOverrides) { 3761 VariableDeclaration field, Set<FieldElement> staticFieldOverrides) {
3762 PropertyInducingElement element = field.element; 3762 PropertyInducingElement element = field.element;
3763 assert(element.isStatic); 3763 assert(element.isStatic);
3764 3764
3765 _loader.startCheckingReferences(); 3765 _loader.startCheckingReferences();
3766 JS.Expression jsInit = _visitInitializer(field); 3766 JS.Expression jsInit = _visitInitializer(field);
3767 bool isLoaded = _loader.finishCheckingReferences(); 3767 bool isLoaded = _loader.finishCheckingReferences();
3768 3768
3769 bool eagerInit = 3769 bool eagerInit =
3770 isLoaded && (field.isConst || _constField.isFieldInitConstant(field)); 3770 isLoaded && (field.isConst || _constants.isFieldInitConstant(field));
3771 3771
3772 var fieldName = field.name.name; 3772 var fieldName = field.name.name;
3773 if (eagerInit && 3773 if (eagerInit &&
3774 !JS.invalidStaticFieldName(fieldName) && 3774 !JS.invalidStaticFieldName(fieldName) &&
3775 !staticFieldOverrides.contains(element)) { 3775 !staticFieldOverrides.contains(element)) {
3776 return annotate( 3776 return annotate(
3777 js.statement('#.# = #;', [ 3777 js.statement('#.# = #;', [
3778 _emitTopLevelName(classElem), 3778 _emitTopLevelName(classElem),
3779 _emitMemberName(fieldName, isStatic: true), 3779 _emitMemberName(fieldName, isStatic: true),
3780 jsInit 3780 jsInit
3781 ]), 3781 ]),
3782 field, 3782 field,
3783 field.element); 3783 field.element);
3784 } 3784 }
3785 3785
3786 // This means it should be treated as a lazy field. 3786 // This means it should be treated as a lazy field.
3787 // TODO(jmesserly): we're throwing away the initializer expression, 3787 // TODO(jmesserly): we're throwing away the initializer expression,
3788 // which will force us to regenerate it. 3788 // which will force us to regenerate it.
3789 return null; 3789 return null;
3790 } 3790 }
3791 3791
3792 /// Emits a top-level field. 3792 /// Emits a top-level field.
3793 JS.ModuleItem _emitTopLevelField(VariableDeclaration field) { 3793 JS.ModuleItem _emitTopLevelField(VariableDeclaration field) {
3794 TopLevelVariableElement element = field.element; 3794 TopLevelVariableElement element = field.element;
3795 assert(element.isStatic); 3795 assert(element.isStatic);
3796 3796
3797 bool eagerInit; 3797 bool eagerInit;
3798 JS.Expression jsInit; 3798 JS.Expression jsInit;
3799 if (field.isConst || _constField.isFieldInitConstant(field)) { 3799 if (field.isConst || _constants.isFieldInitConstant(field)) {
3800 // If the field is constant, try and generate it at the top level. 3800 // If the field is constant, try and generate it at the top level.
3801 _loader.startTopLevel(element); 3801 _loader.startTopLevel(element);
3802 jsInit = _visitInitializer(field); 3802 jsInit = _visitInitializer(field);
3803 _loader.finishTopLevel(element); 3803 _loader.finishTopLevel(element);
3804 eagerInit = _loader.isLoaded(element); 3804 eagerInit = _loader.isLoaded(element);
3805 } else { 3805 } else {
3806 // TODO(jmesserly): we're visiting the initializer here, and again 3806 // TODO(jmesserly): we're visiting the initializer here, and again
3807 // later on when we emit lazy fields. That seems busted. 3807 // later on when we emit lazy fields. That seems busted.
3808 jsInit = _visitInitializer(field); 3808 jsInit = _visitInitializer(field);
3809 eagerInit = false; 3809 eagerInit = false;
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
3954 assert(args.single is JS.ObjectInitializer); 3954 assert(args.single is JS.ObjectInitializer);
3955 return args.single; 3955 return args.single;
3956 } 3956 }
3957 3957
3958 @override 3958 @override
3959 visitInstanceCreationExpression(InstanceCreationExpression node) { 3959 visitInstanceCreationExpression(InstanceCreationExpression node) {
3960 var element = node.staticElement; 3960 var element = node.staticElement;
3961 var constructor = node.constructorName; 3961 var constructor = node.constructorName;
3962 var name = constructor.name; 3962 var name = constructor.name;
3963 var type = constructor.type.type; 3963 var type = constructor.type.type;
3964 if (node.isConst &&
3965 element?.name == 'fromEnvironment' &&
3966 element.library.isDartCore) {
3967 var value = node.accept(_constants.constantVisitor);
3968
3969 if (value == null || value.isNull) {
3970 return new JS.LiteralNull();
3971 }
3972 if (value.isUnknown) {
3973 return type == types.boolType
3974 ? js.boolean(false)
vsm 2016/11/16 19:16:22 Can you add a comment explaining this case? When
Jennifer Messerly 2016/11/16 20:11:48 Sure, as best as I can. Unfortunately behavior of
3975 : new JS.LiteralNull();
3976 }
3977 if (value.type == types.boolType) {
3978 var boolValue = value.toBoolValue();
3979 return boolValue != null ? js.boolean(boolValue) : new JS.LiteralNull();
3980 }
3981 if (value.type == types.intType) {
3982 var intValue = value.toIntValue();
3983 return intValue != null ? js.number(intValue) : new JS.LiteralNull();
3984 }
3985 if (value.type == types.stringType) {
3986 var stringValue = value.toStringValue();
3987 return stringValue != null
3988 ? js.escapedString(stringValue)
3989 : new JS.LiteralNull();
3990 }
3991 throw new StateError('failed to evaluate $node');
3992 }
3964 return _emitInstanceCreationExpression( 3993 return _emitInstanceCreationExpression(
3965 element, type, name, node.argumentList, node.isConst); 3994 element, type, name, node.argumentList, node.isConst);
3966 } 3995 }
3967 3996
3968 /// True if this type is built-in to JS, and we use the values unwrapped. 3997 /// True if this type is built-in to JS, and we use the values unwrapped.
3969 /// For these types we generate a calling convention via static 3998 /// For these types we generate a calling convention via static
3970 /// "extension methods". This allows types to be extended without adding 3999 /// "extension methods". This allows types to be extended without adding
3971 /// extensions directly on the prototype. 4000 /// extensions directly on the prototype.
3972 bool isPrimitiveType(DartType t) => 4001 bool isPrimitiveType(DartType t) =>
3973 typeIsPrimitiveInJS(t) || t == types.stringType; 4002 typeIsPrimitiveInJS(t) || t == types.stringType;
(...skipping 1622 matching lines...) Expand 10 before | Expand all | Expand 10 after
5596 var targetIdentifier = target as SimpleIdentifier; 5625 var targetIdentifier = target as SimpleIdentifier;
5597 5626
5598 if (targetIdentifier.staticElement is! PrefixElement) return false; 5627 if (targetIdentifier.staticElement is! PrefixElement) return false;
5599 var prefix = targetIdentifier.staticElement as PrefixElement; 5628 var prefix = targetIdentifier.staticElement as PrefixElement;
5600 5629
5601 // The library the prefix is referring to must come from a deferred import. 5630 // The library the prefix is referring to must come from a deferred import.
5602 var containingLibrary = (target.root as CompilationUnit).element.library; 5631 var containingLibrary = (target.root as CompilationUnit).element.library;
5603 var imports = containingLibrary.getImportsWithPrefix(prefix); 5632 var imports = containingLibrary.getImportsWithPrefix(prefix);
5604 return imports.length == 1 && imports[0].isDeferred; 5633 return imports.length == 1 && imports[0].isDeferred;
5605 } 5634 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698