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 |