OpCodeUtil.cpp 9.3 KB

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