BasicBlock.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/String.h>
  7. #include <LibJS/Bytecode/BasicBlock.h>
  8. #include <LibJS/Bytecode/Op.h>
  9. #include <sys/mman.h>
  10. namespace JS::Bytecode {
  11. NonnullOwnPtr<BasicBlock> BasicBlock::create(String name)
  12. {
  13. return adopt_own(*new BasicBlock(move(name)));
  14. }
  15. BasicBlock::BasicBlock(String name)
  16. : m_name(move(name))
  17. {
  18. // FIXME: This is not the smartest solution ever. Find something cleverer!
  19. // The main issue we're working around here is that we don't want pointers into the bytecode stream to become invalidated
  20. // during code generation due to dynamic buffer resizing. Otherwise we could just use a Vector.
  21. m_buffer_capacity = 1 * KiB;
  22. m_buffer = (u8*)mmap(nullptr, m_buffer_capacity, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  23. VERIFY(m_buffer != MAP_FAILED);
  24. }
  25. BasicBlock::~BasicBlock()
  26. {
  27. Bytecode::InstructionStreamIterator it(instruction_stream());
  28. while (!it.at_end()) {
  29. auto& to_destroy = (*it);
  30. ++it;
  31. Instruction::destroy(const_cast<Instruction&>(to_destroy));
  32. }
  33. munmap(m_buffer, m_buffer_capacity);
  34. }
  35. void BasicBlock::seal()
  36. {
  37. // FIXME: mprotect the instruction stream as PROT_READ
  38. // This is currently not possible because instructions can have destructors (that clean up strings)
  39. // Instructions should instead be destructor-less and refer to strings in a string table on the Bytecode::Block.
  40. // It also doesn't work because instructions that have String members use RefPtr internally which must be in writable memory.
  41. }
  42. void BasicBlock::dump() const
  43. {
  44. Bytecode::InstructionStreamIterator it(instruction_stream());
  45. if (!m_name.is_empty())
  46. warnln("{}:", m_name);
  47. while (!it.at_end()) {
  48. warnln("[{:4x}] {}", it.offset(), (*it).to_string());
  49. ++it;
  50. }
  51. }
  52. void BasicBlock::grow(size_t additional_size)
  53. {
  54. m_buffer_size += additional_size;
  55. VERIFY(m_buffer_size <= m_buffer_capacity);
  56. }
  57. void InstructionStreamIterator::operator++()
  58. {
  59. m_offset += dereference().length();
  60. }
  61. }