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}