GenerateCFG.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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 GenerateCFG::perform(PassPipelineExecutable& executable)
  9. {
  10. started();
  11. executable.cfg = HashMap<BasicBlock const*, HashTable<BasicBlock const*>> {};
  12. executable.inverted_cfg = HashMap<BasicBlock const*, HashTable<BasicBlock const*>> {};
  13. executable.exported_blocks = HashTable<BasicBlock const*> {};
  14. Vector<InstructionStreamIterator> iterators;
  15. Vector<BasicBlock const&> entered_blocks;
  16. HashTable<BasicBlock const*> seen_blocks;
  17. auto enter_label = [&](auto const& label, auto& entering_block, bool exported = false) {
  18. auto& entry = executable.cfg->ensure(&entering_block);
  19. entry.set(&label->block());
  20. auto& inverse_entry = executable.inverted_cfg->ensure(&label->block());
  21. inverse_entry.set(&entering_block);
  22. if (exported)
  23. executable.exported_blocks->set(&label->block());
  24. if (!seen_blocks.contains(&label->block())) {
  25. seen_blocks.set(&label->block());
  26. entered_blocks.append(label->block());
  27. iterators.empend(label->block().instruction_stream());
  28. }
  29. };
  30. seen_blocks.set(&executable.executable.basic_blocks.first());
  31. entered_blocks.append(executable.executable.basic_blocks.first());
  32. iterators.empend(executable.executable.basic_blocks.first().instruction_stream());
  33. while (!entered_blocks.is_empty()) {
  34. if (iterators.last().at_end()) {
  35. entered_blocks.take_last();
  36. iterators.take_last();
  37. continue;
  38. }
  39. auto& instruction = *iterators.last();
  40. ++iterators.last();
  41. if (!instruction.is_terminator())
  42. continue;
  43. auto& current_block = entered_blocks.last();
  44. if (instruction.type() == Instruction::Type::Jump) {
  45. auto& true_target = static_cast<Op::Jump const&>(instruction).true_target();
  46. enter_label(true_target, current_block);
  47. continue;
  48. }
  49. if (instruction.type() == Instruction::Type::JumpConditional || instruction.type() == Instruction::Type::JumpNullish || instruction.type() == Instruction::Type::JumpUndefined) {
  50. auto& true_target = static_cast<Op::Jump const&>(instruction).true_target();
  51. enter_label(true_target, current_block);
  52. auto& false_target = static_cast<Op::Jump const&>(instruction).false_target();
  53. enter_label(false_target, current_block);
  54. continue;
  55. }
  56. if (instruction.type() == Instruction::Type::Yield) {
  57. auto& continuation = static_cast<Op::Yield const&>(instruction).continuation();
  58. if (continuation.has_value())
  59. enter_label(continuation, current_block, true);
  60. continue;
  61. }
  62. if (instruction.type() == Instruction::Type::EnterUnwindContext) {
  63. auto& entry_point = static_cast<Op::EnterUnwindContext const&>(instruction).entry_point();
  64. auto& handler_target = static_cast<Op::EnterUnwindContext const&>(instruction).handler_target();
  65. auto& finalizer_target = static_cast<Op::EnterUnwindContext const&>(instruction).finalizer_target();
  66. enter_label(&entry_point, current_block);
  67. if (handler_target.has_value())
  68. enter_label(handler_target, current_block);
  69. if (finalizer_target.has_value())
  70. enter_label(finalizer_target, current_block);
  71. continue;
  72. }
  73. if (instruction.type() == Instruction::Type::ContinuePendingUnwind) {
  74. auto& resume_target = static_cast<Op::ContinuePendingUnwind const&>(instruction).resume_target();
  75. enter_label(&resume_target, current_block);
  76. continue;
  77. }
  78. // Otherwise, pop the current block off, it doesn't jump anywhere.
  79. iterators.take_last();
  80. entered_blocks.take_last();
  81. }
  82. finished();
  83. }
  84. }