浏览代码

LibJS: Use macros to generate the common unary/binary bytecode ops

Andreas Kling 4 年之前
父节点
当前提交
ebb40e7d7b
共有 2 个文件被更改,包括 106 次插入751 次删除
  1. 32 249
      Userland/Libraries/LibJS/Bytecode/Op.cpp
  2. 74 502
      Userland/Libraries/LibJS/Bytecode/Op.h

+ 32 - 249
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -58,141 +58,59 @@ void LoadRegister::execute(Bytecode::Interpreter& interpreter) const
     interpreter.reg(m_dst) = interpreter.reg(m_src);
 }
 
-void Add::execute(Bytecode::Interpreter& interpreter) const
+static Value abstract_inequals(GlobalObject& global_object, Value src1, Value src2)
 {
-    interpreter.reg(m_dst) = add(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
+    return Value(!abstract_eq(global_object, src1, src2));
 }
 
-void Sub::execute(Bytecode::Interpreter& interpreter) const
+static Value abstract_equals(GlobalObject& global_object, Value src1, Value src2)
 {
-    interpreter.reg(m_dst) = sub(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
+    return Value(abstract_eq(global_object, src1, src2));
 }
 
-void Mul::execute(Bytecode::Interpreter& interpreter) const
+static Value typed_inequals(GlobalObject&, Value src1, Value src2)
 {
-    interpreter.reg(m_dst) = mul(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
+    return Value(!strict_eq(src1, src2));
 }
 
-void Div::execute(Bytecode::Interpreter& interpreter) const
+static Value typed_equals(GlobalObject&, Value src1, Value src2)
 {
-    interpreter.reg(m_dst) = div(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
+    return Value(strict_eq(src1, src2));
 }
 
-void Mod::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = mod(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void Exp::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = exp(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void GreaterThan::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = greater_than(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void GreaterThanEquals::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = greater_than_equals(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void LessThan::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = less_than(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void LessThanEquals::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = less_than_equals(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void AbstractInequals::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = Value(!abstract_eq(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)));
-}
-
-void AbstractEquals::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = Value(abstract_eq(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)));
-}
-
-void TypedInequals::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = Value(!strict_eq(interpreter.reg(m_src1), interpreter.reg(m_src2)));
-}
-
-void TypedEquals::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = Value(strict_eq(interpreter.reg(m_src1), interpreter.reg(m_src2)));
-}
-
-void BitwiseAnd::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = bitwise_and(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void BitwiseOr::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = bitwise_or(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void BitwiseXor::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = bitwise_xor(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void LeftShift::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = left_shift(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void RightShift::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = right_shift(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void UnsignedRightShift::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = unsigned_right_shift(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
-
-void In::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = in(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
+#define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case)                                                                 \
+    void OpTitleCase::execute(Bytecode::Interpreter& interpreter) const                                                        \
+    {                                                                                                                          \
+        interpreter.reg(m_dst) = op_snake_case(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); \
+    }                                                                                                                          \
+    String OpTitleCase::to_string() const                                                                                      \
+    {                                                                                                                          \
+        return String::formatted(#OpTitleCase " dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);                             \
+    }
 
-void InstanceOf::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = instance_of(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2));
-}
+JS_ENUMERATE_COMMON_BINARY_OPS(JS_DEFINE_COMMON_BINARY_OP)
 
-void BitwiseNot::execute(Bytecode::Interpreter& interpreter) const
+static Value not_(GlobalObject&, Value value)
 {
-    interpreter.reg(m_dst) = bitwise_not(interpreter.global_object(), interpreter.reg(m_src));
+    return Value(!value.to_boolean());
 }
 
-void Not::execute(Bytecode::Interpreter& interpreter) const
+static Value typeof_(GlobalObject& global_object, Value value)
 {
-    interpreter.reg(m_dst) = Value(!interpreter.reg(m_src).to_boolean());
+    return js_string(global_object.vm(), value.typeof());
 }
 
-void UnaryPlus::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = Value(unary_plus(interpreter.global_object(), interpreter.reg(m_src)));
-}
+#define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case)                                        \
+    void OpTitleCase::execute(Bytecode::Interpreter& interpreter) const                              \
+    {                                                                                                \
+        interpreter.reg(m_dst) = op_snake_case(interpreter.global_object(), interpreter.reg(m_src)); \
+    }                                                                                                \
+    String OpTitleCase::to_string() const                                                            \
+    {                                                                                                \
+        return String::formatted(#OpTitleCase " dst:{}, src:{}", m_dst, m_src);                      \
+    }
 
-void UnaryMinus::execute(Bytecode::Interpreter& interpreter) const
-{
-    interpreter.reg(m_dst) = Value(unary_minus(interpreter.global_object(), interpreter.reg(m_src)));
-}
-
-void Typeof::execute(Bytecode::Interpreter& interpreter) const
-{
-    auto& vm = interpreter.global_object().vm();
-    interpreter.reg(m_dst) = Value(js_string(vm, interpreter.reg(m_src).typeof()));
-}
+JS_ENUMERATE_COMMON_UNARY_OPS(JS_DEFINE_COMMON_UNARY_OP)
 
 void NewString::execute(Bytecode::Interpreter& interpreter) const
 {
@@ -305,141 +223,6 @@ String LoadRegister::to_string() const
     return String::formatted("LoadRegister dst:{}, src:{}", m_dst, m_src);
 }
 
-String Add::to_string() const
-{
-    return String::formatted("Add dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String Sub::to_string() const
-{
-    return String::formatted("Sub dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String Mul::to_string() const
-{
-    return String::formatted("Mul dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String Div::to_string() const
-{
-    return String::formatted("Div dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String Mod::to_string() const
-{
-    return String::formatted("Mod dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String Exp::to_string() const
-{
-    return String::formatted("Exp dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String GreaterThan::to_string() const
-{
-    return String::formatted("GreaterThan dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String GreaterThanEquals::to_string() const
-{
-    return String::formatted("GreaterThanEquals dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String LessThan::to_string() const
-{
-    return String::formatted("LessThan dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String LessThanEquals::to_string() const
-{
-    return String::formatted("LessThanEquals dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String AbstractInequals::to_string() const
-{
-    return String::formatted("AbstractInequals dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String AbstractEquals::to_string() const
-{
-    return String::formatted("AbstractEquals dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String TypedInequals::to_string() const
-{
-    return String::formatted("TypedInequals dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String TypedEquals::to_string() const
-{
-    return String::formatted("TypedEquals dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String BitwiseAnd::to_string() const
-{
-    return String::formatted("BitwiseAnd dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String BitwiseOr::to_string() const
-{
-    return String::formatted("BitwiseOr dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String BitwiseXor::to_string() const
-{
-    return String::formatted("BitwiseXor dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String LeftShift::to_string() const
-{
-    return String::formatted("LeftShift dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String RightShift::to_string() const
-{
-    return String::formatted("RightShift dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String UnsignedRightShift::to_string() const
-{
-    return String::formatted("UnsignedRightShift dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String In::to_string() const
-{
-    return String::formatted("In dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String InstanceOf::to_string() const
-{
-    return String::formatted("In dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2);
-}
-
-String BitwiseNot::to_string() const
-{
-    return String::formatted("BitwiseNot dst:{}, src:{}", m_dst, m_src);
-}
-
-String Not::to_string() const
-{
-    return String::formatted("Not dst:{}, src:{}", m_dst, m_src);
-}
-
-String UnaryPlus::to_string() const
-{
-    return String::formatted("UnaryPlus dst:{}, src:{}", m_dst, m_src);
-}
-
-String UnaryMinus::to_string() const
-{
-    return String::formatted("UnaryMinus dst:{}, src:{}", m_dst, m_src);
-}
-
-String Typeof::to_string() const
-{
-    return String::formatted("Typeof dst:{}, src:{}", m_dst, m_src);
-}
-
 String NewString::to_string() const
 {
     return String::formatted("NewString dst:{}, string:\"{}\"", m_dst, m_string);

+ 74 - 502
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -50,508 +50,80 @@ private:
     Register m_src;
 };
 
-class Add final : public Instruction {
-public:
-    Add(Register dst, Register src1, Register src2)
-        : Instruction(Type::Add)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class Sub final : public Instruction {
-public:
-    Sub(Register dst, Register src1, Register src2)
-        : Instruction(Type::Sub)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class Mul final : public Instruction {
-public:
-    Mul(Register dst, Register src1, Register src2)
-        : Instruction(Type::Mul)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class Div final : public Instruction {
-public:
-    Div(Register dst, Register src1, Register src2)
-        : Instruction(Type::Div)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class Mod final : public Instruction {
-public:
-    Mod(Register dst, Register src1, Register src2)
-        : Instruction(Type::Mod)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class Exp final : public Instruction {
-public:
-    Exp(Register dst, Register src1, Register src2)
-        : Instruction(Type::Exp)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class GreaterThan final : public Instruction {
-public:
-    GreaterThan(Register dst, Register src1, Register src2)
-        : Instruction(Type::GreaterThan)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class GreaterThanEquals final : public Instruction {
-public:
-    GreaterThanEquals(Register dst, Register src1, Register src2)
-        : Instruction(Type::GreaterThanEquals)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class LessThan final : public Instruction {
-public:
-    LessThan(Register dst, Register src1, Register src2)
-        : Instruction(Type::LessThan)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class LessThanEquals final : public Instruction {
-public:
-    LessThanEquals(Register dst, Register src1, Register src2)
-        : Instruction(Type::LessThanEquals)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class AbstractInequals final : public Instruction {
-public:
-    AbstractInequals(Register dst, Register src1, Register src2)
-        : Instruction(Type::AbstractInequals)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class AbstractEquals final : public Instruction {
-public:
-    AbstractEquals(Register dst, Register src1, Register src2)
-        : Instruction(Type::AbstractEquals)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class TypedInequals final : public Instruction {
-public:
-    TypedInequals(Register dst, Register src1, Register src2)
-        : Instruction(Type::TypedInequals)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class TypedEquals final : public Instruction {
-public:
-    TypedEquals(Register dst, Register src1, Register src2)
-        : Instruction(Type::TypedEquals)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class BitwiseAnd final : public Instruction {
-public:
-    BitwiseAnd(Register dst, Register src1, Register src2)
-        : Instruction(Type::BitwiseAnd)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class BitwiseOr final : public Instruction {
-public:
-    BitwiseOr(Register dst, Register src1, Register src2)
-        : Instruction(Type::BitwiseOr)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class BitwiseXor final : public Instruction {
-public:
-    BitwiseXor(Register dst, Register src1, Register src2)
-        : Instruction(Type::BitwiseXor)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class LeftShift final : public Instruction {
-public:
-    LeftShift(Register dst, Register src1, Register src2)
-        : Instruction(Type::LeftShift)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class RightShift final : public Instruction {
-public:
-    RightShift(Register dst, Register src1, Register src2)
-        : Instruction(Type::RightShift)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class UnsignedRightShift final : public Instruction {
-public:
-    UnsignedRightShift(Register dst, Register src1, Register src2)
-        : Instruction(Type::UnsignedRightShift)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class In final : public Instruction {
-public:
-    In(Register dst, Register src1, Register src2)
-        : Instruction(Type::In)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class InstanceOf final : public Instruction {
-public:
-    InstanceOf(Register dst, Register src1, Register src2)
-        : Instruction(Type::InstanceOf)
-        , m_dst(dst)
-        , m_src1(src1)
-        , m_src2(src2)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src1;
-    Register m_src2;
-};
-
-class BitwiseNot final : public Instruction {
-public:
-    BitwiseNot(Register dst, Register src)
-        : Instruction(Type::BitwiseNot)
-        , m_dst(dst)
-        , m_src(src)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src;
-};
-
-class Not final : public Instruction {
-public:
-    Not(Register dst, Register src)
-        : Instruction(Type::Not)
-        , m_dst(dst)
-        , m_src(src)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src;
-};
-
-class UnaryPlus final : public Instruction {
-public:
-    UnaryPlus(Register dst, Register src)
-        : Instruction(Type::UnaryPlus)
-        , m_dst(dst)
-        , m_src(src)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src;
-};
-
-class UnaryMinus final : public Instruction {
-public:
-    UnaryMinus(Register dst, Register src)
-        : Instruction(Type::UnaryMinus)
-        , m_dst(dst)
-        , m_src(src)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src;
-};
-
-class Typeof final : public Instruction {
-public:
-    Typeof(Register dst, Register src)
-        : Instruction(Type::Typeof)
-        , m_dst(dst)
-        , m_src(src)
-    {
-    }
-
-    void execute(Bytecode::Interpreter&) const;
-    String to_string() const;
-
-private:
-    Register m_dst;
-    Register m_src;
-};
+#define JS_ENUMERATE_COMMON_BINARY_OPS(O)     \
+    O(Add, add)                               \
+    O(Sub, sub)                               \
+    O(Mul, mul)                               \
+    O(Div, div)                               \
+    O(Exp, exp)                               \
+    O(Mod, mod)                               \
+    O(In, in)                                 \
+    O(InstanceOf, instance_of)                \
+    O(GreaterThan, greater_than)              \
+    O(GreaterThanEquals, greater_than_equals) \
+    O(LessThan, less_than)                    \
+    O(LessThanEquals, less_than_equals)       \
+    O(AbstractInequals, abstract_inequals)    \
+    O(AbstractEquals, abstract_equals)        \
+    O(TypedInequals, typed_inequals)          \
+    O(TypedEquals, typed_equals)              \
+    O(BitwiseAnd, bitwise_and)                \
+    O(BitwiseOr, bitwise_or)                  \
+    O(BitwiseXor, bitwise_xor)                \
+    O(LeftShift, left_shift)                  \
+    O(RightShift, right_shift)                \
+    O(UnsignedRightShift, unsigned_right_shift)
+
+#define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
+    class OpTitleCase final : public Instruction {              \
+    public:                                                     \
+        OpTitleCase(Register dst, Register src1, Register src2) \
+            : Instruction(Type::OpTitleCase)                    \
+            , m_dst(dst)                                        \
+            , m_src1(src1)                                      \
+            , m_src2(src2)                                      \
+        {                                                       \
+        }                                                       \
+                                                                \
+        void execute(Bytecode::Interpreter&) const;             \
+        String to_string() const;                               \
+                                                                \
+    private:                                                    \
+        Register m_dst;                                         \
+        Register m_src1;                                        \
+        Register m_src2;                                        \
+    };
+
+JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP)
+#undef JS_DECLARE_COMMON_BINARY_OP
+
+#define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
+    O(BitwiseNot, bitwise_not)           \
+    O(Not, not_)                         \
+    O(UnaryPlus, unary_plus)             \
+    O(UnaryMinus, unary_minus)           \
+    O(Typeof, typeof_)
+
+#define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
+    class OpTitleCase final : public Instruction {             \
+    public:                                                    \
+        OpTitleCase(Register dst, Register src)                \
+            : Instruction(Type::OpTitleCase)                   \
+            , m_dst(dst)                                       \
+            , m_src(src)                                       \
+        {                                                      \
+        }                                                      \
+                                                               \
+        void execute(Bytecode::Interpreter&) const;            \
+        String to_string() const;                              \
+                                                               \
+    private:                                                   \
+        Register m_dst;                                        \
+        Register m_src;                                        \
+    };
+
+JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
+#undef JS_DECLARE_COMMON_UNARY_OP
 
 class NewString final : public Instruction {
 public: