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
63#define OPCODE_ID_ENUM(opcode, length) opcode,
64 enum OpcodeID : unsigned { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) };
65#undef OPCODE_ID_ENUM
66
67#if ENABLE(C_LOOP) && !HAVE(COMPUTED_GOTO)
68
69#define OPCODE_ID_ENUM(opcode, length) opcode##_wide16 = numOpcodeIDs + opcode,
70 enum OpcodeIDWide16 : unsigned { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) };
71#undef OPCODE_ID_ENUM
72
73#define OPCODE_ID_ENUM(opcode, length) opcode##_wide32 = numOpcodeIDs * 2 + opcode,
74 enum OpcodeIDWide32 : unsigned { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) };
75#undef OPCODE_ID_ENUM
76#endif
77
78extern const unsigned opcodeLengths[];
79
80#define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
81 FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS);
82#undef OPCODE_ID_LENGTHS
83
84#define FOR_EACH_OPCODE_WITH_VALUE_PROFILE(macro) \
85 macro(OpCallVarargs) \
86 macro(OpTailCallVarargs) \
87 macro(OpTailCallForwardArguments) \
88 macro(OpConstructVarargs) \
89 macro(OpGetByVal) \
90 macro(OpGetDirectPname) \
91 macro(OpGetById) \
92 macro(OpGetByIdWithThis) \
93 macro(OpTryGetById) \
94 macro(OpGetByIdDirect) \
95 macro(OpGetByValWithThis) \
96 macro(OpGetFromArguments) \
97 macro(OpToNumber) \
98 macro(OpToObject) \
99 macro(OpGetArgument) \
100 macro(OpToThis) \
101 macro(OpCall) \
102 macro(OpTailCall) \
103 macro(OpCallEval) \
104 macro(OpConstruct) \
105 macro(OpGetFromScope) \
106 macro(OpBitand) \
107 macro(OpBitor) \
108 macro(OpBitnot) \
109 macro(OpBitxor) \
110
111#define FOR_EACH_OPCODE_WITH_ARRAY_PROFILE(macro) \
112 macro(OpHasIndexedProperty) \
113 macro(OpCallVarargs) \
114 macro(OpTailCallVarargs) \
115 macro(OpTailCallForwardArguments) \
116 macro(OpConstructVarargs) \
117 macro(OpGetByVal) \
118 macro(OpInByVal) \
119 macro(OpPutByVal) \
120 macro(OpPutByValDirect) \
121
122#define FOR_EACH_OPCODE_WITH_ARRAY_ALLOCATION_PROFILE(macro) \
123 macro(OpNewArray) \
124 macro(OpNewArrayWithSize) \
125 macro(OpNewArrayBuffer) \
126
127#define FOR_EACH_OPCODE_WITH_OBJECT_ALLOCATION_PROFILE(macro) \
128 macro(OpNewObject) \
129
130#define FOR_EACH_OPCODE_WITH_LLINT_CALL_LINK_INFO(macro) \
131 macro(OpCall) \
132 macro(OpTailCall) \
133 macro(OpCallEval) \
134 macro(OpConstruct) \
135
136IGNORE_WARNINGS_BEGIN("type-limits")
137
138#define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= numOpcodeIDs, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID);
139 FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
140#undef VERIFY_OPCODE_ID
141
142IGNORE_WARNINGS_END
143
144#if ENABLE(COMPUTED_GOTO_OPCODES)
145typedef void* Opcode;
146#else
147typedef OpcodeID Opcode;
148#endif
149
150extern const char* const opcodeNames[];
151
152#if ENABLE(OPCODE_STATS)
153
154struct OpcodeStats {
155 OpcodeStats();
156 ~OpcodeStats();
157 static long long opcodeCounts[numOpcodeIDs];
158 static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs];
159 static int lastOpcode;
160
161 static void recordInstruction(int opcode);
162 static void resetLastInstruction();
163};
164
165#endif
166
167inline bool isBranch(OpcodeID opcodeID)
168{
169 switch (opcodeID) {
170 case op_jmp:
171 case op_jtrue:
172 case op_jfalse:
173 case op_jeq_null:
174 case op_jneq_null:
175 case op_jneq_ptr:
176 case op_jless:
177 case op_jlesseq:
178 case op_jgreater:
179 case op_jgreatereq:
180 case op_jnless:
181 case op_jnlesseq:
182 case op_jngreater:
183 case op_jngreatereq:
184 case op_jeq:
185 case op_jneq:
186 case op_jstricteq:
187 case op_jnstricteq:
188 case op_jbelow:
189 case op_jbeloweq:
190 case op_switch_imm:
191 case op_switch_char:
192 case op_switch_string:
193 return true;
194 default:
195 return false;
196 }
197}
198
199inline bool isUnconditionalBranch(OpcodeID opcodeID)
200{
201 switch (opcodeID) {
202 case op_jmp:
203 return true;
204 default:
205 return false;
206 }
207}
208
209inline bool isTerminal(OpcodeID opcodeID)
210{
211 switch (opcodeID) {
212 case op_ret:
213 case op_end:
214 case op_unreachable:
215 return true;
216 default:
217 return false;
218 }
219}
220
221inline bool isThrow(OpcodeID opcodeID)
222{
223 switch (opcodeID) {
224 case op_throw:
225 case op_throw_static_error:
226 return true;
227 default:
228 return false;
229 }
230}
231
232unsigned metadataSize(OpcodeID);
233unsigned metadataAlignment(OpcodeID);
234
235} // namespace JSC
236
237namespace WTF {
238
239class PrintStream;
240
241void printInternal(PrintStream&, JSC::OpcodeID);
242
243} // namespace WTF
244