| 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'; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 ClassElement cls = lookupMapLibrary.findLocal('LookupMap'); | 194 ClassElement cls = lookupMapLibrary.findLocal('LookupMap'); |
| 195 cls.computeType(backend.resolution); | 195 cls.computeType(backend.resolution); |
| 196 entriesField = cls.lookupMember('_entries'); | 196 entriesField = cls.lookupMember('_entries'); |
| 197 keyField = cls.lookupMember('_key'); | 197 keyField = cls.lookupMember('_key'); |
| 198 valueField = cls.lookupMember('_value'); | 198 valueField = cls.lookupMember('_value'); |
| 199 // TODO(sigmund): Maybe inline nested maps to make the output code smaller? | 199 // TODO(sigmund): Maybe inline nested maps to make the output code smaller? |
| 200 typeLookupMapClass = cls; | 200 typeLookupMapClass = cls; |
| 201 } | 201 } |
| 202 | 202 |
| 203 /// Whether [constant] is an instance of a `LookupMap`. | 203 /// Whether [constant] is an instance of a `LookupMap`. |
| 204 bool isLookupMap(ConstantValue constant) => | 204 bool isLookupMap(ConstantValue constant) { |
| 205 _isEnabled && | 205 if (_isEnabled && constant is ConstructedConstantValue) { |
| 206 constant is ConstructedConstantValue && | 206 ResolutionInterfaceType type = constant.type; |
| 207 constant.type.asRaw().element.isSubclassOf(typeLookupMapClass); | 207 return type.element.isSubclassOf(typeLookupMapClass); |
| 208 } |
| 209 return false; |
| 210 } |
| 208 | 211 |
| 209 /// Registers an instance of a lookup-map with the analysis. | 212 /// Registers an instance of a lookup-map with the analysis. |
| 210 void registerLookupMapReference(ConstantValue lookupMap) { | 213 void registerLookupMapReference(ConstantValue lookupMap) { |
| 211 if (!_isEnabled || !_inCodegen) return; | 214 if (!_isEnabled || !_inCodegen) return; |
| 212 assert(isLookupMap(lookupMap)); | 215 assert(isLookupMap(lookupMap)); |
| 213 _lookupMaps.putIfAbsent( | 216 _lookupMaps.putIfAbsent( |
| 214 lookupMap, () => new _LookupMapInfo(lookupMap, this).._updateUsed()); | 217 lookupMap, () => new _LookupMapInfo(lookupMap, this).._updateUsed()); |
| 215 } | 218 } |
| 216 | 219 |
| 217 /// Whether [key] is a constant value whose type overrides equals. | 220 /// Whether [key] is a constant value whose type overrides equals. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 239 /// Record that [key] is used and update every lookup map that contains it. | 242 /// Record that [key] is used and update every lookup map that contains it. |
| 240 void _addUse(ConstantValue key) { | 243 void _addUse(ConstantValue key) { |
| 241 if (_inUse.add(key)) { | 244 if (_inUse.add(key)) { |
| 242 _pending[key]?.forEach((info) => info._markUsed(key)); | 245 _pending[key]?.forEach((info) => info._markUsed(key)); |
| 243 _pending.remove(key); | 246 _pending.remove(key); |
| 244 } | 247 } |
| 245 } | 248 } |
| 246 | 249 |
| 247 /// If [key] is a type, cache it in [_typeConstants]. | 250 /// If [key] is a type, cache it in [_typeConstants]. |
| 248 _registerTypeKey(ConstantValue key) { | 251 _registerTypeKey(ConstantValue key) { |
| 249 if (key is TypeConstantValue) { | 252 if (key is TypeConstantValue && |
| 250 ClassElement cls = key.representedType.element; | 253 key.representedType is ResolutionInterfaceType) { |
| 251 if (cls == null || !cls.isClass) { | 254 ResolutionInterfaceType type = key.representedType; |
| 252 // TODO(sigmund): report error? | 255 _typeConstants[type.element] = key; |
| 253 return; | 256 } else { |
| 254 } | 257 // TODO(sigmund): report error? |
| 255 _typeConstants[cls] = key; | |
| 256 } | 258 } |
| 257 } | 259 } |
| 258 | 260 |
| 259 /// Callback from the enqueuer, invoked when [element] is instantiated. | 261 /// Callback from the enqueuer, invoked when [element] is instantiated. |
| 260 void registerInstantiatedClass(ClassElement element) { | 262 void registerInstantiatedClass(ClassElement element) { |
| 261 if (!_isEnabled || !_inCodegen) return; | 263 if (!_isEnabled || !_inCodegen) return; |
| 262 // TODO(sigmund): only add if .runtimeType is ever used | 264 // TODO(sigmund): only add if .runtimeType is ever used |
| 263 _addClassUse(element); | 265 _addClassUse(element); |
| 264 } | 266 } |
| 265 | 267 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 assert(!usedEntries.containsKey(key)); | 426 assert(!usedEntries.containsKey(key)); |
| 425 ConstantValue constant = unusedEntries.remove(key); | 427 ConstantValue constant = unusedEntries.remove(key); |
| 426 usedEntries[key] = constant; | 428 usedEntries[key] = constant; |
| 427 analysis.backend.computeImpactForCompileTimeConstant( | 429 analysis.backend.computeImpactForCompileTimeConstant( |
| 428 constant, analysis.impactBuilderForCodegen, false); | 430 constant, analysis.impactBuilderForCodegen, false); |
| 429 } | 431 } |
| 430 | 432 |
| 431 /// Restores [original] to contain all of the entries marked as possibly used. | 433 /// Restores [original] to contain all of the entries marked as possibly used. |
| 432 void _prepareForEmission() { | 434 void _prepareForEmission() { |
| 433 ListConstantValue originalEntries = original.fields[analysis.entriesField]; | 435 ListConstantValue originalEntries = original.fields[analysis.entriesField]; |
| 434 ResolutionDartType listType = originalEntries.type; | 436 ResolutionInterfaceType listType = originalEntries.type; |
| 435 List<ConstantValue> keyValuePairs = <ConstantValue>[]; | 437 List<ConstantValue> keyValuePairs = <ConstantValue>[]; |
| 436 usedEntries.forEach((key, value) { | 438 usedEntries.forEach((key, value) { |
| 437 keyValuePairs.add(key); | 439 keyValuePairs.add(key); |
| 438 keyValuePairs.add(value); | 440 keyValuePairs.add(value); |
| 439 }); | 441 }); |
| 440 | 442 |
| 441 // Note: we are restoring the entries here, see comment in [original]. | 443 // Note: we are restoring the entries here, see comment in [original]. |
| 442 if (singlePair) { | 444 if (singlePair) { |
| 443 assert(keyValuePairs.length == 0 || keyValuePairs.length == 2); | 445 assert(keyValuePairs.length == 0 || keyValuePairs.length == 2); |
| 444 if (keyValuePairs.length == 2) { | 446 if (keyValuePairs.length == 2) { |
| 445 original.fields[analysis.keyField] = keyValuePairs[0]; | 447 original.fields[analysis.keyField] = keyValuePairs[0]; |
| 446 original.fields[analysis.valueField] = keyValuePairs[1]; | 448 original.fields[analysis.valueField] = keyValuePairs[1]; |
| 447 } | 449 } |
| 448 } else { | 450 } else { |
| 449 original.fields[analysis.entriesField] = | 451 original.fields[analysis.entriesField] = |
| 450 new ListConstantValue(listType, keyValuePairs); | 452 new ListConstantValue(listType, keyValuePairs); |
| 451 } | 453 } |
| 452 } | 454 } |
| 453 } | 455 } |
| 454 | 456 |
| 455 final _validLookupMapVersionConstraint = new VersionConstraint.parse('^0.0.1'); | 457 final _validLookupMapVersionConstraint = new VersionConstraint.parse('^0.0.1'); |
| OLD | NEW |