Selaa lähdekoodia

LibJS: Implement bytecode generation for WithStatement

Ali Mohammad Pur 3 vuotta sitten
vanhempi
commit
2000251333

+ 1 - 0
Userland/Libraries/LibJS/AST.h

@@ -844,6 +844,7 @@ public:
 
 
     virtual Completion execute(Interpreter&, GlobalObject&) const override;
     virtual Completion execute(Interpreter&, GlobalObject&) const override;
     virtual void dump(int indent) const override;
     virtual void dump(int indent) const override;
+    virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&) const override;
 
 
 private:
 private:
     NonnullRefPtr<Expression> m_object;
     NonnullRefPtr<Expression> m_object;

+ 9 - 0
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -1618,4 +1618,13 @@ Bytecode::CodeGenerationErrorOr<void> AwaitExpression::generate_bytecode(Bytecod
     return {};
     return {};
 }
 }
 
 
+Bytecode::CodeGenerationErrorOr<void> WithStatement::generate_bytecode(Bytecode::Generator& generator) const
+{
+    TRY(m_object->generate_bytecode(generator));
+    generator.emit<Bytecode::Op::EnterObjectEnvironment>();
+    TRY(m_body->generate_bytecode(generator));
+    generator.emit<Bytecode::Op::LeaveEnvironment>(Bytecode::Op::EnvironmentMode::Lexical);
+    return {};
+}
+
 }
 }

+ 1 - 0
Userland/Libraries/LibJS/Bytecode/Instruction.h

@@ -25,6 +25,7 @@
     O(Decrement)                     \
     O(Decrement)                     \
     O(Div)                           \
     O(Div)                           \
     O(EnterUnwindContext)            \
     O(EnterUnwindContext)            \
+    O(EnterObjectEnvironment)        \
     O(Exp)                           \
     O(Exp)                           \
     O(FinishUnwind)                  \
     O(FinishUnwind)                  \
     O(GetById)                       \
     O(GetById)                       \

+ 15 - 0
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -18,6 +18,7 @@
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/Iterator.h>
 #include <LibJS/Runtime/Iterator.h>
 #include <LibJS/Runtime/IteratorOperations.h>
 #include <LibJS/Runtime/IteratorOperations.h>
+#include <LibJS/Runtime/ObjectEnvironment.h>
 #include <LibJS/Runtime/RegExpObject.h>
 #include <LibJS/Runtime/RegExpObject.h>
 #include <LibJS/Runtime/Value.h>
 #include <LibJS/Runtime/Value.h>
 
 
@@ -274,6 +275,15 @@ ThrowCompletionOr<void> CreateEnvironment::execute_impl(Bytecode::Interpreter& i
     return {};
     return {};
 }
 }
 
 
+ThrowCompletionOr<void> EnterObjectEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
+{
+    auto& old_environment = interpreter.vm().running_execution_context().lexical_environment;
+    interpreter.saved_lexical_environment_stack().append(old_environment);
+    auto object = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
+    interpreter.vm().running_execution_context().lexical_environment = new_object_environment(*object, true, old_environment);
+    return {};
+}
+
 ThrowCompletionOr<void> CreateVariable::execute_impl(Bytecode::Interpreter& interpreter) const
 ThrowCompletionOr<void> CreateVariable::execute_impl(Bytecode::Interpreter& interpreter) const
 {
 {
     auto& vm = interpreter.vm();
     auto& vm = interpreter.vm();
@@ -695,6 +705,11 @@ String CreateVariable::to_string_impl(Bytecode::Executable const& executable) co
     return String::formatted("CreateVariable env:{} immutable:{} {} ({})", mode_string, m_is_immutable, m_identifier, executable.identifier_table->get(m_identifier));
     return String::formatted("CreateVariable env:{} immutable:{} {} ({})", mode_string, m_is_immutable, m_identifier, executable.identifier_table->get(m_identifier));
 }
 }
 
 
+String EnterObjectEnvironment::to_string_impl(const Executable&) const
+{
+    return String::formatted("EnterObjectEnvironment");
+}
+
 String SetVariable::to_string_impl(Bytecode::Executable const& executable) const
 String SetVariable::to_string_impl(Bytecode::Executable const& executable) const
 {
 {
     auto initialization_mode_name = m_initialization_mode == InitializationMode ::Initialize ? "Initialize"
     auto initialization_mode_name = m_initialization_mode == InitializationMode ::Initialize ? "Initialize"

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

@@ -303,6 +303,18 @@ private:
     EnvironmentMode m_mode { EnvironmentMode::Lexical };
     EnvironmentMode m_mode { EnvironmentMode::Lexical };
 };
 };
 
 
+class EnterObjectEnvironment final : public Instruction {
+public:
+    explicit EnterObjectEnvironment()
+        : Instruction(Type::EnterObjectEnvironment)
+    {
+    }
+
+    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
+    String to_string_impl(Bytecode::Executable const&) const;
+    void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
+};
+
 class CreateVariable final : public Instruction {
 class CreateVariable final : public Instruction {
 public:
 public:
     explicit CreateVariable(IdentifierTableIndex identifier, EnvironmentMode mode, bool is_immutable)
     explicit CreateVariable(IdentifierTableIndex identifier, EnvironmentMode mode, bool is_immutable)