Skip to content

Commit 5fe2fa1

Browse files
committed
Auto merge of rust-lang#139241 - bvanjoi:less-decoding, r=<try>
don't store opaque info during encoding Now `remapped_ctxts` reserved and let's check the performance. r? `@petrochenkov`
2 parents c9cd707 + 941e1ef commit 5fe2fa1

File tree

4 files changed

+26
-111
lines changed

4 files changed

+26
-111
lines changed

compiler/rustc_metadata/src/rmeta/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use rustc_serialize::opaque::FileEncoder;
3636
use rustc_session::config::{SymbolManglingVersion, TargetModifier};
3737
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
3838
use rustc_span::edition::Edition;
39-
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData};
39+
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey};
4040
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol};
4141
use rustc_target::spec::{PanicStrategy, TargetTuple};
4242
use table::TableBuilder;
@@ -193,7 +193,7 @@ enum LazyState {
193193
Previous(NonZero<usize>),
194194
}
195195

196-
type SyntaxContextTable = LazyTable<u32, Option<LazyValue<SyntaxContextData>>>;
196+
type SyntaxContextTable = LazyTable<u32, Option<LazyValue<SyntaxContextKey>>>;
197197
type ExpnDataTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnData>>>;
198198
type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
199199

compiler/rustc_middle/src/query/on_disk_cache.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed
1616
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
1717
use rustc_session::Session;
1818
use rustc_span::hygiene::{
19-
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
19+
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey,
2020
};
2121
use rustc_span::source_map::Spanned;
2222
use rustc_span::{
@@ -75,9 +75,9 @@ pub struct OnDiskCache {
7575
alloc_decoding_state: AllocDecodingState,
7676

7777
// A map from syntax context ids to the position of their associated
78-
// `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext`
78+
// `SyntaxContextKey`. We use a `u32` instead of a `SyntaxContext`
7979
// to represent the fact that we are storing *encoded* ids. When we decode
80-
// a `SyntaxContext`, a new id will be allocated from the global `HygieneData`,
80+
// a `SyntaxContextKey`, a new id will be allocated from the global `HygieneData`,
8181
// which will almost certainly be different than the serialized id.
8282
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
8383
// A map from the `DefPathHash` of an `ExpnId` to the position
@@ -305,7 +305,7 @@ impl OnDiskCache {
305305
let mut expn_data = UnhashMap::default();
306306
let mut foreign_expn_data = UnhashMap::default();
307307

308-
// Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
308+
// Encode all hygiene data (`SyntaxContextKey` and `ExpnData`) from the current
309309
// session.
310310

311311
hygiene_encode_context.encode(
@@ -566,7 +566,7 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
566566
// We look up the position of the associated `SyntaxData` and decode it.
567567
let pos = syntax_contexts.get(&id).unwrap();
568568
this.with_position(pos.to_usize(), |decoder| {
569-
let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT);
569+
let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT);
570570
data
571571
})
572572
})

compiler/rustc_middle/src/ty/parameterized.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ trivially_parameterized_over_tcx! {
111111
rustc_span::Span,
112112
rustc_span::Symbol,
113113
rustc_span::def_id::DefPathHash,
114-
rustc_span::hygiene::SyntaxContextData,
114+
rustc_span::hygiene::SyntaxContextKey,
115115
rustc_span::Ident,
116116
rustc_type_ir::Variance,
117117
rustc_hir::Attribute,

compiler/rustc_span/src/hygiene.rs

+18-103
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,14 @@
2424
// because getting it wrong can lead to nested `HygieneData::with` calls that
2525
// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
2626

27-
use std::cell::RefCell;
28-
use std::collections::hash_map::Entry;
29-
use std::collections::hash_set::Entry as SetEntry;
3027
use std::hash::Hash;
3128
use std::sync::Arc;
3229
use std::{fmt, iter, mem};
3330

3431
use rustc_data_structures::fingerprint::Fingerprint;
3532
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3633
use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
37-
use rustc_data_structures::sync::{Lock, WorkerLocal};
34+
use rustc_data_structures::sync::Lock;
3835
use rustc_data_structures::unhash::UnhashMap;
3936
use rustc_hashes::Hash64;
4037
use rustc_index::IndexVec;
@@ -59,10 +56,10 @@ impl !PartialOrd for SyntaxContext {}
5956

6057
/// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal.
6158
/// The other fields are only for caching.
62-
type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
59+
pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
6360

6461
#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)]
65-
pub struct SyntaxContextData {
62+
struct SyntaxContextData {
6663
outer_expn: ExpnId,
6764
outer_transparency: Transparency,
6865
parent: SyntaxContext,
@@ -1266,7 +1263,7 @@ impl HygieneEncodeContext {
12661263
pub fn encode<T>(
12671264
&self,
12681265
encoder: &mut T,
1269-
mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData),
1266+
mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey),
12701267
mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash),
12711268
) {
12721269
// When we serialize a `SyntaxContextData`, we may end up serializing
@@ -1315,18 +1312,12 @@ struct HygieneDecodeContextInner {
13151312
// so that multiple occurrences of the same serialized id are decoded to the same
13161313
// `SyntaxContext`. This only stores `SyntaxContext`s which are completely decoded.
13171314
remapped_ctxts: Vec<Option<SyntaxContext>>,
1318-
1319-
/// Maps serialized `SyntaxContext` ids that are currently being decoded to a `SyntaxContext`.
1320-
decoding: FxHashMap<u32, SyntaxContext>,
13211315
}
13221316

13231317
#[derive(Default)]
13241318
/// Additional information used to assist in decoding hygiene data
13251319
pub struct HygieneDecodeContext {
13261320
inner: Lock<HygieneDecodeContextInner>,
1327-
1328-
/// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread.
1329-
local_in_progress: WorkerLocal<RefCell<FxHashSet<u32>>>,
13301321
}
13311322

13321323
/// Register an expansion which has been decoded from the on-disk-cache for the local crate.
@@ -1397,10 +1388,10 @@ pub fn decode_expn_id(
13971388
// to track which `SyntaxContext`s we have already decoded.
13981389
// The provided closure will be invoked to deserialize a `SyntaxContextData`
13991390
// if we haven't already seen the id of the `SyntaxContext` we are deserializing.
1400-
pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContextData>(
1391+
pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContextKey>(
14011392
d: &mut D,
14021393
context: &HygieneDecodeContext,
1403-
decode_data: F,
1394+
decode_ctxt_key: F,
14041395
) -> SyntaxContext {
14051396
let raw_id: u32 = Decodable::decode(d);
14061397
if raw_id == 0 {
@@ -1409,115 +1400,39 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
14091400
return SyntaxContext::root();
14101401
}
14111402

1412-
let pending_ctxt = {
1413-
let mut inner = context.inner.lock();
1414-
1415-
// Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between
1416-
// raw ids from different crate metadatas.
1417-
if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() {
1418-
// This has already been decoded.
1419-
return ctxt;
1420-
}
1421-
1422-
match inner.decoding.entry(raw_id) {
1423-
Entry::Occupied(ctxt_entry) => {
1424-
let pending_ctxt = *ctxt_entry.get();
1425-
match context.local_in_progress.borrow_mut().entry(raw_id) {
1426-
// We're decoding this already on the current thread. Return here and let the
1427-
// function higher up the stack finish decoding to handle recursive cases.
1428-
// Hopefully having a `SyntaxContext` that refers to an incorrect data is ok
1429-
// during reminder of the decoding process, it's certainly not ok after the
1430-
// top level decoding function returns.
1431-
SetEntry::Occupied(..) => return pending_ctxt,
1432-
// Some other thread is currently decoding this.
1433-
// Race with it (alternatively we could wait here).
1434-
// We cannot return this value, unlike in the recursive case above, because it
1435-
// may expose a `SyntaxContext` pointing to incorrect data to arbitrary code.
1436-
SetEntry::Vacant(entry) => {
1437-
entry.insert();
1438-
pending_ctxt
1439-
}
1440-
}
1441-
}
1442-
Entry::Vacant(entry) => {
1443-
// We are the first thread to start decoding. Mark the current thread as being
1444-
// progress.
1445-
context.local_in_progress.borrow_mut().insert(raw_id);
1446-
1447-
// Allocate and store SyntaxContext id *before* calling the decoder function,
1448-
// as the SyntaxContextData may reference itself.
1449-
let new_ctxt = HygieneData::with(|hygiene_data| {
1450-
// Push a dummy SyntaxContextData to ensure that nobody else can get the
1451-
// same ID as us. This will be overwritten after call `decode_data`.
1452-
hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder());
1453-
SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1)
1454-
});
1455-
entry.insert(new_ctxt);
1456-
new_ctxt
1457-
}
1458-
}
1459-
};
1403+
// Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between
1404+
// raw ids from different crate metadatas.
1405+
if let Some(ctxt) = context.inner.lock().remapped_ctxts.get(raw_id as usize).copied().flatten()
1406+
{
1407+
// This has already been decoded.
1408+
return ctxt;
1409+
}
14601410

14611411
// Don't try to decode data while holding the lock, since we need to
14621412
// be able to recursively decode a SyntaxContext
1463-
let ctxt_data = decode_data(d, raw_id);
1464-
let ctxt_key = ctxt_data.key();
1465-
1466-
let ctxt = HygieneData::with(|hygiene_data| {
1467-
match hygiene_data.syntax_context_map.get(&ctxt_key) {
1468-
// Ensure that syntax contexts are unique.
1469-
// If syntax contexts with the given key already exists, reuse it instead of
1470-
// using `pending_ctxt`.
1471-
// `pending_ctxt` will leave an unused hole in the vector of syntax contexts.
1472-
// Hopefully its value isn't stored anywhere during decoding and its dummy data
1473-
// is never accessed later. The `is_decode_placeholder` asserts on all
1474-
// accesses to syntax context data attempt to ensure it.
1475-
Some(&ctxt) => ctxt,
1476-
// This is a completely new context.
1477-
// Overwrite its placeholder data with our decoded data.
1478-
None => {
1479-
let ctxt_data_ref =
1480-
&mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize];
1481-
let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data);
1482-
// Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1483-
// We don't care what the encoding crate set this to - we want to resolve it
1484-
// from the perspective of the current compilation session.
1485-
ctxt_data_ref.dollar_crate_name = kw::DollarCrate;
1486-
// Make sure nothing weird happened while `decode_data` was running.
1487-
if !prev_ctxt_data.is_decode_placeholder() {
1488-
// Another thread may have already inserted the decoded data,
1489-
// but the decoded data should match.
1490-
assert_eq!(prev_ctxt_data, *ctxt_data_ref);
1491-
}
1492-
hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt);
1493-
pending_ctxt
1494-
}
1495-
}
1496-
});
1497-
1498-
// Mark the context as completed
1499-
context.local_in_progress.borrow_mut().remove(&raw_id);
1413+
let (parent, expn_id, transparency) = decode_ctxt_key(d, raw_id);
1414+
let ctxt =
1415+
HygieneData::with(|hygiene_data| hygiene_data.alloc_ctxt(parent, expn_id, transparency));
15001416

15011417
let mut inner = context.inner.lock();
15021418
let new_len = raw_id as usize + 1;
15031419
if inner.remapped_ctxts.len() < new_len {
15041420
inner.remapped_ctxts.resize(new_len, None);
15051421
}
15061422
inner.remapped_ctxts[raw_id as usize] = Some(ctxt);
1507-
inner.decoding.remove(&raw_id);
15081423

15091424
ctxt
15101425
}
15111426

1512-
fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &SyntaxContextData)>(
1427+
fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &SyntaxContextKey)>(
15131428
ctxts: impl Iterator<Item = SyntaxContext>,
15141429
mut f: F,
15151430
) {
15161431
let all_data: Vec<_> = HygieneData::with(|data| {
15171432
ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect()
15181433
});
15191434
for (ctxt, data) in all_data.into_iter() {
1520-
f(ctxt.0, ctxt, &data);
1435+
f(ctxt.0, ctxt, &data.key());
15211436
}
15221437
}
15231438

0 commit comments

Comments
 (0)