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 compiler.src.inferrer.type_graph_nodes; | 5 library compiler.src.inferrer.type_graph_nodes; |
6 | 6 |
7 import 'dart:collection' show IterableBase; | 7 import 'dart:collection' show IterableBase; |
8 | 8 |
9 import '../common.dart'; | 9 import '../common.dart'; |
10 import '../common/names.dart' show Identifiers; | 10 import '../common/names.dart' show Identifiers; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 _assignments = STOP_TRACKING_ASSIGNMENTS_MARKER; | 230 _assignments = STOP_TRACKING_ASSIGNMENTS_MARKER; |
231 abandonInferencing = true; | 231 abandonInferencing = true; |
232 isStable = true; | 232 isStable = true; |
233 } | 233 } |
234 | 234 |
235 void maybeResume() { | 235 void maybeResume() { |
236 if (!mightResume) return; | 236 if (!mightResume) return; |
237 abandonInferencing = false; | 237 abandonInferencing = false; |
238 doNotEnqueue = false; | 238 doNotEnqueue = false; |
239 } | 239 } |
| 240 |
| 241 /// Destroys information not needed after type inference. |
| 242 void cleanup() { |
| 243 users = null; |
| 244 _assignments = null; |
| 245 } |
240 } | 246 } |
241 | 247 |
242 abstract class ApplyableTypeInformation implements TypeInformation { | 248 abstract class ApplyableTypeInformation implements TypeInformation { |
243 bool mightBePassedToFunctionApply = false; | 249 bool mightBePassedToFunctionApply = false; |
244 } | 250 } |
245 | 251 |
246 /** | 252 /** |
247 * Marker node used only during tree construction but not during actual type | 253 * Marker node used only during tree construction but not during actual type |
248 * refinement. | 254 * refinement. |
249 * | 255 * |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 class MemberTypeInformation extends ElementTypeInformation | 384 class MemberTypeInformation extends ElementTypeInformation |
379 with ApplyableTypeInformation { | 385 with ApplyableTypeInformation { |
380 TypedElement get element => super.element; | 386 TypedElement get element => super.element; |
381 | 387 |
382 /** | 388 /** |
383 * If [element] is a function, [closurizedCount] is the number of | 389 * If [element] is a function, [closurizedCount] is the number of |
384 * times it is closurized. The value gets updated while infering. | 390 * times it is closurized. The value gets updated while infering. |
385 */ | 391 */ |
386 int closurizedCount = 0; | 392 int closurizedCount = 0; |
387 | 393 |
| 394 // Strict `bool` value is computed in cleanup(). Also used as a flag to see if |
| 395 // cleanup has been called. |
| 396 bool _isCalledOnce = null; |
| 397 |
388 /** | 398 /** |
389 * This map contains the callers of [element]. It stores all unique call sites | 399 * This map contains the callers of [element]. It stores all unique call sites |
390 * to enable counting the global number of call sites of [element]. | 400 * to enable counting the global number of call sites of [element]. |
391 * | 401 * |
392 * A call site is either an AST [ast.Node], a [cps_ir.Node] or in the case of | 402 * A call site is either an AST [ast.Node], a [cps_ir.Node] or in the case of |
393 * synthesized calls, an [Element] (see uses of [synthesizeForwardingCall] | 403 * synthesized calls, an [Element] (see uses of [synthesizeForwardingCall] |
394 * in [SimpleTypeInferrerVisitor]). | 404 * in [SimpleTypeInferrerVisitor]). |
| 405 * |
| 406 * The global information is summarized in [cleanup], after which [_callers] |
| 407 * is set to `null`. |
395 */ | 408 */ |
396 final Map<Element, Setlet<Spannable>> _callers = new Map<Element, Setlet>(); | 409 Map<Element, Setlet<Spannable>> _callers; |
397 | 410 |
398 MemberTypeInformation._internal(Element element) | 411 MemberTypeInformation._internal(Element element) |
399 : super._internal(null, element); | 412 : super._internal(null, element); |
400 | 413 |
401 void addCall(Element caller, Spannable node) { | 414 void addCall(Element caller, Spannable node) { |
402 assert(node is ast.Node || node is cps_ir.Node || node is Element); | 415 assert(node is ast.Node || node is cps_ir.Node || node is Element); |
| 416 _callers ??= <Element, Setlet>{}; |
403 _callers.putIfAbsent(caller, () => new Setlet()).add(node); | 417 _callers.putIfAbsent(caller, () => new Setlet()).add(node); |
404 } | 418 } |
405 | 419 |
406 void removeCall(Element caller, node) { | 420 void removeCall(Element caller, node) { |
| 421 if (_callers == null) return; |
407 Setlet calls = _callers[caller]; | 422 Setlet calls = _callers[caller]; |
408 if (calls == null) return; | 423 if (calls == null) return; |
409 calls.remove(node); | 424 calls.remove(node); |
410 if (calls.isEmpty) { | 425 if (calls.isEmpty) { |
411 _callers.remove(caller); | 426 _callers.remove(caller); |
412 } | 427 } |
413 } | 428 } |
414 | 429 |
415 Iterable<Element> get callers => _callers.keys; | 430 Iterable<Element> get callers { |
| 431 // TODO(sra): This is called only from an unused API and a test. If it |
| 432 // becomes used, [cleanup] will need to copy `_caller.keys`. |
| 433 |
| 434 // `simple_inferrer_callers_test.dart` ensures that cleanup has not |
| 435 // happened. |
| 436 return _callers.keys; |
| 437 } |
416 | 438 |
417 bool isCalledOnce() { | 439 bool isCalledOnce() { |
| 440 // If this assert fires it means that this MemberTypeInformation for the |
| 441 // element was not part of type inference. This happens for |
| 442 // ConstructorBodyElements, so guard the call with a test for |
| 443 // ConstructorBodyElement. For other elements, investigate why the element |
| 444 // was not present for type inference. |
| 445 assert(_isCalledOnce != null); |
| 446 return _isCalledOnce ?? false; |
| 447 } |
| 448 |
| 449 bool _computeIsCalledOnce() { |
| 450 if (_callers == null) return false; |
418 int count = 0; | 451 int count = 0; |
419 for (var set in _callers.values) { | 452 for (var set in _callers.values) { |
420 count += set.length; | 453 count += set.length; |
421 if (count > 1) return false; | 454 if (count > 1) return false; |
422 } | 455 } |
423 return count == 1; | 456 return count == 1; |
424 } | 457 } |
425 | 458 |
426 bool get isClosurized => closurizedCount > 0; | 459 bool get isClosurized => closurizedCount > 0; |
427 | 460 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 // The number of assignments of non-final fields is | 556 // The number of assignments of non-final fields is |
524 // not stable. Therefore such a field cannot be stable. | 557 // not stable. Therefore such a field cannot be stable. |
525 if (element.isField && !(element.isConst || element.isFinal)) { | 558 if (element.isField && !(element.isConst || element.isFinal)) { |
526 return false; | 559 return false; |
527 } | 560 } |
528 | 561 |
529 if (element.isFunction) return false; | 562 if (element.isFunction) return false; |
530 | 563 |
531 return super.hasStableType(inferrer); | 564 return super.hasStableType(inferrer); |
532 } | 565 } |
| 566 |
| 567 void cleanup() { |
| 568 // This node is on multiple lists so cleanup() can be called twice. |
| 569 if (_isCalledOnce != null) return; |
| 570 _isCalledOnce = _computeIsCalledOnce(); |
| 571 _callers = null; |
| 572 super.cleanup(); |
| 573 } |
533 } | 574 } |
534 | 575 |
535 /** | 576 /** |
536 * A node representing parameters: | 577 * A node representing parameters: |
537 * | 578 * |
538 * - Parameters | 579 * - Parameters |
539 * - Initializing formals | 580 * - Initializing formals |
540 * | 581 * |
541 * These should never be created directly but instead are constructed by | 582 * These should never be created directly but instead are constructed by |
542 * the [ElementTypeInformation] factory. | 583 * the [ElementTypeInformation] factory. |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 return new ContainerTypeMask(originalType.forwardTo, | 1353 return new ContainerTypeMask(originalType.forwardTo, |
1313 originalType.allocationNode, | 1354 originalType.allocationNode, |
1314 originalType.allocationElement, | 1355 originalType.allocationElement, |
1315 elementType.type, | 1356 elementType.type, |
1316 inferredLength); | 1357 inferredLength); |
1317 } | 1358 } |
1318 return mask; | 1359 return mask; |
1319 } | 1360 } |
1320 | 1361 |
1321 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; | 1362 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; |
| 1363 |
| 1364 void cleanup() { |
| 1365 super.cleanup(); |
| 1366 elementType.cleanup(); |
| 1367 _flowsInto = null; |
| 1368 } |
1322 } | 1369 } |
1323 | 1370 |
1324 /** | 1371 /** |
1325 * An [ElementInContainerTypeInformation] holds the common type of the | 1372 * An [ElementInContainerTypeInformation] holds the common type of the |
1326 * elements in a [ListTypeInformation]. | 1373 * elements in a [ListTypeInformation]. |
1327 */ | 1374 */ |
1328 class ElementInContainerTypeInformation extends InferredTypeInformation { | 1375 class ElementInContainerTypeInformation extends InferredTypeInformation { |
1329 ElementInContainerTypeInformation(MemberTypeInformation context, | 1376 ElementInContainerTypeInformation(MemberTypeInformation context, |
1330 elementType) | 1377 elementType) |
1331 : super(context, elementType); | 1378 : super(context, elementType); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 } | 1522 } |
1476 | 1523 |
1477 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; | 1524 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; |
1478 | 1525 |
1479 bool hasStableType(TypeGraphInferrerEngine inferrer) { | 1526 bool hasStableType(TypeGraphInferrerEngine inferrer) { |
1480 return keyType.isStable && | 1527 return keyType.isStable && |
1481 valueType.isStable && | 1528 valueType.isStable && |
1482 super.hasStableType(inferrer); | 1529 super.hasStableType(inferrer); |
1483 } | 1530 } |
1484 | 1531 |
| 1532 void cleanup() { |
| 1533 super.cleanup(); |
| 1534 keyType.cleanup(); |
| 1535 valueType.cleanup(); |
| 1536 for (TypeInformation info in typeInfoMap.values) { |
| 1537 info.cleanup(); |
| 1538 } |
| 1539 _flowsInto = null; |
| 1540 } |
| 1541 |
1485 String toString() { | 1542 String toString() { |
1486 return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap'; | 1543 return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap'; |
1487 } | 1544 } |
1488 } | 1545 } |
1489 | 1546 |
1490 /** | 1547 /** |
1491 * A [KeyInMapTypeInformation] holds the common type | 1548 * A [KeyInMapTypeInformation] holds the common type |
1492 * for the keys in a [MapTypeInformation] | 1549 * for the keys in a [MapTypeInformation] |
1493 */ | 1550 */ |
1494 class KeyInMapTypeInformation extends InferredTypeInformation { | 1551 class KeyInMapTypeInformation extends InferredTypeInformation { |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1661 } else if (annotation.isVoid) { | 1718 } else if (annotation.isVoid) { |
1662 otherType = compiler.typesTask.nullType; | 1719 otherType = compiler.typesTask.nullType; |
1663 } else { | 1720 } else { |
1664 assert(annotation.isInterfaceType); | 1721 assert(annotation.isInterfaceType); |
1665 otherType = new TypeMask.nonNullSubtype(annotation.element, compiler.world); | 1722 otherType = new TypeMask.nonNullSubtype(annotation.element, compiler.world); |
1666 } | 1723 } |
1667 if (isNullable) otherType = otherType.nullable(); | 1724 if (isNullable) otherType = otherType.nullable(); |
1668 if (type == null) return otherType; | 1725 if (type == null) return otherType; |
1669 return type.intersection(otherType, compiler.world); | 1726 return type.intersection(otherType, compiler.world); |
1670 } | 1727 } |
OLD | NEW |