diff options
author | Andreas Kling <kling@serenityos.org> | 2024-03-03 12:37:28 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2024-03-03 22:27:44 +0100 |
commit | 60a555e3649797084a72908ce4257890271109ad (patch) | |
tree | ceaf3e684e6412861e2a56c751703108e03423a3 | |
parent | 5813df21c8f8f353a040140ed23c3ea3e798897c (diff) |
LibJS/Bytecode: Make NewPrimitiveArray a variable-length instruction
Instead of having a FixedArray with a separate heap allocation, we can
just bake the primitive values into the instruction itself.
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Generator.h | 18 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Interpreter.cpp | 16 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 18 |
4 files changed, 44 insertions, 13 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index da4db0a361..0a2aa5c148 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -1024,14 +1024,15 @@ Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> ArrayExpression::ge if (all_of(m_elements, [](auto element) { return !element || is<PrimitiveLiteral>(*element); })) { // If all elements are constant primitives, we can just emit a single instruction to initialize the array, // instead of emitting instructions to manually evaluate them one-by-one - auto values = MUST(FixedArray<Value>::create(m_elements.size())); + Vector<Value> values; + values.resize(m_elements.size()); for (auto i = 0u; i < m_elements.size(); ++i) { if (!m_elements[i]) continue; values[i] = static_cast<PrimitiveLiteral const&>(*m_elements[i]).value(); } auto dst = choose_dst(generator, preferred_dst); - generator.emit<Bytecode::Op::NewPrimitiveArray>(dst, move(values)); + generator.emit_with_extra_value_slots<Bytecode::Op::NewPrimitiveArray>(values.size(), dst, values); return dst; } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index a716134963..79d0302b29 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -81,12 +81,12 @@ public: op->set_source_record({ m_current_ast_node->start_offset(), m_current_ast_node->end_offset() }); } - template<typename OpType, typename... Args> - void emit_with_extra_operand_slots(size_t extra_operand_slots, Args&&... args) + template<typename OpType, typename ExtraSlotType, typename... Args> + void emit_with_extra_slots(size_t extra_slot_count, Args&&... args) { VERIFY(!is_current_block_terminated()); - size_t size_to_allocate = round_up_to_power_of_two(sizeof(OpType) + extra_operand_slots * sizeof(Operand), alignof(void*)); + size_t size_to_allocate = round_up_to_power_of_two(sizeof(OpType) + extra_slot_count * sizeof(ExtraSlotType), alignof(void*)); size_t slot_offset = m_current_basic_block->size(); grow(size_to_allocate); void* slot = m_current_basic_block->data() + slot_offset; @@ -97,6 +97,18 @@ public: op->set_source_record({ m_current_ast_node->start_offset(), m_current_ast_node->end_offset() }); } + template<typename OpType, typename... Args> + void emit_with_extra_operand_slots(size_t extra_operand_slots, Args&&... args) + { + emit_with_extra_slots<OpType, Operand>(extra_operand_slots, forward<Args>(args)...); + } + + template<typename OpType, typename... Args> + void emit_with_extra_value_slots(size_t extra_operand_slots, Args&&... args) + { + emit_with_extra_slots<OpType, Value>(extra_operand_slots, forward<Args>(args)...); + } + struct ReferenceOperands { Optional<Operand> base {}; // [[Base]] Optional<Operand> referenced_name {}; // [[ReferencedName]] as an operand diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 6869500e99..c4fad2b5a8 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -96,6 +96,16 @@ static ByteString format_operand_list(StringView name, ReadonlySpan<Operand> ope return builder.to_byte_string(); } +static ByteString format_value_list(StringView name, ReadonlySpan<Value> values) +{ + StringBuilder builder; + if (!name.is_empty()) + builder.appendff(", \033[32m{}\033[0m:[", name); + builder.join(", "sv, values); + builder.append("]"sv); + return builder.to_byte_string(); +} + NonnullOwnPtr<CallFrame> CallFrame::create(size_t register_count) { size_t allocation_size = sizeof(CallFrame) + sizeof(Value) * register_count; @@ -870,8 +880,8 @@ ThrowCompletionOr<void> NewArray::execute_impl(Bytecode::Interpreter& interprete ThrowCompletionOr<void> NewPrimitiveArray::execute_impl(Bytecode::Interpreter& interpreter) const { auto array = MUST(Array::create(interpreter.realm(), 0)); - for (size_t i = 0; i < m_values.size(); i++) - array->indexed_properties().put(i, m_values[i], default_attributes); + for (size_t i = 0; i < m_element_count; i++) + array->indexed_properties().put(i, m_elements[i], default_attributes); interpreter.set(dst(), array); return {}; } @@ -1622,7 +1632,7 @@ ByteString NewPrimitiveArray::to_byte_string_impl(Bytecode::Executable const& ex { return ByteString::formatted("NewPrimitiveArray {}, {}"sv, format_operand("dst"sv, dst(), executable), - m_values.span()); + format_value_list("elements"sv, elements())); } ByteString ArrayAppend::to_byte_string_impl(Bytecode::Executable const& executable) const diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index c8489d04f1..ceef01e776 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -290,22 +290,30 @@ private: class NewPrimitiveArray final : public Instruction { public: - NewPrimitiveArray(Operand dst, FixedArray<Value> values) - : Instruction(Type::NewPrimitiveArray, sizeof(*this)) + NewPrimitiveArray(Operand dst, ReadonlySpan<Value> elements) + : Instruction(Type::NewPrimitiveArray, length_impl(elements.size())) , m_dst(dst) - , m_values(move(values)) + , m_element_count(elements.size()) { + for (size_t i = 0; i < m_element_count; ++i) + m_elements[i] = elements[i]; + } + + size_t length_impl(size_t element_count) const + { + return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Value) * element_count); } ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; ByteString to_byte_string_impl(Bytecode::Executable const&) const; Operand dst() const { return m_dst; } - ReadonlySpan<Value> values() const { return m_values.span(); } + ReadonlySpan<Value> elements() const { return { m_elements, m_element_count }; } private: Operand m_dst; - FixedArray<Value> m_values; + size_t m_element_count { 0 }; + Value m_elements[]; }; class ArrayAppend final : public Instruction { |