| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.js_emitter.metadata_collector; | 5 library dart2js.js_emitter.metadata_collector; |
| 6 | 6 |
| 7 import 'package:js_ast/src/precedence.dart' as js_precedence; | 7 import 'package:js_ast/src/precedence.dart' as js_precedence; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../compiler.dart' show Compiler; | 10 import '../compiler.dart' show Compiler; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 bind(_MetadataEntry entry) { | 109 bind(_MetadataEntry entry) { |
| 110 assert(!isBound); | 110 assert(!isBound); |
| 111 _forwardTo = entry; | 111 _forwardTo = entry; |
| 112 } | 112 } |
| 113 } | 113 } |
| 114 | 114 |
| 115 class _MetadataList extends jsAst.DeferredExpression { | 115 class _MetadataList extends jsAst.DeferredExpression { |
| 116 jsAst.Expression _value; | 116 jsAst.Expression _value; |
| 117 | 117 |
| 118 void setExpression(jsAst.Expression value) { | 118 void setExpression(jsAst.Expression value) { |
| 119 // TODO(herhut): Enable the below assertion once incremental mode is gone. | 119 assert(_value == null); |
| 120 // assert(_value == null); | |
| 121 assert(value.precedenceLevel == this.precedenceLevel); | 120 assert(value.precedenceLevel == this.precedenceLevel); |
| 122 _value = value; | 121 _value = value; |
| 123 } | 122 } |
| 124 | 123 |
| 125 jsAst.Expression get value { | 124 jsAst.Expression get value { |
| 126 assert(_value != null); | 125 assert(_value != null); |
| 127 return _value; | 126 return _value; |
| 128 } | 127 } |
| 129 | 128 |
| 130 int get precedenceLevel => js_precedence.PRIMARY; | 129 int get precedenceLevel => js_precedence.PRIMARY; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 149 new Map<OutputUnit, _MetadataList>(); | 148 new Map<OutputUnit, _MetadataList>(); |
| 150 | 149 |
| 151 jsAst.Expression getTypesForOutputUnit(OutputUnit outputUnit) { | 150 jsAst.Expression getTypesForOutputUnit(OutputUnit outputUnit) { |
| 152 return _typesTokens.putIfAbsent(outputUnit, () => new _MetadataList()); | 151 return _typesTokens.putIfAbsent(outputUnit, () => new _MetadataList()); |
| 153 } | 152 } |
| 154 | 153 |
| 155 /// A map used to canonicalize the entries of types. | 154 /// A map used to canonicalize the entries of types. |
| 156 Map<OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>> _typesMap = | 155 Map<OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>> _typesMap = |
| 157 <OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>>{}; | 156 <OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>>{}; |
| 158 | 157 |
| 159 // To support incremental compilation, we have to be able to eagerly emit | |
| 160 // metadata and add metadata later on. We use the below two counters for | |
| 161 // this. | |
| 162 int _globalMetadataCounter = 0; | |
| 163 int _globalTypesCounter = 0; | |
| 164 | |
| 165 MetadataCollector(this._compiler, this._emitter) { | 158 MetadataCollector(this._compiler, this._emitter) { |
| 166 _globalMetadataMap = new Map<String, _BoundMetadataEntry>(); | 159 _globalMetadataMap = new Map<String, _BoundMetadataEntry>(); |
| 167 } | 160 } |
| 168 | 161 |
| 169 JavaScriptBackend get _backend => _compiler.backend; | 162 JavaScriptBackend get _backend => _compiler.backend; |
| 170 TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler; | 163 TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler; |
| 171 DiagnosticReporter get reporter => _compiler.reporter; | 164 DiagnosticReporter get reporter => _compiler.reporter; |
| 172 | 165 |
| 173 bool _mustEmitMetadataFor(Element element) { | 166 bool _mustEmitMetadataFor(Element element) { |
| 174 return _backend.mustRetainMetadata && | 167 return _backend.mustRetainMetadata && |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 | 306 |
| 314 Placeholder getMetadataPlaceholder([debug]) { | 307 Placeholder getMetadataPlaceholder([debug]) { |
| 315 return new _ForwardingMetadataEntry(debug); | 308 return new _ForwardingMetadataEntry(debug); |
| 316 } | 309 } |
| 317 | 310 |
| 318 _MetadataEntry _addGlobalMetadata(jsAst.Node node) { | 311 _MetadataEntry _addGlobalMetadata(jsAst.Node node) { |
| 319 String nameToKey(jsAst.Name name) => "${name.key}"; | 312 String nameToKey(jsAst.Name name) => "${name.key}"; |
| 320 String printed = | 313 String printed = |
| 321 jsAst.prettyPrint(node, _compiler, renamerForNames: nameToKey); | 314 jsAst.prettyPrint(node, _compiler, renamerForNames: nameToKey); |
| 322 return _globalMetadataMap.putIfAbsent(printed, () { | 315 return _globalMetadataMap.putIfAbsent(printed, () { |
| 323 _BoundMetadataEntry result = new _BoundMetadataEntry(node); | 316 return new _BoundMetadataEntry(node); |
| 324 if (_compiler.options.hasIncrementalSupport) { | |
| 325 result.finalize(_globalMetadataCounter++); | |
| 326 } | |
| 327 return result; | |
| 328 }); | 317 }); |
| 329 } | 318 } |
| 330 | 319 |
| 331 jsAst.Expression _computeTypeRepresentation(ResolutionDartType type, | 320 jsAst.Expression _computeTypeRepresentation(ResolutionDartType type, |
| 332 {ignoreTypeVariables: false}) { | 321 {ignoreTypeVariables: false}) { |
| 333 jsAst.Expression representation = | 322 jsAst.Expression representation = |
| 334 _backend.rtiEncoder.getTypeRepresentation(type, (variable) { | 323 _backend.rtiEncoder.getTypeRepresentation(type, (variable) { |
| 335 if (ignoreTypeVariables) return new jsAst.LiteralNull(); | 324 if (ignoreTypeVariables) return new jsAst.LiteralNull(); |
| 336 return _typeVariableHandler.reifyTypeVariable(variable.element); | 325 return _typeVariableHandler.reifyTypeVariable(variable.element); |
| 337 }, (ResolutionTypedefType typedef) { | 326 }, (ResolutionTypedefType typedef) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 349 } | 338 } |
| 350 | 339 |
| 351 jsAst.Expression addTypeInOutputUnit( | 340 jsAst.Expression addTypeInOutputUnit( |
| 352 ResolutionDartType type, OutputUnit outputUnit, | 341 ResolutionDartType type, OutputUnit outputUnit, |
| 353 {ignoreTypeVariables: false}) { | 342 {ignoreTypeVariables: false}) { |
| 354 if (_typesMap[outputUnit] == null) { | 343 if (_typesMap[outputUnit] == null) { |
| 355 _typesMap[outputUnit] = | 344 _typesMap[outputUnit] = |
| 356 new Map<ResolutionDartType, _BoundMetadataEntry>(); | 345 new Map<ResolutionDartType, _BoundMetadataEntry>(); |
| 357 } | 346 } |
| 358 return _typesMap[outputUnit].putIfAbsent(type, () { | 347 return _typesMap[outputUnit].putIfAbsent(type, () { |
| 359 _BoundMetadataEntry result = new _BoundMetadataEntry( | 348 return new _BoundMetadataEntry(_computeTypeRepresentation(type, |
| 360 _computeTypeRepresentation(type, | 349 ignoreTypeVariables: ignoreTypeVariables)); |
| 361 ignoreTypeVariables: ignoreTypeVariables)); | |
| 362 if (_compiler.options.hasIncrementalSupport) { | |
| 363 result.finalize(_globalTypesCounter++); | |
| 364 } | |
| 365 return result; | |
| 366 }); | 350 }); |
| 367 } | 351 } |
| 368 | 352 |
| 369 List<jsAst.DeferredNumber> computeMetadata(FunctionElement element) { | 353 List<jsAst.DeferredNumber> computeMetadata(FunctionElement element) { |
| 370 return reporter.withCurrentElement(element, () { | 354 return reporter.withCurrentElement(element, () { |
| 371 if (!_mustEmitMetadataFor(element)) return const <jsAst.DeferredNumber>[]; | 355 if (!_mustEmitMetadataFor(element)) return const <jsAst.DeferredNumber>[]; |
| 372 List<jsAst.DeferredNumber> metadata = <jsAst.DeferredNumber>[]; | 356 List<jsAst.DeferredNumber> metadata = <jsAst.DeferredNumber>[]; |
| 373 for (MetadataAnnotation annotation in element.metadata) { | 357 for (MetadataAnnotation annotation in element.metadata) { |
| 374 metadata.add(reifyMetadata(annotation)); | 358 metadata.add(reifyMetadata(annotation)); |
| 375 } | 359 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 392 | 376 |
| 393 void countTokensInTypes(Iterable<_BoundMetadataEntry> entries) { | 377 void countTokensInTypes(Iterable<_BoundMetadataEntry> entries) { |
| 394 jsAst.TokenCounter counter = new jsAst.TokenCounter(); | 378 jsAst.TokenCounter counter = new jsAst.TokenCounter(); |
| 395 entries | 379 entries |
| 396 .where((_BoundMetadataEntry e) => e._rc > 0) | 380 .where((_BoundMetadataEntry e) => e._rc > 0) |
| 397 .map((_BoundMetadataEntry e) => e.entry) | 381 .map((_BoundMetadataEntry e) => e.entry) |
| 398 .forEach(counter.countTokens); | 382 .forEach(counter.countTokens); |
| 399 } | 383 } |
| 400 | 384 |
| 401 jsAst.ArrayInitializer finalizeMap(Map<dynamic, _BoundMetadataEntry> map) { | 385 jsAst.ArrayInitializer finalizeMap(Map<dynamic, _BoundMetadataEntry> map) { |
| 402 // When in incremental mode, we allocate entries eagerly. | |
| 403 if (_compiler.options.hasIncrementalSupport) { | |
| 404 return new jsAst.ArrayInitializer(map.values.toList()); | |
| 405 } | |
| 406 | |
| 407 bool isUsed(_BoundMetadataEntry entry) => entry.isUsed; | 386 bool isUsed(_BoundMetadataEntry entry) => entry.isUsed; |
| 408 List<_BoundMetadataEntry> entries = map.values.where(isUsed).toList(); | 387 List<_BoundMetadataEntry> entries = map.values.where(isUsed).toList(); |
| 409 entries.sort(); | 388 entries.sort(); |
| 410 | 389 |
| 411 // TODO(herhut): Bucket entries by index length and use a stable | 390 // TODO(herhut): Bucket entries by index length and use a stable |
| 412 // distribution within buckets. | 391 // distribution within buckets. |
| 413 int count = 0; | 392 int count = 0; |
| 414 for (_BoundMetadataEntry entry in entries) { | 393 for (_BoundMetadataEntry entry in entries) { |
| 415 entry.finalize(count++); | 394 entry.finalize(count++); |
| 416 } | 395 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 447 if (token is _ForwardingMetadataEntry && !token.isBound) { | 426 if (token is _ForwardingMetadataEntry && !token.isBound) { |
| 448 _foundUnboundToken = true; | 427 _foundUnboundToken = true; |
| 449 } | 428 } |
| 450 } | 429 } |
| 451 | 430 |
| 452 bool findUnboundPlaceholders(jsAst.Node node) { | 431 bool findUnboundPlaceholders(jsAst.Node node) { |
| 453 node.accept(this); | 432 node.accept(this); |
| 454 return _foundUnboundToken; | 433 return _foundUnboundToken; |
| 455 } | 434 } |
| 456 } | 435 } |
| OLD | NEW |