diff options
author | Andreas Kling <kling@serenityos.org> | 2021-10-24 15:36:24 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-24 17:18:07 +0200 |
commit | 715e7fada8ed00a7680bb8f4ed65afd3026d3d59 (patch) | |
tree | 16128a8cac827905f38d2f20f2bf8589f9525a59 /Userland/Libraries | |
parent | da9821200113dc1edd59ffb5531c573e963a2ae4 (diff) | |
download | serenity-715e7fada8ed00a7680bb8f4ed65afd3026d3d59.zip |
LibJS: Add the "fast non-local access" optimization to the bytecode VM
The GetVariable bytecode op now caches environment coordinates for fast
cross-scope variable lookup.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.cpp | 24 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 3 |
2 files changed, 24 insertions, 3 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 143cf9780f..8dff0a17bc 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -238,9 +238,27 @@ void ConcatString::execute_impl(Bytecode::Interpreter& interpreter) const void GetVariable::execute_impl(Bytecode::Interpreter& interpreter) const { - auto& vm = interpreter.vm(); - auto reference = vm.resolve_binding(interpreter.current_executable().get_identifier(m_identifier)); - if (vm.exception()) + auto reference = [&] { + auto const& string = interpreter.current_executable().get_identifier(m_identifier); + if (m_cached_environment_coordinate.has_value()) { + auto* environment = interpreter.vm().running_execution_context().lexical_environment; + for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i) + environment = environment->outer_environment(); + VERIFY(environment); + VERIFY(environment->is_declarative_environment()); + if (!environment->is_permanently_screwed_by_eval()) { + return Reference { *environment, string, interpreter.vm().in_strict_mode(), m_cached_environment_coordinate }; + } + m_cached_environment_coordinate = {}; + } + + auto reference = interpreter.vm().resolve_binding(string); + if (reference.environment_coordinate().has_value()) + m_cached_environment_coordinate = reference.environment_coordinate(); + return reference; + }(); + + if (interpreter.vm().exception()) return; interpreter.accumulator() = reference.get_value(interpreter.global_object()); diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 697da20715..7043f6617c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -16,6 +16,7 @@ #include <LibJS/Bytecode/StringTable.h> #include <LibJS/Heap/Cell.h> #include <LibJS/Runtime/Environment.h> +#include <LibJS/Runtime/EnvironmentCoordinate.h> #include <LibJS/Runtime/Value.h> namespace JS::Bytecode::Op { @@ -310,6 +311,8 @@ public: private: IdentifierTableIndex m_identifier; + + Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate; }; class GetById final : public Instruction { |