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

Side by Side Diff: pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart

Issue 1312943007: Add version validation for LookupMap, also add unittest directly in LookupMap. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 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 /// Analysis to determine how to generate code for `LookupMap`s. 5 /// Analysis to determine how to generate code for `LookupMap`s.
6 library compiler.src.js_backend.lookup_map_analysis; 6 library compiler.src.js_backend.lookup_map_analysis;
7 7
8 import '../common/registry.dart' show Registry; 8 import '../common/registry.dart' show Registry;
9 import '../compiler.dart' show Compiler; 9 import '../compiler.dart' show Compiler;
10 import '../diagnostics/messages.dart' show MessageKind;
10 import '../constants/values.dart' show 11 import '../constants/values.dart' show
11 ConstantValue, 12 ConstantValue,
12 ConstructedConstantValue, 13 ConstructedConstantValue,
13 ListConstantValue, 14 ListConstantValue,
14 NullConstantValue, 15 NullConstantValue,
15 TypeConstantValue; 16 TypeConstantValue;
16 import '../dart_types.dart' show DartType; 17 import '../dart_types.dart' show DartType;
17 import '../elements/elements.dart' show Elements, Element, ClassElement, 18 import '../elements/elements.dart' show
18 FieldElement, FunctionElement, FunctionSignature; 19 ClassElement,
20 Element,
21 Elements,
22 FieldElement,
23 FunctionElement,
24 FunctionSignature,
25 LibraryElement,
26 VariableElement;
19 import '../enqueue.dart' show Enqueuer; 27 import '../enqueue.dart' show Enqueuer;
20 import 'js_backend.dart' show JavaScriptBackend; 28 import 'js_backend.dart' show JavaScriptBackend;
21 import '../dart_types.dart' show DynamicType, InterfaceType; 29 import '../dart_types.dart' show DynamicType, InterfaceType;
22 30
23 /// An analysis and optimization to remove unused entries from a `LookupMap`. 31 /// An analysis and optimization to remove unused entries from a `LookupMap`.
24 /// 32 ///
25 /// `LookupMaps` are defined in `package:lookup_map/lookup_map.dart`. They are 33 /// `LookupMaps` are defined in `package:lookup_map/lookup_map.dart`. They are
26 /// simple maps that contain constant expressions as keys, and that only support 34 /// simple maps that contain constant expressions as keys, and that only support
27 /// the lookup operation. 35 /// the lookup operation.
28 /// 36 ///
(...skipping 27 matching lines...) Expand all
56 // TODO(sigmund): add support for const expressions, currently this 64 // TODO(sigmund): add support for const expressions, currently this
57 // implementation only supports Type literals. To support const expressions we 65 // implementation only supports Type literals. To support const expressions we
58 // need to change some of the invariants below (e.g. we can no longer use the 66 // need to change some of the invariants below (e.g. we can no longer use the
59 // ClassElement of a type to refer to keys we need to discover). 67 // ClassElement of a type to refer to keys we need to discover).
60 // TODO(sigmund): detect uses of mirrors 68 // TODO(sigmund): detect uses of mirrors
61 class LookupMapAnalysis { 69 class LookupMapAnalysis {
62 /// Reference to [JavaScriptBackend] to be able to enqueue work when we 70 /// Reference to [JavaScriptBackend] to be able to enqueue work when we
63 /// discover that a key in a map is potentially used. 71 /// discover that a key in a map is potentially used.
64 final JavaScriptBackend backend; 72 final JavaScriptBackend backend;
65 73
74 /// The resolved [VariableElement] associated with the top-level `_version`.
75 VariableElement lookupMapVersionVariable;
76
77 /// The resolved [LibraryElement] associated with
78 /// `package:lookup_map/lookup_map.dart`.
79 LibraryElement lookupMapLibrary;
80
66 /// The resolved [ClassElement] associated with `LookupMap`. 81 /// The resolved [ClassElement] associated with `LookupMap`.
67 ClassElement typeLookupMapClass; 82 ClassElement typeLookupMapClass;
68 83
69 /// The resolved [FieldElement] for `LookupMap._entries`. 84 /// The resolved [FieldElement] for `LookupMap._entries`.
70 FieldElement entriesField; 85 FieldElement entriesField;
71 86
72 /// The resolved [FieldElement] for `LookupMap._key`. 87 /// The resolved [FieldElement] for `LookupMap._key`.
73 FieldElement keyField; 88 FieldElement keyField;
74 89
75 /// The resolved [FieldElement] for `LookupMap._value`. 90 /// The resolved [FieldElement] for `LookupMap._value`.
(...skipping 18 matching lines...) Expand all
94 /// we could allow const instances of these types. However, we internally use 109 /// we could allow const instances of these types. However, we internally use
95 /// a hash map within lookup-maps today, so we need this restriction. 110 /// a hash map within lookup-maps today, so we need this restriction.
96 final _typesWithEquals = <ClassElement, bool>{}; 111 final _typesWithEquals = <ClassElement, bool>{};
97 112
98 /// Pending work to do if we discover that a new key is in use. For each key 113 /// Pending work to do if we discover that a new key is in use. For each key
99 /// that we haven't seen, we record the list of lookup-maps that contain an 114 /// that we haven't seen, we record the list of lookup-maps that contain an
100 /// entry with that key. 115 /// entry with that key.
101 final _pending = <ConstantValue, List<_LookupMapInfo>>{}; 116 final _pending = <ConstantValue, List<_LookupMapInfo>>{};
102 117
103 /// Whether the backend is currently processing the codegen queue. 118 /// Whether the backend is currently processing the codegen queue.
104 // TODO(sigmund): is there a better way to do this. Do we need to plumb the 119 bool _inCodegen = false;
105 // enqueuer on each callback?
106 bool get _inCodegen => backend.compiler.phase == Compiler.PHASE_COMPILING;
107 120
108 LookupMapAnalysis(this.backend); 121 LookupMapAnalysis(this.backend);
109 122
110 /// Whether this analysis and optimization is enabled. 123 /// Whether this analysis and optimization is enabled.
111 bool get _isEnabled { 124 bool get _isEnabled {
112 // `lookupMap==off` kept here to make it easy to test disabling this feature 125 // `lookupMap==off` kept here to make it easy to test disabling this feature
113 if (const String.fromEnvironment('lookupMap') == 'off') return false; 126 if (const String.fromEnvironment('lookupMap') == 'off') return false;
114 return typeLookupMapClass != null; 127 return typeLookupMapClass != null;
115 } 128 }
116 129
117 /// Initializes this analysis by providing the resolver information of 130 /// Initializes this analysis by providing the resolved library. This is
118 /// `LookupMap`. 131 /// invoked during resolution when the `lookup_map` library is discovered.
119 void initRuntimeClass(ClassElement cls) { 132 void init(LibraryElement library) {
133 lookupMapLibrary = library;
134 // We will enable the lookupMapAnalysis as long as we get a known version of
135 // the lookup_map package. We otherwise produce a warning.
136 lookupMapVersionVariable = library.implementation.findLocal('_version');
floitsch 2015/09/07 10:48:02 I think I would have gone with an annotation, but
137 if (lookupMapVersionVariable == null) {
138 backend.compiler.reportInfo(library,
139 MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
140 } else {
141 backend.compiler.enqueuer.resolution.addToWorkList(
142 lookupMapVersionVariable);
143 }
144 }
145
146 /// Checks if the version of lookup_map is valid, and if so, enable this
147 /// analysis during codegen.
148 void onCodegenStart() {
149 _inCodegen = true;
150 // At this point, the lookupMapVersionVariable should be resolved and it's
151 // constant value should be available.
152 ConstantValue value =
153 backend.constants.getConstantValueForVariable(lookupMapVersionVariable);
154 if (value == null) {
155 backend.compiler.reportInfo(lookupMapVersionVariable,
156 MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
157 return;
158 }
159
160 // TODO(sigmund): add proper version resolution using the pub_semver package
161 // when we introduce the next version.
162 String version = value.primitiveValue.slowToString();
163 if (version != '0.0.1') {
164 backend.compiler.reportInfo(lookupMapVersionVariable,
165 MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
166 return;
167 }
168
169 ClassElement cls = lookupMapLibrary.findLocal('LookupMap');
120 cls.computeType(backend.compiler); 170 cls.computeType(backend.compiler);
121 entriesField = cls.lookupMember('_entries'); 171 entriesField = cls.lookupMember('_entries');
122 keyField = cls.lookupMember('_key'); 172 keyField = cls.lookupMember('_key');
123 valueField = cls.lookupMember('_value'); 173 valueField = cls.lookupMember('_value');
124 // TODO(sigmund): Maybe inline nested maps make the output code smaller? 174 // TODO(sigmund): Maybe inline nested maps to make the output code smaller?
125 typeLookupMapClass = cls; 175 typeLookupMapClass = cls;
126 } 176 }
127 177
128 /// Whether [constant] is an instance of a `LookupMap`. 178 /// Whether [constant] is an instance of a `LookupMap`.
129 bool isLookupMap(ConstantValue constant) => 179 bool isLookupMap(ConstantValue constant) =>
130 _isEnabled && 180 _isEnabled &&
131 constant is ConstructedConstantValue && 181 constant is ConstructedConstantValue &&
132 constant.type.asRaw().element.isSubclassOf(typeLookupMapClass); 182 constant.type.asRaw().element.isSubclassOf(typeLookupMapClass);
133 183
134 /// Registers an instance of a lookup-map with the analysis. 184 /// Registers an instance of a lookup-map with the analysis.
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 if (keyValuePairs.length == 2) { 420 if (keyValuePairs.length == 2) {
371 original.fields[analysis.keyField] = keyValuePairs[0]; 421 original.fields[analysis.keyField] = keyValuePairs[0];
372 original.fields[analysis.valueField] = keyValuePairs[1]; 422 original.fields[analysis.valueField] = keyValuePairs[1];
373 } 423 }
374 } else { 424 } else {
375 original.fields[analysis.entriesField] = 425 original.fields[analysis.entriesField] =
376 new ListConstantValue(listType, keyValuePairs); 426 new ListConstantValue(listType, keyValuePairs);
377 } 427 }
378 } 428 }
379 } 429 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698