Block.cpp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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/Block.h>
  8. #include <LibJS/Bytecode/Op.h>
  9. #include <sys/mman.h>
  10. namespace JS::Bytecode {
  11. NonnullOwnPtr<Block> Block::create()
  12. {
  13. return adopt_own(*new Block);
  14. }
  15. Block::Block()
  16. {
  17. // FIXME: This is not the smartest solution ever. Find something cleverer!
  18. // The main issue we're working around here is that we don't want pointers into the bytecode stream to become invalidated
  19. // during code generation due to dynamic buffer resizing. Otherwise we could just use a Vector.
  20. m_buffer_capacity = 64 * KiB;
  21. m_buffer = (u8*)mmap(nullptr, m_buffer_capacity, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  22. VERIFY(m_buffer != MAP_FAILED);
  23. }
  24. Block::~Block()
  25. {
  26. unseal();
  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 Block::seal() const
  36. {
  37. if (mprotect(m_buffer, m_buffer_capacity, PROT_READ) < 0) {
  38. perror("ByteCode::Block::seal: mprotect");
  39. VERIFY_NOT_REACHED();
  40. }
  41. }
  42. void Block::unseal()
  43. {
  44. if (mprotect(m_buffer, m_buffer_capacity, PROT_READ | PROT_WRITE) < 0) {
  45. perror("ByteCode::Block::unseal: mprotect");
  46. VERIFY_NOT_REACHED();
  47. }
  48. }
  49. void Block::dump() const
  50. {
  51. Bytecode::InstructionStreamIterator it(instruction_stream());
  52. while (!it.at_end()) {
  53. warnln("[{:4x}] {}", it.offset(), (*it).to_string());
  54. ++it;
  55. }
  56. }
  57. void Block::grow(size_t additional_size)
  58. {
  59. m_buffer_size += additional_size;
  60. VERIFY(m_buffer_size <= m_buffer_capacity);
  61. }
  62. void InstructionStreamIterator::operator++()
  63. {
  64. m_offset += dereference().length();
  65. }
  66. }