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

/hphp/runtime/vm/translator/hopt/extradata.h

https://bitbucket.org/gnanakeethan/hiphop-php
C Header | 388 lines | 254 code | 58 blank | 76 comment | 9 complexity | 553aec6c3428db7bea5585d763b828db MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010- 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. #ifndef incl_HPHP_VM_EXTRADATA_H_
  17. #define incl_HPHP_VM_EXTRADATA_H_
  18. #include "hphp/runtime/vm/translator/hopt/ir.h"
  19. namespace HPHP { namespace JIT {
  20. //////////////////////////////////////////////////////////////////////
  21. /*
  22. * Some IRInstructions with compile-time-only constants may carry
  23. * along extra data in the form of one of these structures.
  24. *
  25. * Note that this isn't really appropriate for compile-time constants
  26. * that are actually representing user values (we want them to be
  27. * visible to optimization passes, allocatable to registers, etc),
  28. * just compile-time metadata.
  29. *
  30. * These types must:
  31. *
  32. * - Derive from IRExtraData (for overloading purposes)
  33. * - Be arena-allocatable (no non-trivial destructors)
  34. * - Either CopyConstructible, or implement a clone member
  35. * function that takes an arena to clone to
  36. *
  37. * In addition, for extra data used with a cse-able instruction:
  38. *
  39. * - Implement an cseEquals() member that indicates equality for CSE
  40. * purposes.
  41. * - Implement a cseHash() method.
  42. *
  43. * Finally, optionally they may implement a show() method for use in
  44. * debug printouts.
  45. */
  46. /*
  47. * Traits that returns the type of the extra C++ data structure for a
  48. * given instruction, if it has one, along with some other information
  49. * about the type.
  50. */
  51. template<Opcode op> struct OpHasExtraData { enum { value = 0 }; };
  52. template<Opcode op> struct IRExtraDataType;
  53. //////////////////////////////////////////////////////////////////////
  54. struct IRExtraData {};
  55. struct LdSSwitchData : IRExtraData {
  56. struct Elm {
  57. const StringData* str;
  58. Offset dest;
  59. };
  60. explicit LdSSwitchData() = default;
  61. LdSSwitchData(const LdSSwitchData&) = delete;
  62. LdSSwitchData& operator=(const LdSSwitchData&) = delete;
  63. LdSSwitchData* clone(Arena& arena) const {
  64. LdSSwitchData* target = new (arena) LdSSwitchData;
  65. target->func = func;
  66. target->numCases = numCases;
  67. target->defaultOff = defaultOff;
  68. target->cases = new (arena) Elm[numCases];
  69. std::copy(cases, cases + numCases, const_cast<Elm*>(target->cases));
  70. return target;
  71. }
  72. const Func* func;
  73. int64_t numCases;
  74. const Elm* cases;
  75. Offset defaultOff;
  76. };
  77. struct JmpSwitchData : IRExtraData {
  78. JmpSwitchData* clone(Arena& arena) const {
  79. JmpSwitchData* sd = new (arena) JmpSwitchData;
  80. sd->func = func;
  81. sd->base = base;
  82. sd->bounded = bounded;
  83. sd->cases = cases;
  84. sd->defaultOff = defaultOff;
  85. sd->targets = new (arena) Offset[cases];
  86. std::copy(targets, targets + cases, const_cast<Offset*>(sd->targets));
  87. return sd;
  88. }
  89. const Func* func;
  90. int64_t base; // base of switch case
  91. bool bounded; // whether switch is bounded or not
  92. int32_t cases; // number of cases
  93. Offset defaultOff; // offset of default case
  94. Offset* targets; // offsets for all targets
  95. };
  96. struct MarkerData : IRExtraData {
  97. uint32_t bcOff; // the bytecode offset in unit
  98. int32_t stackOff; // stack off from start of trace
  99. const Func* func; // which func are we in
  100. std::string show() const {
  101. return folly::format("--- bc {}, spOff {} ({})",
  102. bcOff,
  103. stackOff,
  104. func->fullName()->data()).str();
  105. }
  106. };
  107. struct LocalId : IRExtraData {
  108. explicit LocalId(uint32_t id)
  109. : locId(id)
  110. {}
  111. bool cseEquals(LocalId o) const { return locId == o.locId; }
  112. size_t cseHash() const { return std::hash<uint32_t>()(locId); }
  113. std::string show() const { return folly::to<std::string>(locId); }
  114. uint32_t locId;
  115. };
  116. struct IterId : IRExtraData {
  117. explicit IterId(uint32_t id)
  118. : iterId(id)
  119. {}
  120. bool cseEquals(IterId o) const { return iterId == o.iterId; }
  121. size_t cseHash() const { return std::hash<uint32_t>()(iterId); }
  122. std::string show() const { return folly::to<std::string>(iterId); }
  123. uint32_t iterId;
  124. };
  125. struct FPushCufData : IRExtraData {
  126. FPushCufData(uint32_t a, int32_t id)
  127. : args(a), iterId(id)
  128. {}
  129. bool cseEquals(FPushCufData o) const {
  130. return iterId == o.iterId && args == o.args;
  131. }
  132. size_t cseHash() const {
  133. return std::hash<uint32_t>()(iterId) ^ std::hash<uint32_t>()(args);
  134. }
  135. std::string show() const {
  136. return folly::to<std::string>(iterId, ',', args);
  137. }
  138. uint32_t args;
  139. uint32_t iterId;
  140. };
  141. struct ConstData : IRExtraData {
  142. template<class T>
  143. explicit ConstData(T data)
  144. : m_dataBits(0)
  145. {
  146. static_assert(sizeof(T) <= sizeof m_dataBits,
  147. "Constant data was larger than supported");
  148. static_assert(std::is_pod<T>::value,
  149. "Constant data wasn't a pod?");
  150. std::memcpy(&m_dataBits, &data, sizeof data);
  151. }
  152. template<class T>
  153. T as() const {
  154. T ret;
  155. std::memcpy(&ret, &m_dataBits, sizeof ret);
  156. return ret;
  157. }
  158. bool cseEquals(ConstData o) const { return m_dataBits == o.m_dataBits; }
  159. size_t cseHash() const { return std::hash<uintptr_t>()(m_dataBits); }
  160. private:
  161. uintptr_t m_dataBits;
  162. };
  163. struct CreateContData : IRExtraData {
  164. const Func* origFunc;
  165. const Func* genFunc;
  166. };
  167. /*
  168. * Information for the REQ_BIND_JMPCC stubs we create when a tracelet
  169. * ends with conditional jumps.
  170. */
  171. struct ReqBindJccData : IRExtraData {
  172. Offset taken;
  173. Offset notTaken;
  174. std::string show() const {
  175. return folly::to<std::string>(taken, ',', notTaken);
  176. }
  177. };
  178. /*
  179. * Information for a conditional side exit based on a type check of a
  180. * local or stack cell.
  181. */
  182. struct SideExitGuardData : IRExtraData {
  183. uint32_t checkedSlot;
  184. Offset taken;
  185. std::string show() const {
  186. return folly::to<std::string>(checkedSlot, ',', taken);
  187. }
  188. };
  189. /*
  190. * Compile-time metadata about an ActRec allocation.
  191. */
  192. struct ActRecInfo : IRExtraData {
  193. const StringData* invName; // may be nullptr
  194. int32_t numArgs;
  195. std::string show() const {
  196. auto numArgsAndCtorFlag = ActRec::decodeNumArgs(numArgs);
  197. return folly::to<std::string>(numArgsAndCtorFlag.first,
  198. numArgsAndCtorFlag.second ? ",ctor" : "",
  199. invName ? " M" : "");
  200. }
  201. };
  202. /*
  203. * Stack offsets.
  204. */
  205. struct StackOffset : IRExtraData {
  206. explicit StackOffset(int32_t offset) : offset(offset) {}
  207. std::string show() const { return folly::to<std::string>(offset); }
  208. bool cseEquals(StackOffset o) const { return offset == o.offset; }
  209. size_t cseHash() const { return std::hash<int32_t>()(offset); }
  210. int32_t offset;
  211. };
  212. /*
  213. * Bytecode offsets.
  214. */
  215. struct BCOffset : IRExtraData {
  216. explicit BCOffset(Offset offset) : offset(offset) {}
  217. std::string show() const { return folly::to<std::string>(offset); }
  218. Offset offset;
  219. };
  220. /*
  221. * DefInlineFP is present when we need to create a frame for inlining.
  222. * This instruction also carries some metadata used by tracebuilder to
  223. * track state during an inlined call.
  224. */
  225. struct DefInlineFPData : IRExtraData {
  226. std::string show() const {
  227. return folly::to<std::string>(
  228. target->fullName()->data(), "(),", retSPOff, ',', retBCOff
  229. );
  230. }
  231. const Func* target;
  232. Offset retBCOff;
  233. Offset retSPOff;
  234. };
  235. /*
  236. * FCallArray offsets
  237. */
  238. struct CallArrayData : IRExtraData {
  239. explicit CallArrayData(Offset pcOffset, Offset aft)
  240. : pc(pcOffset), after(aft) {}
  241. std::string show() const { return folly::to<std::string>(pc, ",", after); }
  242. Offset pc, after;
  243. };
  244. //////////////////////////////////////////////////////////////////////
  245. #define X(op, data) \
  246. template<> struct IRExtraDataType<op> { typedef data type; }; \
  247. template<> struct OpHasExtraData<op> { enum { value = 1 }; }; \
  248. static_assert(boost::has_trivial_destructor<data>::value, \
  249. "IR extra data type must be trivially destructible")
  250. X(JmpSwitchDest, JmpSwitchData);
  251. X(LdSSwitchDestFast, LdSSwitchData);
  252. X(LdSSwitchDestSlow, LdSSwitchData);
  253. X(Marker, MarkerData);
  254. X(RaiseUninitLoc, LocalId);
  255. X(GuardLoc, LocalId);
  256. X(CheckLoc, LocalId);
  257. X(AssertLoc, LocalId);
  258. X(OverrideLoc, LocalId);
  259. X(LdLocAddr, LocalId);
  260. X(DecRefLoc, LocalId);
  261. X(LdLoc, LocalId);
  262. X(StLoc, LocalId);
  263. X(StLocNT, LocalId);
  264. X(IterFree, IterId);
  265. X(CIterFree, IterId);
  266. X(CufIterSpillFrame, FPushCufData);
  267. X(DefConst, ConstData);
  268. X(LdConst, ConstData);
  269. X(SpillFrame, ActRecInfo);
  270. X(GuardStk, StackOffset);
  271. X(CheckStk, StackOffset);
  272. X(CastStk, StackOffset);
  273. X(AssertStk, StackOffset);
  274. X(ReDefSP, StackOffset);
  275. X(ReDefGeneratorSP, StackOffset);
  276. X(DefSP, StackOffset);
  277. X(LdStack, StackOffset);
  278. X(LdStackAddr, StackOffset);
  279. X(DecRefStack, StackOffset);
  280. X(DefInlineFP, DefInlineFPData);
  281. X(ReqBindJmp, BCOffset);
  282. X(ReqBindJmpNoIR, BCOffset);
  283. X(ReqRetranslateNoIR, BCOffset);
  284. X(InlineCreateCont, CreateContData);
  285. X(CallArray, CallArrayData);
  286. X(ReqBindJmpGt, ReqBindJccData);
  287. X(ReqBindJmpGte, ReqBindJccData);
  288. X(ReqBindJmpLt, ReqBindJccData);
  289. X(ReqBindJmpLte, ReqBindJccData);
  290. X(ReqBindJmpEq, ReqBindJccData);
  291. X(ReqBindJmpNeq, ReqBindJccData);
  292. X(ReqBindJmpSame, ReqBindJccData);
  293. X(ReqBindJmpNSame, ReqBindJccData);
  294. X(ReqBindJmpInstanceOfBitmask, ReqBindJccData);
  295. X(ReqBindJmpNInstanceOfBitmask, ReqBindJccData);
  296. X(ReqBindJmpZero, ReqBindJccData);
  297. X(ReqBindJmpNZero, ReqBindJccData);
  298. X(SideExitGuardLoc, SideExitGuardData);
  299. X(SideExitGuardStk, SideExitGuardData);
  300. #undef X
  301. //////////////////////////////////////////////////////////////////////
  302. template<bool hasExtra, Opcode opc, class T> struct AssertExtraTypes {
  303. static void doassert() {
  304. assert(!"called extra on an opcode without extra data");
  305. }
  306. };
  307. template<Opcode opc, class T> struct AssertExtraTypes<true,opc,T> {
  308. static void doassert() {
  309. typedef typename IRExtraDataType<opc>::type ExtraType;
  310. if (!std::is_same<ExtraType,T>::value) {
  311. assert(!"extra<T> was called with an extra data "
  312. "type that doesn't match the opcode type");
  313. }
  314. }
  315. };
  316. // Asserts that Opcode opc has extradata and it is of type T.
  317. template<class T> void assert_opcode_extra(Opcode opc) {
  318. #define O(opcode, dstinfo, srcinfo, flags) \
  319. case opcode: \
  320. AssertExtraTypes< \
  321. OpHasExtraData<opcode>::value,opcode,T \
  322. >::doassert(); \
  323. break;
  324. switch (opc) { IR_OPCODES default: not_reached(); }
  325. #undef O
  326. }
  327. std::string showExtra(Opcode opc, const IRExtraData* data);
  328. //////////////////////////////////////////////////////////////////////
  329. }}
  330. #endif