PlaceBlocks.cpp 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /*
  2. * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Bytecode/PassManager.h>
  7. namespace JS::Bytecode::Passes {
  8. void PlaceBlocks::perform(PassPipelineExecutable& executable)
  9. {
  10. started();
  11. VERIFY(executable.cfg.has_value());
  12. auto cfg = executable.cfg.release_value();
  13. Vector<BasicBlock&> replaced_blocks;
  14. HashTable<BasicBlock const*> reachable_blocks;
  15. // Visit the blocks in CFG order
  16. Function<void(BasicBlock const*)> visit = [&](auto* block) {
  17. if (reachable_blocks.contains(block))
  18. return;
  19. reachable_blocks.set(block);
  20. replaced_blocks.append(*const_cast<BasicBlock*>(block));
  21. auto children = cfg.find(block);
  22. if (children == cfg.end())
  23. return;
  24. for (auto& entry : children->value)
  25. visit(entry);
  26. };
  27. // Make sure to visit the entry block first
  28. visit(executable.executable.basic_blocks.first());
  29. for (auto& entry : cfg)
  30. visit(entry.key);
  31. // Put the unreferenced blocks back in at the end
  32. for (auto& entry : static_cast<Vector<NonnullOwnPtr<BasicBlock>>&>(executable.executable.basic_blocks)) {
  33. if (reachable_blocks.contains(entry.ptr()))
  34. (void)entry.leak_ptr();
  35. else
  36. replaced_blocks.append(*entry.leak_ptr()); // Don't try to do DCE here.
  37. }
  38. executable.executable.basic_blocks.clear();
  39. for (auto& block : replaced_blocks)
  40. executable.executable.basic_blocks.append(adopt_own(block));
  41. finished();
  42. }
  43. }