mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-19 15:32:31 +00:00
LibRegex: Don't blindly treat multi-target tree jumps as a single jump
The tree generation was broken, we just didn't notice it because it was very rarely being picked for more complex bytecodes.
This commit is contained in:
parent
09eb28ee1d
commit
ec0836c9ea
Notes:
github-actions[bot]
2025-04-23 20:59:13 +00:00
Author: https://github.com/alimpfard
Commit: ec0836c9ea
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4441
1 changed files with 49 additions and 35 deletions
|
@ -1345,16 +1345,6 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
|
||||||
Vector<Patch> patch_locations;
|
Vector<Patch> patch_locations;
|
||||||
patch_locations.ensure_capacity(total_nodes);
|
patch_locations.ensure_capacity(total_nodes);
|
||||||
|
|
||||||
auto add_patch_point = [&](Tree const* node, size_t target_ip) {
|
|
||||||
if (!node->has_metadata())
|
|
||||||
return;
|
|
||||||
auto& node_ip = node->metadata_value().first();
|
|
||||||
patch_locations.append({ node_ip, target_ip });
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector<Tree*> nodes_to_visit;
|
|
||||||
nodes_to_visit.append(&trie);
|
|
||||||
|
|
||||||
HashMap<size_t, NonnullOwnPtr<RedBlackTree<u64, u64>>> instruction_positions;
|
HashMap<size_t, NonnullOwnPtr<RedBlackTree<u64, u64>>> instruction_positions;
|
||||||
if (has_any_backwards_jump)
|
if (has_any_backwards_jump)
|
||||||
MUST(instruction_positions.try_ensure_capacity(alternatives.size()));
|
MUST(instruction_positions.try_ensure_capacity(alternatives.size()));
|
||||||
|
@ -1365,6 +1355,16 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto add_patch_point = [&](Tree const* node, size_t target_ip) {
|
||||||
|
if (!node->has_metadata())
|
||||||
|
return;
|
||||||
|
|
||||||
|
patch_locations.append({ node->metadata_value().first(), target_ip });
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<Tree*> nodes_to_visit;
|
||||||
|
nodes_to_visit.append(&trie);
|
||||||
|
|
||||||
// each node:
|
// each node:
|
||||||
// node.re
|
// node.re
|
||||||
// forkjump child1
|
// forkjump child1
|
||||||
|
@ -1431,12 +1431,25 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
|
||||||
|
|
||||||
if (is_jump) {
|
if (is_jump) {
|
||||||
VERIFY(node->has_metadata());
|
VERIFY(node->has_metadata());
|
||||||
QualifiedIP ip = node->metadata_value().first();
|
if (node->metadata_value().size() > 1)
|
||||||
auto intended_jump_ip = ip.instruction_position + jump_offset + opcode.size();
|
target[patch_location] = static_cast<ByteCodeValueType>(0); // Fall through instead.
|
||||||
|
|
||||||
|
auto only_one = node->metadata_value().size() == 1;
|
||||||
|
auto patch_size = opcode.size() - 1;
|
||||||
|
for (auto [alternative_index, instruction_position] : node->metadata_value()) {
|
||||||
|
if (!only_one) {
|
||||||
|
target.append(static_cast<ByteCodeValueType>(OpCodeId::ForkJump));
|
||||||
|
patch_location = target.size();
|
||||||
|
should_negate = false;
|
||||||
|
patch_size = 2;
|
||||||
|
target.append(static_cast<ByteCodeValueType>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto intended_jump_ip = instruction_position + jump_offset + opcode.size();
|
||||||
if (jump_offset < 0) {
|
if (jump_offset < 0) {
|
||||||
VERIFY(has_any_backwards_jump);
|
VERIFY(has_any_backwards_jump);
|
||||||
// We should've already seen this instruction, so we can just patch it in.
|
// We should've already seen this instruction, so we can just patch it in.
|
||||||
auto& ip_mapping = ip_mapping_for_alternative(ip.alternative_index);
|
auto& ip_mapping = ip_mapping_for_alternative(alternative_index);
|
||||||
auto target_ip = ip_mapping.find(intended_jump_ip);
|
auto target_ip = ip_mapping.find(intended_jump_ip);
|
||||||
if (!target_ip) {
|
if (!target_ip) {
|
||||||
RegexDebug dbg;
|
RegexDebug dbg;
|
||||||
|
@ -1447,17 +1460,18 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
|
||||||
}
|
}
|
||||||
|
|
||||||
dbgln("Regex Tree / Unknown backwards jump: {}@{} -> {}",
|
dbgln("Regex Tree / Unknown backwards jump: {}@{} -> {}",
|
||||||
ip.instruction_position,
|
instruction_position,
|
||||||
ip.alternative_index,
|
alternative_index,
|
||||||
intended_jump_ip);
|
intended_jump_ip);
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
ssize_t target_value = *target_ip - patch_location - 1;
|
ssize_t target_value = *target_ip - patch_location - patch_size;
|
||||||
if (should_negate)
|
if (should_negate)
|
||||||
target_value = -target_value + 2; // from -1 to +1.
|
target_value = -target_value + 2; // from -1 to +1.
|
||||||
target[patch_location] = static_cast<ByteCodeValueType>(target_value);
|
target[patch_location] = static_cast<ByteCodeValueType>(target_value);
|
||||||
} else {
|
} else {
|
||||||
patch_locations.append({ QualifiedIP { ip.alternative_index, intended_jump_ip }, patch_location });
|
patch_locations.append({ QualifiedIP { alternative_index, intended_jump_ip }, patch_location });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue