summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-10-24 14:43:00 +0200
committerAndreas Kling <kling@serenityos.org>2021-10-24 17:18:06 +0200
commit3117182c2ed010417d528421d727db4e97c2b2ce (patch)
treea76fe12ac959c0936ea1ff1fcbc51241d261b13d
parent7c7bc4f44a97e11243e82b8dc733fb47e5ed34c4 (diff)
downloadserenity-3117182c2ed010417d528421d727db4e97c2b2ce.zip
LibJS: Implement 'this' in the bytecode VM
ThisExpression now emits a "ResolveThisBinding" bytecode op, which simply loads the VM's current 'this' binding into the accumulator.
-rw-r--r--Userland/Libraries/LibJS/AST.h1
-rw-r--r--Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp5
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Instruction.h1
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Op.cpp10
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Op.h12
5 files changed, 29 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h
index 6b8b46bd9a..47ba73e5c5 100644
--- a/Userland/Libraries/LibJS/AST.h
+++ b/Userland/Libraries/LibJS/AST.h
@@ -1214,6 +1214,7 @@ public:
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
+ virtual void generate_bytecode(Bytecode::Generator&) const override;
};
class CallExpression : public Expression {
diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
index 78a43d7fe4..f7c47751e8 100644
--- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp
@@ -1298,4 +1298,9 @@ void ClassDeclaration::generate_bytecode(Bytecode::Generator& generator) const
generator.emit<Bytecode::Op::SetVariable>(generator.intern_string(m_class_expression.ptr()->name()));
}
+void ThisExpression::generate_bytecode(Bytecode::Generator& generator) const
+{
+ generator.emit<Bytecode::Op::ResolveThisBinding>();
+}
+
}
diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h
index d677ad143b..31776b7d3f 100644
--- a/Userland/Libraries/LibJS/Bytecode/Instruction.h
+++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h
@@ -61,6 +61,7 @@
O(PushDeclarativeEnvironment) \
O(PutById) \
O(PutByValue) \
+ O(ResolveThisBinding) \
O(Return) \
O(RightShift) \
O(SetVariable) \
diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp
index 99e72bf0eb..7082dfdef3 100644
--- a/Userland/Libraries/LibJS/Bytecode/Op.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp
@@ -282,6 +282,11 @@ void Jump::execute_impl(Bytecode::Interpreter& interpreter) const
interpreter.jump(*m_true_target);
}
+void ResolveThisBinding::execute_impl(Bytecode::Interpreter& interpreter) const
+{
+ interpreter.accumulator() = interpreter.vm().resolve_this_binding(interpreter.global_object());
+}
+
void Jump::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
{
if (m_true_target.has_value() && &m_true_target->block() == &from)
@@ -785,4 +790,9 @@ String IteratorResultValue::to_string_impl(Executable const&) const
return "IteratorResultValue";
}
+String ResolveThisBinding::to_string_impl(Bytecode::Executable const&) const
+{
+ return "ResolveThisBinding"sv;
+}
+
}
diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h
index 23f14bc026..1a22f4ef3f 100644
--- a/Userland/Libraries/LibJS/Bytecode/Op.h
+++ b/Userland/Libraries/LibJS/Bytecode/Op.h
@@ -715,6 +715,18 @@ public:
void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
};
+class ResolveThisBinding final : public Instruction {
+public:
+ explicit ResolveThisBinding()
+ : Instruction(Type::ResolveThisBinding)
+ {
+ }
+
+ void execute_impl(Bytecode::Interpreter&) const;
+ String to_string_impl(Bytecode::Executable const&) const;
+ void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
+};
+
}
namespace JS::Bytecode {