1/* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef BYTE_CODE_H
17#define BYTE_CODE_H
18
19#include "ecma-globals.h"
20
21/** \addtogroup parser Parser
22 * @{
23 *
24 * \addtogroup jsparser JavaScript
25 * @{
26 *
27 * \addtogroup jsparser_bytecode Bytecode
28 * @{
29 */
30
31/**
32 * Compact byte code (CBC) is a byte code representation
33 * of EcmaScript which is designed for low memory
34 * environments. Most opcodes are only one or sometimes
35 * two byte long so the CBC provides a small binary size.
36 *
37 * The execution engine of CBC is a stack machine, where
38 * the maximum stack size is known in advance for each
39 * function.
40 */
41
42/**
43 * Byte code flags. Only the lower 5 bit can be used
44 * since the stack change is encoded in the upper
45 * three bits for each instruction between -4 and 3
46 * (except for call / construct opcodes).
47 */
48#define CBC_STACK_ADJUST_BASE          4
49#define CBC_STACK_ADJUST_SHIFT         5
50#define CBC_STACK_ADJUST_VALUE(value)  \
51  (((value) >> CBC_STACK_ADJUST_SHIFT) - CBC_STACK_ADJUST_BASE)
52
53#define CBC_NO_FLAG                    0x00u
54#define CBC_HAS_LITERAL_ARG            0x01u
55#define CBC_HAS_LITERAL_ARG2           0x02u
56#define CBC_HAS_BYTE_ARG               0x04u
57#define CBC_HAS_BRANCH_ARG             0x08u
58
59/* These flags are shared */
60#define CBC_FORWARD_BRANCH_ARG         0x10u
61#define CBC_POP_STACK_BYTE_ARG         0x10u
62
63#define CBC_ARG_TYPES (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2 | CBC_HAS_BYTE_ARG | CBC_HAS_BRANCH_ARG)
64
65#define CBC_HAS_POP_STACK_BYTE_ARG (CBC_HAS_BYTE_ARG | CBC_POP_STACK_BYTE_ARG)
66
67#if ENABLED (JERRY_ES2015)
68/**
69 * CBC_NO_RESULT_OPERATION for ext opcodes
70 */
71#define CBC_EXT_NO_RESULT_OPERATION(opcode) \
72  ((opcode) >= PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL) \
73    && (opcode) <= PARSER_TO_EXT_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK))
74#else /* !ENABLED (JERRY_ES2015) */
75/**
76 * CBC_NO_RESULT_OPERATION for ext opcodes
77 */
78#define CBC_EXT_NO_RESULT_OPERATION(opcode) false
79#endif /* ENABLED (JERRY_ES2015) */
80
81/* Debug macro. */
82#define CBC_ARGS_EQ(op, types) \
83  ((cbc_flags[op] & CBC_ARG_TYPES) == (types))
84
85/* Debug macro. */
86#define CBC_SAME_ARGS(op1, op2) \
87  (CBC_EXT_NO_RESULT_OPERATION (op1) ? ((cbc_ext_flags[PARSER_GET_EXT_OPCODE (op1)] & CBC_ARG_TYPES) \
88                                         == (cbc_ext_flags[PARSER_GET_EXT_OPCODE (op2)] & CBC_ARG_TYPES)) \
89                                     : ((cbc_flags[op1] & CBC_ARG_TYPES) == (cbc_flags[op2] & CBC_ARG_TYPES)))
90
91#define CBC_UNARY_OPERATION(name, group) \
92  CBC_OPCODE (name, CBC_NO_FLAG, 0, \
93              (VM_OC_ ## group) | VM_OC_GET_STACK | VM_OC_PUT_STACK) \
94  CBC_OPCODE (name ## _LITERAL, CBC_HAS_LITERAL_ARG, 1, \
95              (VM_OC_ ## group) | VM_OC_GET_LITERAL | VM_OC_PUT_STACK)
96
97#define CBC_BINARY_OPERATION(name, group) \
98  CBC_OPCODE (name, CBC_NO_FLAG, -1, \
99              (VM_OC_ ## group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
100  CBC_OPCODE (name ## _RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0, \
101              (VM_OC_ ## group) | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \
102  CBC_OPCODE (name ## _TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1, \
103              (VM_OC_ ## group) | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK)
104
105#define CBC_UNARY_LVALUE_OPERATION(name, group) \
106  CBC_OPCODE (name, CBC_NO_FLAG, -2, \
107              (VM_OC_PROP_ ## group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE) \
108  CBC_OPCODE (name ## _PUSH_RESULT, CBC_NO_FLAG, -1, \
109              (VM_OC_PROP_ ## group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \
110  CBC_OPCODE (name ## _BLOCK, CBC_NO_FLAG, -2, \
111              (VM_OC_PROP_ ## group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \
112  CBC_OPCODE (name ## _IDENT, CBC_HAS_LITERAL_ARG, 0, \
113              (VM_OC_ ## group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
114  CBC_OPCODE (name ## _IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1, \
115              (VM_OC_ ## group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \
116  CBC_OPCODE (name ## _IDENT_BLOCK, CBC_HAS_LITERAL_ARG, 0, \
117              (VM_OC_ ## group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK)
118
119#define CBC_UNARY_LVALUE_WITH_IDENT 3
120
121#define CBC_BINARY_WITH_LITERAL 1
122#define CBC_BINARY_WITH_TWO_LITERALS 2
123
124/**
125 * Several opcodes (mostly call and assignment opcodes) have
126 * two forms: one which does not push a return value onto
127 * the stack, and another which does. The reason is that
128 * the return value of these opcodes are often not used
129 * and the first form provides smaller byte code.
130 *
131 * The following rules must be kept by the code generator:
132 *  - only the opcode without return value can be emitted
133 *    by the code generator
134 *  - the first form can be converted to the second form
135 *    by adding 1 to the opcode
136 *  - after the conversion the opcode must be immediately
137 *    flushed, so no further changes are possible
138 *
139 * Hence CBC_NO_RESULT_OPERATION (context_p->last_cbc_opcode)
140 * cannot be true for an opcode which has a result
141 */
142#define CBC_NO_RESULT_OPERATION(opcode) \
143  (((opcode) >= CBC_PRE_INCR && (opcode) < CBC_END) || CBC_EXT_NO_RESULT_OPERATION ((opcode)))
144
145/**
146 * Branch instructions are organized in group of 8 opcodes.
147 *  - 1st opcode: unused, can be used for other purpose
148 *  - 2nd opcode: forward branch with 1 byte offset
149 *  - 3rd opcode: forward branch with 2 byte offset
150 *  - 4th opcode: forward branch with 3 byte offset
151 *  - 5th opcode: unused, can be used for other purpose
152 *  - 6th opcode: backward branch with 1 byte offset
153 *  - 7th opcode: backward branch with 2 byte offset
154 *  - 8th opcode: backward branch with 3 byte offset
155 *
156 * Reasons:
157 *  The branch_opcode & 0x3 tells the length in bytes of the offset
158 *  If branch offset & 0x4 == 0, it is a forward branch. Otherwise
159 *  it is backward.
160 *
161 * The offset bytes are encoded in higher to lower order.
162 */
163
164#define CBC_FORWARD_BRANCH(name, stack, vm_oc) \
165  CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \
166              (vm_oc) | VM_OC_GET_BRANCH) \
167  CBC_OPCODE (name ## _2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \
168              (vm_oc) | VM_OC_GET_BRANCH) \
169  CBC_OPCODE (name ## _3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \
170              (vm_oc) | VM_OC_GET_BRANCH)
171
172#define CBC_BACKWARD_BRANCH(name, stack, vm_oc) \
173  CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack, \
174              (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \
175  CBC_OPCODE (name ## _2, CBC_HAS_BRANCH_ARG, stack, \
176              (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \
177  CBC_OPCODE (name ## _3, CBC_HAS_BRANCH_ARG, stack, \
178              (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH)
179
180#define CBC_BRANCH_OFFSET_LENGTH(opcode) \
181  ((opcode) & 0x3)
182
183#define CBC_BRANCH_IS_BACKWARD(flags) \
184  (!((flags) & CBC_FORWARD_BRANCH_ARG))
185
186#define CBC_BRANCH_IS_FORWARD(flags) \
187  ((flags) & CBC_FORWARD_BRANCH_ARG)
188
189/* Stack consumption of opcodes with context. */
190
191/* PARSER_TRY_CONTEXT_STACK_ALLOCATION must be <= 3 */
192#define PARSER_TRY_CONTEXT_STACK_ALLOCATION 2
193/* PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION must be <= 4 */
194#define PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION 4
195/* PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION must be <= 3 */
196#define PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION 3
197/* PARSER_WITH_CONTEXT_STACK_ALLOCATION must be <= 4 */
198#define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1
199/* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */
200#define PARSER_BLOCK_CONTEXT_STACK_ALLOCATION 1
201
202/**
203 * Opcode definitions.
204 */
205#define CBC_OPCODE_LIST \
206  /* Branch opcodes first. Some other opcodes are mixed. */ \
207  CBC_OPCODE (CBC_EXT_OPCODE, CBC_NO_FLAG, 0, \
208              VM_OC_NONE) \
209  CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD, 0, \
210                      VM_OC_JUMP) \
211  CBC_OPCODE (CBC_POP, CBC_NO_FLAG, -1, \
212              VM_OC_POP) \
213  CBC_BACKWARD_BRANCH (CBC_JUMP_BACKWARD, 0, \
214                       VM_OC_JUMP) \
215  CBC_OPCODE (CBC_POP_BLOCK, CBC_NO_FLAG, -1, \
216              VM_OC_POP_BLOCK | VM_OC_PUT_BLOCK) \
217  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD, -1, \
218                      VM_OC_BRANCH_IF_TRUE) \
219  CBC_OPCODE (CBC_THROW, CBC_NO_FLAG, -1, \
220              VM_OC_THROW | VM_OC_GET_STACK) \
221  CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD, -1, \
222                       VM_OC_BRANCH_IF_TRUE) \
223  CBC_OPCODE (CBC_CONTEXT_END, CBC_NO_FLAG, 0, \
224              VM_OC_CONTEXT_END) \
225  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD, -1, \
226                      VM_OC_BRANCH_IF_FALSE) \
227  CBC_OPCODE (CBC_CREATE_OBJECT, CBC_NO_FLAG, 1, \
228              VM_OC_PUSH_OBJECT | VM_OC_PUT_STACK) \
229  CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD, -1, \
230                       VM_OC_BRANCH_IF_FALSE) \
231  CBC_OPCODE (CBC_SET_PROPERTY, CBC_HAS_LITERAL_ARG, -1, \
232              VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \
233  CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT, 0, \
234                      VM_OC_JUMP_AND_EXIT_CONTEXT) \
235  CBC_OPCODE (CBC_CREATE_ARRAY, CBC_NO_FLAG, 1, \
236              VM_OC_PUSH_ARRAY | VM_OC_PUT_STACK) \
237  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1, \
238                      VM_OC_BRANCH_IF_LOGICAL_TRUE) \
239  CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
240              VM_OC_APPEND_ARRAY) \
241  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1, \
242                      VM_OC_BRANCH_IF_LOGICAL_FALSE) \
243  CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1, \
244              VM_OC_PUSH_ELISON | VM_OC_PUT_STACK) \
245  CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1, \
246                      VM_OC_BRANCH_IF_STRICT_EQUAL) \
247  CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, \
248              VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \
249  CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, \
250                      PARSER_BLOCK_CONTEXT_STACK_ALLOCATION, VM_OC_BLOCK_CREATE_CONTEXT) \
251  \
252  /* Basic opcodes. Note: These 4 opcodes must me in this order */ \
253  CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
254              VM_OC_PUSH | VM_OC_GET_LITERAL) \
255  CBC_OPCODE (CBC_PUSH_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 2, \
256              VM_OC_PUSH_TWO | VM_OC_GET_LITERAL_LITERAL) \
257  CBC_OPCODE (CBC_PUSH_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 2, \
258              VM_OC_PUSH_TWO | VM_OC_GET_THIS_LITERAL) \
259  CBC_OPCODE (CBC_PUSH_THREE_LITERALS, CBC_HAS_LITERAL_ARG2, 3, \
260              VM_OC_PUSH_THREE | VM_OC_GET_LITERAL_LITERAL) \
261  CBC_OPCODE (CBC_PUSH_UNDEFINED, CBC_NO_FLAG, 1, \
262              VM_OC_PUSH_UNDEFINED | VM_OC_PUT_STACK) \
263  CBC_OPCODE (CBC_PUSH_TRUE, CBC_NO_FLAG, 1, \
264              VM_OC_PUSH_TRUE | VM_OC_PUT_STACK) \
265  CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1, \
266              VM_OC_PUSH_FALSE | VM_OC_PUT_STACK) \
267  CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1, \
268              VM_OC_PUSH_THIS | VM_OC_PUT_STACK) \
269  CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1, \
270              VM_OC_PUSH_0 | VM_OC_PUT_STACK) \
271  CBC_OPCODE (CBC_PUSH_NUMBER_POS_BYTE, CBC_HAS_BYTE_ARG, 1, \
272              VM_OC_PUSH_POS_BYTE | VM_OC_PUT_STACK) \
273  CBC_OPCODE (CBC_PUSH_NUMBER_NEG_BYTE, CBC_HAS_BYTE_ARG, 1, \
274              VM_OC_PUSH_NEG_BYTE | VM_OC_PUT_STACK) \
275  /* Note: These 4 opcodes must me in this order */ \
276  CBC_OPCODE (CBC_PUSH_PROP, CBC_NO_FLAG, -1, \
277              VM_OC_PROP_GET | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
278  CBC_OPCODE (CBC_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 0, \
279              VM_OC_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \
280  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1, \
281              VM_OC_PROP_GET | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \
282  CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
283              VM_OC_PROP_GET | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \
284  CBC_OPCODE (CBC_PUSH_IDENT_REFERENCE, CBC_HAS_LITERAL_ARG, 3, \
285              VM_OC_IDENT_REFERENCE | VM_OC_PUT_STACK) \
286  /* Note: These 4 opcodes must me in this order */ \
287  CBC_OPCODE (CBC_PUSH_PROP_REFERENCE, CBC_NO_FLAG, 1, \
288              VM_OC_PROP_REFERENCE | VM_OC_PUT_STACK) \
289  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 2, \
290              VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) \
291  CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 3, \
292              VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \
293  CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, \
294              VM_OC_PROP_REFERENCE | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \
295  CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
296              VM_OC_NEW | VM_OC_PUT_STACK) \
297  CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, \
298              VM_OC_NEW | VM_OC_PUT_STACK) \
299  CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, \
300              VM_OC_NEW | VM_OC_PUT_STACK) \
301  CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, \
302              VM_OC_EVAL) \
303  CBC_OPCODE (CBC_CHECK_VAR, CBC_HAS_LITERAL_ARG, 0, \
304              VM_OC_CHECK_VAR) \
305  CBC_OPCODE (CBC_CHECK_LET, CBC_HAS_LITERAL_ARG, 0, \
306              VM_OC_CHECK_LET) \
307  CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0, \
308              VM_OC_CREATE_BINDING) \
309  CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0, \
310              VM_OC_CREATE_BINDING) \
311  CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0, \
312              VM_OC_CREATE_BINDING) \
313  CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, \
314              VM_OC_CREATE_BINDING) \
315  CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1, \
316              VM_OC_INIT_BINDING) \
317  CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1, \
318              VM_OC_INIT_BINDING) \
319  CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1, \
320              VM_OC_INIT_BINDING) \
321  CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
322              VM_OC_INIT_ARG_OR_FUNC) \
323  CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \
324              VM_OC_VAR_EVAL) \
325  CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
326              VM_OC_VAR_EVAL) \
327  CBC_OPCODE (CBC_SET_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
328              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
329  CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, \
330              VM_OC_SET_BYTECODE_PTR) \
331  CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, \
332              VM_OC_RETURN | VM_OC_GET_STACK) \
333  CBC_OPCODE (CBC_RETURN_WITH_BLOCK, CBC_NO_FLAG, 0, \
334              VM_OC_RETURN) \
335  CBC_OPCODE (CBC_RETURN_WITH_LITERAL, CBC_HAS_LITERAL_ARG, 0, \
336              VM_OC_RETURN | VM_OC_GET_LITERAL) \
337  CBC_OPCODE (CBC_SET_LITERAL_PROPERTY, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
338              VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \
339  CBC_OPCODE (CBC_COPY_TO_GLOBAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
340              VM_OC_COPY_TO_GLOBAL | VM_OC_GET_LITERAL) \
341  CBC_OPCODE (CBC_BREAKPOINT_ENABLED, CBC_NO_FLAG, 0, \
342              VM_OC_BREAKPOINT_ENABLED) \
343  CBC_OPCODE (CBC_BREAKPOINT_DISABLED, CBC_NO_FLAG, 0, \
344              VM_OC_BREAKPOINT_DISABLED) \
345  \
346  /* Unary opcodes. */ \
347  CBC_UNARY_OPERATION (CBC_PLUS, \
348                       PLUS) \
349  CBC_UNARY_OPERATION (CBC_NEGATE, \
350                       MINUS) \
351  CBC_UNARY_OPERATION (CBC_LOGICAL_NOT, \
352                       NOT) \
353  CBC_UNARY_OPERATION (CBC_BIT_NOT, \
354                       BIT_NOT) \
355  CBC_UNARY_OPERATION (CBC_VOID, \
356                       VOID) \
357  CBC_OPCODE (CBC_TYPEOF, CBC_NO_FLAG, 0, \
358              VM_OC_TYPEOF | VM_OC_GET_STACK | VM_OC_PUT_STACK) \
359  CBC_OPCODE (CBC_TYPEOF_IDENT, CBC_HAS_LITERAL_ARG, 1, \
360              VM_OC_TYPEOF_IDENT | VM_OC_PUT_STACK) \
361  \
362  /* Binary opcodes. */ \
363  CBC_BINARY_OPERATION (CBC_BIT_OR, \
364                        BIT_OR) \
365  CBC_BINARY_OPERATION (CBC_BIT_XOR, \
366                        BIT_XOR) \
367  CBC_BINARY_OPERATION (CBC_BIT_AND, \
368                        BIT_AND) \
369  CBC_BINARY_OPERATION (CBC_EQUAL, \
370                        EQUAL) \
371  CBC_BINARY_OPERATION (CBC_NOT_EQUAL, \
372                        NOT_EQUAL) \
373  CBC_BINARY_OPERATION (CBC_STRICT_EQUAL, \
374                        STRICT_EQUAL) \
375  CBC_BINARY_OPERATION (CBC_STRICT_NOT_EQUAL, \
376                        STRICT_NOT_EQUAL) \
377  CBC_BINARY_OPERATION (CBC_LESS, \
378                        LESS) \
379  CBC_BINARY_OPERATION (CBC_GREATER, \
380                        GREATER) \
381  CBC_BINARY_OPERATION (CBC_LESS_EQUAL, \
382                        LESS_EQUAL) \
383  CBC_BINARY_OPERATION (CBC_GREATER_EQUAL, \
384                        GREATER_EQUAL) \
385  CBC_BINARY_OPERATION (CBC_IN, \
386                        IN) \
387  CBC_BINARY_OPERATION (CBC_INSTANCEOF, \
388                        INSTANCEOF) \
389  CBC_BINARY_OPERATION (CBC_LEFT_SHIFT, \
390                        LEFT_SHIFT) \
391  CBC_BINARY_OPERATION (CBC_RIGHT_SHIFT, \
392                        RIGHT_SHIFT) \
393  CBC_BINARY_OPERATION (CBC_UNS_RIGHT_SHIFT, \
394                        UNS_RIGHT_SHIFT) \
395  CBC_BINARY_OPERATION (CBC_ADD, \
396                        ADD) \
397  CBC_BINARY_OPERATION (CBC_SUBTRACT, \
398                        SUB) \
399  CBC_BINARY_OPERATION (CBC_MULTIPLY, \
400                        MUL) \
401  CBC_BINARY_OPERATION (CBC_DIVIDE, \
402                        DIV) \
403  CBC_BINARY_OPERATION (CBC_MODULO, \
404                        MOD) \
405  CBC_BINARY_OPERATION (CBC_EXPONENTIATION, \
406                        EXP) \
407  \
408  /* Unary lvalue opcodes. */ \
409  CBC_OPCODE (CBC_DELETE_PUSH_RESULT, CBC_NO_FLAG, -1, \
410              VM_OC_PROP_DELETE | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
411  CBC_OPCODE (CBC_DELETE_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1, \
412              VM_OC_DELETE | VM_OC_PUT_STACK) \
413  CBC_UNARY_LVALUE_OPERATION (CBC_PRE_INCR, \
414                              PRE_INCR) \
415  CBC_UNARY_LVALUE_OPERATION (CBC_PRE_DECR, \
416                              PRE_DECR) \
417  CBC_UNARY_LVALUE_OPERATION (CBC_POST_INCR, \
418                              POST_INCR) \
419  CBC_UNARY_LVALUE_OPERATION (CBC_POST_DECR, \
420                              POST_DECR) \
421  \
422  /* Call opcodes. */ \
423  CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
424              VM_OC_CALL) \
425  CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
426              VM_OC_CALL | VM_OC_PUT_STACK) \
427  CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
428              VM_OC_CALL | VM_OC_PUT_BLOCK) \
429  CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
430              VM_OC_CALL) \
431  CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, \
432              VM_OC_CALL | VM_OC_PUT_STACK) \
433  CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
434              VM_OC_CALL | VM_OC_PUT_BLOCK) \
435  CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, \
436              VM_OC_CALL) \
437  CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, \
438              VM_OC_CALL | VM_OC_PUT_STACK) \
439  CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1, \
440              VM_OC_CALL | VM_OC_PUT_BLOCK) \
441  CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3, \
442              VM_OC_CALL) \
443  CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2, \
444              VM_OC_CALL | VM_OC_PUT_STACK) \
445  CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3, \
446              VM_OC_CALL | VM_OC_PUT_BLOCK) \
447  CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2, \
448              VM_OC_CALL) \
449  CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1, \
450              VM_OC_CALL | VM_OC_PUT_STACK) \
451  CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2, \
452              VM_OC_CALL | VM_OC_PUT_BLOCK) \
453  CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4, \
454              VM_OC_CALL) \
455  CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, \
456              VM_OC_CALL | VM_OC_PUT_STACK) \
457  CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4, \
458              VM_OC_CALL | VM_OC_PUT_BLOCK) \
459  CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3, \
460              VM_OC_CALL) \
461  CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2, \
462              VM_OC_CALL | VM_OC_PUT_STACK) \
463  CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3, \
464              VM_OC_CALL | VM_OC_PUT_BLOCK) \
465  CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4, \
466              VM_OC_CALL) \
467  CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, \
468              VM_OC_CALL | VM_OC_PUT_STACK) \
469  CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4, \
470              VM_OC_CALL | VM_OC_PUT_BLOCK) \
471  \
472  /* Binary assignment opcodes. */ \
473  CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3, \
474              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE) \
475  CBC_OPCODE (CBC_ASSIGN_PUSH_RESULT, CBC_NO_FLAG, -2, \
476              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \
477  CBC_OPCODE (CBC_ASSIGN_BLOCK, CBC_NO_FLAG, -3, \
478              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \
479  CBC_OPCODE (CBC_ASSIGN_SET_IDENT, CBC_HAS_LITERAL_ARG, -1, \
480              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \
481  CBC_OPCODE (CBC_ASSIGN_SET_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 0, \
482              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \
483  CBC_OPCODE (CBC_ASSIGN_SET_IDENT_BLOCK, CBC_HAS_LITERAL_ARG, -1, \
484              VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \
485  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
486              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
487  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1, \
488              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \
489  CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_BLOCK, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
490              VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \
491  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL, CBC_HAS_LITERAL_ARG, -2, \
492              VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \
493  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_PUSH_RESULT, CBC_HAS_LITERAL_ARG, -1, \
494              VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \
495  CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_BLOCK, CBC_HAS_LITERAL_ARG, -2, \
496              VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \
497  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL, CBC_HAS_LITERAL_ARG, -1, \
498              VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \
499  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 0, \
500              VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \
501  CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_BLOCK, CBC_HAS_LITERAL_ARG, -1, \
502              VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \
503  CBC_OPCODE (CBC_MOV_IDENT, CBC_HAS_LITERAL_ARG, -1, \
504              VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \
505  CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, \
506              VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK) \
507  CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
508              VM_OC_ASSIGN_LET_CONST | VM_OC_GET_LITERAL) \
509  CBC_OPCODE (CBC_ASSIGN_SUPER, CBC_NO_FLAG, -3, \
510              VM_OC_ASSIGN_SUPER) \
511  CBC_OPCODE (CBC_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, \
512              VM_OC_ASSIGN_SUPER | VM_OC_PUT_STACK) \
513  CBC_OPCODE (CBC_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3, \
514              VM_OC_ASSIGN_SUPER | VM_OC_PUT_BLOCK) \
515  \
516  /* Last opcode (not a real opcode). */ \
517  CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, \
518              VM_OC_NONE)
519
520/* All EXT branches are statement block end
521 * marks, so they are always forward branches. */
522
523#define CBC_EXT_OPCODE_LIST \
524  /* Branch opcodes first. Some other opcodes are mixed. */ \
525  CBC_OPCODE (CBC_EXT_NOP, CBC_NO_FLAG, 0, \
526              VM_OC_NONE) \
527  CBC_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT, \
528                      -1 + PARSER_WITH_CONTEXT_STACK_ALLOCATION, VM_OC_WITH) \
529  CBC_OPCODE (CBC_EXT_FOR_IN_GET_NEXT, CBC_NO_FLAG, 1, \
530              VM_OC_FOR_IN_GET_NEXT | VM_OC_PUT_STACK) \
531  CBC_FORWARD_BRANCH (CBC_EXT_FOR_IN_CREATE_CONTEXT, \
532                      -1 + PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_IN_CREATE_CONTEXT) \
533  CBC_OPCODE (CBC_EXT_SET_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
534              VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \
535  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT, 0, \
536                       VM_OC_FOR_IN_HAS_NEXT) \
537  CBC_OPCODE (CBC_EXT_FOR_OF_GET_NEXT, CBC_NO_FLAG, 1, \
538              VM_OC_FOR_OF_GET_NEXT | VM_OC_PUT_STACK) \
539  CBC_FORWARD_BRANCH (CBC_EXT_FOR_OF_CREATE_CONTEXT, \
540                      -1 + PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_OF_CREATE_CONTEXT) \
541  CBC_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1, \
542              VM_OC_PUSH_NAMED_FUNC_EXPR | VM_OC_GET_LITERAL_LITERAL) \
543  CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT, 0, \
544                       VM_OC_FOR_OF_HAS_NEXT) \
545  CBC_OPCODE (CBC_EXT_SET_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
546              VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \
547  CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION, \
548                      VM_OC_TRY) \
549  CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0, \
550              VM_OC_BLOCK_CREATE_CONTEXT) \
551  CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1, \
552                      VM_OC_CATCH) \
553  CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, \
554              VM_OC_RESOLVE_BASE_FOR_CALL) \
555  CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, 0, \
556                      VM_OC_FINALLY) \
557  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, \
558              VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_STACK) \
559  CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, \
560                      VM_OC_DEFAULT_INITIALIZER) \
561  \
562  /* Basic opcodes. */ \
563  CBC_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2, \
564              VM_OC_PUSH_LIT_0 | VM_OC_GET_LITERAL) \
565  CBC_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2, \
566              VM_OC_PUSH_LIT_POS_BYTE | VM_OC_GET_LITERAL) \
567  CBC_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2, \
568              VM_OC_PUSH_LIT_NEG_BYTE | VM_OC_GET_LITERAL) \
569  CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \
570              VM_OC_EXT_VAR_EVAL) \
571  CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
572              VM_OC_EXT_VAR_EVAL) \
573  CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0, \
574              VM_OC_COPY_FROM_ARG) \
575  CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, \
576              VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
577  CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0, \
578              VM_OC_STRING_CONCAT | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \
579  CBC_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1, \
580              VM_OC_STRING_CONCAT | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \
581  CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1, \
582              VM_OC_GET_TEMPLATE_OBJECT | VM_OC_PUT_STACK) \
583  CBC_OPCODE (CBC_EXT_CLONE_CONTEXT, CBC_NO_FLAG, 0, \
584              VM_OC_CLONE_CONTEXT) \
585  CBC_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT, CBC_NO_FLAG, 0, \
586              VM_OC_CLONE_CONTEXT) \
587  CBC_OPCODE (CBC_EXT_RESOURCE_NAME, CBC_NO_FLAG, 0, \
588              VM_OC_RESOURCE_NAME) \
589  CBC_OPCODE (CBC_EXT_LINE, CBC_NO_FLAG, 0, \
590              VM_OC_LINE) \
591  CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0, \
592              VM_OC_ERROR) \
593  CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, \
594              VM_OC_THROW_REFERENCE_ERROR) \
595  CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0, \
596              VM_OC_THROW_CONST_ERROR) \
597  CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0, \
598              VM_OC_REQUIRE_OBJECT_COERCIBLE) \
599  \
600  /* Computed / class property related opcodes. */ \
601  CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY, CBC_NO_FLAG, -2, \
602              VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \
603  CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG, -1, \
604              VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \
605  CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, CBC_HAS_LITERAL_ARG, -1, \
606              VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \
607  CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \
608              VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \
609  CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
610              VM_OC_SET_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \
611  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG, -1, \
612              VM_OC_SET_COMPUTED_PROPERTY | VM_OC_GET_STACK_LITERAL) \
613  CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
614              VM_OC_SET_GETTER | VM_OC_GET_LITERAL_LITERAL) \
615  CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
616              VM_OC_SET_SETTER | VM_OC_GET_LITERAL_LITERAL) \
617  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_HAS_LITERAL_ARG, -1, \
618              VM_OC_SET_GETTER | VM_OC_GET_STACK_LITERAL) \
619  CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \
620              VM_OC_SET_SETTER | VM_OC_GET_STACK_LITERAL) \
621  CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, \
622              VM_OC_SET__PROTO__ | VM_OC_GET_STACK) \
623  \
624  /* Class related opcodes. */ \
625  CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, \
626              VM_OC_PUSH_CLASS_ENVIRONMENT | VM_OC_GET_LITERAL) \
627  CBC_OPCODE (CBC_EXT_PUSH_ANONYMOUS_CLASS_ENV, CBC_NO_FLAG, 1, \
628              VM_OC_PUSH_CLASS_ENVIRONMENT) \
629  CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR, CBC_NO_FLAG, 1, \
630              VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \
631  CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE, CBC_NO_FLAG, 1, \
632              VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \
633  CBC_OPCODE (CBC_EXT_INIT_CLASS, CBC_NO_FLAG, 0, \
634              VM_OC_INIT_CLASS | VM_OC_PUT_STACK) \
635  CBC_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS, CBC_HAS_LITERAL_ARG, -2, \
636              VM_OC_FINALIZE_CLASS | VM_OC_GET_LITERAL) \
637  CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2, \
638              VM_OC_FINALIZE_CLASS) \
639  CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1, \
640              VM_OC_NONE) \
641  CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1, \
642              VM_OC_PUSH_SUPER_CONSTRUCTOR) \
643  CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0, \
644              VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
645  CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2, \
646              VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
647  CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
648              VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
649  CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, \
650              VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
651  CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1, \
652              VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \
653  CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE, CBC_HAS_LITERAL_ARG, 2, \
654              VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \
655  CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1, \
656              VM_OC_RESOLVE_LEXICAL_THIS | VM_OC_PUT_STACK) \
657  CBC_OPCODE (CBC_EXT_LOCAL_EVAL, CBC_HAS_BYTE_ARG, 0, \
658              VM_OC_LOCAL_EVAL) \
659  CBC_OPCODE (CBC_EXT_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
660              VM_OC_SUPER_CALL) \
661  CBC_OPCODE (CBC_EXT_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
662              VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \
663  CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
664              VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \
665  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
666              VM_OC_SUPER_CALL) \
667  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
668              VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \
669  CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
670              VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \
671  \
672  /* Spread / rest operation related opcodes. */ \
673  CBC_OPCODE (CBC_EXT_SPREAD_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
674              VM_OC_SPREAD_ARGUMENTS) \
675  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
676              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \
677  CBC_OPCODE (CBC_EXT_SPREAD_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
678              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \
679  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
680              VM_OC_SPREAD_ARGUMENTS) \
681  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, \
682              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \
683  CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
684              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \
685  CBC_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT, CBC_NO_FLAG, 1, \
686              VM_OC_PUSH_SPREAD_ELEMENT) \
687  CBC_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
688              VM_OC_APPEND_ARRAY) \
689  CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1, \
690              VM_OC_REST_INITIALIZER) \
691  CBC_OPCODE (CBC_EXT_REST_INITIALIZER_2, CBC_NO_FLAG, 1, \
692              VM_OC_REST_INITIALIZER) \
693  CBC_OPCODE (CBC_EXT_REST_INITIALIZER_3, CBC_NO_FLAG, 1, \
694              VM_OC_REST_INITIALIZER) \
695  CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
696              VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \
697  CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
698              VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \
699  \
700  /* Iterator related opcodes. */ \
701  CBC_OPCODE (CBC_EXT_GET_ITERATOR, CBC_NO_FLAG, 1, \
702              VM_OC_GET_ITERATOR) \
703  CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, \
704              VM_OC_ITERATOR_STEP) \
705  CBC_OPCODE (CBC_EXT_ITERATOR_STEP_2, CBC_NO_FLAG, 1, \
706              VM_OC_ITERATOR_STEP) \
707  CBC_OPCODE (CBC_EXT_ITERATOR_STEP_3, CBC_NO_FLAG, 1, \
708              VM_OC_ITERATOR_STEP) \
709  CBC_OPCODE (CBC_EXT_ITERATOR_CLOSE, CBC_NO_FLAG, -1, \
710              VM_OC_ITERATOR_CLOSE | VM_OC_GET_STACK) \
711  \
712  /* Executable object related opcodes. */ \
713  CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1, \
714              VM_OC_CREATE_GENERATOR) \
715  CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0, \
716              VM_OC_YIELD) \
717  CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0, \
718              VM_OC_YIELD) \
719  CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0, \
720              VM_OC_AWAIT) \
721  CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1, \
722              VM_OC_EXT_RETURN | VM_OC_GET_STACK) \
723  CBC_OPCODE (CBC_EXT_RETURN_PROMISE, CBC_NO_FLAG, -1, \
724              VM_OC_RETURN_PROMISE | VM_OC_GET_STACK) \
725  CBC_OPCODE (CBC_EXT_RETURN_PROMISE_UNDEFINED, CBC_NO_FLAG, 0, \
726              VM_OC_RETURN_PROMISE) \
727  CBC_OPCODE (CBC_EXT_PUSH_NEW_TARGET, CBC_NO_FLAG, 1, \
728              VM_OC_PUSH_NEW_TARGET | VM_OC_PUT_STACK) \
729  \
730  /* Last opcode (not a real opcode). */ \
731  CBC_OPCODE (CBC_EXT_END, CBC_NO_FLAG, 0, \
732              VM_OC_NONE)
733
734#define CBC_MAXIMUM_BYTE_VALUE 255
735#define CBC_MAXIMUM_SMALL_VALUE 510
736#define CBC_MAXIMUM_FULL_VALUE 32767
737
738#define CBC_PUSH_NUMBER_BYTE_RANGE_END 256
739
740#define CBC_HIGHEST_BIT_MASK 0x80
741#define CBC_LOWER_SEVEN_BIT_MASK 0x7f
742
743/**
744 * Literal encoding limit when full literal encoding mode is enabled
745 */
746#define CBC_FULL_LITERAL_ENCODING_LIMIT 128
747
748/**
749 * Literal encoding delta when full literal encoding mode is enabled
750 */
751#define CBC_FULL_LITERAL_ENCODING_DELTA 0x8000
752
753/**
754 * Literal encoding limit when full literal encoding mode is disabled
755 */
756#define CBC_SMALL_LITERAL_ENCODING_LIMIT 255
757
758/**
759 * Literal encoding delta when full literal encoding mode is disabled
760 */
761#define CBC_SMALL_LITERAL_ENCODING_DELTA 0xfe01
762
763/**
764 * Literal indicies belong to one of the following groups:
765 *
766 * 0 <= index < argument_end                    : arguments
767 * argument_end <= index < register_end         : registers
768 * register_end <= index < ident_end            : identifiers
769 * ident_end <= index < const_literal_end       : constant literals
770 * const_literal_end <= index < literal_end     : template literals
771 */
772
773/**
774 * Compiled byte code arguments.
775 */
776typedef struct
777{
778  ecma_compiled_code_t header;      /**< compiled code header */
779  uint8_t stack_limit;              /**< maximum number of values stored on the stack */
780  uint8_t argument_end;             /**< number of arguments expected by the function */
781  uint8_t register_end;             /**< end position of the register group */
782  uint8_t ident_end;                /**< end position of the identifier group */
783  uint8_t const_literal_end;        /**< end position of the const literal group */
784  uint8_t literal_end;              /**< end position of the literal group */
785} cbc_uint8_arguments_t;
786
787/**
788 * Compiled byte code arguments.
789 */
790typedef struct
791{
792  ecma_compiled_code_t header;      /**< compiled code header */
793  uint16_t stack_limit;             /**< maximum number of values stored on the stack */
794  uint16_t argument_end;            /**< number of arguments expected by the function */
795  uint16_t register_end;            /**< end position of the register group */
796  uint16_t ident_end;               /**< end position of the identifier group */
797  uint16_t const_literal_end;       /**< end position of the const literal group */
798  uint16_t literal_end;             /**< end position of the literal group */
799  uint16_t padding;                 /**< an unused value */
800} cbc_uint16_arguments_t;
801
802/**
803 * Compact byte code status flags.
804 */
805typedef enum
806{
807  CBC_CODE_FLAGS_FUNCTION = (1u << 0), /**< compiled code is JavaScript function */
808  CBC_CODE_FLAGS_FULL_LITERAL_ENCODING = (1u << 1), /**< full literal encoding mode is enabled */
809  CBC_CODE_FLAGS_UINT16_ARGUMENTS = (1u << 2), /**< compiled code data is cbc_uint16_arguments_t */
810  CBC_CODE_FLAGS_STRICT_MODE = (1u << 3), /**< strict mode is enabled */
811  CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED = (1u << 4), /**< mapped arguments object must be constructed */
812  CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED = (1u << 5), /**< mapped arguments object must be constructed */
813  CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 6), /**< no need to create a lexical environment */
814  CBC_CODE_FLAGS_ARROW_FUNCTION = (1u << 7), /**< this function is an arrow function */
815  CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 8), /**< this function is a static snapshot function */
816  CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 9), /**< this function should be ignored by debugger */
817  CBC_CODE_FLAGS_CLASS_CONSTRUCTOR = (1u << 10), /**< this function is a class constructor */
818  CBC_CODE_FLAGS_GENERATOR = (1u << 11), /**< this function is a generator */
819  CBC_CODE_FLAGS_REST_PARAMETER = (1u << 12), /**< this function has rest parameter */
820  CBC_CODE_FLAG_HAS_TAGGED_LITERALS = (1u << 13), /**< this function has tagged template literal list */
821  CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED = (1u << 14), /**< compiled code needs a lexical block */
822  CBC_CODE_FLAGS_ACCESSOR = (1u << 15) /**< accessor propety 'get' and 'set' functions */
823} cbc_code_flags;
824
825/**
826 * Any arguments object is needed
827 */
828#define CBC_CODE_FLAGS_IS_ARGUMENTS_NEEDED \
829  (CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED | CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED)
830
831#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1,
832
833/**
834 * Opcode list.
835 */
836typedef enum
837{
838  CBC_OPCODE_LIST      /**< list of opcodes */
839} cbc_opcode_t;
840
841/**
842 * Extended opcode list.
843 */
844typedef enum
845{
846  CBC_EXT_OPCODE_LIST  /**< list extended opcodes */
847} cbc_ext_opcode_t;
848
849#undef CBC_OPCODE
850
851/**
852 * Opcode flags.
853 */
854extern const uint8_t cbc_flags[];
855extern const uint8_t cbc_ext_flags[];
856
857#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
858
859/**
860 * Opcode names for debugging.
861 */
862extern const char * const cbc_names[];
863extern const char * const cbc_ext_names[];
864
865#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
866
867/**
868 * @}
869 * @}
870 * @}
871 */
872
873#endif /* !BYTE_CODE_H */
874