summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-10-25 15:16:22 +0200
committerAndreas Kling <kling@serenityos.org>2021-10-25 15:16:22 +0200
commit1dc60b028f37366ec01b809a101224ada7dc82aa (patch)
treeb1a1ef2e0060cb4b70e7d08987abeb33d6d4f750
parentb63d17e2f85cacd3fcc98539e28f31647f974ccf (diff)
downloadserenity-1dc60b028f37366ec01b809a101224ada7dc82aa.zip
LibJS: Add BytecodeGenerator helpers for reference get/put
This allows code sharing between all AST nodes that want to get and/or put through a reference.
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Generator.cpp61
-rw-r--r--Userland/Libraries/LibJS/Bytecode/Generator.h3
2 files changed, 64 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp
index f6dfc923cc..21ee3822c8 100644
--- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp
+++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp
@@ -93,4 +93,65 @@ void Generator::end_breakable_scope()
{
m_breakable_scopes.take_last();
}
+
+void Generator::emit_load_from_reference(JS::ASTNode const& node)
+{
+ if (is<Identifier>(node)) {
+ auto& identifier = static_cast<Identifier const&>(node);
+ emit<Bytecode::Op::GetVariable>(intern_identifier(identifier.string()));
+ return;
+ }
+ if (is<MemberExpression>(node)) {
+ auto& expression = static_cast<MemberExpression const&>(node);
+ expression.object().generate_bytecode(*this);
+
+ auto object_reg = allocate_register();
+ emit<Bytecode::Op::Store>(object_reg);
+
+ if (expression.is_computed()) {
+ expression.property().generate_bytecode(*this);
+ emit<Bytecode::Op::GetByValue>(object_reg);
+ } else {
+ auto identifier_table_ref = intern_identifier(verify_cast<Identifier>(expression.property()).string());
+ emit<Bytecode::Op::GetById>(identifier_table_ref);
+ }
+ return;
+ }
+ VERIFY_NOT_REACHED();
+}
+
+void Generator::emit_store_to_reference(JS::ASTNode const& node)
+{
+ if (is<Identifier>(node)) {
+ auto& identifier = static_cast<Identifier const&>(node);
+ emit<Bytecode::Op::SetVariable>(intern_identifier(identifier.string()));
+ return;
+ }
+ if (is<MemberExpression>(node)) {
+ // NOTE: The value is in the accumulator, so we have to store that away first.
+ auto value_reg = allocate_register();
+ emit<Bytecode::Op::Store>(value_reg);
+
+ auto& expression = static_cast<MemberExpression const&>(node);
+ expression.object().generate_bytecode(*this);
+
+ auto object_reg = allocate_register();
+ emit<Bytecode::Op::Store>(object_reg);
+
+ if (expression.is_computed()) {
+ expression.property().generate_bytecode(*this);
+ auto property_reg = allocate_register();
+ emit<Bytecode::Op::Store>(property_reg);
+ emit<Bytecode::Op::Load>(value_reg);
+ emit<Bytecode::Op::PutByValue>(object_reg, property_reg);
+ } else {
+ emit<Bytecode::Op::Load>(value_reg);
+ auto identifier_table_ref = intern_identifier(verify_cast<Identifier>(expression.property()).string());
+ emit<Bytecode::Op::PutById>(object_reg, identifier_table_ref);
+ }
+ return;
+ }
+ VERIFY_NOT_REACHED();
+}
+
}
diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h
index 48140c9998..669f05a327 100644
--- a/Userland/Libraries/LibJS/Bytecode/Generator.h
+++ b/Userland/Libraries/LibJS/Bytecode/Generator.h
@@ -70,6 +70,9 @@ public:
return *static_cast<OpType*>(slot);
}
+ void emit_load_from_reference(JS::ASTNode const&);
+ void emit_store_to_reference(JS::ASTNode const&);
+
void begin_continuable_scope(Label continue_target);
void end_continuable_scope();
void begin_breakable_scope(Label breakable_target);