PageRenderTime 44ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/vm/jit/ir-instruction-inl.h

https://gitlab.com/Blueprint-Marketing/hhvm
C Header | 297 lines | 212 code | 61 blank | 24 comment | 24 complexity | f56f9c2fee75cba0791cfd2bc1e8f72d MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2015 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include "hphp/runtime/vm/jit/edge.h"
  17. #include <utility>
  18. namespace HPHP { namespace jit {
  19. ///////////////////////////////////////////////////////////////////////////////
  20. inline IRInstruction::IRInstruction(Opcode op,
  21. BCMarker marker,
  22. Edge* edges,
  23. uint32_t numSrcs,
  24. SSATmp** srcs)
  25. : m_typeParam{}
  26. , m_op(op)
  27. , m_numSrcs(numSrcs)
  28. , m_numDsts(0)
  29. , m_hasTypeParam{false}
  30. , m_marker(marker)
  31. , m_id(kTransient)
  32. , m_srcs(srcs)
  33. , m_dest(nullptr)
  34. , m_block(nullptr)
  35. , m_edges(edges)
  36. , m_extra(nullptr)
  37. {
  38. if (op != DefConst) {
  39. // DefConst is the only opcode that's allowed to not have a marker, since
  40. // it's not part of the instruction stream.
  41. assertx(m_marker.valid());
  42. }
  43. }
  44. ///////////////////////////////////////////////////////////////////////////////
  45. inline bool IRInstruction::hasDst() const {
  46. return opcodeHasFlags(op(), HasDest);
  47. }
  48. inline bool IRInstruction::naryDst() const {
  49. return opcodeHasFlags(op(), NaryDest);
  50. }
  51. inline bool IRInstruction::consumesReferences() const {
  52. return opcodeHasFlags(op(), ConsumesRC);
  53. }
  54. inline bool IRInstruction::mayRaiseError() const {
  55. return opcodeHasFlags(op(), MayRaiseError);
  56. }
  57. inline bool IRInstruction::isTerminal() const {
  58. return opcodeHasFlags(op(), Terminal);
  59. }
  60. inline bool IRInstruction::hasEdges() const {
  61. return jit::hasEdges(op());
  62. }
  63. inline bool IRInstruction::isPassthrough() const {
  64. return opcodeHasFlags(op(), Passthrough);
  65. }
  66. inline bool IRInstruction::producesReference() const {
  67. return opcodeHasFlags(op(), ProducesRC);
  68. }
  69. inline SSATmp* IRInstruction::getPassthroughValue() const {
  70. assertx(isPassthrough());
  71. assertx(is(IncRef,
  72. CheckType, AssertType, AssertNonNull,
  73. MapAddElemC, ColAddNewElemC,
  74. CastCtxThis,
  75. Mov));
  76. return src(0);
  77. }
  78. ///////////////////////////////////////////////////////////////////////////////
  79. inline uint32_t IRInstruction::id() const {
  80. assertx(m_id != kTransient);
  81. return m_id;
  82. }
  83. inline bool IRInstruction::isTransient() const {
  84. return m_id == kTransient;
  85. }
  86. template<typename... Args>
  87. bool IRInstruction::is(Opcode op, Args&&... args) const {
  88. return m_op == op || is(std::forward<Args>(args)...);
  89. }
  90. inline bool IRInstruction::is() const {
  91. return false;
  92. }
  93. inline Opcode IRInstruction::op() const {
  94. return m_op;
  95. }
  96. inline const BCMarker& IRInstruction::marker() const {
  97. return m_marker;
  98. }
  99. inline BCMarker& IRInstruction::marker() {
  100. return m_marker;
  101. }
  102. inline bool IRInstruction::hasTypeParam() const { return m_hasTypeParam; }
  103. inline Type IRInstruction::typeParam() const {
  104. assertx(m_hasTypeParam);
  105. return m_typeParam;
  106. }
  107. inline void IRInstruction::setTypeParam(Type t) {
  108. m_hasTypeParam = true;
  109. m_typeParam = t;
  110. }
  111. ///////////////////////////////////////////////////////////////////////////////
  112. inline void IRInstruction::initializeSrcs(uint32_t numSrcs, SSATmp** srcs) {
  113. assertx(!m_srcs && !m_numSrcs);
  114. m_numSrcs = numSrcs;
  115. m_srcs = srcs;
  116. }
  117. inline uint32_t IRInstruction::numSrcs() const {
  118. return m_numSrcs;
  119. }
  120. inline uint32_t IRInstruction::numDsts() const {
  121. return m_numDsts;
  122. }
  123. inline SSATmp* IRInstruction::src(uint32_t i) const {
  124. always_assert(i < numSrcs());
  125. return m_srcs[i];
  126. }
  127. inline SSATmp* IRInstruction::dst() const {
  128. assertx(!naryDst());
  129. return m_dest;
  130. }
  131. inline folly::Range<SSATmp**> IRInstruction::srcs() const {
  132. return folly::Range<SSATmp**>(m_srcs, m_numSrcs);
  133. }
  134. inline folly::Range<SSATmp**> IRInstruction::dsts() {
  135. assertx(naryDst() || m_numDsts <= 1);
  136. if (hasDst()) return folly::Range<SSATmp**>(&m_dest, m_numDsts);
  137. return folly::Range<SSATmp**>(m_dsts, m_numDsts);
  138. }
  139. inline void IRInstruction::setSrc(uint32_t i, SSATmp* newSrc) {
  140. always_assert(i < numSrcs());
  141. m_srcs[i] = newSrc;
  142. }
  143. inline void IRInstruction::setDst(SSATmp* newDst) {
  144. assertx(hasDst());
  145. m_dest = newDst;
  146. m_numDsts = newDst ? 1 : 0;
  147. }
  148. inline void IRInstruction::setDsts(uint32_t numDsts, SSATmp** newDsts) {
  149. assertx(naryDst());
  150. m_numDsts = numDsts;
  151. m_dsts = newDsts;
  152. }
  153. ///////////////////////////////////////////////////////////////////////////////
  154. inline bool IRInstruction::hasExtra() const {
  155. return m_extra;
  156. }
  157. template<Opcode opc>
  158. const typename IRExtraDataType<opc>::type* IRInstruction::extra() const {
  159. assertx(opc == op() && "ExtraData type error");
  160. assertx(m_extra != nullptr);
  161. return static_cast<typename IRExtraDataType<opc>::type*>(m_extra);
  162. }
  163. template<Opcode opc>
  164. typename IRExtraDataType<opc>::type* IRInstruction::extra() {
  165. assertx(opc == op() && "ExtraData type error");
  166. return static_cast<typename IRExtraDataType<opc>::type*>(m_extra);
  167. }
  168. template<class T>
  169. const T* IRInstruction::extra() const {
  170. if (debug) assert_opcode_extra<T>(op());
  171. return static_cast<const T*>(m_extra);
  172. }
  173. inline const IRExtraData* IRInstruction::rawExtra() const {
  174. return m_extra;
  175. }
  176. inline void IRInstruction::setExtra(IRExtraData* data) {
  177. assertx(!m_extra);
  178. m_extra = data;
  179. }
  180. inline void IRInstruction::clearExtra() {
  181. m_extra = nullptr;
  182. }
  183. ///////////////////////////////////////////////////////////////////////////////
  184. inline Block* IRInstruction::block() const {
  185. return m_block;
  186. }
  187. inline void IRInstruction::setBlock(Block* b) {
  188. m_block = b;
  189. }
  190. inline Block* IRInstruction::next() const {
  191. return succ(0);
  192. }
  193. inline Edge* IRInstruction::nextEdge() {
  194. return succEdge(0);
  195. }
  196. inline void IRInstruction::setNext(Block* b) {
  197. return setSucc(0, b);
  198. }
  199. inline Block* IRInstruction::taken() const {
  200. return succ(1);
  201. }
  202. inline Edge* IRInstruction::takenEdge() {
  203. return succEdge(1);
  204. }
  205. inline void IRInstruction::setTaken(Block* b) {
  206. return setSucc(1, b);
  207. }
  208. inline bool IRInstruction::isControlFlow() const {
  209. return bool(taken());
  210. }
  211. inline bool IRInstruction::isBlockEnd() const {
  212. return taken() || isTerminal();
  213. }
  214. inline Block* IRInstruction::succ(int i) const {
  215. assertx(!m_edges || hasEdges());
  216. return m_edges ? m_edges[i].to() : nullptr;
  217. }
  218. inline Edge* IRInstruction::succEdge(int i) {
  219. assertx(!m_edges || hasEdges());
  220. return m_edges && m_edges[i].to() ? &m_edges[i] : nullptr;
  221. }
  222. inline void IRInstruction::setSucc(int i, Block* b) {
  223. if (hasEdges()) {
  224. if (isTransient()) m_edges[i].setTransientTo(b);
  225. else m_edges[i].setTo(b);
  226. } else {
  227. assertx(!b && !m_edges);
  228. }
  229. }
  230. inline void IRInstruction::clearEdges() {
  231. setSucc(0, nullptr);
  232. setSucc(1, nullptr);
  233. m_edges = nullptr;
  234. }
  235. ///////////////////////////////////////////////////////////////////////////////
  236. }}