diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index b4dfd9e6ea..f6e40aab70 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -302,9 +302,7 @@ Bytecode::CodeGenerationErrorOr> BigIntLiteral::gene Bytecode::CodeGenerationErrorOr> StringLiteral::generate_bytecode(Bytecode::Generator& generator, [[maybe_unused]] Optional preferred_dst) const { Bytecode::Generator::SourceLocationScope scope(generator, *this); - auto dst = choose_dst(generator, preferred_dst); - generator.emit(dst, generator.intern_string(m_value)); - return dst; + return generator.add_constant(PrimitiveString::create(generator.vm(), m_value), Bytecode::Generator::DeduplicateConstant::No); } Bytecode::CodeGenerationErrorOr> RegExpLiteral::generate_bytecode(Bytecode::Generator& generator, Optional preferred_dst) const @@ -1165,20 +1163,13 @@ static Bytecode::CodeGenerationErrorOr generate_object_binding_pattern_byt VERIFY_NOT_REACHED(); } - Bytecode::StringTableIndex name_index; - auto value = Bytecode::Operand(generator.allocate_register()); if (name.has>()) { - auto identifier = name.get>()->string(); - name_index = generator.intern_string(identifier); - + auto const& identifier = name.get>()->string(); if (has_rest) { - auto excluded_name = Bytecode::Operand(generator.allocate_register()); - excluded_property_names.append(excluded_name); - generator.emit(excluded_name, name_index); + excluded_property_names.append(generator.add_constant(PrimitiveString::create(generator.vm(), identifier), Bytecode::Generator::DeduplicateConstant::No)); } - generator.emit_get_by_id(value, object, generator.intern_identifier(identifier)); } else { auto expression = name.get>(); diff --git a/Userland/Libraries/LibJS/Bytecode/Executable.cpp b/Userland/Libraries/LibJS/Bytecode/Executable.cpp index ec33c92047..9705ef039c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Executable.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Executable.cpp @@ -50,4 +50,11 @@ void Executable::dump() const warnln(""); } +void Executable::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + for (auto constant : constants) + visitor.visit(constant); +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Executable.h b/Userland/Libraries/LibJS/Bytecode/Executable.h index d31f414d58..150e9bc6f5 100644 --- a/Userland/Libraries/LibJS/Bytecode/Executable.h +++ b/Userland/Libraries/LibJS/Bytecode/Executable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023, Andreas Kling + * Copyright (c) 2021-2024, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -75,6 +75,9 @@ public: DeprecatedFlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); } void dump() const; + +private: + virtual void visit_edges(Visitor&) override; }; } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 813a716a43..67bdf5a1fe 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -15,16 +15,18 @@ namespace JS::Bytecode { -Generator::Generator() - : m_string_table(make()) +Generator::Generator(VM& vm) + : m_vm(vm) + , m_string_table(make()) , m_identifier_table(make()) , m_regex_table(make()) + , m_constants(vm.heap()) { } CodeGenerationErrorOr> Generator::generate(VM& vm, ASTNode const& node, ReadonlySpan parameters, FunctionKind enclosing_function_kind) { - Generator generator; + Generator generator(vm); for (auto const& parameter : parameters) { if (auto const* identifier = parameter.binding.get_pointer>(); diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index 5a2ae26f1a..a716134963 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -25,6 +25,8 @@ namespace JS::Bytecode { class Generator { public: + VM& vm() { return m_vm; } + enum class SurroundingScopeKind { Global, Function, @@ -261,6 +263,8 @@ public: } private: + VM& m_vm; + enum class JumpType { Continue, Break, @@ -268,7 +272,7 @@ private: void generate_scoped_jump(JumpType); void generate_labelled_jump(JumpType, DeprecatedFlyString const& label); - Generator(); + explicit Generator(VM&); ~Generator() = default; void grow(size_t); @@ -286,7 +290,7 @@ private: NonnullOwnPtr m_string_table; NonnullOwnPtr m_identifier_table; NonnullOwnPtr m_regex_table; - Vector m_constants; + MarkedVector m_constants; u32 m_next_register { Register::reserved_register_count }; u32 m_next_block { 1 }; diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index b5ebcbe311..fc4d91e9d8 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -88,7 +88,6 @@ O(NewObject) \ O(NewPrimitiveArray) \ O(NewRegExp) \ - O(NewString) \ O(NewTypeError) \ O(Not) \ O(PostfixDecrement) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index d0fc87c517..4dfa93e31a 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -63,6 +63,8 @@ static ByteString format_operand(StringView name, Operand operand, Bytecode::Exe builder.appendff("Int32({})", value.as_i32()); else if (value.is_double()) builder.appendff("Double({})", value.as_double()); + else if (value.is_string()) + builder.appendff("String(\"{}\")", value.as_string().utf8_string_view()); else if (value.is_undefined()) builder.append("Undefined"sv); else if (value.is_null()) @@ -899,12 +901,6 @@ ThrowCompletionOr IteratorToArray::execute_impl(Bytecode::Interpreter& int return {}; } -ThrowCompletionOr NewString::execute_impl(Bytecode::Interpreter& interpreter) const -{ - interpreter.set(dst(), PrimitiveString::create(interpreter.vm(), interpreter.current_executable().get_string(m_string))); - return {}; -} - ThrowCompletionOr NewObject::execute_impl(Bytecode::Interpreter& interpreter) const { auto& vm = interpreter.vm(); @@ -1656,13 +1652,6 @@ ByteString IteratorToArray::to_byte_string_impl(Bytecode::Executable const& exec format_operand("iterator"sv, iterator(), executable)); } -ByteString NewString::to_byte_string_impl(Bytecode::Executable const& executable) const -{ - return ByteString::formatted("NewString {}, \"{}\"", - format_operand("dst"sv, dst(), executable), - executable.string_table->get(m_string)); -} - ByteString NewObject::to_byte_string_impl(Bytecode::Executable const& executable) const { return ByteString::formatted("NewObject {}", format_operand("dst"sv, dst(), executable)); diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 9a1fc909e5..c1d5dc3302 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -136,26 +136,6 @@ JS_ENUMERATE_COMMON_BINARY_OPS_WITH_FAST_PATH(JS_DECLARE_COMMON_BINARY_OP) JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP) #undef JS_DECLARE_COMMON_UNARY_OP -class NewString final : public Instruction { -public: - NewString(Operand dst, StringTableIndex string) - : Instruction(Type::NewString, sizeof(*this)) - , m_dst(dst) - , m_string(string) - { - } - - ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; - ByteString to_byte_string_impl(Bytecode::Executable const&) const; - - Operand dst() const { return m_dst; } - StringTableIndex index() const { return m_string; } - -private: - Operand m_dst; - StringTableIndex m_string; -}; - class NewObject final : public Instruction { public: explicit NewObject(Operand dst)