regalloc2/ion/
stackmap.rs

1/*
2 * This file was initially derived from the files
3 * `js/src/jit/BacktrackingAllocator.h` and
4 * `js/src/jit/BacktrackingAllocator.cpp` in Mozilla Firefox, and was
5 * originally licensed under the Mozilla Public License 2.0. We
6 * subsequently relicensed it to Apache-2.0 WITH LLVM-exception (see
7 * https://github.com/bytecodealliance/regalloc2/issues/7).
8 *
9 * Since the initial port, the design has been substantially evolved
10 * and optimized.
11 */
12
13//! Stackmap computation.
14
15use super::{Env, ProgPoint, VRegIndex};
16use crate::{ion::data_structures::u64_key, Function};
17
18impl<'a, F: Function> Env<'a, F> {
19    pub fn compute_stackmaps(&mut self) {
20        // For each ref-typed vreg, iterate through ranges and find
21        // safepoints in-range. Add the SpillSlot to the stackmap.
22
23        if self.func.reftype_vregs().is_empty() {
24            return;
25        }
26
27        // Given `safepoints_per_vreg` from the liveness computation,
28        // all we have to do is, for each vreg in this map, step
29        // through the LiveRanges along with a sorted list of
30        // safepoints; and for each safepoint in the current range,
31        // emit the allocation into the `safepoint_slots` list.
32
33        trace!("safepoints_per_vreg = {:?}", self.safepoints_per_vreg);
34
35        for vreg in self.func.reftype_vregs() {
36            trace!("generating safepoint info for vreg {}", vreg);
37            let vreg = VRegIndex::new(vreg.vreg());
38            let mut safepoints: Vec<ProgPoint> = self
39                .safepoints_per_vreg
40                .get(&vreg.index())
41                .unwrap()
42                .iter()
43                .map(|&inst| ProgPoint::before(inst))
44                .collect();
45            safepoints.sort_unstable();
46            trace!(" -> live over safepoints: {:?}", safepoints);
47
48            let mut safepoint_idx = 0;
49            for entry in &self.vregs[vreg.index()].ranges {
50                let range = entry.range;
51                let alloc = self.get_alloc_for_range(entry.index);
52                trace!(" -> range {:?}: alloc {}", range, alloc);
53                while safepoint_idx < safepoints.len() && safepoints[safepoint_idx] < range.to {
54                    if safepoints[safepoint_idx] < range.from {
55                        safepoint_idx += 1;
56                        continue;
57                    }
58
59                    trace!("    -> covers safepoint {:?}", safepoints[safepoint_idx]);
60
61                    self.safepoint_slots
62                        .push((safepoints[safepoint_idx], alloc));
63                    safepoint_idx += 1;
64                }
65            }
66        }
67
68        self.safepoint_slots
69            .sort_unstable_by_key(|(progpoint, slot)| u64_key(progpoint.to_index(), slot.bits()));
70        trace!("final safepoint slots info: {:?}", self.safepoint_slots);
71    }
72}