Chromium Code Reviews| 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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 /// Represents an entry's position in one of the global metadata arrays. | 7 /// Represents an entry's position in one of the global metadata arrays. |
| 8 /// | 8 /// |
| 9 /// [_rc] is used to count the number of references of the token in the | 9 /// [_rc] is used to count the number of references of the token in the |
| 10 /// ast for a program. | 10 /// ast for a program. |
| 11 /// [value] is the actual position, once they have been finalized. | 11 /// [value] is the actual position, once they have been finalized. |
| 12 abstract class _MetadataEntry extends jsAst.DeferredNumber | 12 abstract class _MetadataEntry extends jsAst.DeferredNumber |
| 13 implements Comparable { | 13 implements Comparable, jsAst.ReferenceCountedAstNode { |
| 14 jsAst.Expression get entry; | 14 jsAst.Expression get entry; |
| 15 int get value; | 15 int get value; |
| 16 int get _rc; | 16 int get _rc; |
| 17 | 17 |
| 18 // Mark this entry as seen. On the first time this is seen, the visitor | 18 // Mark this entry as seen. On the first time this is seen, the visitor |
| 19 // will be applied to the [entry] to also mark potential [_MetadataEntry] | 19 // will be applied to the [entry] to also mark potential [_MetadataEntry] |
| 20 // instances in the [entry] as seen. | 20 // instances in the [entry] as seen. |
| 21 markSeen(jsAst.BaseVisitor visitor); | 21 markSeen(jsAst.TokenCounter visitor); |
| 22 } | 22 } |
| 23 | 23 |
| 24 class _BoundMetadataEntry extends _MetadataEntry { | 24 class _BoundMetadataEntry extends _MetadataEntry { |
| 25 int _value = -1; | 25 int _value = -1; |
| 26 int _rc = 0; | 26 int _rc = 0; |
| 27 final jsAst.Expression entry; | 27 final jsAst.Expression entry; |
| 28 | 28 |
| 29 _BoundMetadataEntry(this.entry); | 29 _BoundMetadataEntry(this.entry); |
| 30 | 30 |
| 31 bool get isFinalized => _value != -1; | 31 bool get isFinalized => _value != -1; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 } | 100 } |
| 101 | 101 |
| 102 jsAst.Expression get value { | 102 jsAst.Expression get value { |
| 103 assert(_value != null); | 103 assert(_value != null); |
| 104 return _value; | 104 return _value; |
| 105 } | 105 } |
| 106 | 106 |
| 107 int get precedenceLevel => js_precedence.PRIMARY; | 107 int get precedenceLevel => js_precedence.PRIMARY; |
| 108 } | 108 } |
| 109 | 109 |
| 110 class MetadataCollector implements TokenFinalizer { | 110 class MetadataCollector implements jsAst.TokenFinalizer { |
| 111 final Compiler _compiler; | 111 final Compiler _compiler; |
| 112 final Emitter _emitter; | 112 final Emitter _emitter; |
| 113 | 113 |
| 114 /// A token for a list of expressions that represent metadata, parameter names | 114 /// A token for a list of expressions that represent metadata, parameter names |
| 115 /// and type variable types. | 115 /// and type variable types. |
| 116 final _MetadataList _globalMetadata = new _MetadataList(); | 116 final _MetadataList _globalMetadata = new _MetadataList(); |
| 117 jsAst.Expression get globalMetadata => _globalMetadata; | 117 jsAst.Expression get globalMetadata => _globalMetadata; |
| 118 | 118 |
| 119 /// A map used to canonicalize the entries of globalMetadata. | 119 /// A map used to canonicalize the entries of globalMetadata. |
| 120 Map<String, _BoundMetadataEntry> _globalMetadataMap; | 120 Map<String, _BoundMetadataEntry> _globalMetadataMap; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 | 225 |
| 226 jsAst.Expression reifyExpression(jsAst.Expression expression) { | 226 jsAst.Expression reifyExpression(jsAst.Expression expression) { |
| 227 return _addGlobalMetadata(expression); | 227 return _addGlobalMetadata(expression); |
| 228 } | 228 } |
| 229 | 229 |
| 230 Placeholder getMetadataPlaceholder([debug]) { | 230 Placeholder getMetadataPlaceholder([debug]) { |
| 231 return new _ForwardingMetadataEntry(debug); | 231 return new _ForwardingMetadataEntry(debug); |
| 232 } | 232 } |
| 233 | 233 |
| 234 _MetadataEntry _addGlobalMetadata(jsAst.Node node) { | 234 _MetadataEntry _addGlobalMetadata(jsAst.Node node) { |
| 235 String printed = jsAst.prettyPrint(node, _compiler).getText(); | 235 String nameToHashCode(jsAst.Name name) => "${name.hashCode}"; |
|
sra1
2015/07/01 04:11:09
Q1. Are you guaranteeing somewhere that each uniqu
herhut
2015/07/02 08:54:51
Yes. freshName (which hands out jsAst.Name) produc
| |
| 236 String printed = jsAst.prettyPrint(node, _compiler, | |
| 237 renamerForNames: nameToHashCode) | |
| 238 .getText(); | |
| 236 return _globalMetadataMap.putIfAbsent(printed, () { | 239 return _globalMetadataMap.putIfAbsent(printed, () { |
| 237 _BoundMetadataEntry result = new _BoundMetadataEntry(node); | 240 _BoundMetadataEntry result = new _BoundMetadataEntry(node); |
| 238 if (_compiler.hasIncrementalSupport) { | 241 if (_compiler.hasIncrementalSupport) { |
| 239 result.finalize(_globalMetadataCounter++); | 242 result.finalize(_globalMetadataCounter++); |
| 240 } | 243 } |
| 241 return result; | 244 return result; |
| 242 }); | 245 }); |
| 243 } | 246 } |
| 244 | 247 |
| 245 jsAst.Expression _computeTypeRepresentation(DartType type, | 248 jsAst.Expression _computeTypeRepresentation(DartType type, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 if (link != null) { | 294 if (link != null) { |
| 292 for (; !link.isEmpty; link = link.tail) { | 295 for (; !link.isEmpty; link = link.tail) { |
| 293 metadata.add(reifyMetadata(link.head)); | 296 metadata.add(reifyMetadata(link.head)); |
| 294 } | 297 } |
| 295 } | 298 } |
| 296 return metadata; | 299 return metadata; |
| 297 }); | 300 }); |
| 298 } | 301 } |
| 299 | 302 |
| 300 @override | 303 @override |
| 301 void countTokensInAst(jsAst.Node ast) { | |
| 302 TokenCounter visitor = new TokenCounter(); | |
| 303 visitor.countTokens(ast); | |
| 304 } | |
| 305 | |
| 306 @override | |
| 307 void finalizeTokens() { | 304 void finalizeTokens() { |
| 308 bool checkTokensInTypes(OutputUnit outputUnit, entries) { | 305 bool checkTokensInTypes(OutputUnit outputUnit, entries) { |
| 309 UnBoundDebugger debugger = new UnBoundDebugger(outputUnit); | 306 UnBoundDebugger debugger = new UnBoundDebugger(outputUnit); |
| 310 for (_BoundMetadataEntry entry in entries) { | 307 for (_BoundMetadataEntry entry in entries) { |
| 311 if (!entry.isUsed) continue; | 308 if (!entry.isUsed) continue; |
| 312 if (debugger.findUnboundPlaceholders(entry.entry)) { | 309 if (debugger.findUnboundPlaceholders(entry.entry)) { |
| 313 return false; | 310 return false; |
| 314 } | 311 } |
| 315 } | 312 } |
| 316 return true; | 313 return true; |
| 317 } | 314 } |
| 318 void countTokensInTypes(Iterable<_BoundMetadataEntry> entries) { | 315 void countTokensInTypes(Iterable<_BoundMetadataEntry> entries) { |
| 319 TokenCounter counter = new TokenCounter(); | 316 jsAst.TokenCounter counter = new jsAst.TokenCounter(); |
| 320 entries.where((_BoundMetadataEntry e) => e._rc > 0) | 317 entries.where((_BoundMetadataEntry e) => e._rc > 0) |
| 321 .map((_BoundMetadataEntry e) => e.entry) | 318 .map((_BoundMetadataEntry e) => e.entry) |
| 322 .forEach(counter.countTokens); | 319 .forEach(counter.countTokens); |
| 323 } | 320 } |
| 324 | 321 |
| 325 jsAst.ArrayInitializer finalizeMap(Map<dynamic, _BoundMetadataEntry> map) { | 322 jsAst.ArrayInitializer finalizeMap(Map<dynamic, _BoundMetadataEntry> map) { |
| 326 // When in incremental mode, we allocate entries eagerly. | 323 // When in incremental mode, we allocate entries eagerly. |
| 327 if (_compiler.hasIncrementalSupport) { | 324 if (_compiler.hasIncrementalSupport) { |
| 328 return new jsAst.ArrayInitializer(map.values.toList()); | 325 return new jsAst.ArrayInitializer(map.values.toList()); |
| 329 } | 326 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 353 assert(checkTokensInTypes(outputUnit, typesMap.values)); | 350 assert(checkTokensInTypes(outputUnit, typesMap.values)); |
| 354 countTokensInTypes(typesMap.values); | 351 countTokensInTypes(typesMap.values); |
| 355 token.setExpression(finalizeMap(typesMap)); | 352 token.setExpression(finalizeMap(typesMap)); |
| 356 } else { | 353 } else { |
| 357 token.setExpression(new jsAst.ArrayInitializer([])); | 354 token.setExpression(new jsAst.ArrayInitializer([])); |
| 358 } | 355 } |
| 359 }); | 356 }); |
| 360 } | 357 } |
| 361 } | 358 } |
| 362 | 359 |
| 363 /// Interface for ast nodes that encapsulate an ast that needs to be | |
| 364 /// traversed when counting tokens. | |
| 365 /// | |
| 366 /// TODO(herhut): Find a shared place once namer also uses tokens. | |
| 367 abstract class AstContainer implements jsAst.Node { | |
| 368 jsAst.Node get ast; | |
| 369 } | |
| 370 | |
| 371 abstract class TokenFinalizer { | |
| 372 void countTokensInAst(jsAst.Node ast); | |
| 373 void finalizeTokens(); | |
| 374 } | |
| 375 | |
| 376 class TokenCounter extends jsAst.BaseVisitor { | |
| 377 @override | |
| 378 visitNode(jsAst.Node node) { | |
| 379 if (node is AstContainer) { | |
| 380 node.ast.accept(this); | |
| 381 } else { | |
| 382 super.visitNode(node); | |
| 383 } | |
| 384 } | |
| 385 | |
| 386 @override | |
| 387 visitDeferredNumber(jsAst.DeferredNumber token) { | |
| 388 if (token is _MetadataEntry) { | |
| 389 token.markSeen(this); | |
| 390 } | |
| 391 } | |
| 392 | |
| 393 void countTokens(jsAst.Node node) => node.accept(this); | |
| 394 } | |
| 395 | |
| 396 class UnBoundDebugger extends jsAst.BaseVisitor { | 360 class UnBoundDebugger extends jsAst.BaseVisitor { |
| 397 OutputUnit outputUnit; | 361 OutputUnit outputUnit; |
| 398 bool _foundUnboundToken = false; | 362 bool _foundUnboundToken = false; |
| 399 | 363 |
| 400 UnBoundDebugger(this.outputUnit); | 364 UnBoundDebugger(this.outputUnit); |
| 401 | 365 |
| 402 @override | 366 @override |
| 403 visitDeferredNumber(jsAst.DeferredNumber token) { | 367 visitDeferredNumber(jsAst.DeferredNumber token) { |
| 404 if (token is _ForwardingMetadataEntry && !token.isBound) { | 368 if (token is _ForwardingMetadataEntry && !token.isBound) { |
| 405 _foundUnboundToken = true; | 369 _foundUnboundToken = true; |
| 406 } | 370 } |
| 407 } | 371 } |
| 408 | 372 |
| 409 bool findUnboundPlaceholders(jsAst.Node node) { | 373 bool findUnboundPlaceholders(jsAst.Node node) { |
| 410 node.accept(this); | 374 node.accept(this); |
| 411 return _foundUnboundToken; | 375 return _foundUnboundToken; |
| 412 } | 376 } |
| 413 } | 377 } |
| OLD | NEW |