pub(super) struct CurrentDepGraph<D: Deps> {
encoder: GraphEncoder<D>,
new_node_to_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>,
prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>,
fingerprints: Lock<IndexVec<DepNodeIndex, Option<Fingerprint>>>,
forbidden_edge: Option<EdgeFilter>,
anon_id_seed: Fingerprint,
total_read_count: AtomicU64,
total_duplicate_read_count: AtomicU64,
}
Expand description
CurrentDepGraph
stores the dependency graph for the current session. It
will be populated as we run queries or tasks. We never remove nodes from the
graph: they are only added.
The nodes in it are identified by a DepNodeIndex
. We avoid keeping the nodes
in memory. This is important, because these graph structures are some of the
largest in the compiler.
For this reason, we avoid storing DepNode
s more than once as map
keys. The new_node_to_index
map only contains nodes not in the previous
graph, and we map nodes in the previous graph to indices via a two-step
mapping. SerializedDepGraph
maps from DepNode
to SerializedDepNodeIndex
,
and the prev_index_to_index
vector (which is more compact and faster than
using a map) maps from SerializedDepNodeIndex
to DepNodeIndex
.
This struct uses three locks internally. The data
, new_node_to_index
,
and prev_index_to_index
fields are locked separately. Operations that take
a DepNodeIndex
typically just access the data
field.
We only need to manipulate at most two locks simultaneously:
new_node_to_index
and data
, or prev_index_to_index
and data
. When
manipulating both, we acquire new_node_to_index
or prev_index_to_index
first, and data
second.
Fields§
§encoder: GraphEncoder<D>
§new_node_to_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>
§prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>
§fingerprints: Lock<IndexVec<DepNodeIndex, Option<Fingerprint>>>
This is used to verify that fingerprints do not change between the creation of a node and its recomputation.
forbidden_edge: Option<EdgeFilter>
Used to trap when a specific edge is added to the graph.
This is used for debug purposes and is only active with debug_assertions
.
anon_id_seed: Fingerprint
Anonymous DepNode
s are nodes whose IDs we compute from the list of
their edges. This has the beneficial side-effect that multiple anonymous
nodes can be coalesced into one without changing the semantics of the
dependency graph. However, the merging of nodes can lead to a subtle
problem during red-green marking: The color of an anonymous node from
the current session might “shadow” the color of the node with the same
ID from the previous session. In order to side-step this problem, we make
sure that anonymous NodeId
s allocated in different sessions don’t overlap.
This is implemented by mixing a session-key into the ID fingerprint of
each anon node. The session-key is just a random number generated when
the DepGraph
is created.
total_read_count: AtomicU64
These are simple counters that are for profiling and
debugging and only active with debug_assertions
.
total_duplicate_read_count: AtomicU64
Implementations§
source§impl<D: Deps> CurrentDepGraph<D>
impl<D: Deps> CurrentDepGraph<D>
fn new( profiler: &SelfProfilerRef, prev_graph_node_count: usize, encoder: FileEncoder, record_graph: bool, record_stats: bool, previous: Arc<SerializedDepGraph>, ) -> Self
fn record_edge( &self, dep_node_index: DepNodeIndex, key: DepNode, fingerprint: Fingerprint, )
sourcefn intern_new_node(
&self,
key: DepNode,
edges: EdgesVec,
current_fingerprint: Fingerprint,
) -> DepNodeIndex
fn intern_new_node( &self, key: DepNode, edges: EdgesVec, current_fingerprint: Fingerprint, ) -> DepNodeIndex
Writes the node to the current dep-graph and allocates a DepNodeIndex
for it.
Assumes that this is a node that has no equivalent in the previous dep-graph.
fn intern_node( &self, prev_graph: &SerializedDepGraph, key: DepNode, edges: EdgesVec, fingerprint: Option<Fingerprint>, ) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>)
fn promote_node_and_deps_to_current( &self, prev_graph: &SerializedDepGraph, prev_index: SerializedDepNodeIndex, ) -> DepNodeIndex
fn debug_assert_not_in_new_nodes( &self, prev_graph: &SerializedDepGraph, prev_index: SerializedDepNodeIndex, )
Auto Trait Implementations§
impl<D> !Freeze for CurrentDepGraph<D>
impl<D> !RefUnwindSafe for CurrentDepGraph<D>
impl<D> Send for CurrentDepGraph<D>where
D: Send,
impl<D> !Sync for CurrentDepGraph<D>
impl<D> Unpin for CurrentDepGraph<D>where
D: Unpin,
impl<D> !UnwindSafe for CurrentDepGraph<D>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
source§impl<T> Filterable for T
impl<T> Filterable for T
source§fn filterable(
self,
filter_name: &'static str,
) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>
fn filterable( self, filter_name: &'static str, ) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
source§impl<I, T> UpcastFrom<I, T> for T
impl<I, T> UpcastFrom<I, T> for T
fn upcast_from(from: T, _tcx: I) -> T
source§impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
default fn from_cycle_error( tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed, ) -> T
source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<'a, T> Captures<'a> for Twhere
T: ?Sized,
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> MaybeSendSync for T
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.
Size: 512 bytes