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 |