OpCodeUtil.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeByteCodePch.h"
  6. namespace Js
  7. {
  8. bool OpCodeUtil::IsPrefixOpcode(OpCode op)
  9. {
  10. return op <= OpCode::ExtendedLargeLayoutPrefix && op != OpCode::EndOfBlock;
  11. }
  12. bool OpCodeUtil::IsSmallEncodedOpcode(OpCode op)
  13. {
  14. return op <= Js::OpCode::MaxByteSizedOpcodes;
  15. }
  16. uint OpCodeUtil::EncodedSize(OpCode op, LayoutSize layoutSize)
  17. {
  18. return (layoutSize == SmallLayout && IsSmallEncodedOpcode(op)) ? sizeof(BYTE) : sizeof(OpCode);
  19. }
  20. void OpCodeUtil::ConvertOpToNonProfiled(OpCode& op)
  21. {
  22. if (IsProfiledCallOp(op) || IsProfiledCallOpWithICIndex(op))
  23. {
  24. op = ConvertProfiledCallOpToNonProfiled(op);
  25. }
  26. else if (IsProfiledReturnTypeCallOp(op))
  27. {
  28. op = ConvertProfiledReturnTypeCallOpToNonProfiled(op);
  29. }
  30. else
  31. {
  32. ConvertNonCallOpToNonProfiled(op);
  33. }
  34. }
  35. void OpCodeUtil::ConvertNonCallOpToProfiled(OpCode& op)
  36. {
  37. Assert(OpCodeAttr::HasProfiledOp(op));
  38. op += 1;
  39. Assert(OpCodeAttr::IsProfiledOp(op));
  40. }
  41. void OpCodeUtil::ConvertNonCallOpToProfiledWithICIndex(OpCode& op)
  42. {
  43. Assert(OpCodeAttr::HasProfiledOp(op) && OpCodeAttr::HasProfiledOpWithICIndex(op));
  44. op += 2;
  45. Assert(OpCodeAttr::IsProfiledOpWithICIndex(op));
  46. }
  47. void OpCodeUtil::ConvertNonCallOpToNonProfiled(OpCode& op)
  48. {
  49. if (OpCodeAttr::IsProfiledOp(op))
  50. {
  51. op -= 1;
  52. Assert(OpCodeAttr::HasProfiledOp(op));
  53. }
  54. else if (OpCodeAttr::IsProfiledOpWithICIndex(op))
  55. {
  56. op -= 2;
  57. Assert(OpCodeAttr::HasProfiledOpWithICIndex(op));
  58. }
  59. else
  60. {
  61. Assert(false);
  62. }
  63. }
  64. bool OpCodeUtil::IsCallOp(OpCode op)
  65. {
  66. return op >= Js::OpCode::CallI && op <= Js::OpCode::CallIExtendedFlags;
  67. }
  68. bool OpCodeUtil::IsProfiledCallOp(OpCode op)
  69. {
  70. return op >= Js::OpCode::ProfiledCallI && op <= Js::OpCode::ProfiledCallIExtendedFlags;
  71. }
  72. bool OpCodeUtil::IsProfiledCallOpWithICIndex(OpCode op)
  73. {
  74. return op >= Js::OpCode::ProfiledCallIWithICIndex && op <= Js::OpCode::ProfiledCallIExtendedFlagsWithICIndex;
  75. }
  76. bool OpCodeUtil::IsProfiledReturnTypeCallOp(OpCode op)
  77. {
  78. return op >= Js::OpCode::ProfiledReturnTypeCallI && op <= Js::OpCode::ProfiledReturnTypeCallIExtendedFlags;
  79. }
  80. #if DBG
  81. OpCode OpCodeUtil::DebugConvertProfiledCallToNonProfiled(OpCode op)
  82. {
  83. switch (op)
  84. {
  85. case Js::OpCode::ProfiledCallI:
  86. case Js::OpCode::ProfiledCallIWithICIndex:
  87. return Js::OpCode::CallI;
  88. case Js::OpCode::ProfiledCallIFlags:
  89. case Js::OpCode::ProfiledCallIFlagsWithICIndex:
  90. return Js::OpCode::CallIFlags;
  91. case Js::OpCode::ProfiledCallIExtendedFlags:
  92. case Js::OpCode::ProfiledCallIExtendedFlagsWithICIndex:
  93. return Js::OpCode::CallIExtendedFlags;
  94. case Js::OpCode::ProfiledCallIExtended:
  95. case Js::OpCode::ProfiledCallIExtendedWithICIndex:
  96. return Js::OpCode::CallIExtended;
  97. default:
  98. Assert(false);
  99. };
  100. return Js::OpCode::Nop;
  101. }
  102. OpCode OpCodeUtil::DebugConvertProfiledReturnTypeCallToNonProfiled(OpCode op)
  103. {
  104. switch (op)
  105. {
  106. case Js::OpCode::ProfiledReturnTypeCallI:
  107. return Js::OpCode::CallI;
  108. case Js::OpCode::ProfiledReturnTypeCallIFlags:
  109. return Js::OpCode::CallIFlags;
  110. case Js::OpCode::ProfiledReturnTypeCallIExtendedFlags:
  111. return Js::OpCode::CallIExtendedFlags;
  112. case Js::OpCode::ProfiledReturnTypeCallIExtended:
  113. return Js::OpCode::CallIExtended;
  114. default:
  115. Assert(false);
  116. };
  117. return Js::OpCode::Nop;
  118. }
  119. #endif
  120. OpCode OpCodeUtil::ConvertProfiledCallOpToNonProfiled(OpCode op)
  121. {
  122. OpCode newOpcode;
  123. if (IsProfiledCallOp(op))
  124. {
  125. newOpcode = (OpCode)(op - Js::OpCode::ProfiledCallI + Js::OpCode::CallI);
  126. }
  127. else if (IsProfiledCallOpWithICIndex(op))
  128. {
  129. newOpcode = (OpCode)(op - Js::OpCode::ProfiledCallIWithICIndex + Js::OpCode::CallI);
  130. }
  131. else
  132. {
  133. Assert(false);
  134. __assume(false);
  135. }
  136. Assert(DebugConvertProfiledCallToNonProfiled(op) == newOpcode);
  137. return newOpcode;
  138. }
  139. OpCode OpCodeUtil::ConvertProfiledReturnTypeCallOpToNonProfiled(OpCode op)
  140. {
  141. OpCode newOpcode;
  142. if (IsProfiledReturnTypeCallOp(op))
  143. {
  144. newOpcode = (OpCode)(op - Js::OpCode::ProfiledReturnTypeCallI + Js::OpCode::CallI);
  145. }
  146. else
  147. {
  148. Assert(false);
  149. __assume(false);
  150. }
  151. Assert(DebugConvertProfiledReturnTypeCallToNonProfiled(op) == newOpcode);
  152. return newOpcode;
  153. }
  154. OpCode OpCodeUtil::ConvertCallOpToProfiled(OpCode op, bool withICIndex)
  155. {
  156. return (!withICIndex) ?
  157. (OpCode)(op - OpCode::CallI + OpCode::ProfiledCallI) :
  158. (OpCode)(op - OpCode::CallI + OpCode::ProfiledCallIWithICIndex);
  159. }
  160. OpCode OpCodeUtil::ConvertCallOpToProfiledReturnType(OpCode op)
  161. {
  162. return (OpCode)(op - OpCode::CallI + OpCode::ProfiledReturnTypeCallI);
  163. }
  164. CompileAssert(((int)Js::OpCode::CallIExtendedFlags - (int)Js::OpCode::CallI) == ((int)Js::OpCode::ProfiledCallIExtendedFlags - (int)Js::OpCode::ProfiledCallI));
  165. CompileAssert(((int)Js::OpCode::CallIExtendedFlags - (int)Js::OpCode::CallI) == ((int)Js::OpCode::ProfiledReturnTypeCallIExtendedFlags - (int)Js::OpCode::ProfiledReturnTypeCallI));
  166. CompileAssert(((int)Js::OpCode::CallIExtendedFlags - (int)Js::OpCode::CallI) == ((int)Js::OpCode::ProfiledCallIExtendedFlagsWithICIndex - (int)Js::OpCode::ProfiledCallIWithICIndex));
  167. // Only include the opcode name on debug and test build
  168. #if DBG_DUMP || ENABLE_DEBUG_CONFIG_OPTIONS
  169. char16 const * const OpCodeUtil::OpCodeNames[] =
  170. {
  171. #define DEF_OP(x, y, ...) _u("") STRINGIZEW(x) _u(""),
  172. #include "OpCodeList.h"
  173. #undef DEF_OP
  174. };
  175. char16 const * const OpCodeUtil::ExtendedOpCodeNames[] =
  176. {
  177. #define DEF_OP(x, y, ...) _u("") STRINGIZEW(x) _u(""),
  178. #include "ExtendedOpCodeList.h"
  179. #undef DEF_OP
  180. };
  181. char16 const * const OpCodeUtil::BackendOpCodeNames[] =
  182. {
  183. #define DEF_OP(x, y, ...) _u("") STRINGIZEW(x) _u(""),
  184. #include "BackendOpCodeList.h"
  185. #undef DEF_OP
  186. };
  187. char16 const * OpCodeUtil::GetOpCodeName(OpCode op)
  188. {
  189. if (op <= Js::OpCode::MaxByteSizedOpcodes)
  190. {
  191. Assert((uint)op < _countof(OpCodeNames));
  192. __analysis_assume((uint)op < _countof(OpCodeNames));
  193. return OpCodeNames[(uint)op];
  194. }
  195. else if (op < Js::OpCode::ByteCodeLast)
  196. {
  197. uint opIndex = op - (Js::OpCode::MaxByteSizedOpcodes + 1);
  198. Assert(opIndex < _countof(ExtendedOpCodeNames));
  199. __analysis_assume(opIndex < _countof(ExtendedOpCodeNames));
  200. return ExtendedOpCodeNames[opIndex];
  201. }
  202. uint opIndex = op - (Js::OpCode::ByteCodeLast + 1);
  203. Assert(opIndex < _countof(BackendOpCodeNames));
  204. __analysis_assume(opIndex < _countof(BackendOpCodeNames));
  205. return BackendOpCodeNames[opIndex];
  206. }
  207. #else
  208. wchar const * OpCodeUtil::GetOpCodeName(OpCode op)
  209. {
  210. return _u("<NotAvail>");
  211. }
  212. #endif
  213. OpLayoutType const OpCodeUtil::OpCodeLayouts[] =
  214. {
  215. #define DEF_OP(x, y, ...) OpLayoutType::y,
  216. #include "OpCodeList.h"
  217. };
  218. OpLayoutType const OpCodeUtil::ExtendedOpCodeLayouts[] =
  219. {
  220. #define DEF_OP(x, y, ...) OpLayoutType::y,
  221. #include "ExtendedOpCodeList.h"
  222. };
  223. OpLayoutType const OpCodeUtil::BackendOpCodeLayouts[] =
  224. {
  225. #define DEF_OP(x, y, ...) OpLayoutType::y,
  226. #include "BackendOpCodeList.h"
  227. };
  228. OpLayoutType OpCodeUtil::GetOpCodeLayout(OpCode op)
  229. {
  230. if ((uint)op <= (uint)Js::OpCode::MaxByteSizedOpcodes)
  231. {
  232. AnalysisAssert((uint)op < _countof(OpCodeLayouts));
  233. return OpCodeLayouts[(uint)op];
  234. }
  235. else if (op < Js::OpCode::ByteCodeLast)
  236. {
  237. uint opIndex = op - (Js::OpCode::MaxByteSizedOpcodes + 1);
  238. AnalysisAssert(opIndex < _countof(ExtendedOpCodeLayouts));
  239. return ExtendedOpCodeLayouts[opIndex];
  240. }
  241. uint opIndex = op - (Js::OpCode::ByteCodeLast + 1);
  242. AnalysisAssert(opIndex < _countof(BackendOpCodeLayouts));
  243. return BackendOpCodeLayouts[opIndex];
  244. }
  245. bool OpCodeUtil::IsValidByteCodeOpcode(OpCode op)
  246. {
  247. CompileAssert((int)Js::OpCode::MaxByteSizedOpcodes + 1 + _countof(OpCodeUtil::ExtendedOpCodeLayouts) == (int)Js::OpCode::ByteCodeLast);
  248. return (uint)op < _countof(OpCodeLayouts)
  249. || (op > Js::OpCode::MaxByteSizedOpcodes && op < Js::OpCode::ByteCodeLast);
  250. }
  251. bool OpCodeUtil::IsValidOpcode(OpCode op)
  252. {
  253. return IsValidByteCodeOpcode(op)
  254. || (op > Js::OpCode::ByteCodeLast && op < Js::OpCode::Count);
  255. }
  256. };