diff options
author | Andreas Kling <kling@serenityos.org> | 2021-10-25 15:16:22 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-25 15:16:22 +0200 |
commit | 1dc60b028f37366ec01b809a101224ada7dc82aa (patch) | |
tree | b1a1ef2e0060cb4b70e7d08987abeb33d6d4f750 | |
parent | b63d17e2f85cacd3fcc98539e28f31647f974ccf (diff) | |
download | serenity-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.cpp | 61 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Generator.h | 3 |
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); |