|
@@ -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();
|
|
|
+}
|
|
|
+
|
|
|
}
|