1/*
2 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <[email protected]>
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
40namespace JSC {
41
42#define FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION(macro, extension__) \
43 FOR_EACH_BYTECODE_ID(macro) \
44 extension__
45
46#define FOR_EACH_CORE_OPCODE_ID(macro) \
47 FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION(macro, /* No extension */ )
48
49#define FOR_EACH_OPCODE_ID(macro) \
50 FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION( \
51 macro, \
52 FOR_EACH_LLINT_OPCODE_EXTENSION(macro) \
53 )
54
55
56const int maxOpcodeLength = 40;
57#if ENABLE(C_LOOP)
58const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_CLOOP_BYTECODE_HELPER_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
59#else
60const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
61#endif
62
63constexpr 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
83extern const unsigned opcodeLengths[];
84extern 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#define FOR_EACH_OPCODE_WITH_VALUE_PROFILE(macro) \
92 macro(OpCallVarargs) \
93 macro(OpTailCallVarargs) \
94 macro(OpTailCallForwardArguments) \
95 macro(OpConstructVarargs) \
96 macro(OpGetByVal) \
97 macro(OpGetDirectPname) \
98 macro(OpGetById) \
99 macro(OpGetByIdWithThis) \
100 macro(OpTryGetById) \
101 macro(OpGetByIdDirect) \
102 macro(OpGetByValWithThis) \
103 macro(OpGetFromArguments) \
104 macro(OpToNumber) \
105 macro(OpToNumeric) \
106 macro(OpToObject) \
107 macro(OpGetArgument) \
108 macro(OpGetInternalField) \
109 macro(OpToThis) \
110 macro(OpCall) \
111 macro(OpTailCall) \
112 macro(OpCallEval) \
113 macro(OpConstruct) \
114 macro(OpGetFromScope) \
115 macro(OpBitand) \
116 macro(OpBitor) \
117 macro(OpBitnot) \
118 macro(OpBitxor) \
119 macro(OpLshift) \
120 macro(OpRshift) \
121
122#define FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(macro) \
123 macro(OpHasIndexedProperty) \
124 macro(OpCallVarargs) \
125 macro(OpTailCallVarargs) \
126 macro(OpTailCallForwardArguments) \
127 macro(OpConstructVarargs) \
128 macro(OpGetByVal) \
129 macro(OpInByVal) \
130 macro(OpPutByVal) \
131 macro(OpPutByValDirect) \
132
133#define FOR_EACH_OPCODE_WITH_ARRAY_ALLOCATION_PROFILE(macro) \
134 macro(OpNewArray) \
135 macro(OpNewArrayWithSize) \
136 macro(OpNewArrayBuffer) \
137
138#define FOR_EACH_OPCODE_WITH_OBJECT_ALLOCATION_PROFILE(macro) \
139 macro(OpNewObject) \
140
141#define FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(macro) \
142 macro(OpCall) \
143 macro(OpTailCall) \
144 macro(OpCallEval) \
145 macro(OpConstruct) \
146
147IGNORE_WARNINGS_BEGIN("type-limits")
148
149#define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= numOpcodeIDs, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID);
150 FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
151#undef VERIFY_OPCODE_ID
152
153IGNORE_WARNINGS_END
154
155#if ENABLE(COMPUTED_GOTO_OPCODES)
156typedef void* Opcode;
157#else
158typedef OpcodeID Opcode;
159#endif
160
161extern const char* const opcodeNames[];
162extern const char* const wasmOpcodeNames[];
163
164#if ENABLE(OPCODE_STATS)
165
166struct OpcodeStats {
167 OpcodeStats();
168 ~OpcodeStats();
169 static long long opcodeCounts[numOpcodeIDs];
170 static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs];
171 static int lastOpcode;
172
173 static void recordInstruction(int opcode);
174 static void resetLastInstruction();
175};
176
177#endif
178
179inline bool isBranch(OpcodeID opcodeID)
180{
181 switch (opcodeID) {
182 case op_jmp:
183 case op_jtrue:
184 case op_jfalse:
185 case op_jeq_null:
186 case op_jneq_null:
187 case op_jundefined_or_null:
188 case op_jnundefined_or_null:
189 case op_jneq_ptr:
190 case op_jless:
191 case op_jlesseq:
192 case op_jgreater:
193 case op_jgreatereq:
194 case op_jnless:
195 case op_jnlesseq:
196 case op_jngreater:
197 case op_jngreatereq:
198 case op_jeq:
199 case op_jneq:
200 case op_jstricteq:
201 case op_jnstricteq:
202 case op_jbelow:
203 case op_jbeloweq:
204 case op_switch_imm:
205 case op_switch_char:
206 case op_switch_string:
207 return true;
208 default:
209 return false;
210 }
211}
212
213inline bool isUnconditionalBranch(OpcodeID opcodeID)
214{
215 switch (opcodeID) {
216 case op_jmp:
217 return true;
218 default:
219 return false;
220 }
221}
222
223inline bool isTerminal(OpcodeID opcodeID)
224{
225 switch (opcodeID) {
226 case op_ret:
227 case op_end:
228 case op_unreachable:
229 return true;
230 default:
231 return false;
232 }
233}
234
235inline bool isThrow(OpcodeID opcodeID)
236{
237 switch (opcodeID) {
238 case op_throw:
239 case op_throw_static_error:
240 return true;
241 default:
242 return false;
243 }
244}
245
246unsigned metadataSize(OpcodeID);
247unsigned metadataAlignment(OpcodeID);
248
249} // namespace JSC
250
251namespace WTF {
252
253class PrintStream;
254
255void printInternal(PrintStream&, JSC::OpcodeID);
256
257} // namespace WTF
258