|
4 | 4 | //! This pass performs the following transformations.
|
5 | 5 | //! 1. It generates a fresh batch of locals for each captured upvars.
|
6 | 6 | //!
|
7 |
| -//! For each upvar, whether used or not, a fresh local is created with the same type. |
| 7 | +//! For each upvar, whether used or not, a fresh local is created with the same |
| 8 | +//! type. |
8 | 9 | //!
|
9 |
| -//! 2. It replaces the places pointing into those upvars with places pointing into those locals instead |
| 10 | +//! 2. It replaces the places pointing into those upvars with places pointing |
| 11 | +//! into those locals instead |
10 | 12 | //!
|
11 |
| -//! Each place that starts with access into the coroutine structure `_1` is replaced with the fresh local as |
12 |
| -//! the base. For instance, `(_1.4 as Some).0` is rewritten into `(_34 as Some).0` when `_34` is the fresh local |
| 13 | +//! Each place that starts with access into the coroutine structure `_1` is |
| 14 | +//! replaced with the fresh local as the base. For instance, `(_1.4 as Some).0` |
| 15 | +//! is rewritten into `(_34 as Some).0` when `_34` is the fresh local |
13 | 16 | //! corresponding to the captured upvar stored in `_1.4`.
|
14 | 17 | //!
|
15 | 18 | //! 3. It assembles an prologue to replace the current entry block.
|
16 | 19 | //!
|
17 |
| -//! This prologue block transfers every captured upvar into its corresponding fresh local, *via scratch locals*. |
18 |
| -//! The upvars are first completely moved into the scratch locals in batch, and then moved into the destination |
19 |
| -//! locals in batch. |
20 |
| -//! The reason is that it is possible that coroutine layout may change and the source memory location of |
21 |
| -//! an upvar may not necessarily be mapped exactly to the same place as in the `Unresumed` state. |
22 |
| -//! While coroutine layout ensures that the same saved local has stable offsets throughout its lifetime, |
23 |
| -//! technically the upvar in `Unresumed` state and their fresh locals are different saved locals. |
24 |
| -//! This scratch locals re-estabilish safety so that the correct data permutation can take place. |
| 20 | +//! This prologue block transfers every captured upvar into its corresponding |
| 21 | +//! fresh local, *via scratch locals*. |
| 22 | +//! The upvars are first completely moved into the scratch locals in batch, |
| 23 | +//! and then moved into the destination locals in batch. |
| 24 | +//! The reason is that it is possible that coroutine layout may change and the |
| 25 | +//! source memory location of an upvar may not necessarily be mapped exactly to |
| 26 | +//! the same place as in the `Unresumed` state. |
| 27 | +//! While coroutine layout ensures that the same saved local has stable offsets |
| 28 | +//! throughout its lifetime, technically the upvar in `Unresumed` state and |
| 29 | +//! their fresh locals are different saved locals. |
| 30 | +//! This scratch locals re-estabilish safety so that the correct data |
| 31 | +//! permutation can take place. |
| 32 | +//! |
| 33 | +//! By enabling the feature gate `new_coroutine_layout`, the new coroutine |
| 34 | +//! layout calculator enters in effect and further guarantee that the upvars in |
| 35 | +//! the `Unresumed` state will share the same memory offsets as |
| 36 | +//! their corresponding saved locals, if exist. |
| 37 | +//! This policy enables further optimisation opportunities, so that the |
| 38 | +//! copies inserted by this pass will be elided away beyond the codegen phase. |
25 | 39 |
|
26 | 40 | use rustc_abi::FieldIdx;
|
27 | 41 | use rustc_index::{IndexSlice, IndexVec};
|
|
0 commit comments