| OLD | NEW |
| 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 'package:pub_semver/pub_semver.dart'; | 8 import 'package:pub_semver/pub_semver.dart'; |
| 9 | 9 |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| 11 import '../common_elements.dart'; | 11 import '../common_elements.dart'; |
| 12 import '../compile_time_constants.dart'; | 12 import '../compile_time_constants.dart'; |
| 13 import '../constants/constant_system.dart'; | 13 import '../constants/constant_system.dart'; |
| 14 import '../constants/values.dart' | 14 import '../constants/values.dart' |
| 15 show | 15 show |
| 16 ConstantValue, | 16 ConstantValue, |
| 17 ConstructedConstantValue, | 17 ConstructedConstantValue, |
| 18 ListConstantValue, | 18 ListConstantValue, |
| 19 NullConstantValue, | 19 NullConstantValue, |
| 20 StringConstantValue, | 20 StringConstantValue, |
| 21 TypeConstantValue; | 21 TypeConstantValue; |
| 22 import '../elements/elements.dart' show ClassElement, FieldElement; | 22 import '../elements/elements.dart' show FieldElement; |
| 23 import '../elements/entities.dart'; | 23 import '../elements/entities.dart'; |
| 24 import '../elements/resolution_types.dart' show ResolutionInterfaceType; | 24 import '../elements/types.dart'; |
| 25 import '../universe/use.dart' show ConstantUse, StaticUse; | 25 import '../universe/use.dart' show ConstantUse, StaticUse; |
| 26 import '../universe/world_impact.dart' | 26 import '../universe/world_impact.dart' |
| 27 show WorldImpact, StagedWorldImpactBuilder; | 27 show WorldImpact, StagedWorldImpactBuilder; |
| 28 | 28 |
| 29 /// Lookup map handling for resolution. | 29 /// Lookup map handling for resolution. |
| 30 /// | 30 /// |
| 31 /// This analysis checks for the import of `package:lookup_map/lookup_map.dart`, | 31 /// This analysis checks for the import of `package:lookup_map/lookup_map.dart`, |
| 32 /// and if found, read the `_version` variable from it. | 32 /// and if found, read the `_version` variable from it. |
| 33 /// | 33 /// |
| 34 /// In [LookupMapAnalysis] the value of `_version` is checked to ensure that it | 34 /// In [LookupMapAnalysis] the value of `_version` is checked to ensure that it |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 /// | 108 /// |
| 109 /// * Include all allocated types if the program contains `e.runtimeType` | 109 /// * Include all allocated types if the program contains `e.runtimeType` |
| 110 /// expressions. | 110 /// expressions. |
| 111 /// | 111 /// |
| 112 /// * Include all generic-type arguments, if the program uses type | 112 /// * Include all generic-type arguments, if the program uses type |
| 113 /// variables in expressions such as `class A<T> { Type get extract => T }`. | 113 /// variables in expressions such as `class A<T> { Type get extract => T }`. |
| 114 /// | 114 /// |
| 115 // TODO(sigmund): add support for const expressions, currently this | 115 // TODO(sigmund): add support for const expressions, currently this |
| 116 // implementation only supports Type literals. To support const expressions we | 116 // implementation only supports Type literals. To support const expressions we |
| 117 // need to change some of the invariants below (e.g. we can no longer use the | 117 // need to change some of the invariants below (e.g. we can no longer use the |
| 118 // ClassElement of a type to refer to keys we need to discover). | 118 // ClassEntity of a type to refer to keys we need to discover). |
| 119 // TODO(sigmund): detect uses of mirrors | 119 // TODO(sigmund): detect uses of mirrors |
| 120 class LookupMapAnalysis { | 120 class LookupMapAnalysis { |
| 121 const LookupMapAnalysis._(); | 121 const LookupMapAnalysis._(); |
| 122 | 122 |
| 123 factory LookupMapAnalysis( | 123 factory LookupMapAnalysis( |
| 124 DiagnosticReporter reporter, | 124 DiagnosticReporter reporter, |
| 125 ConstantSystem constantSystem, | 125 ConstantSystem constantSystem, |
| 126 ConstantEnvironment constants, | 126 ConstantEnvironment constants, |
| 127 ElementEnvironment elementEnvironment, | 127 ElementEnvironment elementEnvironment, |
| 128 CommonElements commonElements, | 128 CommonElements commonElements, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 150 } catch (e) {} | 150 } catch (e) {} |
| 151 | 151 |
| 152 if (version == null || !_validLookupMapVersionConstraint.allows(version)) { | 152 if (version == null || !_validLookupMapVersionConstraint.allows(version)) { |
| 153 reporter.reportHintMessage(lookupMapVersionVariable, | 153 reporter.reportHintMessage(lookupMapVersionVariable, |
| 154 MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP); | 154 MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP); |
| 155 return const LookupMapAnalysis._(); | 155 return const LookupMapAnalysis._(); |
| 156 } | 156 } |
| 157 | 157 |
| 158 ClassEntity typeLookupMapClass = | 158 ClassEntity typeLookupMapClass = |
| 159 elementEnvironment.lookupClass(analysis.lookupMapLibrary, 'LookupMap'); | 159 elementEnvironment.lookupClass(analysis.lookupMapLibrary, 'LookupMap'); |
| 160 FieldElement entriesField = | 160 FieldEntity entriesField = |
| 161 elementEnvironment.lookupClassMember(typeLookupMapClass, '_entries'); | 161 elementEnvironment.lookupClassMember(typeLookupMapClass, '_entries'); |
| 162 FieldElement keyField = | 162 FieldEntity keyField = |
| 163 elementEnvironment.lookupClassMember(typeLookupMapClass, '_key'); | 163 elementEnvironment.lookupClassMember(typeLookupMapClass, '_key'); |
| 164 FieldElement valueField = | 164 FieldEntity valueField = |
| 165 elementEnvironment.lookupClassMember(typeLookupMapClass, '_value'); | 165 elementEnvironment.lookupClassMember(typeLookupMapClass, '_value'); |
| 166 // TODO(sigmund): Maybe inline nested maps to make the output code smaller? | 166 // TODO(sigmund): Maybe inline nested maps to make the output code smaller? |
| 167 | 167 |
| 168 return new _LookupMapAnalysis(constantSystem, commonElements, entriesField, | 168 return new _LookupMapAnalysis(constantSystem, elementEnvironment, |
| 169 keyField, valueField, typeLookupMapClass); | 169 commonElements, entriesField, keyField, valueField, typeLookupMapClass); |
| 170 } | 170 } |
| 171 | 171 |
| 172 /// Compute the [WorldImpact] for the constants registered since last flush. | 172 /// Compute the [WorldImpact] for the constants registered since last flush. |
| 173 WorldImpact flush() => const WorldImpact(); | 173 WorldImpact flush() => const WorldImpact(); |
| 174 | 174 |
| 175 /// Whether [constant] is an instance of a `LookupMap`. | 175 /// Whether [constant] is an instance of a `LookupMap`. |
| 176 bool isLookupMap(ConstantValue constant) => false; | 176 bool isLookupMap(ConstantValue constant) => false; |
| 177 | 177 |
| 178 /// Registers an instance of a lookup-map with the analysis. | 178 /// Registers an instance of a lookup-map with the analysis. |
| 179 void registerLookupMapReference(ConstantValue lookupMap) {} | 179 void registerLookupMapReference(ConstantValue lookupMap) {} |
| 180 | 180 |
| 181 /// Callback from the enqueuer, invoked when [element] is instantiated. | 181 /// Callback from the enqueuer, invoked when [element] is instantiated. |
| 182 void registerInstantiatedClass(ClassElement element) {} | 182 void registerInstantiatedClass(ClassEntity element) {} |
| 183 | 183 |
| 184 /// Callback from the enqueuer, invoked when [type] is instantiated. | 184 /// Callback from the enqueuer, invoked when [type] is instantiated. |
| 185 void registerInstantiatedType(ResolutionInterfaceType type) {} | 185 void registerInstantiatedType(InterfaceType type) {} |
| 186 | 186 |
| 187 /// Callback from the codegen enqueuer, invoked when a constant (which is | 187 /// Callback from the codegen enqueuer, invoked when a constant (which is |
| 188 /// possibly a const key or a type literal) is used in the program. | 188 /// possibly a const key or a type literal) is used in the program. |
| 189 void registerTypeConstant(ClassElement element) {} | 189 void registerTypeConstant(ClassEntity element) {} |
| 190 | 190 |
| 191 void registerConstantKey(ConstantValue constant) {} | 191 void registerConstantKey(ConstantValue constant) {} |
| 192 | 192 |
| 193 void logSummary(void log(String message)) {} | 193 void logSummary(void log(String message)) {} |
| 194 | 194 |
| 195 void onQueueClosed() {} | 195 void onQueueClosed() {} |
| 196 } | 196 } |
| 197 | 197 |
| 198 class _LookupMapAnalysis implements LookupMapAnalysis { | 198 class _LookupMapAnalysis implements LookupMapAnalysis { |
| 199 static final Uri PACKAGE_LOOKUP_MAP = | 199 static final Uri PACKAGE_LOOKUP_MAP = |
| 200 new Uri(scheme: 'package', path: 'lookup_map/lookup_map.dart'); | 200 new Uri(scheme: 'package', path: 'lookup_map/lookup_map.dart'); |
| 201 | 201 |
| 202 final ConstantSystem _constantSystem; | 202 final ConstantSystem _constantSystem; |
| 203 | 203 |
| 204 final ElementEnvironment _elementEnvironment; |
| 205 |
| 204 final CommonElements _commonElements; | 206 final CommonElements _commonElements; |
| 205 | 207 |
| 206 /// The resolved [ClassElement] associated with `LookupMap`. | 208 /// The resolved [ClassEntity] associated with `LookupMap`. |
| 207 final ClassElement _typeLookupMapClass; | 209 final ClassEntity _typeLookupMapClass; |
| 208 | 210 |
| 209 /// The resolved [FieldElement] for `LookupMap._entries`. | 211 /// The resolved [FieldEntity] for `LookupMap._entries`. |
| 210 final FieldElement _entriesField; | 212 final FieldEntity _entriesField; |
| 211 | 213 |
| 212 /// The resolved [FieldElement] for `LookupMap._key`. | 214 /// The resolved [FieldEntity] for `LookupMap._key`. |
| 213 final FieldElement _keyField; | 215 final FieldEntity _keyField; |
| 214 | 216 |
| 215 /// The resolved [FieldElement] for `LookupMap._value`. | 217 /// The resolved [FieldEntity] for `LookupMap._value`. |
| 216 final FieldElement _valueField; | 218 final FieldEntity _valueField; |
| 217 | 219 |
| 218 /// Constant instances of `LookupMap` and information about them tracked by | 220 /// Constant instances of `LookupMap` and information about them tracked by |
| 219 /// this analysis. | 221 /// this analysis. |
| 220 final Map<ConstantValue, _LookupMapInfo> _lookupMaps = {}; | 222 final Map<ConstantValue, _LookupMapInfo> _lookupMaps = {}; |
| 221 | 223 |
| 222 /// Keys that we have discovered to be in use in the program. | 224 /// Keys that we have discovered to be in use in the program. |
| 223 final _inUse = new Set<ConstantValue>(); | 225 final Set<ConstantValue> _inUse = new Set<ConstantValue>(); |
| 224 | 226 |
| 225 /// Internal helper to memoize the mapping between class elements and their | 227 /// Internal helper to memoize the mapping between class elements and their |
| 226 /// corresponding type constants. | 228 /// corresponding type constants. |
| 227 final _typeConstants = <ClassElement, TypeConstantValue>{}; | 229 final Map<ClassEntity, TypeConstantValue> _typeConstants = |
| 230 <ClassEntity, TypeConstantValue>{}; |
| 228 | 231 |
| 229 /// Internal helper to memoize which classes (ignoring Type) override equals. | 232 /// Internal helper to memoize which classes (ignoring Type) override equals. |
| 230 /// | 233 /// |
| 231 /// Const keys of these types will not be tree-shaken because we can't | 234 /// Const keys of these types will not be tree-shaken because we can't |
| 232 /// statically guarantee that the program doesn't produce an equivalent key at | 235 /// statically guarantee that the program doesn't produce an equivalent key at |
| 233 /// runtime. Technically if we limit lookup-maps to check for identical keys, | 236 /// runtime. Technically if we limit lookup-maps to check for identical keys, |
| 234 /// we could allow const instances of these types. However, we internally use | 237 /// we could allow const instances of these types. However, we internally use |
| 235 /// a hash map within lookup-maps today, so we need this restriction. | 238 /// a hash map within lookup-maps today, so we need this restriction. |
| 236 final _typesWithEquals = <ClassElement, bool>{}; | 239 final Map<ClassEntity, bool> _typesWithEquals = <ClassEntity, bool>{}; |
| 237 | 240 |
| 238 /// Pending work to do if we discover that a new key is in use. For each key | 241 /// Pending work to do if we discover that a new key is in use. For each key |
| 239 /// that we haven't seen, we record the list of lookup-maps that contain an | 242 /// that we haven't seen, we record the list of lookup-maps that contain an |
| 240 /// entry with that key. | 243 /// entry with that key. |
| 241 final _pending = <ConstantValue, List<_LookupMapInfo>>{}; | 244 final _pending = <ConstantValue, List<_LookupMapInfo>>{}; |
| 242 | 245 |
| 243 final StagedWorldImpactBuilder _impactBuilder = | 246 final StagedWorldImpactBuilder _impactBuilder = |
| 244 new StagedWorldImpactBuilder(); | 247 new StagedWorldImpactBuilder(); |
| 245 | 248 |
| 246 _LookupMapAnalysis( | 249 _LookupMapAnalysis( |
| 247 this._constantSystem, | 250 this._constantSystem, |
| 251 this._elementEnvironment, |
| 248 this._commonElements, | 252 this._commonElements, |
| 249 this._entriesField, | 253 this._entriesField, |
| 250 this._keyField, | 254 this._keyField, |
| 251 this._valueField, | 255 this._valueField, |
| 252 this._typeLookupMapClass); | 256 this._typeLookupMapClass); |
| 253 | 257 |
| 254 /// Compute the [WorldImpact] for the constants registered since last flush. | 258 /// Compute the [WorldImpact] for the constants registered since last flush. |
| 255 WorldImpact flush() { | 259 WorldImpact flush() { |
| 256 return _impactBuilder.flush(); | 260 return _impactBuilder.flush(); |
| 257 } | 261 } |
| 258 | 262 |
| 259 /// Whether [constant] is an instance of a `LookupMap`. | 263 /// Whether [constant] is an instance of a `LookupMap`. |
| 260 bool isLookupMap(ConstantValue constant) { | 264 bool isLookupMap(ConstantValue constant) { |
| 261 if (constant is ConstructedConstantValue) { | 265 if (constant is ConstructedConstantValue) { |
| 262 ResolutionInterfaceType type = constant.type; | 266 InterfaceType type = constant.type; |
| 263 return type.element.isSubclassOf(_typeLookupMapClass); | 267 ClassEntity superclass = type.element; |
| 268 while (superclass != null) { |
| 269 if (superclass == _typeLookupMapClass) return true; |
| 270 superclass = _elementEnvironment.getSuperClass(superclass); |
| 271 } |
| 264 } | 272 } |
| 265 return false; | 273 return false; |
| 266 } | 274 } |
| 267 | 275 |
| 268 /// Registers an instance of a lookup-map with the analysis. | 276 /// Registers an instance of a lookup-map with the analysis. |
| 269 void registerLookupMapReference(ConstantValue lookupMap) { | 277 void registerLookupMapReference(ConstantValue lookupMap) { |
| 270 assert(isLookupMap(lookupMap)); | 278 assert(isLookupMap(lookupMap)); |
| 271 _lookupMaps.putIfAbsent( | 279 _lookupMaps.putIfAbsent( |
| 272 lookupMap, () => new _LookupMapInfo(lookupMap, this).._updateUsed()); | 280 lookupMap, () => new _LookupMapInfo(lookupMap, this).._updateUsed()); |
| 273 } | 281 } |
| 274 | 282 |
| 275 /// Whether [key] is a constant value whose type overrides equals. | 283 /// Whether [key] is a constant value whose type overrides equals. |
| 276 bool _overridesEquals(ConstantValue key) { | 284 bool _overridesEquals(ConstantValue key) { |
| 277 if (key is ConstructedConstantValue) { | 285 if (key is ConstructedConstantValue) { |
| 278 ClassElement element = key.type.element; | 286 ClassEntity element = key.type.element; |
| 279 return _typesWithEquals.putIfAbsent( | 287 return _typesWithEquals.putIfAbsent(element, () { |
| 280 element, () => !element.lookupMember('==').enclosingClass.isObject); | 288 ClassEntity cls = element; |
| 289 while (cls != _commonElements.objectClass) { |
| 290 MemberEntity member = |
| 291 _elementEnvironment.lookupClassMember(cls, '=='); |
| 292 if (member != null) { |
| 293 return true; |
| 294 } |
| 295 cls = _elementEnvironment.getSuperClass(cls); |
| 296 } |
| 297 return false; |
| 298 }); |
| 281 } | 299 } |
| 282 return false; | 300 return false; |
| 283 } | 301 } |
| 284 | 302 |
| 285 /// Whether we need to preserve [key]. This is true for keys that are not | 303 /// Whether we need to preserve [key]. This is true for keys that are not |
| 286 /// candidates for tree-shaking in the first place (primitives and non-type | 304 /// candidates for tree-shaking in the first place (primitives and non-type |
| 287 /// const values overriding equals) and keys that we have seen in the program. | 305 /// const values overriding equals) and keys that we have seen in the program. |
| 288 bool _shouldKeep(ConstantValue key) => | 306 bool _shouldKeep(ConstantValue key) => |
| 289 key.isPrimitive || _inUse.contains(key) || _overridesEquals(key); | 307 key.isPrimitive || _inUse.contains(key) || _overridesEquals(key); |
| 290 | 308 |
| 291 void _addClassUse(ClassElement cls) { | 309 void _addClassUse(ClassEntity cls) { |
| 292 ConstantValue key = _typeConstants.putIfAbsent( | 310 ConstantValue key = _typeConstants.putIfAbsent( |
| 293 cls, () => _constantSystem.createType(_commonElements, cls.rawType)); | 311 cls, |
| 312 () => _constantSystem.createType( |
| 313 _commonElements, _elementEnvironment.getRawType(cls))); |
| 294 _addUse(key); | 314 _addUse(key); |
| 295 } | 315 } |
| 296 | 316 |
| 297 /// Record that [key] is used and update every lookup map that contains it. | 317 /// Record that [key] is used and update every lookup map that contains it. |
| 298 void _addUse(ConstantValue key) { | 318 void _addUse(ConstantValue key) { |
| 299 if (_inUse.add(key)) { | 319 if (_inUse.add(key)) { |
| 300 _pending[key]?.forEach((info) => info._markUsed(key)); | 320 _pending[key]?.forEach((info) => info._markUsed(key)); |
| 301 _pending.remove(key); | 321 _pending.remove(key); |
| 302 } | 322 } |
| 303 } | 323 } |
| 304 | 324 |
| 305 /// If [key] is a type, cache it in [_typeConstants]. | 325 /// If [key] is a type, cache it in [_typeConstants]. |
| 306 _registerTypeKey(ConstantValue key) { | 326 _registerTypeKey(ConstantValue key) { |
| 307 if (key is TypeConstantValue && | 327 if (key is TypeConstantValue && key.representedType is InterfaceType) { |
| 308 key.representedType is ResolutionInterfaceType) { | 328 InterfaceType type = key.representedType; |
| 309 ResolutionInterfaceType type = key.representedType; | |
| 310 _typeConstants[type.element] = key; | 329 _typeConstants[type.element] = key; |
| 311 } else { | 330 } else { |
| 312 // TODO(sigmund): report error? | 331 // TODO(sigmund): report error? |
| 313 } | 332 } |
| 314 } | 333 } |
| 315 | 334 |
| 316 /// Callback from the enqueuer, invoked when [element] is instantiated. | 335 /// Callback from the enqueuer, invoked when [element] is instantiated. |
| 317 void registerInstantiatedClass(ClassElement element) { | 336 void registerInstantiatedClass(ClassEntity element) { |
| 318 // TODO(sigmund): only add if .runtimeType is ever used | 337 // TODO(sigmund): only add if .runtimeType is ever used |
| 319 _addClassUse(element); | 338 _addClassUse(element); |
| 320 } | 339 } |
| 321 | 340 |
| 322 /// Callback from the enqueuer, invoked when [type] is instantiated. | 341 /// Callback from the enqueuer, invoked when [type] is instantiated. |
| 323 void registerInstantiatedType(ResolutionInterfaceType type) { | 342 void registerInstantiatedType(InterfaceType type) { |
| 324 // TODO(sigmund): only add if .runtimeType is ever used | 343 // TODO(sigmund): only add if .runtimeType is ever used |
| 325 _addClassUse(type.element); | 344 _addClassUse(type.element); |
| 326 // TODO(sigmund): only do this when type-argument expressions are used? | 345 // TODO(sigmund): only do this when type-argument expressions are used? |
| 327 _addGenerics(type); | 346 _addGenerics(type); |
| 328 } | 347 } |
| 329 | 348 |
| 330 /// Records generic type arguments in [type], in case they are retrieved and | 349 /// Records generic type arguments in [type], in case they are retrieved and |
| 331 /// returned using a type-argument expression. | 350 /// returned using a type-argument expression. |
| 332 void _addGenerics(ResolutionInterfaceType type) { | 351 void _addGenerics(InterfaceType type) { |
| 333 if (!type.isGeneric) return; | 352 if (type.typeArguments.isEmpty) return; |
| 334 for (var arg in type.typeArguments) { | 353 for (DartType arg in type.typeArguments) { |
| 335 if (arg is ResolutionInterfaceType) { | 354 if (arg is InterfaceType) { |
| 336 _addClassUse(arg.element); | 355 _addClassUse(arg.element); |
| 337 // Note: this call was needed to generate correct code for | 356 // Note: this call was needed to generate correct code for |
| 338 // type_lookup_map/generic_type_test | 357 // type_lookup_map/generic_type_test |
| 339 // TODO(sigmund): can we get rid of this? | 358 // TODO(sigmund): can we get rid of this? |
| 340 _impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 359 _impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
| 341 // TODO(johnniwinther): Find the right [CallStructure]. | 360 // TODO(johnniwinther): Find the right [CallStructure]. |
| 342 _commonElements.createRuntimeType, | 361 _commonElements.createRuntimeType, |
| 343 null)); | 362 null)); |
| 344 _addGenerics(arg); | 363 _addGenerics(arg); |
| 345 } | 364 } |
| 346 } | 365 } |
| 347 } | 366 } |
| 348 | 367 |
| 349 /// Callback from the codegen enqueuer, invoked when a constant (which is | 368 /// Callback from the codegen enqueuer, invoked when a constant (which is |
| 350 /// possibly a const key or a type literal) is used in the program. | 369 /// possibly a const key or a type literal) is used in the program. |
| 351 void registerTypeConstant(ClassElement element) { | 370 void registerTypeConstant(ClassEntity element) { |
| 352 _addClassUse(element); | 371 _addClassUse(element); |
| 353 } | 372 } |
| 354 | 373 |
| 355 void registerConstantKey(ConstantValue constant) { | 374 void registerConstantKey(ConstantValue constant) { |
| 356 if (constant.isPrimitive || _overridesEquals(constant)) return; | 375 if (constant.isPrimitive || _overridesEquals(constant)) return; |
| 357 _addUse(constant); | 376 _addUse(constant); |
| 358 } | 377 } |
| 359 | 378 |
| 360 void logSummary(void log(String message)) { | 379 void logSummary(void log(String message)) { |
| 361 // When --verbose is passed, we show the total number and set of keys that | 380 // When --verbose is passed, we show the total number and set of keys that |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 assert(!usedEntries.containsKey(key)); | 494 assert(!usedEntries.containsKey(key)); |
| 476 ConstantValue constant = unusedEntries.remove(key); | 495 ConstantValue constant = unusedEntries.remove(key); |
| 477 usedEntries[key] = constant; | 496 usedEntries[key] = constant; |
| 478 analysis._impactBuilder | 497 analysis._impactBuilder |
| 479 .registerConstantUse(new ConstantUse.lookupMap(constant)); | 498 .registerConstantUse(new ConstantUse.lookupMap(constant)); |
| 480 } | 499 } |
| 481 | 500 |
| 482 /// Restores [original] to contain all of the entries marked as possibly used. | 501 /// Restores [original] to contain all of the entries marked as possibly used. |
| 483 void _prepareForEmission() { | 502 void _prepareForEmission() { |
| 484 ListConstantValue originalEntries = original.fields[analysis._entriesField]; | 503 ListConstantValue originalEntries = original.fields[analysis._entriesField]; |
| 485 ResolutionInterfaceType listType = originalEntries.type; | 504 InterfaceType listType = originalEntries.type; |
| 486 List<ConstantValue> keyValuePairs = <ConstantValue>[]; | 505 List<ConstantValue> keyValuePairs = <ConstantValue>[]; |
| 487 usedEntries.forEach((key, value) { | 506 usedEntries.forEach((key, value) { |
| 488 keyValuePairs.add(key); | 507 keyValuePairs.add(key); |
| 489 keyValuePairs.add(value); | 508 keyValuePairs.add(value); |
| 490 }); | 509 }); |
| 491 | 510 |
| 492 // Note: we are restoring the entries here, see comment in [original]. | 511 // Note: we are restoring the entries here, see comment in [original]. |
| 493 if (singlePair) { | 512 if (singlePair) { |
| 494 assert(keyValuePairs.length == 0 || keyValuePairs.length == 2); | 513 assert(keyValuePairs.length == 0 || keyValuePairs.length == 2); |
| 495 if (keyValuePairs.length == 2) { | 514 if (keyValuePairs.length == 2) { |
| 496 original.fields[analysis._keyField] = keyValuePairs[0]; | 515 original.fields[analysis._keyField] = keyValuePairs[0]; |
| 497 original.fields[analysis._valueField] = keyValuePairs[1]; | 516 original.fields[analysis._valueField] = keyValuePairs[1]; |
| 498 } | 517 } |
| 499 } else { | 518 } else { |
| 500 original.fields[analysis._entriesField] = | 519 original.fields[analysis._entriesField] = |
| 501 new ListConstantValue(listType, keyValuePairs); | 520 new ListConstantValue(listType, keyValuePairs); |
| 502 } | 521 } |
| 503 } | 522 } |
| 504 } | 523 } |
| 505 | 524 |
| 506 final _validLookupMapVersionConstraint = new VersionConstraint.parse('^0.0.1'); | 525 final _validLookupMapVersionConstraint = new VersionConstraint.parse('^0.0.1'); |
| OLD | NEW |