mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 11:55:12 +00:00
LibJS/Bytecode: Move environment coordinate caches to Executable
Moving them out of the respective instructions allows the bytecode stream to be immutable.
This commit is contained in:
parent
5c7e5cc738
commit
2e23f00a2f
7 changed files with 31 additions and 20 deletions
|
@ -314,7 +314,7 @@ Bytecode::CodeGenerationErrorOr<void> Identifier::generate_bytecode(Bytecode::Ge
|
||||||
} else if (is_local()) {
|
} else if (is_local()) {
|
||||||
generator.emit<Bytecode::Op::GetLocal>(local_variable_index());
|
generator.emit<Bytecode::Op::GetLocal>(local_variable_index());
|
||||||
} else {
|
} else {
|
||||||
generator.emit<Bytecode::Op::GetVariable>(generator.intern_identifier(m_string));
|
generator.emit<Bytecode::Op::GetVariable>(generator.intern_identifier(m_string), generator.next_environment_variable_cache());
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -1061,7 +1061,7 @@ Bytecode::CodeGenerationErrorOr<void> FunctionDeclaration::generate_bytecode(Byt
|
||||||
if (m_is_hoisted) {
|
if (m_is_hoisted) {
|
||||||
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
Bytecode::Generator::SourceLocationScope scope(generator, *this);
|
||||||
auto index = generator.intern_identifier(name());
|
auto index = generator.intern_identifier(name());
|
||||||
generator.emit<Bytecode::Op::GetVariable>(index);
|
generator.emit<Bytecode::Op::GetVariable>(index, generator.next_environment_variable_cache());
|
||||||
generator.emit<Bytecode::Op::SetVariable>(index, Bytecode::Op::SetVariable::InitializationMode::Set, Bytecode::Op::EnvironmentMode::Var);
|
generator.emit<Bytecode::Op::SetVariable>(index, Bytecode::Op::SetVariable::InitializationMode::Set, Bytecode::Op::EnvironmentMode::Var);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
@ -1534,7 +1534,7 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode
|
||||||
// a `with` binding, so we can skip this.
|
// a `with` binding, so we can skip this.
|
||||||
auto& identifier = static_cast<Identifier const&>(*m_callee);
|
auto& identifier = static_cast<Identifier const&>(*m_callee);
|
||||||
if (!identifier.is_local() && !identifier.is_global()) {
|
if (!identifier.is_local() && !identifier.is_global()) {
|
||||||
generator.emit<Bytecode::Op::GetCalleeAndThisFromEnvironment>(generator.intern_identifier(identifier.string()), callee_reg, this_reg);
|
generator.emit<Bytecode::Op::GetCalleeAndThisFromEnvironment>(generator.intern_identifier(identifier.string()), callee_reg, this_reg, generator.next_environment_variable_cache());
|
||||||
} else {
|
} else {
|
||||||
TRY(m_callee->generate_bytecode(generator));
|
TRY(m_callee->generate_bytecode(generator));
|
||||||
generator.emit<Bytecode::Op::Store>(callee_reg);
|
generator.emit<Bytecode::Op::Store>(callee_reg);
|
||||||
|
|
|
@ -18,6 +18,7 @@ Executable::Executable(
|
||||||
NonnullRefPtr<SourceCode const> source_code,
|
NonnullRefPtr<SourceCode const> source_code,
|
||||||
size_t number_of_property_lookup_caches,
|
size_t number_of_property_lookup_caches,
|
||||||
size_t number_of_global_variable_caches,
|
size_t number_of_global_variable_caches,
|
||||||
|
size_t number_of_environment_variable_caches,
|
||||||
size_t number_of_registers,
|
size_t number_of_registers,
|
||||||
Vector<NonnullOwnPtr<BasicBlock>> basic_blocks,
|
Vector<NonnullOwnPtr<BasicBlock>> basic_blocks,
|
||||||
bool is_strict_mode)
|
bool is_strict_mode)
|
||||||
|
@ -31,6 +32,7 @@ Executable::Executable(
|
||||||
{
|
{
|
||||||
property_lookup_caches.resize(number_of_property_lookup_caches);
|
property_lookup_caches.resize(number_of_property_lookup_caches);
|
||||||
global_variable_caches.resize(number_of_global_variable_caches);
|
global_variable_caches.resize(number_of_global_variable_caches);
|
||||||
|
environment_variable_caches.resize(number_of_environment_variable_caches);
|
||||||
}
|
}
|
||||||
|
|
||||||
Executable::~Executable() = default;
|
Executable::~Executable() = default;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <LibJS/Bytecode/IdentifierTable.h>
|
#include <LibJS/Bytecode/IdentifierTable.h>
|
||||||
#include <LibJS/Bytecode/StringTable.h>
|
#include <LibJS/Bytecode/StringTable.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
|
#include <LibJS/Runtime/EnvironmentCoordinate.h>
|
||||||
|
|
||||||
namespace JS::Bytecode {
|
namespace JS::Bytecode {
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ public:
|
||||||
NonnullRefPtr<SourceCode const>,
|
NonnullRefPtr<SourceCode const>,
|
||||||
size_t number_of_property_lookup_caches,
|
size_t number_of_property_lookup_caches,
|
||||||
size_t number_of_global_variable_caches,
|
size_t number_of_global_variable_caches,
|
||||||
|
size_t number_of_environment_variable_caches,
|
||||||
size_t number_of_registers,
|
size_t number_of_registers,
|
||||||
Vector<NonnullOwnPtr<BasicBlock>>,
|
Vector<NonnullOwnPtr<BasicBlock>>,
|
||||||
bool is_strict_mode);
|
bool is_strict_mode);
|
||||||
|
@ -48,6 +50,7 @@ public:
|
||||||
DeprecatedFlyString name;
|
DeprecatedFlyString name;
|
||||||
Vector<PropertyLookupCache> property_lookup_caches;
|
Vector<PropertyLookupCache> property_lookup_caches;
|
||||||
Vector<GlobalVariableCache> global_variable_caches;
|
Vector<GlobalVariableCache> global_variable_caches;
|
||||||
|
Vector<Optional<EnvironmentCoordinate>> environment_variable_caches;
|
||||||
Vector<NonnullOwnPtr<BasicBlock>> basic_blocks;
|
Vector<NonnullOwnPtr<BasicBlock>> basic_blocks;
|
||||||
NonnullOwnPtr<StringTable> string_table;
|
NonnullOwnPtr<StringTable> string_table;
|
||||||
NonnullOwnPtr<IdentifierTable> identifier_table;
|
NonnullOwnPtr<IdentifierTable> identifier_table;
|
||||||
|
|
|
@ -63,6 +63,7 @@ CodeGenerationErrorOr<NonnullRefPtr<Executable>> Generator::generate(ASTNode con
|
||||||
node.source_code(),
|
node.source_code(),
|
||||||
generator.m_next_property_lookup_cache,
|
generator.m_next_property_lookup_cache,
|
||||||
generator.m_next_global_variable_cache,
|
generator.m_next_global_variable_cache,
|
||||||
|
generator.m_next_environment_variable_cache,
|
||||||
generator.m_next_register,
|
generator.m_next_register,
|
||||||
move(generator.m_root_basic_blocks),
|
move(generator.m_root_basic_blocks),
|
||||||
is_strict_mode));
|
is_strict_mode));
|
||||||
|
|
|
@ -206,6 +206,7 @@ public:
|
||||||
void emit_get_by_id_with_this(IdentifierTableIndex, Register);
|
void emit_get_by_id_with_this(IdentifierTableIndex, Register);
|
||||||
|
|
||||||
[[nodiscard]] size_t next_global_variable_cache() { return m_next_global_variable_cache++; }
|
[[nodiscard]] size_t next_global_variable_cache() { return m_next_global_variable_cache++; }
|
||||||
|
[[nodiscard]] size_t next_environment_variable_cache() { return m_next_environment_variable_cache++; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class JumpType {
|
enum class JumpType {
|
||||||
|
@ -236,6 +237,7 @@ private:
|
||||||
u32 m_next_block { 1 };
|
u32 m_next_block { 1 };
|
||||||
u32 m_next_property_lookup_cache { 0 };
|
u32 m_next_property_lookup_cache { 0 };
|
||||||
u32 m_next_global_variable_cache { 0 };
|
u32 m_next_global_variable_cache { 0 };
|
||||||
|
u32 m_next_environment_variable_cache { 0 };
|
||||||
FunctionKind m_enclosing_function_kind { FunctionKind::Normal };
|
FunctionKind m_enclosing_function_kind { FunctionKind::Normal };
|
||||||
Vector<LabelableScope> m_continuable_scopes;
|
Vector<LabelableScope> m_continuable_scopes;
|
||||||
Vector<LabelableScope> m_breakable_scopes;
|
Vector<LabelableScope> m_breakable_scopes;
|
||||||
|
|
|
@ -812,23 +812,24 @@ ThrowCompletionOr<void> GetVariable::execute_impl(Bytecode::Interpreter& interpr
|
||||||
{
|
{
|
||||||
auto& vm = interpreter.vm();
|
auto& vm = interpreter.vm();
|
||||||
|
|
||||||
if (m_cached_environment_coordinate.has_value()) {
|
auto& cached_environment_coordinate = interpreter.current_executable().environment_variable_caches[m_cache_index];
|
||||||
|
if (cached_environment_coordinate.has_value()) {
|
||||||
auto environment = vm.running_execution_context().lexical_environment;
|
auto environment = vm.running_execution_context().lexical_environment;
|
||||||
for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i)
|
for (size_t i = 0; i < cached_environment_coordinate->hops; ++i)
|
||||||
environment = environment->outer_environment();
|
environment = environment->outer_environment();
|
||||||
VERIFY(environment);
|
VERIFY(environment);
|
||||||
VERIFY(environment->is_declarative_environment());
|
VERIFY(environment->is_declarative_environment());
|
||||||
if (!environment->is_permanently_screwed_by_eval()) {
|
if (!environment->is_permanently_screwed_by_eval()) {
|
||||||
interpreter.accumulator() = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, m_cached_environment_coordinate.value().index, vm.in_strict_mode()));
|
interpreter.accumulator() = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, cached_environment_coordinate.value().index, vm.in_strict_mode()));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
m_cached_environment_coordinate = {};
|
cached_environment_coordinate = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const& string = interpreter.current_executable().get_identifier(m_identifier);
|
auto const& string = interpreter.current_executable().get_identifier(m_identifier);
|
||||||
auto reference = TRY(vm.resolve_binding(string));
|
auto reference = TRY(vm.resolve_binding(string));
|
||||||
if (reference.environment_coordinate().has_value())
|
if (reference.environment_coordinate().has_value())
|
||||||
m_cached_environment_coordinate = reference.environment_coordinate();
|
cached_environment_coordinate = reference.environment_coordinate();
|
||||||
interpreter.accumulator() = TRY(reference.get_value(vm));
|
interpreter.accumulator() = TRY(reference.get_value(vm));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -837,27 +838,28 @@ ThrowCompletionOr<void> GetCalleeAndThisFromEnvironment::execute_impl(Bytecode::
|
||||||
{
|
{
|
||||||
auto& vm = interpreter.vm();
|
auto& vm = interpreter.vm();
|
||||||
|
|
||||||
if (m_cached_environment_coordinate.has_value()) {
|
auto& cached_environment_coordinate = interpreter.current_executable().environment_variable_caches[m_cache_index];
|
||||||
|
if (cached_environment_coordinate.has_value()) {
|
||||||
auto environment = vm.running_execution_context().lexical_environment;
|
auto environment = vm.running_execution_context().lexical_environment;
|
||||||
for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i)
|
for (size_t i = 0; i < cached_environment_coordinate->hops; ++i)
|
||||||
environment = environment->outer_environment();
|
environment = environment->outer_environment();
|
||||||
VERIFY(environment);
|
VERIFY(environment);
|
||||||
VERIFY(environment->is_declarative_environment());
|
VERIFY(environment->is_declarative_environment());
|
||||||
if (!environment->is_permanently_screwed_by_eval()) {
|
if (!environment->is_permanently_screwed_by_eval()) {
|
||||||
interpreter.reg(m_callee_reg) = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, m_cached_environment_coordinate.value().index, vm.in_strict_mode()));
|
interpreter.reg(m_callee_reg) = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, cached_environment_coordinate.value().index, vm.in_strict_mode()));
|
||||||
Value this_value = js_undefined();
|
Value this_value = js_undefined();
|
||||||
if (auto base_object = environment->with_base_object())
|
if (auto base_object = environment->with_base_object())
|
||||||
this_value = base_object;
|
this_value = base_object;
|
||||||
interpreter.reg(m_this_reg) = this_value;
|
interpreter.reg(m_this_reg) = this_value;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
m_cached_environment_coordinate = {};
|
cached_environment_coordinate = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const& string = interpreter.current_executable().get_identifier(m_identifier);
|
auto const& string = interpreter.current_executable().get_identifier(m_identifier);
|
||||||
auto reference = TRY(vm.resolve_binding(string));
|
auto reference = TRY(vm.resolve_binding(string));
|
||||||
if (reference.environment_coordinate().has_value())
|
if (reference.environment_coordinate().has_value())
|
||||||
m_cached_environment_coordinate = reference.environment_coordinate();
|
cached_environment_coordinate = reference.environment_coordinate();
|
||||||
|
|
||||||
interpreter.reg(m_callee_reg) = TRY(reference.get_value(vm));
|
interpreter.reg(m_callee_reg) = TRY(reference.get_value(vm));
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include <LibJS/Bytecode/StringTable.h>
|
#include <LibJS/Bytecode/StringTable.h>
|
||||||
#include <LibJS/Heap/Cell.h>
|
#include <LibJS/Heap/Cell.h>
|
||||||
#include <LibJS/Runtime/Environment.h>
|
#include <LibJS/Runtime/Environment.h>
|
||||||
#include <LibJS/Runtime/EnvironmentCoordinate.h>
|
|
||||||
#include <LibJS/Runtime/Iterator.h>
|
#include <LibJS/Runtime/Iterator.h>
|
||||||
#include <LibJS/Runtime/Value.h>
|
#include <LibJS/Runtime/Value.h>
|
||||||
#include <LibJS/Runtime/ValueTraits.h>
|
#include <LibJS/Runtime/ValueTraits.h>
|
||||||
|
@ -451,11 +450,12 @@ private:
|
||||||
|
|
||||||
class GetCalleeAndThisFromEnvironment final : public Instruction {
|
class GetCalleeAndThisFromEnvironment final : public Instruction {
|
||||||
public:
|
public:
|
||||||
explicit GetCalleeAndThisFromEnvironment(IdentifierTableIndex identifier, Register callee_reg, Register this_reg)
|
explicit GetCalleeAndThisFromEnvironment(IdentifierTableIndex identifier, Register callee_reg, Register this_reg, u32 cache_index)
|
||||||
: Instruction(Type::GetCalleeAndThisFromEnvironment, sizeof(*this))
|
: Instruction(Type::GetCalleeAndThisFromEnvironment, sizeof(*this))
|
||||||
, m_identifier(identifier)
|
, m_identifier(identifier)
|
||||||
, m_callee_reg(callee_reg)
|
, m_callee_reg(callee_reg)
|
||||||
, m_this_reg(this_reg)
|
, m_this_reg(this_reg)
|
||||||
|
, m_cache_index(cache_index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,20 +463,21 @@ public:
|
||||||
DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
|
DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
|
||||||
|
|
||||||
IdentifierTableIndex identifier() const { return m_identifier; }
|
IdentifierTableIndex identifier() const { return m_identifier; }
|
||||||
|
u32 cache_index() const { return m_cache_index; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IdentifierTableIndex m_identifier;
|
IdentifierTableIndex m_identifier;
|
||||||
Register m_callee_reg;
|
Register m_callee_reg;
|
||||||
Register m_this_reg;
|
Register m_this_reg;
|
||||||
|
u32 m_cache_index { 0 };
|
||||||
Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetVariable final : public Instruction {
|
class GetVariable final : public Instruction {
|
||||||
public:
|
public:
|
||||||
explicit GetVariable(IdentifierTableIndex identifier)
|
explicit GetVariable(IdentifierTableIndex identifier, u32 cache_index)
|
||||||
: Instruction(Type::GetVariable, sizeof(*this))
|
: Instruction(Type::GetVariable, sizeof(*this))
|
||||||
, m_identifier(identifier)
|
, m_identifier(identifier)
|
||||||
|
, m_cache_index(cache_index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,11 +485,11 @@ public:
|
||||||
DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
|
DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
|
||||||
|
|
||||||
IdentifierTableIndex identifier() const { return m_identifier; }
|
IdentifierTableIndex identifier() const { return m_identifier; }
|
||||||
|
u32 cache_index() const { return m_cache_index; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IdentifierTableIndex m_identifier;
|
IdentifierTableIndex m_identifier;
|
||||||
|
u32 m_cache_index { 0 };
|
||||||
Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetGlobal final : public Instruction {
|
class GetGlobal final : public Instruction {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue