瀏覽代碼

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. :^)
Andreas Kling 1 年之前
父節點
當前提交
3a73eb99ac

+ 5 - 4
Userland/Libraries/LibJS/Bytecode/BasicBlock.cpp

@@ -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))
 {
 }
 

+ 5 - 2
Userland/Libraries/LibJS/Bytecode/BasicBlock.h

@@ -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 };

+ 1 - 1
Userland/Libraries/LibJS/Bytecode/Generator.cpp

@@ -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());
     }
 

+ 3 - 3
Userland/Libraries/LibJS/Bytecode/Generator.h

@@ -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();

+ 17 - 0
Userland/Libraries/LibJS/Bytecode/Label.cpp

@@ -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())
+{
+}
+
+}

+ 8 - 12
Userland/Libraries/LibJS/Bytecode/Label.h

@@ -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 };
 };
 
 }

+ 1 - 0
Userland/Libraries/LibJS/CMakeLists.txt

@@ -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