Instruction.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Forward.h>
  8. #include <AK/Span.h>
  9. #include <LibJS/Forward.h>
  10. #define ENUMERATE_BYTECODE_OPS(O) \
  11. O(Add) \
  12. O(Append) \
  13. O(BitwiseAnd) \
  14. O(BitwiseNot) \
  15. O(BitwiseOr) \
  16. O(BitwiseXor) \
  17. O(BlockDeclarationInstantiation) \
  18. O(Call) \
  19. O(ConcatString) \
  20. O(ContinuePendingUnwind) \
  21. O(CopyObjectExcludingProperties) \
  22. O(CreateLexicalEnvironment) \
  23. O(CreateVariable) \
  24. O(Decrement) \
  25. O(DeleteById) \
  26. O(DeleteByValue) \
  27. O(DeleteVariable) \
  28. O(Div) \
  29. O(EnterUnwindContext) \
  30. O(EnterObjectEnvironment) \
  31. O(Exp) \
  32. O(GetById) \
  33. O(GetByValue) \
  34. O(GetIterator) \
  35. O(GetMethod) \
  36. O(GetNewTarget) \
  37. O(GetObjectPropertyIterator) \
  38. O(GetVariable) \
  39. O(GreaterThan) \
  40. O(GreaterThanEquals) \
  41. O(In) \
  42. O(Increment) \
  43. O(InstanceOf) \
  44. O(IteratorClose) \
  45. O(IteratorNext) \
  46. O(IteratorResultDone) \
  47. O(IteratorResultValue) \
  48. O(IteratorToArray) \
  49. O(Jump) \
  50. O(JumpConditional) \
  51. O(JumpNullish) \
  52. O(JumpUndefined) \
  53. O(LeaveLexicalEnvironment) \
  54. O(LeaveUnwindContext) \
  55. O(LeftShift) \
  56. O(LessThan) \
  57. O(LessThanEquals) \
  58. O(Load) \
  59. O(LoadImmediate) \
  60. O(LooselyEquals) \
  61. O(LooselyInequals) \
  62. O(Mod) \
  63. O(Mul) \
  64. O(NewArray) \
  65. O(NewBigInt) \
  66. O(NewClass) \
  67. O(NewFunction) \
  68. O(NewObject) \
  69. O(NewRegExp) \
  70. O(NewString) \
  71. O(NewTypeError) \
  72. O(Not) \
  73. O(PushDeclarativeEnvironment) \
  74. O(PutById) \
  75. O(PutByValue) \
  76. O(ResolveThisBinding) \
  77. O(ResolveSuperBase) \
  78. O(Return) \
  79. O(RightShift) \
  80. O(ScheduleJump) \
  81. O(SetVariable) \
  82. O(Store) \
  83. O(StrictlyEquals) \
  84. O(StrictlyInequals) \
  85. O(Sub) \
  86. O(SuperCall) \
  87. O(Throw) \
  88. O(ThrowIfNotObject) \
  89. O(ToNumeric) \
  90. O(Typeof) \
  91. O(TypeofVariable) \
  92. O(UnaryMinus) \
  93. O(UnaryPlus) \
  94. O(UnsignedRightShift) \
  95. O(Yield)
  96. namespace JS::Bytecode {
  97. class alignas(void*) Instruction {
  98. public:
  99. constexpr static bool IsTerminator = false;
  100. enum class Type {
  101. #define __BYTECODE_OP(op) \
  102. op,
  103. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  104. #undef __BYTECODE_OP
  105. };
  106. bool is_terminator() const;
  107. Type type() const { return m_type; }
  108. size_t length() const;
  109. DeprecatedString to_deprecated_string(Bytecode::Executable const&) const;
  110. ThrowCompletionOr<void> execute(Bytecode::Interpreter&) const;
  111. void replace_references(BasicBlock const&, BasicBlock const&);
  112. void replace_references(Register, Register);
  113. static void destroy(Instruction&);
  114. protected:
  115. explicit Instruction(Type type)
  116. : m_type(type)
  117. {
  118. }
  119. private:
  120. Type m_type {};
  121. };
  122. class InstructionStreamIterator {
  123. public:
  124. explicit InstructionStreamIterator(ReadonlyBytes bytes)
  125. : m_bytes(bytes)
  126. {
  127. }
  128. size_t offset() const { return m_offset; }
  129. bool at_end() const { return m_offset >= m_bytes.size(); }
  130. void jump(size_t offset)
  131. {
  132. VERIFY(offset <= m_bytes.size());
  133. m_offset = offset;
  134. }
  135. Instruction const& operator*() const { return dereference(); }
  136. ALWAYS_INLINE void operator++()
  137. {
  138. VERIFY(!at_end());
  139. m_offset += dereference().length();
  140. }
  141. private:
  142. Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_bytes.data() + offset()); }
  143. ReadonlyBytes m_bytes;
  144. size_t m_offset { 0 };
  145. };
  146. }