| 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 } | |
| 246 } | 240 } |
| 247 | 241 |
| 248 abstract class ApplyableTypeInformation implements TypeInformation { | 242 abstract class ApplyableTypeInformation implements TypeInformation { |
| 249 bool mightBePassedToFunctionApply = false; | 243 bool mightBePassedToFunctionApply = false; |
| 250 } | 244 } |
| 251 | 245 |
| 252 /** | 246 /** |
| 253 * Marker node used only during tree construction but not during actual type | 247 * Marker node used only during tree construction but not during actual type |
| 254 * refinement. | 248 * refinement. |
| 255 * | 249 * |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 class MemberTypeInformation extends ElementTypeInformation | 378 class MemberTypeInformation extends ElementTypeInformation |
| 385 with ApplyableTypeInformation { | 379 with ApplyableTypeInformation { |
| 386 TypedElement get element => super.element; | 380 TypedElement get element => super.element; |
| 387 | 381 |
| 388 /** | 382 /** |
| 389 * If [element] is a function, [closurizedCount] is the number of | 383 * If [element] is a function, [closurizedCount] is the number of |
| 390 * times it is closurized. The value gets updated while infering. | 384 * times it is closurized. The value gets updated while infering. |
| 391 */ | 385 */ |
| 392 int closurizedCount = 0; | 386 int closurizedCount = 0; |
| 393 | 387 |
| 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 | |
| 398 /** | 388 /** |
| 399 * This map contains the callers of [element]. It stores all unique call sites | 389 * This map contains the callers of [element]. It stores all unique call sites |
| 400 * to enable counting the global number of call sites of [element]. | 390 * to enable counting the global number of call sites of [element]. |
| 401 * | 391 * |
| 402 * A call site is either an AST [ast.Node], a [cps_ir.Node] or in the case of | 392 * A call site is either an AST [ast.Node], a [cps_ir.Node] or in the case of |
| 403 * synthesized calls, an [Element] (see uses of [synthesizeForwardingCall] | 393 * synthesized calls, an [Element] (see uses of [synthesizeForwardingCall] |
| 404 * in [SimpleTypeInferrerVisitor]). | 394 * in [SimpleTypeInferrerVisitor]). |
| 405 * | |
| 406 * The global information is summarized in [cleanup], after which [_callers] | |
| 407 * is set to `null`. | |
| 408 */ | 395 */ |
| 409 Map<Element, Setlet<Spannable>> _callers; | 396 final Map<Element, Setlet<Spannable>> _callers = new Map<Element, Setlet>(); |
| 410 | 397 |
| 411 MemberTypeInformation._internal(Element element) | 398 MemberTypeInformation._internal(Element element) |
| 412 : super._internal(null, element); | 399 : super._internal(null, element); |
| 413 | 400 |
| 414 void addCall(Element caller, Spannable node) { | 401 void addCall(Element caller, Spannable node) { |
| 415 assert(node is ast.Node || node is cps_ir.Node || node is Element); | 402 assert(node is ast.Node || node is cps_ir.Node || node is Element); |
| 416 _callers ??= <Element, Setlet>{}; | |
| 417 _callers.putIfAbsent(caller, () => new Setlet()).add(node); | 403 _callers.putIfAbsent(caller, () => new Setlet()).add(node); |
| 418 } | 404 } |
| 419 | 405 |
| 420 void removeCall(Element caller, node) { | 406 void removeCall(Element caller, node) { |
| 421 if (_callers == null) return; | |
| 422 Setlet calls = _callers[caller]; | 407 Setlet calls = _callers[caller]; |
| 423 if (calls == null) return; | 408 if (calls == null) return; |
| 424 calls.remove(node); | 409 calls.remove(node); |
| 425 if (calls.isEmpty) { | 410 if (calls.isEmpty) { |
| 426 _callers.remove(caller); | 411 _callers.remove(caller); |
| 427 } | 412 } |
| 428 } | 413 } |
| 429 | 414 |
| 430 Iterable<Element> get callers { | 415 Iterable<Element> get callers => _callers.keys; |
| 431 // TODO(sra): This is called only from an unused API. If it becomes used, | |
| 432 // [cleanup] will need to copy `_caller.keys`. | |
| 433 assert(false); // Unused. | |
| 434 return _callers.keys; | |
| 435 } | |
| 436 | 416 |
| 437 bool isCalledOnce() { | 417 bool isCalledOnce() { |
| 438 assert(_isCalledOnce != null); | |
| 439 return _isCalledOnce; | |
| 440 } | |
| 441 | |
| 442 bool _computeIsCalledOnce() { | |
| 443 if (_callers == null) return false; | |
| 444 int count = 0; | 418 int count = 0; |
| 445 for (var set in _callers.values) { | 419 for (var set in _callers.values) { |
| 446 count += set.length; | 420 count += set.length; |
| 447 if (count > 1) return false; | 421 if (count > 1) return false; |
| 448 } | 422 } |
| 449 return count == 1; | 423 return count == 1; |
| 450 } | 424 } |
| 451 | 425 |
| 452 bool get isClosurized => closurizedCount > 0; | 426 bool get isClosurized => closurizedCount > 0; |
| 453 | 427 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 // The number of assignments of non-final fields is | 523 // The number of assignments of non-final fields is |
| 550 // not stable. Therefore such a field cannot be stable. | 524 // not stable. Therefore such a field cannot be stable. |
| 551 if (element.isField && !(element.isConst || element.isFinal)) { | 525 if (element.isField && !(element.isConst || element.isFinal)) { |
| 552 return false; | 526 return false; |
| 553 } | 527 } |
| 554 | 528 |
| 555 if (element.isFunction) return false; | 529 if (element.isFunction) return false; |
| 556 | 530 |
| 557 return super.hasStableType(inferrer); | 531 return super.hasStableType(inferrer); |
| 558 } | 532 } |
| 559 | |
| 560 void cleanup() { | |
| 561 if (_isCalledOnce != null) return; | |
| 562 _isCalledOnce = _computeIsCalledOnce(); | |
| 563 _callers = null; | |
| 564 super.cleanup(); | |
| 565 } | |
| 566 } | 533 } |
| 567 | 534 |
| 568 /** | 535 /** |
| 569 * A node representing parameters: | 536 * A node representing parameters: |
| 570 * | 537 * |
| 571 * - Parameters | 538 * - Parameters |
| 572 * - Initializing formals | 539 * - Initializing formals |
| 573 * | 540 * |
| 574 * These should never be created directly but instead are constructed by | 541 * These should never be created directly but instead are constructed by |
| 575 * the [ElementTypeInformation] factory. | 542 * the [ElementTypeInformation] factory. |
| (...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 return new ContainerTypeMask(originalType.forwardTo, | 1312 return new ContainerTypeMask(originalType.forwardTo, |
| 1346 originalType.allocationNode, | 1313 originalType.allocationNode, |
| 1347 originalType.allocationElement, | 1314 originalType.allocationElement, |
| 1348 elementType.type, | 1315 elementType.type, |
| 1349 inferredLength); | 1316 inferredLength); |
| 1350 } | 1317 } |
| 1351 return mask; | 1318 return mask; |
| 1352 } | 1319 } |
| 1353 | 1320 |
| 1354 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; | 1321 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; |
| 1355 | |
| 1356 void cleanup() { | |
| 1357 super.cleanup(); | |
| 1358 elementType.cleanup(); | |
| 1359 _flowsInto = null; | |
| 1360 } | |
| 1361 } | 1322 } |
| 1362 | 1323 |
| 1363 /** | 1324 /** |
| 1364 * An [ElementInContainerTypeInformation] holds the common type of the | 1325 * An [ElementInContainerTypeInformation] holds the common type of the |
| 1365 * elements in a [ListTypeInformation]. | 1326 * elements in a [ListTypeInformation]. |
| 1366 */ | 1327 */ |
| 1367 class ElementInContainerTypeInformation extends InferredTypeInformation { | 1328 class ElementInContainerTypeInformation extends InferredTypeInformation { |
| 1368 ElementInContainerTypeInformation(MemberTypeInformation context, | 1329 ElementInContainerTypeInformation(MemberTypeInformation context, |
| 1369 elementType) | 1330 elementType) |
| 1370 : super(context, elementType); | 1331 : super(context, elementType); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 } | 1475 } |
| 1515 | 1476 |
| 1516 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; | 1477 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; |
| 1517 | 1478 |
| 1518 bool hasStableType(TypeGraphInferrerEngine inferrer) { | 1479 bool hasStableType(TypeGraphInferrerEngine inferrer) { |
| 1519 return keyType.isStable && | 1480 return keyType.isStable && |
| 1520 valueType.isStable && | 1481 valueType.isStable && |
| 1521 super.hasStableType(inferrer); | 1482 super.hasStableType(inferrer); |
| 1522 } | 1483 } |
| 1523 | 1484 |
| 1524 void cleanup() { | |
| 1525 super.cleanup(); | |
| 1526 keyType.cleanup(); | |
| 1527 valueType.cleanup(); | |
| 1528 for (TypeInformation info in typeInfoMap.values) { | |
| 1529 info.cleanup(); | |
| 1530 } | |
| 1531 _flowsInto = null; | |
| 1532 } | |
| 1533 | |
| 1534 String toString() { | 1485 String toString() { |
| 1535 return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap'; | 1486 return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap'; |
| 1536 } | 1487 } |
| 1537 } | 1488 } |
| 1538 | 1489 |
| 1539 /** | 1490 /** |
| 1540 * A [KeyInMapTypeInformation] holds the common type | 1491 * A [KeyInMapTypeInformation] holds the common type |
| 1541 * for the keys in a [MapTypeInformation] | 1492 * for the keys in a [MapTypeInformation] |
| 1542 */ | 1493 */ |
| 1543 class KeyInMapTypeInformation extends InferredTypeInformation { | 1494 class KeyInMapTypeInformation extends InferredTypeInformation { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 } else if (annotation.isVoid) { | 1661 } else if (annotation.isVoid) { |
| 1711 otherType = compiler.typesTask.nullType; | 1662 otherType = compiler.typesTask.nullType; |
| 1712 } else { | 1663 } else { |
| 1713 assert(annotation.isInterfaceType); | 1664 assert(annotation.isInterfaceType); |
| 1714 otherType = new TypeMask.nonNullSubtype(annotation.element, compiler.world); | 1665 otherType = new TypeMask.nonNullSubtype(annotation.element, compiler.world); |
| 1715 } | 1666 } |
| 1716 if (isNullable) otherType = otherType.nullable(); | 1667 if (isNullable) otherType = otherType.nullable(); |
| 1717 if (type == null) return otherType; | 1668 if (type == null) return otherType; |
| 1718 return type.intersection(otherType, compiler.world); | 1669 return type.intersection(otherType, compiler.world); |
| 1719 } | 1670 } |
| OLD | NEW |