commit | 30e8ed841079aa89e1284dd78e271dbe332d5b3a | [log] [tgz] |
---|---|---|
author | Paul Berry <paulberry@google.com> | Thu Aug 24 14:02:29 2023 +0000 |
committer | Commit Queue <dart-scoped@luci-project-accounts.iam.gserviceaccount.com> | Thu Aug 24 14:02:29 2023 +0000 |
tree | 9320d2032ca5cb332c8578f81474361c25cda9a7 | |
parent | 9f9da91b84609fd00573dae6a886d76b094b5d16 [diff] |
Flow analysis: fix field promotion based on condition variables. When the result of an `is` test or null check is stored in a boolean variable, and later recalled for use in flow control, the flow models that were computed at the time the variable was stored need to be updated to reflect any further change to flow state that happened between the test and the usage. This is done by `FlowModel.rebaseForward` method. `rebaseForward` takes two flow models as input: `this`, which represents the flow state that was computed at the time the condition variable was stored, and `base`, which represents the flow state at the time the condition variable is recalled. Flow analysis adds promotion keys for variables to the flow state at the time their declarations are encountered, and in certain circumstances removes them after they go out of scope. But for properties, it only adds promotion keys when the promotion occurs. So prior to the addition of field promotion, if `this` contained a promotion key that wasn't present in `base`, that could only mean that the promotion key was associated with a variable that had gone out of scope; accordingly, it was safe for `rebaseForward` to simply ignore that key. (It did so implicitly, by only ever examining the promotion keys in `this`). But with the addition of field promotion, it is now possible that the promotion key represents a property that was promoted in `this`, and hence the promotion needs to be kept. This CL adds the necessary logic to keep the promotion. In addition, there is a subtle difference in the relationship between the `PromotionModel` and `SsaNode` data structures for local variables versus properties. For local variables, the promotion key is determined solely from the variable name; then, this promotion key is looked up in the current `FlowModel` to obtain a `PromotionModel`, and the `PromotionModel` contains a prointer to the `SsaNode`. For properties, the property name is looked up in the `promotableProperties` map of the parent `SsaNode`; this points to a `_PropertySsaNode`, which contains the promotion key, and when this promotion key is looked up in the current `FlowModel` to obtain a `PromotionModel`, that `PromotionModel` contains a pointer to a bogus `SsaNode`. For local variables, the `SsaNode` pointed to by the `PromotionModel` is important, because if it's different between `this` and `base`, then the variable in question received a new value between the time the condition variable was stored and the time the condition variable was recalled; therefore the promotion should be disregarded. However, for properties, the `SsaNode` pointed to by the `PromotionModel` is bogus, so if it's different between `this` and `base`, that shouldn't block promotion. This CL adds the necessary logic to avoid the `SsaNode` check for properties. This situation is very confusing so I've added more detail to the comment above `PromotionModel.SsaNode` explaining it. In a future CL I will try to clean up the confusing situation by eliminating the bogus `SsaNode`s pointed to by `PromotionModel`s for properties. Fixes https://github.com/dart-lang/sdk/issues/53273. Bug: https://github.com/dart-lang/sdk/issues/53273 Change-Id: I1d528e25de1eb2ed63d0ee1a00faa5ad5b5061ca Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/321752 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
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 is free and open source.
See LICENSE and PATENT_GRANT.
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).
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.
The easiest way to contribute to Dart is to file issues.
You can also contribute patches, as described in Contributing.