AK+LibRegex: Only set node metadata on Trie::ensure_child if missing

a290034a81 passed an empty vector to this,
which caused nodes that appeared multiple times to reset the trie
metadata...which broke the optimisation.

This patchset makes the function take a 'provide missing metadata'
function instead, and only invokes it when the node is missing rather
than unconditionally setting the metadata on all nodes.
This commit is contained in:
Ali Mohammad Pur
2025-11-20 23:47:21 +01:00
committed by Ali Mohammad Pur
parent 2c5beeabe3
commit d5d37abfa5
Notes: github-actions[bot] 2025-11-21 01:47:30 +00:00
2 changed files with 17 additions and 11 deletions

View File

@@ -95,23 +95,29 @@ public:
ValueType const& value() const { return m_value; }
ValueType& value() { return m_value; }
ErrorOr<Trie*> ensure_child(ValueType value, Optional<MetadataType> metadata = {})
template<typename F = Function<Optional<MetadataType>()>>
ErrorOr<Trie*> ensure_child(ValueType value, F metadata_if_missing = [] { return OptionalNone {}; })
{
auto it = m_children.find(value);
if (it == m_children.end()) {
OwnPtr<Trie> node;
if constexpr (requires { { value->try_clone() } -> SpecializationOf<ErrorOr>; })
node = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(TRY(value->try_clone()), move(metadata))));
Optional<MetadataType> missing_metadata;
if constexpr (requires { { metadata_if_missing() } -> SpecializationOf<ErrorOr>; })
missing_metadata = TRY(metadata_if_missing());
else
node = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(value, move(metadata))));
missing_metadata = metadata_if_missing();
if constexpr (requires { { value->try_clone() } -> SpecializationOf<ErrorOr>; })
node = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(TRY(value->try_clone()), move(missing_metadata))));
else
node = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Trie(value, move(missing_metadata))));
auto& node_ref = *node;
TRY(m_children.try_set(move(value), node.release_nonnull()));
return &static_cast<BaseType&>(node_ref);
}
auto& node_ref = *it->value;
if (metadata.has_value())
node_ref.m_metadata = move(metadata);
return &static_cast<BaseType&>(node_ref);
}
@@ -129,9 +135,9 @@ public:
};
for (; it != end; ++it) {
if constexpr (requires { { ValueType::ElementType::try_create(*it) } -> SpecializationOf<ErrorOr>; })
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(TRY(ValueType::ElementType::try_create(*it)), TRY(invoke_provide_missing_metadata(static_cast<BaseType&>(*last_root_node), it)))));
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(TRY(ValueType::ElementType::try_create(*it)), [&] { return invoke_provide_missing_metadata(static_cast<BaseType&>(*last_root_node), it); })));
else
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(*it, TRY(invoke_provide_missing_metadata(static_cast<BaseType&>(*last_root_node), it)))));
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(*it, [&] { return invoke_provide_missing_metadata(static_cast<BaseType&>(*last_root_node), it); })));
}
last_root_node->set_metadata(move(metadata));
return static_cast<BaseType*>(last_root_node);
@@ -144,9 +150,9 @@ public:
Trie* last_root_node = &traverse_until_last_accessible_node(it, end);
for (; it != end; ++it) {
if constexpr (requires { { ValueType::ElementType::try_create(*it) } -> SpecializationOf<ErrorOr>; })
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(TRY(ValueType::ElementType::try_create(*it)), {})));
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(TRY(ValueType::ElementType::try_create(*it)))));
else
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(*it, {})));
last_root_node = static_cast<Trie*>(TRY(last_root_node->ensure_child(*it)));
}
return static_cast<BaseType*>(last_root_node);
}

View File

@@ -1467,7 +1467,7 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
node_key_bytes.append(edge.jump_insn);
}
active_node = static_cast<decltype(active_node)>(MUST(active_node->ensure_child(DisjointSpans<ByteCodeValueType const> { move(node_key_bytes) }, Vector<NodeMetadataEntry> {})));
active_node = static_cast<decltype(active_node)>(MUST(active_node->ensure_child(DisjointSpans<ByteCodeValueType const> { move(node_key_bytes) }, [] -> Vector<NodeMetadataEntry> { return {}; })));
auto next_compare = [&alternative, &state](StaticallyInterpretedCompares& compares) {
TemporaryChange state_change { state.instruction_position, state.instruction_position };