diff options
Diffstat (limited to 'Userland/Libraries/LibJS/Bytecode/Pass/PlaceBlocks.cpp')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Pass/PlaceBlocks.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Pass/PlaceBlocks.cpp b/Userland/Libraries/LibJS/Bytecode/Pass/PlaceBlocks.cpp new file mode 100644 index 0000000000..4a320ac470 --- /dev/null +++ b/Userland/Libraries/LibJS/Bytecode/Pass/PlaceBlocks.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Bytecode/PassManager.h> + +namespace JS::Bytecode::Passes { + +void PlaceBlocks::perform(PassPipelineExecutable& executable) +{ + started(); + + VERIFY(executable.cfg.has_value()); + auto cfg = executable.cfg.release_value(); + + Vector<BasicBlock&> replaced_blocks; + HashTable<BasicBlock const*> reachable_blocks; + + // Visit the blocks in CFG order + AK::Function<void(BasicBlock const*)> visit = [&](auto* block) { + if (reachable_blocks.contains(block)) + return; + + reachable_blocks.set(block); + replaced_blocks.append(*const_cast<BasicBlock*>(block)); + + for (auto& entry : cfg.get(block).value_or({})) + visit(entry); + }; + + // Make sure to visit the entry block first + visit(&executable.executable.basic_blocks.first()); + + for (auto& entry : cfg) + visit(entry.key); + + // Put the unreferenced blocks back in at the end + for (auto& entry : static_cast<Vector<NonnullOwnPtr<BasicBlock>>&>(executable.executable.basic_blocks)) { + if (reachable_blocks.contains(entry.ptr())) + (void)entry.leak_ptr(); + else + replaced_blocks.append(*entry.leak_ptr()); // Don't try to do DCE here. + } + + executable.executable.basic_blocks.clear(); + for (auto& block : replaced_blocks) + executable.executable.basic_blocks.append(adopt_own(block)); + + finished(); +} + +} |