Parcourir la source

LibJS/JIT: Support the EnterObjectEnvironment bytecode instruction

We can now use `with` statements in jitted code. :^)
Andreas Kling il y a 1 an
Parent
commit
cb7169d73f

+ 9 - 5
Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -444,6 +444,13 @@ void Interpreter::catch_exception()
     vm().running_execution_context().lexical_environment = context.lexical_environment;
 }
 
+void Interpreter::enter_object_environment(Object& object)
+{
+    auto& old_environment = vm().running_execution_context().lexical_environment;
+    saved_lexical_environment_stack().append(old_environment);
+    vm().running_execution_context().lexical_environment = new_object_environment(object, true, old_environment);
+}
+
 ThrowCompletionOr<NonnullRefPtr<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, DeprecatedFlyString const& name)
 {
     auto executable_result = Bytecode::Generator::generate(node, kind);
@@ -743,11 +750,8 @@ ThrowCompletionOr<void> CreateLexicalEnvironment::execute_impl(Bytecode::Interpr
 
 ThrowCompletionOr<void> EnterObjectEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
 {
-    auto& vm = interpreter.vm();
-    auto& old_environment = vm.running_execution_context().lexical_environment;
-    interpreter.saved_lexical_environment_stack().append(old_environment);
-    auto object = TRY(interpreter.accumulator().to_object(vm));
-    vm.running_execution_context().lexical_environment = new_object_environment(object, true, old_environment);
+    auto object = TRY(interpreter.accumulator().to_object(interpreter.vm()));
+    interpreter.enter_object_environment(*object);
     return {};
 }
 

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

@@ -76,6 +76,8 @@ public:
     void leave_unwind_context();
     void catch_exception();
 
+    void enter_object_environment(Object&);
+
     Executable& current_executable() { return *m_current_executable; }
     Executable const& current_executable() const { return *m_current_executable; }
     BasicBlock const& current_block() const { return *m_current_block; }

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

@@ -1988,6 +1988,20 @@ void Compiler::compile_leave_lexical_environment(Bytecode::Op::LeaveLexicalEnvir
     native_call((void*)cxx_leave_lexical_environment);
 }
 
+static Value cxx_enter_object_environment(VM& vm, Value value)
+{
+    auto object = TRY_OR_SET_EXCEPTION(value.to_object(vm));
+    vm.bytecode_interpreter().enter_object_environment(*object);
+    return {};
+}
+
+void Compiler::compile_enter_object_environment(Bytecode::Op::EnterObjectEnvironment const&)
+{
+    load_accumulator(ARG1);
+    native_call((void*)cxx_enter_object_environment);
+    check_exception();
+}
+
 static Value cxx_concat_string(VM& vm, Value lhs, Value rhs)
 {
     auto string = TRY_OR_SET_EXCEPTION(rhs.to_primitive_string(vm));

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

@@ -86,6 +86,7 @@ private:
         O(Catch, catch)                                                          \
         O(CreateLexicalEnvironment, create_lexical_environment)                  \
         O(LeaveLexicalEnvironment, leave_lexical_environment)                    \
+        O(EnterObjectEnvironment, enter_object_environment)                      \
         O(ToNumeric, to_numeric)                                                 \
         O(ResolveThisBinding, resolve_this_binding)                              \
         O(Return, return)                                                        \