BackEndOpcodeAttr.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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. #include "BackEndOpcodeAttr.h"
  7. namespace OpCodeAttr
  8. {
  9. // OpSideEffect:
  10. // Opcode has side effect not just to the dst/src on the instruction.
  11. // The opcode cannot be deadstored. (e.g. StFld, LdFld from DOM, call valueOf/toString/getter/setter)
  12. // Doesn't include all "exit" script (e.g. LdThis doesn't have side effect for HostDispatch for exiting script to getting the name space parent)
  13. // OpHasImplicitCall:
  14. // Include all possible exit scripts, call valueOf/toString/getter/setter
  15. // OpSerialized:
  16. // Op is a serialized (indirected) variant of another op code
  17. enum OpCodeAttrEnum
  18. {
  19. None = 0x00000000,
  20. OpSideEffect = 0x00000001, // If dst is unused and src can’t call implicitcalls, it still can not be dead-stored (Could throw an exception, etc)
  21. OpUseAllFields = 0x00000002,
  22. OpTempNumberSources = 0x00000004, // OpCode does support temp values as source
  23. OpTempNumberProducing = 0x00000008, // OpCode can produce a temp value
  24. OpTempNumberTransfer = 0x00000010 | OpTempNumberSources, // OpCode transfers a temp value
  25. OpTempObjectSources = 0x00000020, // OpCode does support temp values as source
  26. OpTempObjectProducing = 0x00000040, // OpCode can produce a temp value
  27. OpTempObjectTransfer = 0x00000080 | OpTempObjectSources, // OpCode transfers a temp value
  28. OpTempObjectCanStoreTemp = 0x00000100 | OpTempObjectProducing, // OpCode can produce a temp value, and once marked, it will always produce a temp value so we can store other temp value in the object
  29. OpInlineCallInstr = 0x00000200,
  30. OpCallsValueOf = 0x00000400, // Could have valueOf/ToString side-effect
  31. OpCallInstr = 0x00000800,
  32. OpDoNotTransfer = 0x00001000,
  33. OpHasImplicitCall = 0x00002000, // Evaluating the src may call JS user code implicitly (getters/setters/valueof/tostring/DOM callbacks/etc)
  34. OpFastFldInstr = 0x00004000,
  35. OpBailOutRec = 0x00008000,
  36. OpInlinableBuiltIn = 0x00010000, // OpCode is an inlineable built-in, such as InlineMathSin, etc.
  37. OpNonIntTransfer = 0x00020000, // OpCode may transfer a non-integer value from the non-constant source to the destination
  38. OpIsInt32 = 0x00040000, // OpCode converts its srcs to int32 or a narrower int type, and produces an int32
  39. OpProducesNumber = 0x00080000, // OpCode always produces a number
  40. OpCanLoadFixedFields = 0x00100000, // OpCode can use fixed fields
  41. OpCanCSE = 0x00200000, // Opcode has no side-effect and always produces the same value for a given input (InlineMathAbs is OK, InlineMathRandom is not)
  42. OpNoFallThrough = 0x00400000, // Opcode doesn't fallthrough in flow and it always jumps to the return from this opcode
  43. OpPostOpDbgBailOut = 0x00800000, // Generate bail out after this opcode. This must be a helper call and needs bailout on return from it. Used for Fast F12.
  44. OpHasMultiSizeLayout = 0x01000000,
  45. OpHasProfiled = 0x02000000,
  46. OpHasProfiledWithICIndex = 0x04000000,
  47. OpDeadFallThrough = 0x08000000,
  48. OpProfiled = 0x10000000, // OpCode is a profiled variant
  49. OpProfiledWithICIndex = 0x20000000, // OpCode is a profiled with IC index variant
  50. OpBackEndOnly = 0x40000000,
  51. OpByteCodeOnly = 0x80000000,
  52. };
  53. static const int OpcodeAttributes[] =
  54. {
  55. #define DEF_OP(name, jnLayout, attrib, ...) attrib,
  56. #include "ByteCode\OpCodeList.h"
  57. #undef DEF_OP
  58. };
  59. static const int ExtendedOpcodeAttributes[] =
  60. {
  61. #define DEF_OP(name, jnLayout, attrib, ...) attrib,
  62. #include "ByteCode\ExtendedOpCodeList.h"
  63. #undef DEF_OP
  64. };
  65. static const int BackendOpCodeAttributes[] =
  66. {
  67. #define DEF_OP(name, jnLayout, attrib, ...) attrib,
  68. #include "BackendOpCodeList.h"
  69. #undef DEF_OP
  70. };
  71. static const int GetOpCodeAttributes(Js::OpCode op)
  72. {
  73. if (op <= Js::OpCode::MaxByteSizedOpcodes)
  74. {
  75. AnalysisAssert(op < _countof(OpcodeAttributes));
  76. return OpcodeAttributes[(int)op];
  77. }
  78. else if (op < Js::OpCode::ByteCodeLast)
  79. {
  80. uint opIndex = op - (Js::OpCode::MaxByteSizedOpcodes + 1);
  81. AnalysisAssert(opIndex < _countof(ExtendedOpcodeAttributes));
  82. return ExtendedOpcodeAttributes[opIndex];
  83. }
  84. uint opIndex = op - (Js::OpCode::ByteCodeLast + 1);
  85. AnalysisAssert(opIndex < _countof(BackendOpCodeAttributes));
  86. return BackendOpCodeAttributes[opIndex];
  87. }
  88. bool HasSideEffects(Js::OpCode opcode)
  89. {
  90. return ((GetOpCodeAttributes(opcode) & OpSideEffect) != 0);
  91. };
  92. bool CanCSE(Js::OpCode opcode)
  93. {
  94. Assert(((GetOpCodeAttributes(opcode) & OpCanCSE) == 0) || ((GetOpCodeAttributes(opcode) & OpSideEffect) == 0));
  95. return ((GetOpCodeAttributes(opcode) & OpCanCSE) != 0);
  96. };
  97. bool UseAllFields(Js::OpCode opcode)
  98. {
  99. return ((GetOpCodeAttributes(opcode) & OpUseAllFields) != 0);
  100. }
  101. bool NonTempNumberSources(Js::OpCode opcode)
  102. {
  103. return ((GetOpCodeAttributes(opcode) & OpTempNumberSources) == 0);
  104. }
  105. bool TempNumberSources(Js::OpCode opcode)
  106. {
  107. return ((GetOpCodeAttributes(opcode) & OpTempNumberSources) != 0);
  108. }
  109. bool TempNumberProducing(Js::OpCode opcode)
  110. {
  111. return ((GetOpCodeAttributes(opcode) & OpTempNumberProducing) != 0);
  112. }
  113. bool TempNumberTransfer(Js::OpCode opcode)
  114. {
  115. return ((GetOpCodeAttributes(opcode) & OpTempNumberTransfer) == OpTempNumberTransfer);
  116. }
  117. bool TempObjectSources(Js::OpCode opcode)
  118. {
  119. return ((GetOpCodeAttributes(opcode) & OpTempObjectSources) != 0);
  120. }
  121. bool TempObjectProducing(Js::OpCode opcode)
  122. {
  123. return ((GetOpCodeAttributes(opcode) & OpTempObjectProducing) != 0);
  124. }
  125. bool TempObjectTransfer(Js::OpCode opcode)
  126. {
  127. return ((GetOpCodeAttributes(opcode) & OpTempObjectTransfer) == OpTempObjectTransfer);
  128. }
  129. bool TempObjectCanStoreTemp(Js::OpCode opcode)
  130. {
  131. return ((GetOpCodeAttributes(opcode) & OpTempObjectCanStoreTemp) == OpTempObjectCanStoreTemp);
  132. }
  133. bool CallInstr(Js::OpCode opcode)
  134. {
  135. return ((GetOpCodeAttributes(opcode) & OpCallInstr) != 0);
  136. }
  137. bool InlineCallInstr(Js::OpCode opcode)
  138. {
  139. return ((GetOpCodeAttributes(opcode) & OpInlineCallInstr) != 0);
  140. }
  141. bool CallsValueOf(Js::OpCode opcode)
  142. {
  143. return ((GetOpCodeAttributes(opcode) & OpCallsValueOf) != 0);
  144. }
  145. bool FastFldInstr(Js::OpCode opcode)
  146. {
  147. return ((GetOpCodeAttributes(opcode) & OpFastFldInstr) != 0);
  148. }
  149. bool BailOutRec(Js::OpCode opcode)
  150. {
  151. return ((GetOpCodeAttributes(opcode) & OpBailOutRec) != 0);
  152. }
  153. bool ByteCodeOnly(Js::OpCode opcode)
  154. {
  155. return ((GetOpCodeAttributes(opcode) & OpByteCodeOnly) != 0);
  156. }
  157. bool BackEndOnly(Js::OpCode opcode)
  158. {
  159. return ((GetOpCodeAttributes(opcode) & OpBackEndOnly) != 0);
  160. }
  161. bool DoNotTransfer(Js::OpCode opcode)
  162. {
  163. return ((GetOpCodeAttributes(opcode) & OpDoNotTransfer) != 0);
  164. }
  165. bool HasImplicitCall(Js::OpCode opcode)
  166. {
  167. return ((GetOpCodeAttributes(opcode) & OpHasImplicitCall) != 0);
  168. }
  169. bool IsProfiledOp(Js::OpCode opcode)
  170. {
  171. return ((GetOpCodeAttributes(opcode) & OpProfiled) != 0);
  172. }
  173. bool IsProfiledOpWithICIndex(Js::OpCode opcode)
  174. {
  175. return ((GetOpCodeAttributes(opcode) & OpProfiledWithICIndex) != 0);
  176. }
  177. bool IsInlineBuiltIn(Js::OpCode opcode)
  178. {
  179. return ((GetOpCodeAttributes(opcode) & OpInlinableBuiltIn) != 0);
  180. }
  181. bool NonIntTransfer(Js::OpCode opcode)
  182. {
  183. return ((GetOpCodeAttributes(opcode) & OpNonIntTransfer) != 0);
  184. }
  185. bool IsInt32(Js::OpCode opcode)
  186. {
  187. return ((GetOpCodeAttributes(opcode) & OpIsInt32) != 0);
  188. }
  189. bool ProducesNumber(Js::OpCode opcode, Js::ScriptContext *const scriptContext)
  190. {
  191. return ((GetOpCodeAttributes(opcode) & OpProducesNumber) != 0);
  192. }
  193. bool HasFallThrough(Js::OpCode opcode)
  194. {
  195. return ((GetOpCodeAttributes(opcode) & OpNoFallThrough) == 0);
  196. }
  197. bool NeedsPostOpDbgBailOut(Js::OpCode opcode)
  198. {
  199. return ((GetOpCodeAttributes(opcode) & OpPostOpDbgBailOut) != 0);
  200. }
  201. bool HasMultiSizeLayout(Js::OpCode opcode)
  202. {
  203. return ((GetOpCodeAttributes(opcode) & OpHasMultiSizeLayout) != 0);
  204. }
  205. bool HasProfiledOp(Js::OpCode opcode)
  206. {
  207. return ((GetOpCodeAttributes(opcode) & OpHasProfiled) != 0);
  208. }
  209. bool HasProfiledOpWithICIndex(Js::OpCode opcode)
  210. {
  211. return ((GetOpCodeAttributes(opcode) & OpHasProfiledWithICIndex) != 0);
  212. }
  213. bool HasDeadFallThrough(Js::OpCode opcode)
  214. {
  215. return ((GetOpCodeAttributes(opcode) & OpDeadFallThrough) != 0);
  216. }
  217. bool CanLoadFixedFields(Js::OpCode opcode)
  218. {
  219. return ((GetOpCodeAttributes(opcode) & OpCanLoadFixedFields) != 0);
  220. }
  221. }; // OpCodeAttr