mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:24:57 +00:00
LibJS/Bytecode: Make primitive strings be constants
Instead of emitting a NewString instruction to construct a primitive string from a parsed literal, we now instantiate the PrimitiveString on the heap during codegen.
This commit is contained in:
parent
fd694e8672
commit
46d209c55b
8 changed files with 27 additions and 52 deletions
|
@ -302,9 +302,7 @@ Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> BigIntLiteral::gene
|
|||
Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> StringLiteral::generate_bytecode(Bytecode::Generator& generator, [[maybe_unused]] Optional<Bytecode::Operand> preferred_dst) const
|
||||
{
|
||||
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
||||
auto dst = choose_dst(generator, preferred_dst);
|
||||
generator.emit<Bytecode::Op::NewString>(dst, generator.intern_string(m_value));
|
||||
return dst;
|
||||
return generator.add_constant(PrimitiveString::create(generator.vm(), m_value), Bytecode::Generator::DeduplicateConstant::No);
|
||||
}
|
||||
|
||||
Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> RegExpLiteral::generate_bytecode(Bytecode::Generator& generator, Optional<Bytecode::Operand> preferred_dst) const
|
||||
|
@ -1165,20 +1163,13 @@ static Bytecode::CodeGenerationErrorOr<void> generate_object_binding_pattern_byt
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
Bytecode::StringTableIndex name_index;
|
||||
|
||||
auto value = Bytecode::Operand(generator.allocate_register());
|
||||
|
||||
if (name.has<NonnullRefPtr<Identifier const>>()) {
|
||||
auto identifier = name.get<NonnullRefPtr<Identifier const>>()->string();
|
||||
name_index = generator.intern_string(identifier);
|
||||
|
||||
auto const& identifier = name.get<NonnullRefPtr<Identifier const>>()->string();
|
||||
if (has_rest) {
|
||||
auto excluded_name = Bytecode::Operand(generator.allocate_register());
|
||||
excluded_property_names.append(excluded_name);
|
||||
generator.emit<Bytecode::Op::NewString>(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<NonnullRefPtr<Expression const>>();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021-2024, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,16 +15,18 @@
|
|||
|
||||
namespace JS::Bytecode {
|
||||
|
||||
Generator::Generator()
|
||||
: m_string_table(make<StringTable>())
|
||||
Generator::Generator(VM& vm)
|
||||
: m_vm(vm)
|
||||
, m_string_table(make<StringTable>())
|
||||
, m_identifier_table(make<IdentifierTable>())
|
||||
, m_regex_table(make<RegexTable>())
|
||||
, m_constants(vm.heap())
|
||||
{
|
||||
}
|
||||
|
||||
CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate(VM& vm, ASTNode const& node, ReadonlySpan<FunctionParameter> parameters, FunctionKind enclosing_function_kind)
|
||||
{
|
||||
Generator generator;
|
||||
Generator generator(vm);
|
||||
|
||||
for (auto const& parameter : parameters) {
|
||||
if (auto const* identifier = parameter.binding.get_pointer<NonnullRefPtr<Identifier const>>();
|
||||
|
|
|
@ -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<StringTable> m_string_table;
|
||||
NonnullOwnPtr<IdentifierTable> m_identifier_table;
|
||||
NonnullOwnPtr<RegexTable> m_regex_table;
|
||||
Vector<Value> m_constants;
|
||||
MarkedVector<Value> m_constants;
|
||||
|
||||
u32 m_next_register { Register::reserved_register_count };
|
||||
u32 m_next_block { 1 };
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
O(NewObject) \
|
||||
O(NewPrimitiveArray) \
|
||||
O(NewRegExp) \
|
||||
O(NewString) \
|
||||
O(NewTypeError) \
|
||||
O(Not) \
|
||||
O(PostfixDecrement) \
|
||||
|
|
|
@ -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<void> IteratorToArray::execute_impl(Bytecode::Interpreter& int
|
|||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> NewString::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
interpreter.set(dst(), PrimitiveString::create(interpreter.vm(), interpreter.current_executable().get_string(m_string)));
|
||||
return {};
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> 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));
|
||||
|
|
|
@ -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<void> 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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue