Skip to content

Commit

Permalink
LibJS/Bytecode: Add environment coordinate caching to SetVariable
Browse files Browse the repository at this point in the history
This means that SetVariable instructions will now remember which
(relative) environment contains the targeted binding, letting it bypass
the full binding resolution machinery on subsequent accesses.
  • Loading branch information
awesomekling committed May 13, 2024
1 parent d79438a commit 9c08ac7
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
19 changes: 19 additions & 0 deletions Userland/Libraries/LibJS/Bytecode/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,25 @@ ThrowCompletionOr<void> CreateArguments::execute_impl(Bytecode::Interpreter& int
ThrowCompletionOr<void> SetVariable::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& vm = interpreter.vm();

if (m_cache.is_valid()) {
auto* environment = m_mode == EnvironmentMode::Lexical
? interpreter.running_execution_context().lexical_environment.ptr()
: interpreter.running_execution_context().variable_environment.ptr();
for (size_t i = 0; i < m_cache.hops; ++i)
environment = environment->outer_environment();
if (!environment->is_permanently_screwed_by_eval()) {
auto value = interpreter.get(src());
if (m_initialization_mode == InitializationMode::Initialize) {
TRY(static_cast<DeclarativeEnvironment&>(*environment).initialize_binding_direct(vm, m_cache.index, value, Environment::InitializeBindingHint::Normal));
return {};
}
TRY(static_cast<DeclarativeEnvironment&>(*environment).set_mutable_binding_direct(vm, m_cache.index, value, vm.in_strict_mode()));
return {};
}
m_cache = {};
}

auto const& name = interpreter.current_executable().get_identifier(m_identifier);
TRY(set_variable(vm,
name,
Expand Down
9 changes: 6 additions & 3 deletions Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,12 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(VM&, De
// 4.1.1.1.1 InitializeBinding ( N, V, hint ), https://tc39.es/proposal-explicit-resource-management/#sec-declarative-environment-records
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(VM& vm, DeprecatedFlyString const& name, Value value, Environment::InitializeBindingHint hint)
{
auto binding_and_index = find_binding_and_index(name);
VERIFY(binding_and_index.has_value());
auto& binding = binding_and_index->binding();
return initialize_binding_direct(vm, find_binding_and_index(name)->index().value(), value, hint);
}

ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding_direct(VM& vm, size_t index, Value value, Environment::InitializeBindingHint hint)
{
auto& binding = m_bindings.at(index);

// 1. Assert: envRec must have an uninitialized binding for N.
VERIFY(binding.initialized == false);
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class DeclarativeEnvironment : public Environment {
return names;
}

ThrowCompletionOr<void> initialize_binding_direct(VM&, size_t index, Value, InitializeBindingHint);
ThrowCompletionOr<void> set_mutable_binding_direct(VM&, size_t index, Value, bool strict);
ThrowCompletionOr<Value> get_binding_value_direct(VM&, size_t index) const;

Expand Down

0 comments on commit 9c08ac7

Please sign in to comment.