Skip to content

Commit 01183d7

Browse files
committed
rustc_span: Optimize span parent get/set methods
1 parent af3d100 commit 01183d7

File tree

2 files changed

+67
-25
lines changed

2 files changed

+67
-25
lines changed

compiler/rustc_span/src/lib.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,9 @@ impl SpanData {
525525
fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
526526
Span::new(self.lo, self.hi, ctxt, self.parent)
527527
}
528+
/// Avoid if possible, `Span::with_parent` should be preferred.
528529
#[inline]
529-
pub fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
530+
fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
530531
Span::new(self.lo, self.hi, self.ctxt, parent)
531532
}
532533
/// Returns `true` if this is a dummy span with any hygienic context.
@@ -580,14 +581,6 @@ impl Span {
580581
pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
581582
self.map_ctxt(|_| ctxt)
582583
}
583-
#[inline]
584-
pub fn parent(self) -> Option<LocalDefId> {
585-
self.data().parent
586-
}
587-
#[inline]
588-
pub fn with_parent(self, ctxt: Option<LocalDefId>) -> Span {
589-
self.data().with_parent(ctxt)
590-
}
591584

592585
#[inline]
593586
pub fn is_visible(self, sm: &SourceMap) -> bool {

compiler/rustc_span/src/span_encoding.rs

+65-16
Original file line numberDiff line numberDiff line change
@@ -322,29 +322,28 @@ impl Span {
322322
}
323323
}
324324

325-
// For optimization we are interested in cases in which the context is inline and the context
326-
// update doesn't change format. All non-inline or format changing scenarios require accessing
327-
// interner and can fall back to `Span::new`.
328325
#[inline]
329-
pub fn map_ctxt(self, update: impl FnOnce(SyntaxContext) -> SyntaxContext) -> Span {
330-
match_span_kind! {
326+
pub fn map_ctxt(self, map: impl FnOnce(SyntaxContext) -> SyntaxContext) -> Span {
327+
let data = match_span_kind! {
331328
self,
332329
InlineCtxt(span) => {
333-
let updated_ctxt32 = update(SyntaxContext::from_u16(span.ctxt)).as_u32();
334-
// Any small new context including zero will preserve the format.
335-
return if updated_ctxt32 <= MAX_CTXT {
336-
InlineCtxt::span(span.lo, span.len, updated_ctxt32 as u16)
330+
// This format occurs 1-2 orders of magnitude more often than others (#125017),
331+
// so it makes sense to micro-optimize it to avoid `span.data()` and `Span::new()`.
332+
let new_ctxt = map(SyntaxContext::from_u16(span.ctxt));
333+
let new_ctxt32 = new_ctxt.as_u32();
334+
return if new_ctxt32 <= MAX_CTXT {
335+
// Any small new context including zero will preserve the format.
336+
InlineCtxt::span(span.lo, span.len, new_ctxt32 as u16)
337337
} else {
338-
span.data().with_ctxt(SyntaxContext::from_u32(updated_ctxt32))
338+
span.data().with_ctxt(new_ctxt)
339339
};
340340
},
341-
InlineParent(_span) => {},
342-
PartiallyInterned(_span) => {},
343-
Interned(_span) => {},
344-
}
341+
InlineParent(span) => span.data(),
342+
PartiallyInterned(span) => span.data(),
343+
Interned(span) => span.data(),
344+
};
345345

346-
let data = self.data_untracked();
347-
data.with_ctxt(update(data.ctxt))
346+
data.with_ctxt(map(data.ctxt))
348347
}
349348

350349
// Returns either syntactic context, if it can be retrieved without taking the interner lock,
@@ -381,6 +380,56 @@ impl Span {
381380
}),
382381
}
383382
}
383+
384+
#[inline]
385+
pub fn with_parent(self, parent: Option<LocalDefId>) -> Span {
386+
let data = match_span_kind! {
387+
self,
388+
InlineCtxt(span) => {
389+
// This format occurs 1-2 orders of magnitude more often than others (#126544),
390+
// so it makes sense to micro-optimize it to avoid `span.data()` and `Span::new()`.
391+
if parent.is_none() {
392+
// Only if the new parent is `None` the format will be preserved.
393+
return self;
394+
} else if span.ctxt == 0
395+
&& let Some(parent) = parent
396+
&& let parent32 = parent.local_def_index.as_u32()
397+
&& parent32 <= MAX_CTXT
398+
{
399+
// Otherwise the new format may be `InlineParent` if the new parent is small.
400+
return InlineParent::span(span.lo, span.len, parent32 as u16);
401+
}
402+
span.data()
403+
},
404+
InlineParent(span) => span.data(),
405+
PartiallyInterned(span) => span.data(),
406+
Interned(span) => span.data(),
407+
};
408+
409+
if let Some(old_parent) = data.parent {
410+
// FIXME: Is this tracking necessary?
411+
(*SPAN_TRACK)(old_parent);
412+
}
413+
data.with_parent(parent)
414+
}
415+
416+
#[inline]
417+
pub fn parent(self) -> Option<LocalDefId> {
418+
let interned_parent =
419+
|index: u32| with_span_interner(|interner| interner.spans[index as usize].parent);
420+
let parent = match_span_kind! {
421+
self,
422+
InlineCtxt(_span) => return None,
423+
InlineParent(span) => Some(LocalDefId { local_def_index: DefIndex::from_u32(span.parent as u32) }),
424+
PartiallyInterned(span) => interned_parent(span.index),
425+
Interned(span) => interned_parent(span.index),
426+
};
427+
if let Some(parent) = parent {
428+
// FIXME: Is this tracking necessary?
429+
(*SPAN_TRACK)(parent);
430+
}
431+
parent
432+
}
384433
}
385434

386435
#[derive(Default)]

0 commit comments

Comments
 (0)