Skip to content

Commit dc7e5bd

Browse files
committed
Auto merge of #59749 - petrochenkov:upspan, r=<try>
[do not merge] Measure upper limit for performance of 32 bit `Span` What would happen if span interner accesses were cheap and didn't require any synchronization? r? @ghost
2 parents 3750348 + 7c2ab8d commit dc7e5bd

File tree

6 files changed

+19
-41
lines changed

6 files changed

+19
-41
lines changed

src/bootstrap/builder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,8 @@ impl<'a> Builder<'a> {
438438
doc::EditionGuide,
439439
),
440440
Kind::Dist => describe!(
441-
dist::Docs,
442-
dist::RustcDocs,
441+
// dist::Docs,
442+
// dist::RustcDocs,
443443
dist::Mingw,
444444
dist::Rustc,
445445
dist::DebuggerScripts,

src/librustc_data_structures/sync.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ impl<T> Once<T> {
517517
}
518518

519519
#[derive(Debug)]
520-
pub struct Lock<T>(InnerLock<T>);
520+
pub struct Lock<T>(pub InnerLock<T>);
521521

522522
impl<T> Lock<T> {
523523
#[inline(always)]

src/libsyntax/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@ pub fn with_globals<F, R>(f: F) -> R
9898
{
9999
let globals = Globals::new();
100100
GLOBALS.set(&globals, || {
101-
syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, f)
101+
syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, unsafe {
102+
syntax_pos::SPAN_INTERNER_BACKDOOR =
103+
globals.syntax_pos_globals.span_interner.0.as_ptr();
104+
f
105+
})
102106
})
103107
}
104108

src/libsyntax_pos/hygiene.rs

+3
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,17 @@ pub fn clear_markings() {
218218
}
219219

220220
impl SyntaxContext {
221+
#[inline]
221222
pub const fn empty() -> Self {
222223
SyntaxContext(0)
223224
}
224225

226+
#[inline]
225227
crate fn as_u32(self) -> u32 {
226228
self.0
227229
}
228230

231+
#[inline]
229232
crate fn from_u32(raw: u32) -> SyntaxContext {
230233
SyntaxContext(raw)
231234
}

src/libsyntax_pos/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#![feature(rustc_attrs)]
1919
#![feature(specialization)]
2020
#![feature(step_trait)]
21+
#![feature(stmt_expr_attributes)]
2122

2223
use serialize::{Encodable, Decodable, Encoder, Decoder};
2324

@@ -29,7 +30,7 @@ pub mod hygiene;
2930
pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind};
3031

3132
mod span_encoding;
32-
pub use span_encoding::{Span, DUMMY_SP};
33+
pub use span_encoding::{Span, DUMMY_SP, SPAN_INTERNER_BACKDOOR};
3334

3435
pub mod symbol;
3536

@@ -48,7 +49,7 @@ use std::path::PathBuf;
4849

4950
pub struct Globals {
5051
symbol_interner: Lock<symbol::Interner>,
51-
span_interner: Lock<span_encoding::SpanInterner>,
52+
pub span_interner: Lock<span_encoding::SpanInterner>,
5253
hygiene_data: Lock<hygiene::HygieneData>,
5354
}
5455

src/libsyntax_pos/span_encoding.rs

+5-35
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,19 @@
44
// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
55
// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
66

7-
use crate::GLOBALS;
87
use crate::{BytePos, SpanData};
98
use crate::hygiene::SyntaxContext;
109

1110
use rustc_data_structures::fx::FxHashMap;
12-
use std::hash::{Hash, Hasher};
1311

1412
/// A compressed span.
1513
/// Contains either fields of `SpanData` inline if they are small, or index into span interner.
1614
/// The primary goal of `Span` is to be as small as possible and fit into other structures
1715
/// (that's why it uses `packed` as well). Decoding speed is the second priority.
1816
/// See `SpanData` for the info on span fields in decoded representation.
19-
#[repr(packed)]
17+
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
2018
pub struct Span(u32);
2119

22-
impl Copy for Span {}
23-
impl Clone for Span {
24-
#[inline]
25-
fn clone(&self) -> Span {
26-
*self
27-
}
28-
}
29-
impl PartialEq for Span {
30-
#[inline]
31-
fn eq(&self, other: &Span) -> bool {
32-
let a = self.0;
33-
let b = other.0;
34-
a == b
35-
}
36-
}
37-
impl Eq for Span {}
38-
impl Hash for Span {
39-
#[inline]
40-
fn hash<H: Hasher>(&self, state: &mut H) {
41-
let a = self.0;
42-
a.hash(state)
43-
}
44-
}
45-
4620
/// Dummy span, both position and length are zero, syntax context is zero as well.
4721
/// This span is kept inline and encoded with format 0.
4822
pub const DUMMY_SP: Span = Span(0);
@@ -98,7 +72,7 @@ fn encode(sd: &SpanData) -> Span {
9872
(base << INLINE_OFFSETS[BASE_INDEX]) | (len << INLINE_OFFSETS[LEN_INDEX]) |
9973
(ctxt << INLINE_OFFSETS[CTXT_INDEX]) | TAG_INLINE
10074
} else {
101-
let index = with_span_interner(|interner| interner.intern(sd));
75+
let index = unsafe { (*SPAN_INTERNER_BACKDOOR).intern(sd) };
10276
(index << INTERNED_INDEX_OFFSET) | TAG_INTERNED
10377
};
10478
Span(val)
@@ -109,7 +83,7 @@ fn decode(span: Span) -> SpanData {
10983
let val = span.0;
11084

11185
// Extract a field at position `pos` having size `size`.
112-
let extract = |pos: u32, size: u32| {
86+
let extract = #[inline] |pos: u32, size: u32| {
11387
let mask = ((!0u32) as u64 >> (32 - size)) as u32; // Can't shift u32 by 32
11488
(val >> pos) & mask
11589
};
@@ -120,7 +94,7 @@ fn decode(span: Span) -> SpanData {
12094
extract(INLINE_OFFSETS[CTXT_INDEX], INLINE_SIZES[CTXT_INDEX]),
12195
)} else {
12296
let index = extract(INTERNED_INDEX_OFFSET, INTERNED_INDEX_SIZE);
123-
return with_span_interner(|interner| *interner.get(index));
97+
return unsafe { *(*SPAN_INTERNER_BACKDOOR).get(index) };
12498
};
12599
SpanData { lo: BytePos(base), hi: BytePos(base + len), ctxt: SyntaxContext::from_u32(ctxt) }
126100
}
@@ -149,8 +123,4 @@ impl SpanInterner {
149123
}
150124
}
151125

152-
// If an interner exists, return it. Otherwise, prepare a fresh one.
153-
#[inline]
154-
fn with_span_interner<T, F: FnOnce(&mut SpanInterner) -> T>(f: F) -> T {
155-
GLOBALS.with(|globals| f(&mut *globals.span_interner.lock()))
156-
}
126+
pub static mut SPAN_INTERNER_BACKDOOR: *mut SpanInterner = std::ptr::null_mut();

0 commit comments

Comments
 (0)