123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- /*
- * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <LibJS/Bytecode/PassManager.h>
- #include <string.h>
- namespace JS::Bytecode::Passes {
- void UnifySameBlocks::perform(PassPipelineExecutable& executable)
- {
- started();
- VERIFY(executable.cfg.has_value());
- VERIFY(executable.inverted_cfg.has_value());
- auto cfg = executable.cfg.release_value();
- auto inverted_cfg = executable.inverted_cfg.release_value();
- HashMap<BasicBlock const*, BasicBlock const*> equal_blocks;
- for (size_t i = 0; i < executable.executable.basic_blocks.size(); ++i) {
- auto& block = executable.executable.basic_blocks[i];
- auto block_bytes = block->instruction_stream();
- for (auto& candidate_block : executable.executable.basic_blocks.span().slice(i + 1)) {
- if (equal_blocks.contains(&*candidate_block))
- continue;
- // FIXME: This can probably be relaxed a bit...
- if (candidate_block->size() != block->size())
- continue;
- auto candidate_bytes = candidate_block->instruction_stream();
- // FIXME: NewBigInt's value is not correctly reflected by its encoding in memory,
- // this will yield false negatives for blocks containing that
- if (memcmp(candidate_bytes.data(), block_bytes.data(), candidate_block->size()) == 0)
- equal_blocks.set(candidate_block.ptr(), block);
- }
- }
- auto replace_blocks = [&](auto& match, auto& replacement) {
- Optional<size_t> first_successor_position;
- auto it = executable.executable.basic_blocks.find_if([match](auto& block) { return match == block; });
- VERIFY(!it.is_end());
- executable.executable.basic_blocks.remove(it.index());
- if (!first_successor_position.has_value())
- first_successor_position = it.index();
- for (auto& block : executable.executable.basic_blocks) {
- InstructionStreamIterator it { block->instruction_stream() };
- while (!it.at_end()) {
- auto& instruction = *it;
- ++it;
- const_cast<Instruction&>(instruction).replace_references(*match, replacement);
- }
- }
- return first_successor_position;
- };
- for (auto& entry : equal_blocks)
- (void)replace_blocks(entry.key, *entry.value);
- finished();
- }
- }
|