Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 772fe96

Browse files
committedAug 31, 2024·
perform less decoding if it has the same syntax context
1 parent 9649706 commit 772fe96

File tree

6 files changed

+196
-132
lines changed

6 files changed

+196
-132
lines changed
 

‎compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -468,15 +468,28 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
468468
};
469469

470470
let cname = cdata.root.name();
471-
rustc_span::hygiene::decode_syntax_context(self, &cdata.hygiene_context, |_, id| {
472-
debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
473-
cdata
474-
.root
475-
.syntax_contexts
476-
.get(cdata, id)
477-
.unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}"))
478-
.decode((cdata, sess))
479-
})
471+
rustc_span::hygiene::decode_syntax_context(
472+
self,
473+
&cdata.hygiene_context,
474+
|_, id| {
475+
debug!("SpecializedDecoder<SyntaxContextKey>: decoding {}", id);
476+
cdata
477+
.root
478+
.syntax_context_keys
479+
.get(cdata, id)
480+
.unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}"))
481+
.decode((cdata, sess))
482+
},
483+
|_, id| {
484+
debug!("SpecializedDecoder<SyntaxContextData>: decoding {}", id);
485+
cdata
486+
.root
487+
.syntax_context_data
488+
.get(cdata, id)
489+
.unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}"))
490+
.decode((cdata, sess))
491+
},
492+
)
480493
}
481494

482495
fn decode_expn_id(&mut self) -> ExpnId {

‎compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
684684
// the incremental cache. If this causes us to deserialize a `Span`, then we may load
685685
// additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode
686686
// the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used.
687-
let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene());
687+
let (syntax_context_keys, syntax_context_data, expn_data, expn_hashes) =
688+
stat!("hygiene", || self.encode_hygiene());
688689

689690
let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map());
690691

@@ -737,7 +738,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
737738
exported_symbols,
738739
interpret_alloc_index,
739740
tables,
740-
syntax_contexts,
741+
syntax_context_keys,
742+
syntax_context_data,
741743
expn_data,
742744
expn_hashes,
743745
def_path_hash_map,
@@ -1807,17 +1809,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
18071809
self.lazy_array(foreign_modules.iter().map(|(_, m)| m).cloned())
18081810
}
18091811

1810-
fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) {
1811-
let mut syntax_contexts: TableBuilder<_, _> = Default::default();
1812+
fn encode_hygiene(
1813+
&mut self,
1814+
) -> (SyntaxContextKeyTable, SyntaxContextDataTable, ExpnDataTable, ExpnHashTable) {
1815+
let mut syntax_context_keys: TableBuilder<_, _> = Default::default();
1816+
let mut syntax_context_data: TableBuilder<_, _> = Default::default();
18121817
let mut expn_data_table: TableBuilder<_, _> = Default::default();
18131818
let mut expn_hash_table: TableBuilder<_, _> = Default::default();
18141819

18151820
self.hygiene_ctxt.encode(
1816-
&mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
1817-
|(this, syntax_contexts, _, _), index, ctxt_data| {
1818-
syntax_contexts.set_some(index, this.lazy(ctxt_data));
1821+
&mut (
1822+
&mut *self,
1823+
&mut syntax_context_keys,
1824+
&mut syntax_context_data,
1825+
&mut expn_data_table,
1826+
&mut expn_hash_table,
1827+
),
1828+
|(this, syntax_context_keys, syntax_context_data, _, _), index, ctxt_data| {
1829+
syntax_context_keys.set_some(index, this.lazy(&ctxt_data.0));
1830+
syntax_context_data.set_some(index, this.lazy(&ctxt_data.1));
18191831
},
1820-
|(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
1832+
|(this, _, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
18211833
if let Some(index) = index.as_local() {
18221834
expn_data_table.set_some(index.as_raw(), this.lazy(expn_data));
18231835
expn_hash_table.set_some(index.as_raw(), this.lazy(hash));
@@ -1826,7 +1838,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
18261838
);
18271839

18281840
(
1829-
syntax_contexts.encode(&mut self.opaque),
1841+
syntax_context_keys.encode(&mut self.opaque),
1842+
syntax_context_data.encode(&mut self.opaque),
18301843
expn_data_table.encode(&mut self.opaque),
18311844
expn_hash_table.encode(&mut self.opaque),
18321845
)

‎compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use rustc_serialize::opaque::FileEncoder;
3434
use rustc_session::config::SymbolManglingVersion;
3535
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
3636
use rustc_span::edition::Edition;
37-
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData};
37+
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData, SyntaxContextKey};
3838
use rustc_span::symbol::{Ident, Symbol};
3939
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
4040
use rustc_target::abi::{FieldIdx, VariantIdx};
@@ -193,7 +193,8 @@ enum LazyState {
193193
Previous(NonZero<usize>),
194194
}
195195

196-
type SyntaxContextTable = LazyTable<u32, Option<LazyValue<SyntaxContextData>>>;
196+
type SyntaxContextKeyTable = LazyTable<u32, Option<LazyValue<SyntaxContextKey>>>;
197+
type SyntaxContextDataTable = LazyTable<u32, Option<LazyValue<SyntaxContextData>>>;
197198
type ExpnDataTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnData>>>;
198199
type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
199200

@@ -276,7 +277,8 @@ pub(crate) struct CrateRoot {
276277

277278
exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
278279

279-
syntax_contexts: SyntaxContextTable,
280+
syntax_context_keys: SyntaxContextKeyTable,
281+
syntax_context_data: SyntaxContextDataTable,
280282
expn_data: ExpnDataTable,
281283
expn_hashes: ExpnHashTable,
282284

‎compiler/rustc_middle/src/query/on_disk_cache.rs

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
2121
use rustc_session::Session;
2222
use rustc_span::hygiene::{
2323
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
24+
SyntaxContextKey,
2425
};
2526
use rustc_span::source_map::SourceMap;
2627
use rustc_span::{
@@ -36,8 +37,9 @@ const TAG_FULL_SPAN: u8 = 0;
3637
const TAG_PARTIAL_SPAN: u8 = 1;
3738
const TAG_RELATIVE_SPAN: u8 = 2;
3839

39-
const TAG_SYNTAX_CONTEXT: u8 = 0;
40-
const TAG_EXPN_DATA: u8 = 1;
40+
const TAG_SYNTAX_CONTEXT_KEY: u8 = 0;
41+
const TAG_SYNTAX_CONTEXT_DATA: u8 = 1;
42+
const TAG_EXPN_DATA: u8 = 2;
4143

4244
// Tags for encoding Symbol's
4345
const SYMBOL_STR: u8 = 0;
@@ -77,7 +79,8 @@ pub struct OnDiskCache<'sess> {
7779
// to represent the fact that we are storing *encoded* ids. When we decode
7880
// a `SyntaxContext`, a new id will be allocated from the global `HygieneData`,
7981
// which will almost certainly be different than the serialized id.
80-
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
82+
syntax_context_keys: FxHashMap<u32, AbsoluteBytePos>,
83+
syntax_context_data: FxHashMap<u32, AbsoluteBytePos>,
8184
// A map from the `DefPathHash` of an `ExpnId` to the position
8285
// of their associated `ExpnData`. Ideally, we would store a `DefId`,
8386
// but we need to decode this before we've constructed a `TyCtxt` (which
@@ -108,7 +111,8 @@ struct Footer {
108111
// without measurable overhead. This permits larger const allocations without ICEing.
109112
interpret_alloc_index: Vec<u64>,
110113
// See `OnDiskCache.syntax_contexts`
111-
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
114+
syntax_context_keys: FxHashMap<u32, AbsoluteBytePos>,
115+
syntax_context_data: FxHashMap<u32, AbsoluteBytePos>,
112116
// See `OnDiskCache.expn_data`
113117
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
114118
foreign_expn_data: UnhashMap<ExpnHash, u32>,
@@ -179,7 +183,8 @@ impl<'sess> OnDiskCache<'sess> {
179183
query_result_index: footer.query_result_index.into_iter().collect(),
180184
prev_side_effects_index: footer.side_effects_index.into_iter().collect(),
181185
alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
182-
syntax_contexts: footer.syntax_contexts,
186+
syntax_context_keys: footer.syntax_context_keys,
187+
syntax_context_data: footer.syntax_context_data,
183188
expn_data: footer.expn_data,
184189
foreign_expn_data: footer.foreign_expn_data,
185190
hygiene_context: Default::default(),
@@ -196,7 +201,8 @@ impl<'sess> OnDiskCache<'sess> {
196201
query_result_index: Default::default(),
197202
prev_side_effects_index: Default::default(),
198203
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
199-
syntax_contexts: FxHashMap::default(),
204+
syntax_context_keys: FxHashMap::default(),
205+
syntax_context_data: FxHashMap::default(),
200206
expn_data: UnhashMap::default(),
201207
foreign_expn_data: UnhashMap::default(),
202208
hygiene_context: Default::default(),
@@ -301,7 +307,8 @@ impl<'sess> OnDiskCache<'sess> {
301307
interpret_alloc_index
302308
};
303309

304-
let mut syntax_contexts = FxHashMap::default();
310+
let mut syntax_context_keys = FxHashMap::default();
311+
let mut syntax_context_data = FxHashMap::default();
305312
let mut expn_data = UnhashMap::default();
306313
let mut foreign_expn_data = UnhashMap::default();
307314

@@ -312,8 +319,12 @@ impl<'sess> OnDiskCache<'sess> {
312319
&mut encoder,
313320
|encoder, index, ctxt_data| {
314321
let pos = AbsoluteBytePos::new(encoder.position());
315-
encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data);
316-
syntax_contexts.insert(index, pos);
322+
encoder.encode_tagged(TAG_SYNTAX_CONTEXT_KEY, &ctxt_data.0);
323+
syntax_context_keys.insert(index, pos);
324+
325+
let pos = AbsoluteBytePos::new(encoder.position());
326+
encoder.encode_tagged(TAG_SYNTAX_CONTEXT_DATA, &ctxt_data.1);
327+
syntax_context_data.insert(index, pos);
317328
},
318329
|encoder, expn_id, data, hash| {
319330
if expn_id.krate == LOCAL_CRATE {
@@ -335,7 +346,8 @@ impl<'sess> OnDiskCache<'sess> {
335346
query_result_index,
336347
side_effects_index,
337348
interpret_alloc_index,
338-
syntax_contexts,
349+
syntax_context_keys,
350+
syntax_context_data,
339351
expn_data,
340352
foreign_expn_data,
341353
},
@@ -442,7 +454,8 @@ impl<'sess> OnDiskCache<'sess> {
442454
file_index_to_file: &self.file_index_to_file,
443455
file_index_to_stable_id: &self.file_index_to_stable_id,
444456
alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
445-
syntax_contexts: &self.syntax_contexts,
457+
syntax_context_keys: &self.syntax_context_keys,
458+
syntax_context_data: &self.syntax_context_data,
446459
expn_data: &self.expn_data,
447460
foreign_expn_data: &self.foreign_expn_data,
448461
hygiene_context: &self.hygiene_context,
@@ -463,7 +476,8 @@ pub struct CacheDecoder<'a, 'tcx> {
463476
file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
464477
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
465478
alloc_decoding_session: AllocDecodingSession<'a>,
466-
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
479+
syntax_context_keys: &'a FxHashMap<u32, AbsoluteBytePos>,
480+
syntax_context_data: &'a FxHashMap<u32, AbsoluteBytePos>,
467481
expn_data: &'a UnhashMap<ExpnHash, AbsoluteBytePos>,
468482
foreign_expn_data: &'a UnhashMap<ExpnHash, u32>,
469483
hygiene_context: &'a HygieneDecodeContext,
@@ -584,16 +598,26 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
584598

585599
impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
586600
fn decode_syntax_context(&mut self) -> SyntaxContext {
587-
let syntax_contexts = self.syntax_contexts;
588-
rustc_span::hygiene::decode_syntax_context(self, self.hygiene_context, |this, id| {
589-
// This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
590-
// We look up the position of the associated `SyntaxData` and decode it.
591-
let pos = syntax_contexts.get(&id).unwrap();
592-
this.with_position(pos.to_usize(), |decoder| {
593-
let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT);
594-
data
595-
})
596-
})
601+
rustc_span::hygiene::decode_syntax_context(
602+
self,
603+
self.hygiene_context,
604+
|this, id| {
605+
// This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
606+
// We look up the position of the associated `SyntaxData` and decode it.
607+
let pos = this.syntax_context_keys.get(&id).unwrap();
608+
this.with_position(pos.to_usize(), |decoder| {
609+
let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT_KEY);
610+
data
611+
})
612+
},
613+
|this, id| {
614+
let pos = this.syntax_context_data.get(&id).unwrap();
615+
this.with_position(pos.to_usize(), |decoder| {
616+
let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT_DATA);
617+
data
618+
})
619+
},
620+
)
597621
}
598622

599623
fn decode_expn_id(&mut self) -> ExpnId {

‎compiler/rustc_middle/src/ty/parameterized.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ trivially_parameterized_over_tcx! {
107107
rustc_span::Span,
108108
rustc_span::Symbol,
109109
rustc_span::def_id::DefPathHash,
110+
rustc_span::hygiene::SyntaxContextKey,
110111
rustc_span::hygiene::SyntaxContextData,
111112
rustc_span::symbol::Ident,
112113
rustc_type_ir::Variance,

‎compiler/rustc_span/src/hygiene.rs

Lines changed: 100 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,21 @@ pub struct SyntaxContext(u32);
5454
impl !Ord for SyntaxContext {}
5555
impl !PartialOrd for SyntaxContext {}
5656

57-
#[derive(Debug, Encodable, Decodable, Clone)]
58-
pub struct SyntaxContextData {
57+
#[derive(Debug, Encodable, Decodable, Clone, Copy, Hash, PartialEq, Eq)]
58+
pub struct SyntaxContextKey {
5959
outer_expn: ExpnId,
6060
outer_transparency: Transparency,
6161
parent: SyntaxContext,
62+
}
63+
64+
impl SyntaxContextKey {
65+
fn new(outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext) -> Self {
66+
SyntaxContextKey { outer_expn, outer_transparency, parent }
67+
}
68+
}
69+
70+
#[derive(Debug, Encodable, Decodable, Clone, Copy)]
71+
pub struct SyntaxContextData {
6272
/// This context, but with all transparent and semi-transparent expansions filtered away.
6373
opaque: SyntaxContext,
6474
/// This context, but with all transparent expansions filtered away.
@@ -332,8 +342,9 @@ pub(crate) struct HygieneData {
332342
foreign_expn_data: FxHashMap<ExpnId, ExpnData>,
333343
foreign_expn_hashes: FxHashMap<ExpnId, ExpnHash>,
334344
expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
335-
syntax_context_data: Vec<SyntaxContextData>,
336-
syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>,
345+
syntax_context_data: Vec<(SyntaxContextKey, SyntaxContextData)>,
346+
syntax_context_data_map: FxHashMap<SyntaxContextKey, SyntaxContextData>,
347+
syntax_context_map: FxHashMap<SyntaxContextKey, SyntaxContext>,
337348
/// Maps the `local_hash` of an `ExpnData` to the next disambiguator value.
338349
/// This is used by `update_disambiguator` to keep track of which `ExpnData`s
339350
/// would have collisions without a disambiguator.
@@ -359,14 +370,19 @@ impl HygieneData {
359370
foreign_expn_hashes: FxHashMap::default(),
360371
expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
361372
.collect(),
362-
syntax_context_data: vec![SyntaxContextData {
363-
outer_expn: ExpnId::root(),
364-
outer_transparency: Transparency::Opaque,
365-
parent: SyntaxContext(0),
366-
opaque: SyntaxContext(0),
367-
opaque_and_semitransparent: SyntaxContext(0),
368-
dollar_crate_name: kw::DollarCrate,
369-
}],
373+
syntax_context_data: vec![(
374+
SyntaxContextKey {
375+
outer_expn: ExpnId::root(),
376+
outer_transparency: Transparency::Opaque,
377+
parent: SyntaxContext(0),
378+
},
379+
SyntaxContextData {
380+
opaque: SyntaxContext(0),
381+
opaque_and_semitransparent: SyntaxContext(0),
382+
dollar_crate_name: kw::DollarCrate,
383+
},
384+
)],
385+
syntax_context_data_map: FxHashMap::default(),
370386
syntax_context_map: FxHashMap::default(),
371387
expn_data_disambiguators: UnhashMap::default(),
372388
}
@@ -416,24 +432,24 @@ impl HygieneData {
416432
}
417433

418434
fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
419-
self.syntax_context_data[ctxt.0 as usize].opaque
435+
self.syntax_context_data[ctxt.0 as usize].1.opaque
420436
}
421437

422438
fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
423-
self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
439+
self.syntax_context_data[ctxt.0 as usize].1.opaque_and_semitransparent
424440
}
425441

426442
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
427-
self.syntax_context_data[ctxt.0 as usize].outer_expn
443+
self.syntax_context_data[ctxt.0 as usize].0.outer_expn
428444
}
429445

430446
fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
431-
let data = &self.syntax_context_data[ctxt.0 as usize];
447+
let data = &self.syntax_context_data[ctxt.0 as usize].0;
432448
(data.outer_expn, data.outer_transparency)
433449
}
434450

435451
fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext {
436-
self.syntax_context_data[ctxt.0 as usize].parent
452+
self.syntax_context_data[ctxt.0 as usize].0.parent
437453
}
438454

439455
fn remove_mark(&self, ctxt: &mut SyntaxContext) -> (ExpnId, Transparency) {
@@ -542,61 +558,55 @@ impl HygieneData {
542558
transparency: Transparency,
543559
) -> SyntaxContext {
544560
let syntax_context_data = &mut self.syntax_context_data;
545-
let mut opaque = syntax_context_data[ctxt.0 as usize].opaque;
561+
let mut opaque = syntax_context_data[ctxt.0 as usize].1.opaque;
546562
let mut opaque_and_semitransparent =
547-
syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent;
563+
syntax_context_data[ctxt.0 as usize].1.opaque_and_semitransparent;
548564

549565
if transparency >= Transparency::Opaque {
550566
let parent = opaque;
551-
opaque = *self
552-
.syntax_context_map
553-
.entry((parent, expn_id, transparency))
554-
.or_insert_with(|| {
555-
let new_opaque = SyntaxContext(syntax_context_data.len() as u32);
556-
syntax_context_data.push(SyntaxContextData {
557-
outer_expn: expn_id,
558-
outer_transparency: transparency,
559-
parent,
560-
opaque: new_opaque,
561-
opaque_and_semitransparent: new_opaque,
562-
dollar_crate_name: kw::DollarCrate,
563-
});
564-
new_opaque
565-
});
567+
let key = SyntaxContextKey::new(expn_id, transparency, parent);
568+
opaque = *self.syntax_context_map.entry(key).or_insert_with(|| {
569+
let new_opaque = SyntaxContext(syntax_context_data.len() as u32);
570+
let data = SyntaxContextData {
571+
opaque: new_opaque,
572+
opaque_and_semitransparent: new_opaque,
573+
dollar_crate_name: kw::DollarCrate,
574+
};
575+
syntax_context_data.push((key, data));
576+
self.syntax_context_data_map.insert(key, data);
577+
new_opaque
578+
});
566579
}
567580

568581
if transparency >= Transparency::SemiTransparent {
569582
let parent = opaque_and_semitransparent;
570-
opaque_and_semitransparent = *self
571-
.syntax_context_map
572-
.entry((parent, expn_id, transparency))
573-
.or_insert_with(|| {
574-
let new_opaque_and_semitransparent =
575-
SyntaxContext(syntax_context_data.len() as u32);
576-
syntax_context_data.push(SyntaxContextData {
577-
outer_expn: expn_id,
578-
outer_transparency: transparency,
579-
parent,
580-
opaque,
581-
opaque_and_semitransparent: new_opaque_and_semitransparent,
582-
dollar_crate_name: kw::DollarCrate,
583-
});
584-
new_opaque_and_semitransparent
585-
});
583+
let key = SyntaxContextKey::new(expn_id, transparency, parent);
584+
opaque_and_semitransparent = *self.syntax_context_map.entry(key).or_insert_with(|| {
585+
let new_opaque_and_semitransparent =
586+
SyntaxContext(syntax_context_data.len() as u32);
587+
let data = SyntaxContextData {
588+
opaque,
589+
opaque_and_semitransparent: new_opaque_and_semitransparent,
590+
dollar_crate_name: kw::DollarCrate,
591+
};
592+
syntax_context_data.push((key, data));
593+
self.syntax_context_data_map.insert(key, data);
594+
new_opaque_and_semitransparent
595+
});
586596
}
587597

588598
let parent = ctxt;
589-
*self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| {
599+
let key = SyntaxContextKey::new(expn_id, transparency, parent);
600+
*self.syntax_context_map.entry(key).or_insert_with(|| {
590601
let new_opaque_and_semitransparent_and_transparent =
591602
SyntaxContext(syntax_context_data.len() as u32);
592-
syntax_context_data.push(SyntaxContextData {
593-
outer_expn: expn_id,
594-
outer_transparency: transparency,
595-
parent,
603+
let data = SyntaxContextData {
596604
opaque,
597605
opaque_and_semitransparent,
598606
dollar_crate_name: kw::DollarCrate,
599-
});
607+
};
608+
syntax_context_data.push((key, data));
609+
self.syntax_context_data_map.insert(key, data);
600610
new_opaque_and_semitransparent_and_transparent
601611
})
602612
}
@@ -623,7 +633,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb
623633
data.syntax_context_data
624634
.iter()
625635
.rev()
626-
.take_while(|scdata| scdata.dollar_crate_name == kw::DollarCrate)
636+
.take_while(|scdata| scdata.1.dollar_crate_name == kw::DollarCrate)
627637
.count(),
628638
)
629639
});
@@ -634,7 +644,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb
634644
range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect();
635645
HygieneData::with(|data| {
636646
range_to_update.zip(names).for_each(|(idx, name)| {
637-
data.syntax_context_data[idx].dollar_crate_name = name;
647+
data.syntax_context_data[idx].1.dollar_crate_name = name;
638648
})
639649
})
640650
}
@@ -670,7 +680,7 @@ pub fn debug_hygiene_data(verbose: bool) -> String {
670680
data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
671681
s.push_str(&format!(
672682
"\n#{}: parent: {:?}, outer_mark: ({:?}, {:?})",
673-
id, ctxt.parent, ctxt.outer_expn, ctxt.outer_transparency,
683+
id, ctxt.0.parent, ctxt.0.outer_expn, ctxt.0.outer_transparency,
674684
));
675685
});
676686
s
@@ -884,7 +894,7 @@ impl SyntaxContext {
884894
}
885895

886896
pub(crate) fn dollar_crate_name(self) -> Symbol {
887-
HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
897+
HygieneData::with(|data| data.syntax_context_data[self.0 as usize].1.dollar_crate_name)
888898
}
889899

890900
pub fn edition(self) -> Edition {
@@ -1210,7 +1220,7 @@ impl HygieneEncodeContext {
12101220
pub fn encode<T>(
12111221
&self,
12121222
encoder: &mut T,
1213-
mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData),
1223+
mut encode_ctxt: impl FnMut(&mut T, u32, &(SyntaxContextKey, SyntaxContextData)),
12141224
mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash),
12151225
) {
12161226
// When we serialize a `SyntaxContextData`, we may end up serializing
@@ -1342,10 +1352,15 @@ pub fn decode_expn_id(
13421352
// to track which `SyntaxContext`s we have already decoded.
13431353
// The provided closure will be invoked to deserialize a `SyntaxContextData`
13441354
// if we haven't already seen the id of the `SyntaxContext` we are deserializing.
1345-
pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContextData>(
1355+
pub fn decode_syntax_context<
1356+
D: Decoder,
1357+
F0: FnOnce(&mut D, u32) -> SyntaxContextKey,
1358+
F1: FnOnce(&mut D, u32) -> SyntaxContextData,
1359+
>(
13461360
d: &mut D,
13471361
context: &HygieneDecodeContext,
1348-
decode_data: F,
1362+
decode_ctxt_key: F0,
1363+
decode_ctxt_data: F1,
13491364
) -> SyntaxContext {
13501365
let raw_id: u32 = Decodable::decode(d);
13511366
if raw_id == 0 {
@@ -1387,16 +1402,20 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
13871402
// as the SyntaxContextData may reference itself.
13881403
let new_ctxt = HygieneData::with(|hygiene_data| {
13891404
let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32);
1390-
// Push a dummy SyntaxContextData to ensure that nobody else can get the
1391-
// same ID as us. This will be overwritten after call `decode_Data`
1392-
hygiene_data.syntax_context_data.push(SyntaxContextData {
1393-
outer_expn: ExpnId::root(),
1394-
outer_transparency: Transparency::Transparent,
1395-
parent: SyntaxContext::root(),
1396-
opaque: SyntaxContext::root(),
1397-
opaque_and_semitransparent: SyntaxContext::root(),
1398-
dollar_crate_name: kw::Empty,
1399-
});
1405+
// Push a dummy data to ensure that nobody else can get the
1406+
// same ID as us. `SyntaxContextKey` will be overwritten after call `decode_Data`
1407+
hygiene_data.syntax_context_data.push((
1408+
SyntaxContextKey {
1409+
outer_expn: ExpnId::root(),
1410+
outer_transparency: Transparency::Transparent,
1411+
parent: SyntaxContext::root(),
1412+
},
1413+
SyntaxContextData {
1414+
opaque: SyntaxContext::root(),
1415+
opaque_and_semitransparent: SyntaxContext::root(),
1416+
dollar_crate_name: kw::Empty,
1417+
},
1418+
));
14001419
new_ctxt
14011420
});
14021421
entry.insert(new_ctxt);
@@ -1407,33 +1426,25 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
14071426

14081427
// Don't try to decode data while holding the lock, since we need to
14091428
// be able to recursively decode a SyntaxContext
1410-
let mut ctxt_data = decode_data(d, raw_id);
1411-
// Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`
1412-
// We don't care what the encoding crate set this to - we want to resolve it
1413-
// from the perspective of the current compilation session
1414-
ctxt_data.dollar_crate_name = kw::DollarCrate;
1429+
let ctxt_key = decode_ctxt_key(d, raw_id);
1430+
let ctxt_data = HygieneData::with(|hygiene_data| {
1431+
hygiene_data.syntax_context_data_map.get(&ctxt_key).copied()
1432+
})
1433+
.unwrap_or_else(|| decode_ctxt_data(d, raw_id));
14151434

14161435
// Overwrite the dummy data with our decoded SyntaxContextData
14171436
HygieneData::with(|hygiene_data| {
1418-
if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize)
1419-
&& old.outer_expn == ctxt_data.outer_expn
1420-
&& old.outer_transparency == ctxt_data.outer_transparency
1421-
&& old.parent == ctxt_data.parent
1422-
{
1423-
ctxt_data = old.clone();
1424-
}
1425-
14261437
let dummy = std::mem::replace(
14271438
&mut hygiene_data.syntax_context_data[ctxt.as_u32() as usize],
1428-
ctxt_data,
1439+
(ctxt_key, ctxt_data),
14291440
);
14301441
if cfg!(not(parallel_compiler)) {
14311442
// Make sure nothing weird happened while `decode_data` was running.
14321443
// We used `kw::Empty` for the dummy value and we expect nothing to be
14331444
// modifying the dummy entry.
14341445
// This does not hold for the parallel compiler as another thread may
14351446
// have inserted the fully decoded data.
1436-
assert_eq!(dummy.dollar_crate_name, kw::Empty);
1447+
assert_eq!(dummy.1.dollar_crate_name, kw::Empty);
14371448
}
14381449
});
14391450

@@ -1452,7 +1463,7 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
14521463
ctxt
14531464
}
14541465

1455-
fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &SyntaxContextData)>(
1466+
fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &(SyntaxContextKey, SyntaxContextData))>(
14561467
ctxts: impl Iterator<Item = SyntaxContext>,
14571468
mut f: F,
14581469
) {

0 commit comments

Comments
 (0)
Please sign in to comment.