/ bytecode / Opcode.h
Opcode.h
  1  /*
  2   * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
  3   * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
  4   *
  5   * Redistribution and use in source and binary forms, with or without
  6   * modification, are permitted provided that the following conditions
  7   * are met:
  8   *
  9   * 1.  Redistributions of source code must retain the above copyright
 10   *     notice, this list of conditions and the following disclaimer.
 11   * 2.  Redistributions in binary form must reproduce the above copyright
 12   *     notice, this list of conditions and the following disclaimer in the
 13   *     documentation and/or other materials provided with the distribution.
 14   * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 15   *     its contributors may be used to endorse or promote products derived
 16   *     from this software without specific prior written permission.
 17   *
 18   * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 19   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 20   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 21   * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 22   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 24   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 25   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 27   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28   */
 29  
 30  #pragma once
 31  
 32  #include "Bytecodes.h"
 33  #include "LLIntOpcode.h"
 34  
 35  #include <algorithm>
 36  #include <string.h>
 37  
 38  #include <wtf/Assertions.h>
 39  #include <wtf/MathExtras.h>
 40  
 41  namespace JSC {
 42  
 43  #define FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION(macro, extension__) \
 44      FOR_EACH_BYTECODE_ID(macro) \
 45      extension__
 46  
 47  #define FOR_EACH_CORE_OPCODE_ID(macro) \
 48      FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION(macro, /* No extension */ )
 49  
 50  #define FOR_EACH_OPCODE_ID(macro) \
 51      FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION( \
 52          macro, \
 53          FOR_EACH_LLINT_OPCODE_EXTENSION(macro) \
 54      )
 55  
 56  
 57  #if ENABLE(C_LOOP)
 58  const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_CLOOP_BYTECODE_HELPER_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
 59  #else
 60  const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
 61  #endif
 62  
 63  constexpr int numWasmOpcodeIDs = NUMBER_OF_WASM_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
 64  
 65  #define OPCODE_ID_ENUM(opcode, length) opcode,
 66      enum OpcodeID : unsigned { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) };
 67      enum WasmOpcodeID : unsigned { FOR_EACH_WASM_ID(OPCODE_ID_ENUM) };
 68  #undef OPCODE_ID_ENUM
 69  
 70  #if ENABLE(C_LOOP) && !HAVE(COMPUTED_GOTO)
 71  
 72  #define OPCODE_ID_ENUM(opcode, length) opcode##_wide16 = numOpcodeIDs + opcode,
 73      enum OpcodeIDWide16 : unsigned { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) };
 74      enum WasmOpcodeIDWide16 : unsigned { FOR_EACH_WASM_ID(OPCODE_ID_ENUM) };
 75  #undef OPCODE_ID_ENUM
 76  
 77  #define OPCODE_ID_ENUM(opcode, length) opcode##_wide32 = numOpcodeIDs * 2 + opcode,
 78      enum OpcodeIDWide32 : unsigned { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) };
 79      enum WasmOpcodeIDWide32 : unsigned { FOR_EACH_WASM_ID(OPCODE_ID_ENUM) };
 80  #undef OPCODE_ID_ENUM
 81  #endif
 82  
 83  extern const unsigned opcodeLengths[];
 84  extern const unsigned wasmOpcodeLengths[];
 85  
 86  #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
 87      FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS);
 88      FOR_EACH_WASM_ID(OPCODE_ID_LENGTHS);
 89  #undef OPCODE_ID_LENGTHS
 90  
 91  static constexpr unsigned maxJSOpcodeLength = /* Opcode */ 1 + /* Wide32 Opcode */ 1 + /* Operands */ (MAX_LENGTH_OF_BYTECODE_IDS - 1) * 4;
 92  static constexpr unsigned maxWasmOpcodeLength = /* Opcode */ 1 + /* Wide32 Opcode */ 1 + /* Operands */ (MAX_LENGTH_OF_WASM_IDS - 1) * 4;
 93  static constexpr unsigned maxOpcodeLength = std::max(maxJSOpcodeLength, maxWasmOpcodeLength);
 94  static constexpr unsigned bitWidthForMaxOpcodeLength = WTF::getMSBSetConstexpr(maxOpcodeLength) + 1;
 95  
 96  #define FOR_EACH_OPCODE_WITH_VALUE_PROFILE(macro) \
 97      macro(OpCallVarargs) \
 98      macro(OpTailCallVarargs) \
 99      macro(OpTailCallForwardArguments) \
100      macro(OpConstructVarargs) \
101      macro(OpGetByVal) \
102      macro(OpGetDirectPname) \
103      macro(OpGetById) \
104      macro(OpGetByIdWithThis) \
105      macro(OpTryGetById) \
106      macro(OpGetByIdDirect) \
107      macro(OpGetByValWithThis) \
108      macro(OpGetPrototypeOf) \
109      macro(OpGetFromArguments) \
110      macro(OpToNumber) \
111      macro(OpToNumeric) \
112      macro(OpToObject) \
113      macro(OpGetArgument) \
114      macro(OpGetInternalField) \
115      macro(OpToThis) \
116      macro(OpCall) \
117      macro(OpTailCall) \
118      macro(OpCallEval) \
119      macro(OpConstruct) \
120      macro(OpGetFromScope) \
121      macro(OpBitand) \
122      macro(OpBitor) \
123      macro(OpBitnot) \
124      macro(OpBitxor) \
125      macro(OpLshift) \
126      macro(OpRshift) \
127      macro(OpGetPrivateName) \
128  
129  #define FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(macro) \
130      macro(OpHasEnumerableIndexedProperty) \
131      macro(OpCallVarargs) \
132      macro(OpTailCallVarargs) \
133      macro(OpTailCallForwardArguments) \
134      macro(OpConstructVarargs) \
135      macro(OpGetByVal) \
136      macro(OpInByVal) \
137      macro(OpPutByVal) \
138      macro(OpPutByValDirect) \
139  
140  #define FOR_EACH_OPCODE_WITH_ARRAY_ALLOCATION_PROFILE(macro) \
141      macro(OpNewArray) \
142      macro(OpNewArrayWithSize) \
143      macro(OpNewArrayBuffer) \
144  
145  #define FOR_EACH_OPCODE_WITH_OBJECT_ALLOCATION_PROFILE(macro) \
146      macro(OpNewObject) \
147  
148  #define FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(macro) \
149      macro(OpCall) \
150      macro(OpTailCall) \
151      macro(OpCallEval) \
152      macro(OpConstruct) \
153      macro(OpIteratorOpen) \
154      macro(OpIteratorNext) \
155  
156  
157  IGNORE_WARNINGS_BEGIN("type-limits")
158  
159  #define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= numOpcodeIDs, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID);
160      FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
161  #undef VERIFY_OPCODE_ID
162  
163  IGNORE_WARNINGS_END
164  
165  #if ENABLE(COMPUTED_GOTO_OPCODES)
166  typedef void* Opcode;
167  #else
168  typedef OpcodeID Opcode;
169  #endif
170  
171  extern const char* const opcodeNames[];
172  extern const char* const wasmOpcodeNames[];
173  
174  #if ENABLE(OPCODE_STATS)
175  
176  struct OpcodeStats {
177      OpcodeStats();
178      ~OpcodeStats();
179      static long long opcodeCounts[numOpcodeIDs];
180      static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs];
181      static int lastOpcode;
182      
183      static void recordInstruction(int opcode);
184      static void resetLastInstruction();
185  };
186  
187  #endif
188  
189  inline bool isBranch(OpcodeID opcodeID)
190  {
191      switch (opcodeID) {
192      case op_jmp:
193      case op_jtrue:
194      case op_jfalse:
195      case op_jeq_null:
196      case op_jneq_null:
197      case op_jundefined_or_null:
198      case op_jnundefined_or_null:
199      case op_jneq_ptr:
200      case op_jless:
201      case op_jlesseq:
202      case op_jgreater:
203      case op_jgreatereq:
204      case op_jnless:
205      case op_jnlesseq:
206      case op_jngreater:
207      case op_jngreatereq:
208      case op_jeq:
209      case op_jneq:
210      case op_jstricteq:
211      case op_jnstricteq:
212      case op_jbelow:
213      case op_jbeloweq:
214      case op_switch_imm:
215      case op_switch_char:
216      case op_switch_string:
217          return true;
218      default:
219          return false;
220      }
221  }
222  
223  inline bool isUnconditionalBranch(OpcodeID opcodeID)
224  {
225      switch (opcodeID) {
226      case op_jmp:
227          return true;
228      default:
229          return false;
230      }
231  }
232  
233  inline bool isTerminal(OpcodeID opcodeID)
234  {
235      switch (opcodeID) {
236      case op_ret:
237      case op_end:
238      case op_unreachable:
239          return true;
240      default:
241          return false;
242      }
243  }
244  
245  inline bool isThrow(OpcodeID opcodeID)
246  {
247      switch (opcodeID) {
248      case op_throw:
249      case op_throw_static_error:
250          return true;
251      default:
252          return false;
253      }
254  }
255  
256  unsigned metadataSize(OpcodeID);
257  unsigned metadataAlignment(OpcodeID);
258  
259  } // namespace JSC
260  
261  namespace WTF {
262  
263  class PrintStream;
264  
265  void printInternal(PrintStream&, JSC::OpcodeID);
266  
267  } // namespace WTF