LibJS/Bytecode: Store labels as basic block index during compilation

Instead of storing a BasicBlock* and forcing the size of Label to be
sizeof(BasicBlock*), we now store the basic block index as a u32.

This means the final version of the bytecode is able to keep labels
at sizeof(u32), shrinking the size of many instructions. :^)
This commit is contained in:
Andreas Kling 2024-05-06 08:06:56 +02:00
parent 5a08544138
commit 3a73eb99ac
7 changed files with 40 additions and 22 deletions

View file

@ -10,13 +10,14 @@
namespace JS::Bytecode {
NonnullOwnPtr<BasicBlock> BasicBlock::create(String name)
NonnullOwnPtr<BasicBlock> BasicBlock::create(u32 index, String name)
{
return adopt_own(*new BasicBlock(move(name)));
return adopt_own(*new BasicBlock(index, move(name)));
}
BasicBlock::BasicBlock(String name)
: m_name(move(name))
BasicBlock::BasicBlock(u32 index, String name)
: m_index(index)
, m_name(move(name))
{
}

View file

@ -25,9 +25,11 @@ class BasicBlock {
AK_MAKE_NONCOPYABLE(BasicBlock);
public:
static NonnullOwnPtr<BasicBlock> create(String name);
static NonnullOwnPtr<BasicBlock> create(u32 index, String name);
~BasicBlock();
u32 index() const { return m_index; }
ReadonlyBytes instruction_stream() const { return m_buffer.span(); }
u8* data() { return m_buffer.data(); }
u8 const* data() const { return m_buffer.data(); }
@ -50,8 +52,9 @@ public:
void add_source_map_entry(size_t bytecode_offset, SourceRecord const& source_record) { m_source_map.set(bytecode_offset, source_record); }
private:
explicit BasicBlock(String name);
explicit BasicBlock(u32 index, String name);
u32 m_index { 0 };
Vector<u8> m_buffer;
BasicBlock const* m_handler { nullptr };
BasicBlock const* m_finalizer { nullptr };

View file

@ -135,7 +135,7 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate(VM& vm, ASTN
}
for (auto label_offset : label_offsets) {
auto& label = *reinterpret_cast<Label*>(bytecode.data() + label_offset);
auto* block = &label.block();
auto* block = generator.m_root_basic_blocks[label.basic_block_index()].ptr();
label.set_address(block_offsets.get(block).value());
}

View file

@ -150,12 +150,12 @@ public:
{
if (name.is_empty())
name = MUST(String::number(m_next_block++));
auto block = BasicBlock::create(name);
auto block = BasicBlock::create(m_root_basic_blocks.size(), name);
if (auto const* context = m_current_unwind_context) {
if (context->handler().has_value())
block->set_handler(context->handler().value().block());
block->set_handler(*m_root_basic_blocks[context->handler().value().basic_block_index()]);
if (m_current_unwind_context->finalizer().has_value())
block->set_finalizer(context->finalizer().value().block());
block->set_finalizer(*m_root_basic_blocks[context->finalizer().value().basic_block_index()]);
}
m_root_basic_blocks.append(move(block));
return *m_root_basic_blocks.last();

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2024, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Bytecode/BasicBlock.h>
#include <LibJS/Bytecode/Label.h>
namespace JS::Bytecode {
Label::Label(Bytecode::BasicBlock const& basic_block)
: m_address_or_basic_block_index(basic_block.index())
{
}
}

View file

@ -14,27 +14,23 @@ class BasicBlock;
class Label {
public:
explicit Label(BasicBlock const& block)
: m_block(&block)
explicit Label(BasicBlock const&);
explicit Label(u32 basic_block_index)
: m_address_or_basic_block_index(basic_block_index)
{
}
// Used while compiling.
BasicBlock const& block() const { return *m_block; }
size_t basic_block_index() const { return m_address_or_basic_block_index; }
// Used after compiling.
size_t address() const { return m_address; }
size_t address() const { return m_address_or_basic_block_index; }
void set_address(size_t address) { m_address = address; }
void set_address(size_t address) { m_address_or_basic_block_index = address; }
private:
union {
// Relevant while compiling.
BasicBlock const* m_block { nullptr };
// Relevant after compiling.
size_t m_address;
};
u32 m_address_or_basic_block_index { 0 };
};
}

View file

@ -9,6 +9,7 @@ set(SOURCES
Bytecode/IdentifierTable.cpp
Bytecode/Instruction.cpp
Bytecode/Interpreter.cpp
Bytecode/Label.cpp
Bytecode/RegexTable.cpp
Bytecode/StringTable.cpp
Console.cpp