Sfoglia il codice sorgente

LibJS/JIT: Compile the GetCalleeAndThisFromEnvironment instruction

Andreas Kling 1 anno fa
parent
commit
935d67cfcf

+ 48 - 0
Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp

@@ -327,4 +327,52 @@ ThrowCompletionOr<Value> get_variable(Bytecode::Interpreter& interpreter, Deprec
     return TRY(reference.get_value(vm));
 }
 
+ThrowCompletionOr<CalleeAndThis> get_callee_and_this_from_environment(Bytecode::Interpreter& interpreter, DeprecatedFlyString const& name, u32 cache_index)
+{
+    auto& vm = interpreter.vm();
+
+    Value callee = js_undefined();
+    Value this_value = js_undefined();
+
+    auto& cached_environment_coordinate = interpreter.current_executable().environment_variable_caches[cache_index];
+    if (cached_environment_coordinate.has_value()) {
+        auto environment = vm.running_execution_context().lexical_environment;
+        for (size_t i = 0; i < cached_environment_coordinate->hops; ++i)
+            environment = environment->outer_environment();
+        VERIFY(environment);
+        VERIFY(environment->is_declarative_environment());
+        if (!environment->is_permanently_screwed_by_eval()) {
+            callee = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, cached_environment_coordinate.value().index, vm.in_strict_mode()));
+            this_value = js_undefined();
+            if (auto base_object = environment->with_base_object())
+                this_value = base_object;
+            return CalleeAndThis {
+                .callee = callee,
+                .this_value = this_value,
+            };
+        }
+        cached_environment_coordinate = {};
+    }
+
+    auto reference = TRY(vm.resolve_binding(name));
+    if (reference.environment_coordinate().has_value())
+        cached_environment_coordinate = reference.environment_coordinate();
+
+    callee = TRY(reference.get_value(vm));
+
+    if (reference.is_property_reference()) {
+        this_value = reference.get_this_value();
+    } else {
+        if (reference.is_environment_reference()) {
+            if (auto base_object = reference.base_environment().with_base_object(); base_object != nullptr)
+                this_value = base_object;
+        }
+    }
+
+    return CalleeAndThis {
+        .callee = callee,
+        .this_value = this_value,
+    };
+}
+
 }

+ 6 - 0
Userland/Libraries/LibJS/Bytecode/CommonImplementations.h

@@ -25,4 +25,10 @@ Value new_function(VM&, FunctionExpression const&, Optional<IdentifierTableIndex
 ThrowCompletionOr<void> put_by_value(VM&, Value base, Value property_key_value, Value value, Op::PropertyKind);
 ThrowCompletionOr<Value> get_variable(Bytecode::Interpreter&, DeprecatedFlyString const& name, u32 cache_index);
 
+struct CalleeAndThis {
+    Value callee;
+    Value this_value;
+};
+ThrowCompletionOr<CalleeAndThis> get_callee_and_this_from_environment(Bytecode::Interpreter&, DeprecatedFlyString const& name, u32 cache_index);
+
 }

+ 3 - 38
Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -786,44 +786,9 @@ ThrowCompletionOr<void> GetVariable::execute_impl(Bytecode::Interpreter& interpr
 
 ThrowCompletionOr<void> GetCalleeAndThisFromEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
 {
-    auto& vm = interpreter.vm();
-
-    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;
-        for (size_t i = 0; i < cached_environment_coordinate->hops; ++i)
-            environment = environment->outer_environment();
-        VERIFY(environment);
-        VERIFY(environment->is_declarative_environment());
-        if (!environment->is_permanently_screwed_by_eval()) {
-            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();
-            if (auto base_object = environment->with_base_object())
-                this_value = base_object;
-            interpreter.reg(m_this_reg) = this_value;
-            return {};
-        }
-        cached_environment_coordinate = {};
-    }
-
-    auto const& string = interpreter.current_executable().get_identifier(m_identifier);
-    auto reference = TRY(vm.resolve_binding(string));
-    if (reference.environment_coordinate().has_value())
-        cached_environment_coordinate = reference.environment_coordinate();
-
-    interpreter.reg(m_callee_reg) = TRY(reference.get_value(vm));
-
-    Value this_value = js_undefined();
-    if (reference.is_property_reference()) {
-        this_value = reference.get_this_value();
-    } else {
-        if (reference.is_environment_reference()) {
-            if (auto base_object = reference.base_environment().with_base_object(); base_object != nullptr)
-                this_value = base_object;
-        }
-    }
-    interpreter.reg(m_this_reg) = this_value;
-
+    auto callee_and_this = TRY(get_callee_and_this_from_environment(interpreter, interpreter.current_executable().get_identifier(m_identifier), m_cache_index));
+    interpreter.reg(m_callee_reg) = callee_and_this.callee;
+    interpreter.reg(m_this_reg) = callee_and_this.this_value;
     return {};
 }
 

+ 2 - 0
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -470,6 +470,8 @@ public:
 
     IdentifierTableIndex identifier() const { return m_identifier; }
     u32 cache_index() const { return m_cache_index; }
+    Register callee() const { return m_callee_reg; }
+    Register this_() const { return m_this_reg; }
 
 private:
     IdentifierTableIndex m_identifier;

+ 34 - 0
Userland/Libraries/LibJS/JIT/Compiler.cpp

@@ -674,6 +674,37 @@ void Compiler::compile_get_variable(Bytecode::Op::GetVariable const& op)
     check_exception();
 }
 
+static Value cxx_get_callee_and_this_from_environment(VM& vm, DeprecatedFlyString const& name, u32 cache_index, Bytecode::Register callee_reg, Bytecode::Register this_reg)
+{
+    auto& bytecode_interpreter = vm.bytecode_interpreter();
+    auto callee_and_this = TRY_OR_SET_EXCEPTION(Bytecode::get_callee_and_this_from_environment(
+        bytecode_interpreter,
+        name,
+        cache_index));
+
+    bytecode_interpreter.reg(callee_reg) = callee_and_this.callee;
+    bytecode_interpreter.reg(this_reg) = callee_and_this.this_value;
+    return {};
+}
+
+void Compiler::compile_get_callee_and_this_from_environment(Bytecode::Op::GetCalleeAndThisFromEnvironment const& op)
+{
+    m_assembler.mov(
+        Assembler::Operand::Register(ARG1),
+        Assembler::Operand::Imm64(bit_cast<u64>(&m_bytecode_executable.get_identifier(op.identifier()))));
+    m_assembler.mov(
+        Assembler::Operand::Register(ARG2),
+        Assembler::Operand::Imm64(op.cache_index()));
+    m_assembler.mov(
+        Assembler::Operand::Register(ARG3),
+        Assembler::Operand::Imm64(op.callee().index()));
+    m_assembler.mov(
+        Assembler::Operand::Register(ARG4),
+        Assembler::Operand::Imm64(op.this_().index()));
+    m_assembler.native_call((void*)cxx_get_callee_and_this_from_environment);
+    check_exception();
+}
+
 static Value cxx_to_numeric(VM& vm, Value value)
 {
     return TRY_OR_SET_EXCEPTION(value.to_numeric(vm));
@@ -924,6 +955,9 @@ OwnPtr<NativeExecutable> Compiler::compile(Bytecode::Executable& bytecode_execut
             case Bytecode::Instruction::Type::GetVariable:
                 compiler.compile_get_variable(static_cast<Bytecode::Op::GetVariable const&>(op));
                 break;
+            case Bytecode::Instruction::Type::GetCalleeAndThisFromEnvironment:
+                compiler.compile_get_callee_and_this_from_environment(static_cast<Bytecode::Op::GetCalleeAndThisFromEnvironment const&>(op));
+                break;
             case Bytecode::Instruction::Type::PutById:
                 compiler.compile_put_by_id(static_cast<Bytecode::Op::PutById const&>(op));
                 break;

+ 1 - 0
Userland/Libraries/LibJS/JIT/Compiler.h

@@ -96,6 +96,7 @@ private:
     void compile_get_by_value(Bytecode::Op::GetByValue const&);
     void compile_get_global(Bytecode::Op::GetGlobal const&);
     void compile_get_variable(Bytecode::Op::GetVariable const&);
+    void compile_get_callee_and_this_from_environment(Bytecode::Op::GetCalleeAndThisFromEnvironment const&);
 
     void compile_put_by_id(Bytecode::Op::PutById const&);
     void compile_put_by_value(Bytecode::Op::PutByValue const&);