From 9e6ad303141c3db314928384181cc5b656667458 Mon Sep 17 00:00:00 2001 From: James Moschou Date: Wed, 14 Oct 2026 01:48:05 +0200 Subject: [PATCH] Ensure all node edges get properly removed when a subgraph is being invalidated --- .../Attribute/AttributeID/AttributeID.cpp | 2 +- .../Attribute/AttributeID/WeakAttributeID.cpp | 15 +++++++++++++-- .../Attribute/AttributeID/WeakAttributeID.h | 11 +++++++++-- Sources/ComputeCxx/Graph/Graph.cpp | 10 +++++----- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Sources/ComputeCxx/Attribute/AttributeID/AttributeID.cpp b/Sources/ComputeCxx/Attribute/AttributeID/AttributeID.cpp index 3bacd89..553920f 100644 --- a/Sources/ComputeCxx/Attribute/AttributeID/AttributeID.cpp +++ b/Sources/ComputeCxx/Attribute/AttributeID/AttributeID.cpp @@ -74,7 +74,7 @@ OffsetAttributeID AttributeID::resolve_slow(TraversalOptions options) const { } if (options & TraversalOptions::EvaluateWeakReferences) { - if (indirect_node->source().expired()) { + if (indirect_node->source().is_freed()) { if (options & TraversalOptions::AssertNotNil) { precondition_failure("invalid indirect ref: %u", _value); } diff --git a/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.cpp b/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.cpp index 86f7621..99a8a7f 100644 --- a/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.cpp +++ b/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.cpp @@ -6,7 +6,7 @@ namespace IAG { -bool WeakAttributeID::expired() const { +bool WeakAttributeID::is_expired() const { uint64_t raw_page_seed = data::table::shared().raw_page_seed(_identifier.page_ptr()); if (raw_page_seed & 0xff00000000) { auto zone_info = data::zone::info::from_raw_value(uint32_t(raw_page_seed)); @@ -17,8 +17,19 @@ bool WeakAttributeID::expired() const { return true; } +bool WeakAttributeID::is_freed() const { + uint64_t raw_page_seed = data::table::shared().raw_page_seed(_identifier.page_ptr()); + if (raw_page_seed & 0xff00000000) { + auto zone_info = data::zone::info::from_raw_value(uint32_t(raw_page_seed)); + if (zone_info.zone_id() == _seed) { + return false; + } + } + return true; +} + AttributeID WeakAttributeID::evaluate() const { - return _identifier && !expired() ? _identifier : AttributeID(IAGAttributeNil); + return _identifier && !is_expired() ? _identifier : AttributeID(IAGAttributeNil); }; } // namespace IAG diff --git a/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.h b/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.h index 4a77316..d91fcd2 100644 --- a/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.h +++ b/Sources/ComputeCxx/Attribute/AttributeID/WeakAttributeID.h @@ -25,9 +25,16 @@ class WeakAttributeID { AttributeID identifier() const { return _identifier; }; uint32_t seed() const { return _seed; } - bool expired() const; + /// Returns true if the attribute can no longer be evaluated. + bool is_expired() const; - /// Returns the attribute it is has not expired, otherwise returns the nil + /// Returns true when the attribute's subgraph has been freed (or reused). + /// + /// This method may return false if the attribute's subgraph has been + /// invalidated but not yet destroyed. + bool is_freed() const; + + /// Returns the attribute if it has not expired, otherwise returns the nil /// attribute. AttributeID evaluate() const; }; diff --git a/Sources/ComputeCxx/Graph/Graph.cpp b/Sources/ComputeCxx/Graph/Graph.cpp index 75f967c..95b624b 100644 --- a/Sources/ComputeCxx/Graph/Graph.cpp +++ b/Sources/ComputeCxx/Graph/Graph.cpp @@ -523,7 +523,7 @@ void Graph::remove_indirect_node(data::ptr indirect_node) { return; } - if (indirect_node->source().expired()) { + if (indirect_node->source().is_freed()) { return; } @@ -557,7 +557,7 @@ void Graph::remove_indirect_node(data::ptr indirect_node) { } break; } else { - if (source_indirect_node->source().expired()) { + if (source_indirect_node->source().is_freed()) { break; } @@ -625,7 +625,7 @@ bool Graph::remove_removed_output(AttributeID attribute, AttributeID output, boo if (output_indirect_node->is_mutable()) { auto &mutable_output_indirect_node = output_indirect_node->to_mutable(); auto initial_source = mutable_output_indirect_node.initial_source(); - if (initial_source.identifier() && !initial_source.identifier().is_nil() && !initial_source.expired()) { + if (initial_source.identifier() && !initial_source.identifier().is_nil() && !initial_source.is_expired()) { new_source = initial_source; new_offset = mutable_output_indirect_node.initial_offset(); } @@ -637,7 +637,7 @@ bool Graph::remove_removed_output(AttributeID attribute, AttributeID output, boo output_indirect_node->modify(new_source, new_offset); - if (new_source.identifier() && !new_source.identifier().is_nil() && !new_source.expired()) { + if (new_source.identifier() && !new_source.identifier().is_nil() && !new_source.is_expired()) { add_input_dependencies(output, new_source.identifier()); } @@ -918,7 +918,7 @@ bool Graph::indirect_attribute_reset(data::ptr indirect_node, bool auto initial_source = indirect_node->to_mutable().initial_source(); auto initial_offset = indirect_node->to_mutable().initial_offset(); - if (!initial_source.expired()) { + if (!initial_source.is_expired()) { new_source = initial_source; new_offset = initial_offset; } else {