c921dd813c65e0ccb3a86f91aa77bf8a1208143a
[WebKit-https.git] / Source / JavaScriptCore / bytecode / 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
40 namespace 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
56 const int maxOpcodeLength = 40;
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 #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
78 extern 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
136 IGNORE_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
142 IGNORE_WARNINGS_END
143
144 #if ENABLE(COMPUTED_GOTO_OPCODES)
145 typedef void* Opcode;
146 #else
147 typedef OpcodeID Opcode;
148 #endif
149
150 extern const char* const opcodeNames[];
151
152 #if ENABLE(OPCODE_STATS)
153
154 struct 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
167 inline 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
199 inline bool isUnconditionalBranch(OpcodeID opcodeID)
200 {
201     switch (opcodeID) {
202     case op_jmp:
203         return true;
204     default:
205         return false;
206     }
207 }
208
209 inline 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
221 inline 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
232 unsigned metadataSize(OpcodeID);
233 unsigned metadataAlignment(OpcodeID);
234
235 } // namespace JSC
236
237 namespace WTF {
238
239 class PrintStream;
240
241 void printInternal(PrintStream&, JSC::OpcodeID);
242
243 } // namespace WTF