Skip to content

Commit 2bdc69c

Browse files
kalenikaliaksandrawesomekling
authored andcommitted
LibJS: Add caching of this value in ResolveThisBinding instruction
Because "this" value cannot be changed during function execution it is safe to compute it once and then use for future access. This optimization makes ai-astar.js run 8% faster.
1 parent bbd80d2 commit 2bdc69c

File tree

3 files changed

+12
-2
lines changed

3 files changed

+12
-2
lines changed

Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Realm& realm, Execu
208208
else
209209
push_call_frame(make<CallFrame>(), executable.number_of_registers);
210210

211+
TemporaryChange restore_this_value { m_this_value, {} };
212+
211213
for (;;) {
212214
Bytecode::InstructionStreamIterator pc(m_current_block->instruction_stream());
213215
TemporaryChange temp_change { m_pc, &pc };

Userland/Libraries/LibJS/Bytecode/Interpreter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class Interpreter {
9595

9696
VM::InterpreterExecutionScope ast_interpreter_scope(Realm&);
9797

98+
Optional<Value>& this_value() { return m_this_value; }
99+
98100
void visit_edges(Cell::Visitor&);
99101

100102
private:
@@ -119,6 +121,7 @@ class Interpreter {
119121
Span<Value> m_current_call_frame;
120122
Optional<BasicBlock const*> m_pending_jump;
121123
BasicBlock const* m_scheduled_jump { nullptr };
124+
Optional<Value> m_this_value;
122125
Optional<Value> m_return_value;
123126
Optional<Value> m_saved_exception;
124127
Executable* m_current_executable { nullptr };

Userland/Libraries/LibJS/Bytecode/Op.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,8 +732,13 @@ ThrowCompletionOr<void> Jump::execute_impl(Bytecode::Interpreter& interpreter) c
732732

733733
ThrowCompletionOr<void> ResolveThisBinding::execute_impl(Bytecode::Interpreter& interpreter) const
734734
{
735-
auto& vm = interpreter.vm();
736-
interpreter.accumulator() = TRY(vm.resolve_this_binding());
735+
if (!interpreter.this_value().has_value()) {
736+
// OPTIMIZATION: Because the value of 'this' cannot be reassigned during a function execution, it's
737+
// resolved once and then saved for subsequent use.
738+
auto& vm = interpreter.vm();
739+
interpreter.this_value() = TRY(vm.resolve_this_binding());
740+
}
741+
interpreter.accumulator() = interpreter.this_value().value();
737742
return {};
738743
}
739744

0 commit comments

Comments
 (0)