From 0f70ff9a676367178272b4919c6ec5e34667d64e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 7 May 2024 12:16:37 +0200 Subject: [PATCH] LibJS/Bytecode: Only emit ResolveThisBinding once per basic block Once executed, this instruction will always produce the same result in subsequent executions, so it's okay to cache it. Unfortunately it may throw, so we can't just hoist it to the top of every executable, since that would break observable execution order. --- Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 10 +++------- Userland/Libraries/LibJS/Bytecode/BasicBlock.h | 6 ++++++ Userland/Libraries/LibJS/Bytecode/Generator.cpp | 10 ++++++++++ Userland/Libraries/LibJS/Bytecode/Generator.h | 2 ++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index fad316e040..6d95b6940f 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -426,8 +426,7 @@ Bytecode::CodeGenerationErrorOr> AssignmentExpressio // https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation // 1. Let env be GetThisEnvironment(). // 2. Let actualThis be ? env.GetThisBinding(). - this_value = Bytecode::Operand(generator.allocate_register()); - generator.emit(*this_value); + this_value = generator.get_this(); // SuperProperty : super [ Expression ] // 3. Let propertyNameReference be ? Evaluation of Expression. @@ -1486,8 +1485,7 @@ static Bytecode::CodeGenerationErrorOr get_base_and_value_from_mem if (is(member_expression.object())) { // 1. Let env be GetThisEnvironment(). // 2. Let actualThis be ? env.GetThisBinding(). - auto this_value = Bytecode::Operand(generator.allocate_register()); - generator.emit(this_value); + auto this_value = generator.get_this(); Optional computed_property; @@ -2718,9 +2716,7 @@ Bytecode::CodeGenerationErrorOr> SpreadExpression::g Bytecode::CodeGenerationErrorOr> ThisExpression::generate_bytecode(Bytecode::Generator& generator, Optional preferred_dst) const { Bytecode::Generator::SourceLocationScope scope(generator, *this); - auto dst = choose_dst(generator, preferred_dst); - generator.emit(dst); - return dst; + return generator.get_this(preferred_dst); } static Bytecode::Operand generate_await( diff --git a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h index d33aab9f87..5f13ab95c0 100644 --- a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h +++ b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,9 @@ public: auto const& source_map() const { return m_source_map; } void add_source_map_entry(size_t bytecode_offset, SourceRecord const& source_record) { m_source_map.set(bytecode_offset, source_record); } + auto const& this_() const { return m_this; } + void set_this(Operand operand) { m_this = operand; } + private: explicit BasicBlock(u32 index, String name); @@ -62,6 +66,8 @@ private: bool m_terminated { false }; HashMap m_source_map; + + Optional m_this; }; } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 278e39c580..aaa41c3504 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -798,4 +798,14 @@ void Generator::set_local_initialized(u32 local_index) m_initialized_locals.set(local_index); } +Operand Generator::get_this(Optional preferred_dst) +{ + if (m_current_basic_block->this_().has_value()) + return m_current_basic_block->this_().value(); + auto dst = preferred_dst.has_value() ? preferred_dst.value() : Operand(allocate_register()); + emit(dst); + m_current_basic_block->set_this(dst); + return dst; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index b3665bf2fb..28eefc1c02 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -257,6 +257,8 @@ public: m_boundaries.take_last(); } + [[nodiscard]] Operand get_this(Optional preferred_dst = {}); + void emit_get_by_id(Operand dst, Operand base, IdentifierTableIndex property_identifier, Optional base_identifier = {}); void emit_get_by_id_with_this(Operand dst, Operand base, IdentifierTableIndex, Operand this_value);