LibRegex: Make append_alternation() actually skip the common blocks

Previously we started with 'left_skip' set to zero, which made it so
that no blocks were selected to be skipped.
This commit is contained in:
Ali Mohammad Pur 2023-06-13 23:25:00 +03:30 committed by Andreas Kling
parent b1ca2e5e39
commit fb262de7cb

View file

@ -701,7 +701,7 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
for (auto& entry : alternatives)
basic_blocks.append(Regex<PosixBasicParser>::split_basic_blocks(entry));
size_t left_skip = 0;
Optional<size_t> left_skip;
size_t shared_block_count = basic_blocks.first().size();
for (auto& entry : basic_blocks)
shared_block_count = min(shared_block_count, entry.size());
@ -741,21 +741,48 @@ void Optimizer::append_alternation(ByteCode& target, Span<ByteCode> alternatives
state.instruction_position += opcode.size();
skip = state.instruction_position;
}
left_skip = min(skip, left_skip);
if (left_skip.has_value())
left_skip = min(skip, *left_skip);
else
left_skip = skip;
}
}
// Remove forward jumps as they no longer make sense.
state.instruction_position = 0;
for (size_t i = 0; i < left_skip.value_or(0);) {
auto& opcode = alternatives[0].get_opcode(state);
switch (opcode.opcode_id()) {
case OpCodeId::Jump:
case OpCodeId::ForkJump:
case OpCodeId::JumpNonEmpty:
case OpCodeId::ForkStay:
case OpCodeId::ForkReplaceJump:
case OpCodeId::ForkReplaceStay:
if (opcode.argument(0) + opcode.size() > left_skip.value_or(0)) {
left_skip = i;
goto break_out;
}
break;
default:
break;
}
i += opcode.size();
}
break_out:;
dbgln_if(REGEX_DEBUG, "Skipping {}/{} bytecode entries from {}", left_skip, 0, alternatives[0].size());
if (left_skip > 0) {
target.extend(alternatives[0].release_slice(basic_blocks.first().first().start, left_skip));
if (left_skip.has_value() && *left_skip > 0) {
target.extend(alternatives[0].release_slice(basic_blocks.first().first().start, *left_skip));
auto first = true;
for (auto& entry : alternatives) {
if (first) {
first = false;
continue;
}
entry = entry.release_slice(left_skip);
entry = entry.release_slice(*left_skip);
}
}