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