mirror of
https://github.com/RGBCube/serenity
synced 2025-05-19 16:35:06 +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::CodeGenerationErrorOr<Optional<Bytecode::Operand>> StringLiteral::generate_bytecode(Bytecode::Generator& generator, [[maybe_unused]] Optional<Bytecode::Operand> preferred_dst) const
|
||||||
{
|
{
|
||||||
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
||||||
auto dst = choose_dst(generator, preferred_dst);
|
return generator.add_constant(PrimitiveString::create(generator.vm(), m_value), Bytecode::Generator::DeduplicateConstant::No);
|
||||||
generator.emit<Bytecode::Op::NewString>(dst, generator.intern_string(m_value));
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> RegExpLiteral::generate_bytecode(Bytecode::Generator& generator, Optional<Bytecode::Operand> preferred_dst) const
|
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();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Bytecode::StringTableIndex name_index;
|
|
||||||
|
|
||||||
auto value = Bytecode::Operand(generator.allocate_register());
|
auto value = Bytecode::Operand(generator.allocate_register());
|
||||||
|
|
||||||
if (name.has<NonnullRefPtr<Identifier const>>()) {
|
if (name.has<NonnullRefPtr<Identifier const>>()) {
|
||||||
auto identifier = name.get<NonnullRefPtr<Identifier const>>()->string();
|
auto const& identifier = name.get<NonnullRefPtr<Identifier const>>()->string();
|
||||||
name_index = generator.intern_string(identifier);
|
|
||||||
|
|
||||||
if (has_rest) {
|
if (has_rest) {
|
||||||
auto excluded_name = Bytecode::Operand(generator.allocate_register());
|
excluded_property_names.append(generator.add_constant(PrimitiveString::create(generator.vm(), identifier), Bytecode::Generator::DeduplicateConstant::No));
|
||||||
excluded_property_names.append(excluded_name);
|
|
||||||
generator.emit<Bytecode::Op::NewString>(excluded_name, name_index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generator.emit_get_by_id(value, object, generator.intern_identifier(identifier));
|
generator.emit_get_by_id(value, object, generator.intern_identifier(identifier));
|
||||||
} else {
|
} else {
|
||||||
auto expression = name.get<NonnullRefPtr<Expression const>>();
|
auto expression = name.get<NonnullRefPtr<Expression const>>();
|
||||||
|
|
|
@ -50,4 +50,11 @@ void Executable::dump() const
|
||||||
warnln("");
|
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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -75,6 +75,9 @@ public:
|
||||||
DeprecatedFlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
|
DeprecatedFlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
|
||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void visit_edges(Visitor&) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,18 @@
|
||||||
|
|
||||||
namespace JS::Bytecode {
|
namespace JS::Bytecode {
|
||||||
|
|
||||||
Generator::Generator()
|
Generator::Generator(VM& vm)
|
||||||
: m_string_table(make<StringTable>())
|
: m_vm(vm)
|
||||||
|
, m_string_table(make<StringTable>())
|
||||||
, m_identifier_table(make<IdentifierTable>())
|
, m_identifier_table(make<IdentifierTable>())
|
||||||
, m_regex_table(make<RegexTable>())
|
, 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)
|
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) {
|
for (auto const& parameter : parameters) {
|
||||||
if (auto const* identifier = parameter.binding.get_pointer<NonnullRefPtr<Identifier const>>();
|
if (auto const* identifier = parameter.binding.get_pointer<NonnullRefPtr<Identifier const>>();
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace JS::Bytecode {
|
||||||
|
|
||||||
class Generator {
|
class Generator {
|
||||||
public:
|
public:
|
||||||
|
VM& vm() { return m_vm; }
|
||||||
|
|
||||||
enum class SurroundingScopeKind {
|
enum class SurroundingScopeKind {
|
||||||
Global,
|
Global,
|
||||||
Function,
|
Function,
|
||||||
|
@ -261,6 +263,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
VM& m_vm;
|
||||||
|
|
||||||
enum class JumpType {
|
enum class JumpType {
|
||||||
Continue,
|
Continue,
|
||||||
Break,
|
Break,
|
||||||
|
@ -268,7 +272,7 @@ private:
|
||||||
void generate_scoped_jump(JumpType);
|
void generate_scoped_jump(JumpType);
|
||||||
void generate_labelled_jump(JumpType, DeprecatedFlyString const& label);
|
void generate_labelled_jump(JumpType, DeprecatedFlyString const& label);
|
||||||
|
|
||||||
Generator();
|
explicit Generator(VM&);
|
||||||
~Generator() = default;
|
~Generator() = default;
|
||||||
|
|
||||||
void grow(size_t);
|
void grow(size_t);
|
||||||
|
@ -286,7 +290,7 @@ private:
|
||||||
NonnullOwnPtr<StringTable> m_string_table;
|
NonnullOwnPtr<StringTable> m_string_table;
|
||||||
NonnullOwnPtr<IdentifierTable> m_identifier_table;
|
NonnullOwnPtr<IdentifierTable> m_identifier_table;
|
||||||
NonnullOwnPtr<RegexTable> m_regex_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_register { Register::reserved_register_count };
|
||||||
u32 m_next_block { 1 };
|
u32 m_next_block { 1 };
|
||||||
|
|
|
@ -88,7 +88,6 @@
|
||||||
O(NewObject) \
|
O(NewObject) \
|
||||||
O(NewPrimitiveArray) \
|
O(NewPrimitiveArray) \
|
||||||
O(NewRegExp) \
|
O(NewRegExp) \
|
||||||
O(NewString) \
|
|
||||||
O(NewTypeError) \
|
O(NewTypeError) \
|
||||||
O(Not) \
|
O(Not) \
|
||||||
O(PostfixDecrement) \
|
O(PostfixDecrement) \
|
||||||
|
|
|
@ -63,6 +63,8 @@ static ByteString format_operand(StringView name, Operand operand, Bytecode::Exe
|
||||||
builder.appendff("Int32({})", value.as_i32());
|
builder.appendff("Int32({})", value.as_i32());
|
||||||
else if (value.is_double())
|
else if (value.is_double())
|
||||||
builder.appendff("Double({})", value.as_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())
|
else if (value.is_undefined())
|
||||||
builder.append("Undefined"sv);
|
builder.append("Undefined"sv);
|
||||||
else if (value.is_null())
|
else if (value.is_null())
|
||||||
|
@ -899,12 +901,6 @@ ThrowCompletionOr<void> IteratorToArray::execute_impl(Bytecode::Interpreter& int
|
||||||
return {};
|
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
|
ThrowCompletionOr<void> NewObject::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
auto& vm = interpreter.vm();
|
auto& vm = interpreter.vm();
|
||||||
|
@ -1656,13 +1652,6 @@ ByteString IteratorToArray::to_byte_string_impl(Bytecode::Executable const& exec
|
||||||
format_operand("iterator"sv, iterator(), executable));
|
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
|
ByteString NewObject::to_byte_string_impl(Bytecode::Executable const& executable) const
|
||||||
{
|
{
|
||||||
return ByteString::formatted("NewObject {}", format_operand("dst"sv, dst(), executable));
|
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)
|
JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
|
||||||
#undef 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 {
|
class NewObject final : public Instruction {
|
||||||
public:
|
public:
|
||||||
explicit NewObject(Operand dst)
|
explicit NewObject(Operand dst)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue