Skip to content

Commit 80ab154

Browse files
committed
Update from review comments.
1 parent e11094b commit 80ab154

File tree

1 file changed

+39
-12
lines changed

1 file changed

+39
-12
lines changed

cranelift/codegen/src/machinst/buffer.rs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,20 @@ pub struct MachBuffer<I: VCodeInst> {
162162
/// Latest branches, to facilitate in-place editing for better fallthrough
163163
/// behavior and empty-block removal.
164164
latest_branches: SmallVec<[MachBranch; 4]>,
165-
/// All labels at the current offset (emission tail). For correctness, this
166-
/// *must* be complete, because we rely on it to update labels when we
167-
/// truncate branches.
165+
/// All labels at the current offset (emission tail). This is lazily
166+
/// cleared: it is actually accurate as long as the current offset is
167+
/// `labels_at_tail_off`, but if `cur_offset()` has grown larger, it should
168+
/// be considered as empty.
169+
///
170+
/// For correctness, this *must* be complete (i.e., the vector must contain
171+
/// all labels whose offsets are resolved to the current tail), because we
172+
/// rely on it to update labels when we truncate branches.
168173
labels_at_tail: SmallVec<[MachLabel; 4]>,
174+
/// The last offset at which `labels_at_tail` is valid. It is conceptually
175+
/// always describing the tail of the buffer, but we do not clear
176+
/// `labels_at_tail` eagerly when the tail grows, rather we lazily clear it
177+
/// when the offset has grown past this (`labels_at_tail_off`) point.
178+
labels_at_tail_off: CodeOffset,
169179
}
170180

171181
/// A `MachBuffer` once emission is completed: holds generated code and records,
@@ -226,6 +236,7 @@ impl<I: VCodeInst> MachBuffer<I> {
226236
island_worst_case_size: 0,
227237
latest_branches: SmallVec::new(),
228238
labels_at_tail: SmallVec::new(),
239+
labels_at_tail_off: 0,
229240
}
230241
}
231242

@@ -238,7 +249,6 @@ impl<I: VCodeInst> MachBuffer<I> {
238249
pub fn put1(&mut self, value: u8) {
239250
trace!("MachBuffer: put byte @ {}: {:x}", self.cur_offset(), value);
240251
self.data.push(value);
241-
self.labels_at_tail.clear();
242252
}
243253

244254
/// Add 2 bytes.
@@ -250,7 +260,6 @@ impl<I: VCodeInst> MachBuffer<I> {
250260
);
251261
let bytes = value.to_le_bytes();
252262
self.data.extend_from_slice(&bytes[..]);
253-
self.labels_at_tail.clear();
254263
}
255264

256265
/// Add 4 bytes.
@@ -262,7 +271,6 @@ impl<I: VCodeInst> MachBuffer<I> {
262271
);
263272
let bytes = value.to_le_bytes();
264273
self.data.extend_from_slice(&bytes[..]);
265-
self.labels_at_tail.clear();
266274
}
267275

268276
/// Add 8 bytes.
@@ -274,7 +282,6 @@ impl<I: VCodeInst> MachBuffer<I> {
274282
);
275283
let bytes = value.to_le_bytes();
276284
self.data.extend_from_slice(&bytes[..]);
277-
self.labels_at_tail.clear();
278285
}
279286

280287
/// Add a slice of bytes.
@@ -285,7 +292,6 @@ impl<I: VCodeInst> MachBuffer<I> {
285292
data.len()
286293
);
287294
self.data.extend_from_slice(data);
288-
self.labels_at_tail.clear();
289295
}
290296

291297
/// Reserve appended space and return a mutable slice referring to it.
@@ -294,7 +300,6 @@ impl<I: VCodeInst> MachBuffer<I> {
294300
let off = self.data.len();
295301
let new_len = self.data.len() + len;
296302
self.data.resize(new_len, 0);
297-
self.labels_at_tail.clear();
298303
&mut self.data[off..]
299304
}
300305

@@ -335,10 +340,21 @@ impl<I: VCodeInst> MachBuffer<I> {
335340
);
336341
let offset = self.cur_offset();
337342
self.label_offsets[label.0 as usize] = offset;
343+
self.lazily_clear_labels_at_tail();
338344
self.labels_at_tail.push(label);
339345
self.optimize_branches();
340346
}
341347

348+
/// Lazily clear `labels_at_tail` if the tail offset has moved beyond the
349+
/// offset that it applies to.
350+
fn lazily_clear_labels_at_tail(&mut self) {
351+
let offset = self.cur_offset();
352+
if offset > self.labels_at_tail_off {
353+
self.labels_at_tail_off = offset;
354+
self.labels_at_tail.clear();
355+
}
356+
}
357+
342358
/// Resolve a label to an offset, if known. May return `UNKNOWN_LABEL_OFFSET`.
343359
fn resolve_label_offset(&self, label: MachLabel) -> CodeOffset {
344360
let alias = self.label_aliases[label.0 as usize];
@@ -396,6 +412,7 @@ impl<I: VCodeInst> MachBuffer<I> {
396412
debug_assert!(end > start);
397413
assert!(!self.fixup_records.is_empty());
398414
let fixup = self.fixup_records.len() - 1;
415+
self.lazily_clear_labels_at_tail();
399416
self.latest_branches.push(MachBranch {
400417
start,
401418
end,
@@ -421,6 +438,7 @@ impl<I: VCodeInst> MachBuffer<I> {
421438
assert!(!self.fixup_records.is_empty());
422439
let fixup = self.fixup_records.len() - 1;
423440
let inverted = Some(SmallVec::from(inverted));
441+
self.lazily_clear_labels_at_tail();
424442
self.latest_branches.push(MachBranch {
425443
start,
426444
end,
@@ -432,11 +450,13 @@ impl<I: VCodeInst> MachBuffer<I> {
432450
}
433451

434452
fn truncate_last_branch(&mut self) {
453+
self.lazily_clear_labels_at_tail();
435454
let b = self.latest_branches.pop().unwrap();
436455
assert!(b.end == self.cur_offset());
437456
self.data.truncate(b.start as usize);
438457
self.fixup_records.truncate(b.fixup);
439458
let cur_off = self.cur_offset();
459+
self.labels_at_tail_off = cur_off;
440460
trace!(
441461
"truncate_last_branch: truncated {:?}; off now {}",
442462
b,
@@ -450,12 +470,18 @@ impl<I: VCodeInst> MachBuffer<I> {
450470
}
451471

452472
fn optimize_branches(&mut self) {
473+
self.lazily_clear_labels_at_tail();
453474
trace!(
454475
"enter optimize_branches:\n b = {:?}\n l = {:?}\n f = {:?}",
455476
self.latest_branches,
456477
self.labels_at_tail,
457478
self.fixup_records
458479
);
480+
481+
// We continue to munch on branches at the tail of the buffer until no
482+
// more rules apply. Note that the loop only continues if a branch is
483+
// actually truncated (or if labels are redirected away from a branch),
484+
// so this always makes progress.
459485
while let Some(b) = self.latest_branches.last() {
460486
let cur_off = self.cur_offset();
461487
trace!("optimize_branches: last branch {:?} at off {}", b, cur_off);
@@ -962,9 +988,10 @@ struct MachBranch {
962988
fixup: usize,
963989
inverted: Option<SmallVec<[u8; 8]>>,
964990
/// All labels pointing to the start of this branch. For correctness, this
965-
/// *must* be complete: we rely on being able to redirect all labels that
966-
/// could jump to this branch before removing it, if it is otherwise
967-
/// unreachable.
991+
/// *must* be complete (i.e., must contain all labels whose resolved offsets
992+
/// are at the start of this branch): we rely on being able to redirect all
993+
/// labels that could jump to this branch before removing it, if it is
994+
/// otherwise unreachable.
968995
labels_at_this_branch: SmallVec<[MachLabel; 4]>,
969996
}
970997

0 commit comments

Comments
 (0)