Flow analysis: fix interaction of field promotion and try/finally.

Try/finally statements have an unusual property that needs to be
handled in a special way by flow analysis: within the `finally` block,
the `try` block might not have run to completion, but after the
try/finally statement, the `try` block is known to have run to
completion. Therefore, even though the code that follows the
try/finally statement is immediately preceded by the end of the
`finally` block, the flow states of those two control flow points
might not be the same.

Flow analysis accounts for this situation by analyzing the `finally`
block as though it started executing right after the beginning of the
`try` block, but with all variables that are written within the `try`
block demoted. Then, after it finishes analyzing the `finally` block,
it builds a fresh flow model by starting with the flow state after the
end of the `try` block, and then applying any promotions that were
performed within the `finally` block. This is accomplished by the
`FlowModel.attachFinally` method.

The following changes had to be made to make this work with field
promotion:

- If a given promotion key appears in the "after try" model but not
  the "after finally" model, it might represent a field that was
  promoted during the `try` block, so the promotion needs to be
  preserved. Previously, this situation could only occur if the
  promotion key represented a variable declared in the `try` block
  (and therefore the variable would not be accessible after the
  try/finally statement), so the promotion could be safely dropped.

- If a given promotion key appears in the "after try" model and the
  "after finally" model, but not the "before finally" model, it might
  represent a field that was promoted within both the `try` and
  `finally` blocks, so the promotions need to be combined. Previously,
  this situation could not occur, so the promotion could be safely
  dropped.

- If a given promotion key is associated with the same SSA node in the
  "before finally" and "after finally" models, but a different SSA
  node in the "after try" model, that means that the corresponding
  variable was assigned in the `try` block but not in the `finally`
  block. If any properties of the variable were promoted within the
  `finally` block, those promotions were applied to the SSA nodes used
  by the `finally` block, and don't appear in the SSA nodes used in
  the "after try" model. So those promotions need to be
  transferred. This is accomplished by the new
  `SsaNode._applyPropertyPromotions` method.

- If a given promotion key appears in the "after finally" model but
  not the "after try" model, it might represent a field that was
  promoted during the `finally` block, so the promotion needs to be
  preserved. Previously, this situation could only occur if the
  promotion key represented a variable declared in the `finally` block
  (and therefore the variable would not be accessible after the
  try/finally statement), so the promotion could be safely dropped.

Fixes https://github.com/dart-lang/sdk/issues/53225.

Bug: https://github.com/dart-lang/sdk/issues/53225
Change-Id: Ie4b635dbf838447d6964c326e1ecebfff99bed8e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/320961
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
4 files changed
tree: 9706a9f72e30dbe1b9e86098519b58eda4a96ca7
  1. .dart_tool/
  2. .github/
  3. benchmarks/
  4. build/
  5. docs/
  6. pkg/
  7. runtime/
  8. samples/
  9. sdk/
  10. tests/
  11. third_party/
  12. tools/
  13. utils/
  14. .clang-format
  15. .gitattributes
  16. .gitconfig
  17. .gitignore
  18. .gn
  19. .mailmap
  20. .style.yapf
  21. .vpython
  22. AUTHORS
  23. BUILD.gn
  24. CHANGELOG.md
  25. codereview.settings
  26. CONTRIBUTING.md
  27. DEPS
  28. LICENSE
  29. OWNERS
  30. PATENT_GRANT
  31. PRESUBMIT.py
  32. README.dart-sdk
  33. README.md
  34. sdk.code-workspace
  35. sdk_args.gni
  36. SECURITY.md
  37. WATCHLISTS
README.md

Dart

A client-optimized language for fast apps on any platform

Dart is:

  • Optimized for UI: Develop with a programming language specialized around the needs of user interface creation.

  • Productive: Make changes iteratively: use hot reload to see the result instantly in your running app.

  • Fast on all platforms: Compile to ARM & x64 machine code for mobile, desktop, and backend. Or compile to JavaScript for the web.

Dart's flexible compiler technology lets you run Dart code in different ways, depending on your target platform and goals:

  • Dart Native: For programs targeting devices (mobile, desktop, server, and more), Dart Native includes both a Dart VM with JIT (just-in-time) compilation and an AOT (ahead-of-time) compiler for producing machine code.

  • Dart Web: For programs targeting the web, Dart Web includes both a development time compiler (dartdevc) and a production time compiler (dart2js).

Dart platforms illustration

License & patents

Dart is free and open source.

See LICENSE and PATENT_GRANT.

Using Dart

Visit dart.dev to learn more about the language, tools, and to find codelabs.

Browse pub.dev for more packages and libraries contributed by the community and the Dart team.

Our API reference documentation is published at api.dart.dev, based on the stable release. (We also publish docs from our beta and dev channels, as well as from the primary development branch).

Building Dart

If you want to build Dart yourself, here is a guide to getting the source, preparing your machine to build the SDK, and building.

There are more documents on our wiki.

Contributing to Dart

The easiest way to contribute to Dart is to file issues.

You can also contribute patches, as described in Contributing.