Skip to content

Commit aff596d

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 96d700f + 4f208af commit aff596d

File tree

6 files changed

+23
-150
lines changed

6 files changed

+23
-150
lines changed

src/bootstrap/builder.rs

+6-111
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(unused)]
2+
13
use std::any::Any;
24
use std::cell::{Cell, RefCell};
35
use std::collections::BTreeSet;
@@ -326,120 +328,23 @@ pub enum Kind {
326328
impl<'a> Builder<'a> {
327329
fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
328330
macro_rules! describe {
329-
($($rule:ty),+ $(,)?) => {{
330-
vec![$(StepDescription::from::<$rule>()),+]
331+
($($rule:ty),* $(,)?) => {{
332+
vec![$(StepDescription::from::<$rule>()),*]
331333
}};
332334
}
333335
match kind {
334336
Kind::Build => describe!(
335-
compile::Std,
336-
compile::Test,
337-
compile::Rustc,
338-
compile::CodegenBackend,
339-
compile::StartupObjects,
340-
tool::BuildManifest,
341-
tool::Rustbook,
342-
tool::ErrorIndex,
343-
tool::UnstableBookGen,
344-
tool::Tidy,
345-
tool::Linkchecker,
346-
tool::CargoTest,
347-
tool::Compiletest,
348-
tool::RemoteTestServer,
349-
tool::RemoteTestClient,
350-
tool::RustInstaller,
351-
tool::Cargo,
352-
tool::Rls,
353-
tool::Rustdoc,
354-
tool::Clippy,
355-
native::Llvm,
356-
tool::Rustfmt,
357-
tool::Miri,
358-
native::Lld
359337
),
360338
Kind::Check => describe!(
361-
check::Std,
362-
check::Test,
363-
check::Rustc,
364-
check::CodegenBackend,
365-
check::Rustdoc
366339
),
367340
Kind::Test => describe!(
368341
test::Tidy,
369-
test::Ui,
370-
test::RunPass,
371-
test::CompileFail,
372-
test::RunFail,
373-
test::RunPassValgrind,
374-
test::MirOpt,
375-
test::Codegen,
376-
test::CodegenUnits,
377-
test::Assembly,
378-
test::Incremental,
379-
test::Debuginfo,
380-
test::UiFullDeps,
381-
test::RunPassFullDeps,
382-
test::Rustdoc,
383-
test::Pretty,
384-
test::RunPassPretty,
385-
test::RunFailPretty,
386-
test::RunPassValgrindPretty,
387-
test::Crate,
388-
test::CrateLibrustc,
389-
test::CrateRustdoc,
390-
test::Linkcheck,
391-
test::Cargotest,
392-
test::Cargo,
393-
test::Rls,
394-
test::ErrorIndex,
395-
test::Distcheck,
396-
test::RunMakeFullDeps,
397-
test::Nomicon,
398-
test::Reference,
399-
test::RustdocBook,
400-
test::RustByExample,
401-
test::TheBook,
402-
test::UnstableBook,
403-
test::RustcBook,
404-
test::EmbeddedBook,
405-
test::EditionGuide,
406-
test::Rustfmt,
407-
test::Miri,
408-
test::Clippy,
409-
test::CompiletestTest,
410-
test::RustdocJSStd,
411-
test::RustdocJSNotStd,
412-
test::RustdocTheme,
413-
test::RustdocUi,
414-
// Run bootstrap close to the end as it's unlikely to fail
415-
test::Bootstrap,
416-
// Run run-make last, since these won't pass without make on Windows
417-
test::RunMake,
418342
),
419-
Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
343+
Kind::Bench => describe!(
344+
),
420345
Kind::Doc => describe!(
421-
doc::UnstableBook,
422-
doc::UnstableBookGen,
423-
doc::TheBook,
424-
doc::Standalone,
425-
doc::Std,
426-
doc::Test,
427-
doc::WhitelistedRustc,
428-
doc::Rustc,
429-
doc::Rustdoc,
430-
doc::ErrorIndex,
431-
doc::Nomicon,
432-
doc::Reference,
433-
doc::RustdocBook,
434-
doc::RustByExample,
435-
doc::RustcBook,
436-
doc::CargoBook,
437-
doc::EmbeddedBook,
438-
doc::EditionGuide,
439346
),
440347
Kind::Dist => describe!(
441-
dist::Docs,
442-
dist::RustcDocs,
443348
dist::Mingw,
444349
dist::Rustc,
445350
dist::DebuggerScripts,
@@ -458,16 +363,6 @@ impl<'a> Builder<'a> {
458363
dist::HashSign
459364
),
460365
Kind::Install => describe!(
461-
install::Docs,
462-
install::Std,
463-
install::Cargo,
464-
install::Rls,
465-
install::Rustfmt,
466-
install::Clippy,
467-
install::Miri,
468-
install::Analysis,
469-
install::Src,
470-
install::Rustc
471366
),
472367
}
473368
}

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)