1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 14:38:11 +00:00

LibJS: Add bytecode instruction handles

This change removes the mmap inside of Block in favor of a growing
vector of bytes. This is favorable for two reasons:
  - We don't take more space than we need
  - There is no limit to the growth of the vector (previously, if
    the Block overstepped its 64kb boundary, it would just crash)

However, if that vector happens to resize, any pointer pointing into
that vector would become invalid. To avoid this, this commit adds an
InstructionHandle<Op> class which just stores a block and an offset
into that block.
This commit is contained in:
Matthew Olsson 2021-06-08 14:46:46 -07:00 committed by Andreas Kling
parent 83be39c91a
commit a01bd35c67
8 changed files with 81 additions and 79 deletions

View file

@ -7,8 +7,8 @@
#pragma once
#include <AK/OwnPtr.h>
#include <LibJS/Bytecode/Block.h>
#include <LibJS/Bytecode/Label.h>
#include <LibJS/Bytecode/Register.h>
#include <LibJS/Forward.h>
namespace JS::Bytecode {
@ -20,21 +20,15 @@ public:
Register allocate_register();
template<typename OpType, typename... Args>
OpType& emit(Args&&... args)
InstructionHandle<OpType> emit(Args&&... args)
{
void* slot = next_slot();
grow(sizeof(OpType));
new (slot) OpType(forward<Args>(args)...);
return *static_cast<OpType*>(slot);
return make_instruction<OpType>(0, forward<Args>(args)...);
}
template<typename OpType, typename... Args>
OpType& emit_with_extra_register_slots(size_t extra_register_slots, Args&&... args)
InstructionHandle<OpType> emit_with_extra_register_slots(size_t extra_register_slots, Args&&... args)
{
void* slot = next_slot();
grow(sizeof(OpType) + extra_register_slots * sizeof(Register));
new (slot) OpType(forward<Args>(args)...);
return *static_cast<OpType*>(slot);
return make_instruction<OpType>(extra_register_slots, forward<Args>(args)...);
}
Label make_label() const;
@ -48,8 +42,15 @@ private:
Generator();
~Generator();
void grow(size_t);
void* next_slot();
template<typename OpType, typename... Args>
InstructionHandle<OpType> make_instruction(size_t extra_register_slots, Args&&... args)
{
auto& buffer = m_block->buffer();
auto offset = buffer.size();
buffer.resize(buffer.size() + sizeof(OpType) + extra_register_slots * sizeof(Register));
new (buffer.data() + offset) OpType(forward<Args>(args)...);
return InstructionHandle<OpType>(offset, m_block);
}
OwnPtr<Block> m_block;
u32 m_next_register { 1 };