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> ArrayExpression::ge if (all_of(m_elements, [](auto element) { return !element || is(*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::create(m_elements.size())); + Vector values; + values.resize(m_elements.size()); for (auto i = 0u; i < m_elements.size(); ++i) { if (!m_elements[i]) continue; values[i] = static_cast(*m_elements[i]).value(); } auto dst = choose_dst(generator, preferred_dst); - generator.emit(dst, move(values)); + generator.emit_with_extra_value_slots(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 - void emit_with_extra_operand_slots(size_t extra_operand_slots, Args&&... args) + template + 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 + void emit_with_extra_operand_slots(size_t extra_operand_slots, Args&&... args) + { + emit_with_extra_slots(extra_operand_slots, forward(args)...); + } + + template + void emit_with_extra_value_slots(size_t extra_operand_slots, Args&&... args) + { + emit_with_extra_slots(extra_operand_slots, forward(args)...); + } + struct ReferenceOperands { Optional base {}; // [[Base]] Optional 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 ope return builder.to_byte_string(); } +static ByteString format_value_list(StringView name, ReadonlySpan 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::create(size_t register_count) { size_t allocation_size = sizeof(CallFrame) + sizeof(Value) * register_count; @@ -870,8 +880,8 @@ ThrowCompletionOr NewArray::execute_impl(Bytecode::Interpreter& interprete ThrowCompletionOr 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 values) - : Instruction(Type::NewPrimitiveArray, sizeof(*this)) + NewPrimitiveArray(Operand dst, ReadonlySpan 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 execute_impl(Bytecode::Interpreter&) const; ByteString to_byte_string_impl(Bytecode::Executable const&) const; Operand dst() const { return m_dst; } - ReadonlySpan values() const { return m_values.span(); } + ReadonlySpan elements() const { return { m_elements, m_element_count }; } private: Operand m_dst; - FixedArray m_values; + size_t m_element_count { 0 }; + Value m_elements[]; }; class ArrayAppend final : public Instruction {