Coverage Report

Created: 2026-10-17 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/njs/src/njs_vmcode.c
Line
Count
Source
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) NGINX, Inc.
5
 */
6
7
8
#include <njs_main.h>
9
10
11
struct njs_property_next_s {
12
    uint32_t     index;
13
    njs_array_t  *array;
14
};
15
16
static njs_jump_off_t njs_vmcode_object(njs_vm_t *vm, njs_value_t *retval);
17
static njs_jump_off_t njs_vmcode_array(njs_vm_t *vm, u_char *pc,
18
    njs_value_t *retval);
19
static njs_jump_off_t njs_vmcode_function(njs_vm_t *vm, u_char *pc);
20
static njs_jump_off_t njs_vmcode_arguments(njs_vm_t *vm, u_char *pc);
21
static njs_jump_off_t njs_vmcode_regexp(njs_vm_t *vm, u_char *pc,
22
    njs_value_t *retval);
23
static njs_jump_off_t njs_vmcode_template_literal(njs_vm_t *vm,
24
    njs_value_t *retval);
25
26
static njs_jump_off_t njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value,
27
    njs_value_t *key, njs_value_t *retval);
28
static njs_jump_off_t njs_vmcode_array_init(njs_vm_t *vm, u_char *pc,
29
    njs_value_t *array, njs_value_t *value);
30
static njs_jump_off_t njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value,
31
    njs_value_t *key, njs_value_t *retval);
32
static njs_jump_off_t njs_vmcode_property_in(njs_vm_t *vm,
33
    njs_value_t *value, njs_value_t *key, njs_value_t *retval);
34
static njs_jump_off_t njs_vmcode_property_foreach(njs_vm_t *vm,
35
    njs_value_t *object, u_char *pc, njs_value_t *retval);
36
static njs_jump_off_t njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
37
    njs_value_t *constructor, njs_value_t *retval);
38
static njs_jump_off_t njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value,
39
    njs_value_t *retval);
40
static njs_jump_off_t njs_vmcode_debugger(njs_vm_t *vm, njs_value_t *retval);
41
42
static void njs_vmcode_return(njs_vm_t *vm, njs_value_t *dst,
43
    njs_value_t *retval);
44
static njs_jump_off_t njs_vmcode_import(njs_vm_t *vm, njs_mod_t *module,
45
    njs_value_t *retval);
46
47
static njs_int_t njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
48
    njs_value_t *dst, njs_promise_capability_t *pcap, njs_async_ctx_t *actx);
49
50
static njs_jump_off_t njs_vmcode_try_start(njs_vm_t *vm, njs_value_t *value,
51
    njs_value_t *offset, u_char *pc);
52
static njs_jump_off_t njs_vmcode_try_break(njs_vm_t *vm, njs_value_t *value,
53
    njs_value_t *offset);
54
static njs_jump_off_t njs_vmcode_try_continue(njs_vm_t *vm, njs_value_t *value,
55
    njs_value_t *offset);
56
static njs_jump_off_t njs_vmcode_try_end(njs_vm_t *vm, njs_value_t *invld,
57
    njs_value_t *offset);
58
static njs_jump_off_t njs_vmcode_finally(njs_vm_t *vm, njs_value_t *dst,
59
    njs_value_t *retval, u_char *pc);
60
static void njs_vmcode_error(njs_vm_t *vm, u_char *pc);
61
static njs_int_t njs_throw_cannot_property(njs_vm_t *vm, njs_value_t *object,
62
    njs_value_t *key, const char *what);
63
64
static njs_jump_off_t njs_string_concat(njs_vm_t *vm, njs_value_t *val1,
65
    njs_value_t *val2, njs_value_t *retval);
66
static njs_jump_off_t njs_values_equal(njs_vm_t *vm, njs_value_t *val1,
67
    njs_value_t *val2);
68
static njs_jump_off_t njs_primitive_values_compare(njs_vm_t *vm,
69
    njs_value_t *val1, njs_value_t *val2);
70
static njs_jump_off_t njs_function_frame_create(njs_vm_t *vm,
71
    njs_value_t *value, const njs_value_t *this, uintptr_t nargs,
72
    njs_bool_t ctor);
73
74
75
#define njs_vmcode_operand(vm, index, _retval)                                \
76
9.61M
    do {                                                                      \
77
9.61M
        _retval = njs_scope_valid_value(vm, index);                           \
78
9.61M
        if (njs_slow_path(_retval == NULL)) {                                 \
79
0
            goto error;                                                       \
80
0
        }                                                                     \
81
9.61M
    } while (0)
82
83
84
njs_int_t
85
njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc, njs_value_t *rval,
86
    void *promise_cap, void *async_ctx)
87
77.6k
{
88
77.6k
    u_char                       *catch;
89
77.6k
    double                       num, exponent;
90
77.6k
    int32_t                      i32;
91
77.6k
    uint32_t                     u32;
92
77.6k
    njs_bool_t                   valid, lambda_call;
93
77.6k
    njs_value_t                  *retval, *value1, *value2;
94
77.6k
    njs_value_t                  *src, *s1, *s2, dst;
95
77.6k
    njs_value_t                  *function, name;
96
77.6k
    njs_value_t                  numeric1, numeric2, primitive1, primitive2;
97
77.6k
    njs_frame_t                  *frame;
98
77.6k
    njs_jump_off_t               ret;
99
77.6k
    njs_vmcode_1addr_t           *put_arg;
100
77.6k
    njs_vmcode_await_t           *await;
101
77.6k
    njs_native_frame_t           *previous, *native;
102
77.6k
    njs_property_next_t          *next;
103
77.6k
    njs_vmcode_import_t          *import;
104
77.6k
    njs_vmcode_array_init_t      *array_init;
105
77.6k
    njs_vmcode_generic_t         *vmcode;
106
77.6k
    njs_vmcode_variable_t        *var;
107
77.6k
    njs_vmcode_prop_get_t        *get;
108
77.6k
    njs_vmcode_prop_set_t        *set;
109
77.6k
    njs_vmcode_prop_next_t       *pnext;
110
77.6k
    njs_vmcode_test_jump_t       *test_jump;
111
77.6k
    njs_vmcode_equal_jump_t      *equal;
112
77.6k
    njs_vmcode_try_return_t      *try_return;
113
77.6k
    njs_vmcode_method_frame_t    *method_frame;
114
77.6k
    njs_vmcode_prop_accessor_t   *accessor;
115
77.6k
    njs_vmcode_try_trampoline_t  *try_trampoline;
116
77.6k
    njs_vmcode_function_frame_t  *function_frame;
117
118
77.6k
    njs_vmcode_debug(vm, pc, "ENTER");
119
120
#if !defined(NJS_HAVE_COMPUTED_GOTO)
121
    #define SWITCH(op)      switch (op)
122
    #define CASE(op)        case op
123
    #define BREAK           pc += ret; NEXT
124
125
    #define NEXT            vmcode = (njs_vmcode_generic_t *) pc;             \
126
                            goto next
127
128
    #define NEXT_LBL        next:
129
    #define FALLTHROUGH     NJS_FALLTHROUGH
130
131
#else
132
5.52M
    #define SWITCH(op)      goto *switch_tbl[(uint8_t) op];
133
5.20M
    #define CASE(op)        case_ ## op
134
3.76M
    #define BREAK           pc += ret; NEXT
135
136
5.45M
    #define NEXT            vmcode = (njs_vmcode_generic_t *) pc;             \
137
5.45M
                            SWITCH (vmcode->code)
138
139
77.6k
    #define NEXT_LBL
140
77.6k
    #define FALLTHROUGH
141
142
6.67M
    #define NJS_GOTO_ROW(name)   [ (uint8_t) name ] = &&case_ ## name
143
144
77.6k
    static const void * const switch_tbl[NJS_VMCODES] = {
145
146
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PUT_ARG),
147
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_STOP),
148
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_JUMP),
149
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ATOM_SET),
150
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_SET),
151
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ACCESSOR),
152
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_IF_TRUE_JUMP),
153
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_IF_FALSE_JUMP),
154
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_IF_EQUAL_JUMP),
155
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_INIT),
156
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_ARRAY_INIT),
157
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_RETURN),
158
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_FUNCTION_FRAME),
159
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_METHOD_FRAME),
160
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_FUNCTION_CALL),
161
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_NEXT),
162
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_ARGUMENTS),
163
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROTO_INIT),
164
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TO_PROPERTY_KEY),
165
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TO_PROPERTY_KEY_CHK),
166
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_SET_FUNCTION_NAME),
167
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_IMPORT),
168
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_AWAIT),
169
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TRY_START),
170
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_THROW),
171
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TRY_BREAK),
172
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TRY_CONTINUE),
173
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TRY_END),
174
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_CATCH),
175
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_FINALLY),
176
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_LET),
177
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_LET_UPDATE),
178
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_INITIALIZATION_TEST),
179
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_NOT_INITIALIZED),
180
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_ASSIGNMENT_ERROR),
181
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_ERROR),
182
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_MOVE),
183
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ATOM_GET),
184
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_GET),
185
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_INCREMENT),
186
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_POST_INCREMENT),
187
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_DECREMENT),
188
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_POST_DECREMENT),
189
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TRY_RETURN),
190
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_GLOBAL_GET),
191
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_LESS),
192
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_GREATER),
193
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_LESS_OR_EQUAL),
194
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_GREATER_OR_EQUAL),
195
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_ADDITION),
196
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_EQUAL),
197
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_NOT_EQUAL),
198
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_SUBTRACTION),
199
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_MULTIPLICATION),
200
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_EXPONENTIATION),
201
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_DIVISION),
202
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_REMAINDER),
203
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_BITWISE_AND),
204
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_BITWISE_OR),
205
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_BITWISE_XOR),
206
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_LEFT_SHIFT),
207
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_RIGHT_SHIFT),
208
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_UNSIGNED_RIGHT_SHIFT),
209
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TEMPLATE_LITERAL),
210
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_IN),
211
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_DELETE),
212
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_FOREACH),
213
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_STRICT_EQUAL),
214
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_STRICT_NOT_EQUAL),
215
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TEST_IF_TRUE),
216
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TEST_IF_FALSE),
217
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_COALESCE),
218
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_OPTIONAL_CHAIN),
219
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_UNARY_PLUS),
220
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_UNARY_NEGATION),
221
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_BITWISE_NOT),
222
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_LOGICAL_NOT),
223
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_OBJECT),
224
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_ARRAY),
225
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_FUNCTION),
226
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_REGEXP),
227
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_INSTANCE_OF),
228
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_TYPEOF),
229
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_VOID),
230
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_DELETE),
231
77.6k
        NJS_GOTO_ROW(NJS_VMCODE_DEBUGGER),
232
77.6k
    };
233
234
77.6k
#endif
235
236
77.6k
    if (async_ctx != NULL && ((njs_async_ctx_t *) async_ctx)->throw_flag) {
237
0
        goto error;
238
0
    }
239
240
77.6k
    vmcode = (njs_vmcode_generic_t *) pc;
241
242
77.6k
NEXT_LBL;
243
244
77.6k
    SWITCH (vmcode->code) {
245
246
320k
    CASE (NJS_VMCODE_MOVE):
247
320k
        njs_vmcode_debug_opcode();
248
249
320k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
250
320k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
251
320k
        *retval = *value1;
252
253
320k
        pc += sizeof(njs_vmcode_move_t);
254
320k
        NEXT;
255
256
331k
    CASE (NJS_VMCODE_PROPERTY_ATOM_GET):
257
331k
        njs_vmcode_debug_opcode();
258
259
331k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
260
331k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
261
331k
        get = (njs_vmcode_prop_get_t *) pc;
262
331k
        njs_vmcode_operand(vm, get->value, retval);
263
264
331k
        ret = njs_value_property(vm, value1, value2->atom_id, retval);
265
331k
        if (njs_slow_path(ret == NJS_ERROR)) {
266
18
            goto error;
267
18
        }
268
269
331k
        pc += sizeof(njs_vmcode_prop_get_t);
270
331k
        NEXT;
271
272
331k
    CASE (NJS_VMCODE_PROPERTY_GET):
273
18.3k
        njs_vmcode_debug_opcode();
274
275
18.3k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
276
18.3k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
277
278
18.3k
        get = (njs_vmcode_prop_get_t *) pc;
279
18.3k
        njs_vmcode_operand(vm, get->value, retval);
280
281
18.3k
        if (njs_slow_path(!njs_is_index_or_key(value2))) {
282
0
            if (njs_slow_path(njs_is_null_or_undefined(value1))) {
283
0
                (void) njs_throw_cannot_property(vm, value1, value2, "get");
284
0
                goto error;
285
0
            }
286
287
0
            ret = njs_value_to_key(vm, &primitive1, value2);
288
0
            if (njs_slow_path(ret != NJS_OK)) {
289
0
                goto error;
290
0
            }
291
292
0
            value2 = &primitive1;
293
0
        }
294
295
18.3k
        if (value2->atom_id == NJS_ATOM_STRING_unknown) {
296
18.3k
            num = njs_number(value2);
297
298
18.3k
            if (njs_fast_path(njs_number_is_atom_index(num, &u32))) {
299
18.3k
                value2->atom_id = njs_number_atom(u32);
300
301
18.3k
            } else {
302
0
                ret = njs_atom_atomize_key(vm, value2);
303
0
                if (njs_slow_path(ret != NJS_OK)) {
304
0
                    goto error;
305
0
                }
306
0
            }
307
18.3k
        }
308
309
18.3k
        ret = njs_value_property(vm, value1, value2->atom_id, retval);
310
18.3k
        if (njs_slow_path(ret == NJS_ERROR)) {
311
0
            goto error;
312
0
        }
313
314
18.3k
        pc += sizeof(njs_vmcode_prop_get_t);
315
18.3k
        NEXT;
316
317
18.3k
    CASE (NJS_VMCODE_INCREMENT):
318
0
        njs_vmcode_debug_opcode();
319
320
0
        njs_vmcode_operand(vm, vmcode->operand3, value2);
321
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
322
323
0
        if (njs_slow_path(!njs_is_numeric(value2))) {
324
0
            ret = njs_value_to_numeric(vm, value2, &numeric1);
325
0
            if (njs_slow_path(ret != NJS_OK)) {
326
0
                goto error;
327
0
            }
328
329
0
            num = njs_number(&numeric1);
330
331
0
        } else {
332
0
            num = njs_number(value2);
333
0
        }
334
335
0
        njs_set_number(value1, num + 1);
336
337
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
338
339
0
        *retval = *value1;
340
341
0
        pc += sizeof(njs_vmcode_3addr_t);
342
0
        NEXT;
343
344
18.3k
    CASE (NJS_VMCODE_POST_INCREMENT):
345
18.3k
        njs_vmcode_debug_opcode();
346
347
18.3k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
348
18.3k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
349
350
18.3k
        if (njs_slow_path(!njs_is_numeric(value2))) {
351
18.3k
            ret = njs_value_to_numeric(vm, value2, &numeric1);
352
18.3k
            if (njs_slow_path(ret != NJS_OK)) {
353
0
                goto error;
354
0
            }
355
356
18.3k
            num = njs_number(&numeric1);
357
358
18.3k
        } else {
359
35
            num = njs_number(value2);
360
35
        }
361
362
18.3k
        njs_set_number(value1, num + 1);
363
364
18.3k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
365
366
18.3k
        njs_set_number(retval, num);
367
368
18.3k
        pc += sizeof(njs_vmcode_3addr_t);
369
18.3k
        NEXT;
370
371
18.3k
    CASE (NJS_VMCODE_DECREMENT):
372
2.16k
        njs_vmcode_debug_opcode();
373
374
2.16k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
375
2.16k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
376
377
2.16k
        if (njs_slow_path(!njs_is_numeric(value2))) {
378
2.16k
            ret = njs_value_to_numeric(vm, value2, &numeric1);
379
2.16k
            if (njs_slow_path(ret != NJS_OK)) {
380
0
                goto error;
381
0
            }
382
383
2.16k
            num = njs_number(&numeric1);
384
385
2.16k
        } else {
386
0
            num = njs_number(value2);
387
0
        }
388
389
2.16k
        njs_set_number(value1, num - 1);
390
391
2.16k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
392
393
2.16k
        *retval = *value1;
394
395
2.16k
        pc += sizeof(njs_vmcode_3addr_t);
396
2.16k
        NEXT;
397
398
20.4k
    CASE (NJS_VMCODE_POST_DECREMENT):
399
20.4k
        njs_vmcode_debug_opcode();
400
401
20.4k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
402
20.4k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
403
404
20.4k
        if (njs_slow_path(!njs_is_numeric(value2))) {
405
2.16k
            ret = njs_value_to_numeric(vm, value2, &numeric1);
406
2.16k
            if (njs_slow_path(ret != NJS_OK)) {
407
0
                goto error;
408
0
            }
409
410
2.16k
            num = njs_number(&numeric1);
411
412
18.3k
        } else {
413
18.3k
            num = njs_number(value2);
414
18.3k
        }
415
416
20.4k
        njs_set_number(value1, num - 1);
417
418
20.4k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
419
420
20.4k
        njs_set_number(retval, num);
421
422
20.4k
        pc += sizeof(njs_vmcode_3addr_t);
423
20.4k
        NEXT;
424
425
282k
    CASE (NJS_VMCODE_GLOBAL_GET):
426
282k
        njs_vmcode_debug_opcode();
427
428
282k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
429
282k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
430
431
282k
        get = (njs_vmcode_prop_get_t *) pc;
432
282k
        njs_vmcode_operand(vm, get->value, retval);
433
434
282k
        ret = njs_value_property_val(vm, value1, value2, retval);
435
282k
        if (njs_slow_path(ret == NJS_ERROR)) {
436
0
            goto error;
437
0
        }
438
439
282k
        pc += sizeof(njs_vmcode_prop_get_t);
440
441
282k
        if (ret == NJS_OK) {
442
260k
            pc += sizeof(njs_vmcode_error_t);
443
260k
        }
444
445
282k
        NEXT;
446
447
    /*
448
     * njs_vmcode_try_return() saves a return value to use it later by
449
     * njs_vmcode_finally(), and jumps to the nearest try_break block.
450
     */
451
282k
    CASE (NJS_VMCODE_TRY_RETURN):
452
0
        njs_vmcode_debug_opcode();
453
454
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
455
456
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
457
0
        *retval = *value1;
458
459
0
        try_return = (njs_vmcode_try_return_t *) pc;
460
0
        pc += try_return->offset;
461
0
        NEXT;
462
463
2.23k
    CASE (NJS_VMCODE_LESS):
464
2.23k
        njs_vmcode_debug_opcode();
465
466
2.23k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
467
2.23k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
468
469
2.23k
        if (njs_slow_path(!njs_is_primitive(value1))) {
470
0
            ret = njs_value_to_primitive(vm, &primitive1, value1,
471
0
                                         NJS_HINT_NUMBER);
472
0
            if (ret != NJS_OK) {
473
0
                goto error;
474
0
            }
475
476
0
            value1 = &primitive1;
477
0
        }
478
479
2.23k
        if (njs_slow_path(!njs_is_primitive(value2))) {
480
0
            ret = njs_value_to_primitive(vm, &primitive2, value2,
481
0
                                         NJS_HINT_NUMBER);
482
0
            if (ret != NJS_OK) {
483
0
                goto error;
484
0
            }
485
486
0
            value2 = &primitive2;
487
0
        }
488
489
2.23k
        if (njs_slow_path(njs_is_symbol(value1)
490
2.23k
                          || njs_is_symbol(value2)))
491
0
        {
492
0
            njs_symbol_conversion_failed(vm, 0);
493
0
            goto error;
494
0
        }
495
496
2.23k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
497
498
2.23k
        njs_set_boolean(retval,
499
2.23k
                        njs_primitive_values_compare(vm, value1, value2) > 0);
500
501
2.23k
        pc += sizeof(njs_vmcode_3addr_t);
502
2.23k
        NEXT;
503
504
18.5k
    CASE (NJS_VMCODE_GREATER):
505
18.5k
        njs_vmcode_debug_opcode();
506
507
18.5k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
508
18.5k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
509
510
18.5k
        if (njs_slow_path(!njs_is_primitive(value1))) {
511
0
            ret = njs_value_to_primitive(vm, &primitive1, value1,
512
0
                                         NJS_HINT_NUMBER);
513
0
            if (ret != NJS_OK) {
514
0
                goto error;
515
0
            }
516
517
0
            value1 = &primitive1;
518
0
        }
519
520
18.5k
        if (njs_slow_path(!njs_is_primitive(value2))) {
521
9
            ret = njs_value_to_primitive(vm, &primitive2, value2,
522
9
                                         NJS_HINT_NUMBER);
523
9
            if (ret != NJS_OK) {
524
0
                goto error;
525
0
            }
526
527
9
            value2 = &primitive2;
528
9
        }
529
530
18.5k
        if (njs_slow_path(njs_is_symbol(value1)
531
18.5k
                          || njs_is_symbol(value2)))
532
0
        {
533
0
            njs_symbol_conversion_failed(vm, 0);
534
0
            goto error;
535
0
        }
536
537
18.5k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
538
539
18.5k
        njs_set_boolean(retval,
540
18.5k
                        njs_primitive_values_compare(vm, value2, value1) > 0);
541
542
18.5k
        pc += sizeof(njs_vmcode_3addr_t);
543
18.5k
        NEXT;
544
545
28.3k
    CASE (NJS_VMCODE_LESS_OR_EQUAL):
546
28.3k
        njs_vmcode_debug_opcode();
547
548
28.3k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
549
28.3k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
550
551
28.3k
        if (njs_slow_path(!njs_is_primitive(value1))) {
552
63
            ret = njs_value_to_primitive(vm, &primitive1, value1,
553
63
                                         NJS_HINT_NUMBER);
554
63
            if (ret != NJS_OK) {
555
0
                goto error;
556
0
            }
557
558
63
            value1 = &primitive1;
559
63
        }
560
561
28.3k
        if (njs_slow_path(!njs_is_primitive(value2))) {
562
28.3k
            ret = njs_value_to_primitive(vm, &primitive2, value2,
563
28.3k
                                         NJS_HINT_NUMBER);
564
28.3k
            if (ret != NJS_OK) {
565
0
                goto error;
566
0
            }
567
568
28.3k
            value2 = &primitive2;
569
28.3k
        }
570
571
28.3k
        if (njs_slow_path(njs_is_symbol(value1)
572
28.3k
                          || njs_is_symbol(value2)))
573
0
        {
574
0
            njs_symbol_conversion_failed(vm, 0);
575
0
            goto error;
576
0
        }
577
578
28.3k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
579
580
28.3k
        njs_set_boolean(retval,
581
28.3k
                        njs_primitive_values_compare(vm, value2, value1) == 0);
582
583
28.3k
        pc += sizeof(njs_vmcode_3addr_t);
584
28.3k
        NEXT;
585
586
39.1k
    CASE (NJS_VMCODE_GREATER_OR_EQUAL):
587
39.1k
        njs_vmcode_debug_opcode();
588
589
39.1k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
590
39.1k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
591
592
39.1k
        if (njs_slow_path(!njs_is_primitive(value1))) {
593
28.2k
            ret = njs_value_to_primitive(vm, &primitive1, value1,
594
28.2k
                                         NJS_HINT_NUMBER);
595
28.2k
            if (ret != NJS_OK) {
596
0
                goto error;
597
0
            }
598
599
28.2k
            value1 = &primitive1;
600
28.2k
        }
601
602
39.1k
        if (njs_slow_path(!njs_is_primitive(value2))) {
603
2.16k
            ret = njs_value_to_primitive(vm, &primitive2, value2,
604
2.16k
                                         NJS_HINT_NUMBER);
605
2.16k
            if (ret != NJS_OK) {
606
0
                goto error;
607
0
            }
608
609
2.16k
            value2 = &primitive2;
610
2.16k
        }
611
612
39.1k
        if (njs_slow_path(njs_is_symbol(value1)
613
39.1k
                          || njs_is_symbol(value2)))
614
0
        {
615
0
            njs_symbol_conversion_failed(vm, 0);
616
0
            goto error;
617
0
        }
618
619
39.1k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
620
621
39.1k
        njs_set_boolean(retval,
622
39.1k
                        njs_primitive_values_compare(vm, value1, value2) == 0);
623
624
39.1k
        pc += sizeof(njs_vmcode_3addr_t);
625
39.1k
        NEXT;
626
627
202k
    CASE (NJS_VMCODE_ADDITION):
628
202k
        njs_vmcode_debug_opcode();
629
630
202k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
631
202k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
632
633
202k
        if (njs_slow_path(!njs_is_primitive(value1))) {
634
3.02k
            ret = njs_value_to_primitive(vm, &primitive1, value1,
635
3.02k
                                         NJS_HINT_NONE);
636
3.02k
            if (ret != NJS_OK) {
637
0
                goto error;
638
0
            }
639
640
3.02k
            value1 = &primitive1;
641
3.02k
        }
642
643
202k
        if (njs_slow_path(!njs_is_primitive(value2))) {
644
58.8k
            ret = njs_value_to_primitive(vm, &primitive2, value2,
645
58.8k
                                         NJS_HINT_NONE);
646
58.8k
            if (ret != NJS_OK) {
647
0
                goto error;
648
0
            }
649
650
58.8k
            value2 = &primitive2;
651
58.8k
        }
652
653
202k
        if (njs_slow_path(njs_is_symbol(value1)
654
202k
                          || njs_is_symbol(value2)))
655
0
        {
656
0
            njs_symbol_conversion_failed(vm,
657
0
                (njs_is_string(value1) || njs_is_string(value2)));
658
659
0
            goto error;
660
0
        }
661
662
202k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
663
664
202k
        if (njs_fast_path(njs_is_numeric(value1)
665
202k
                          && njs_is_numeric(value2)))
666
34.7k
        {
667
34.7k
            njs_set_number(retval, njs_number(value1)
668
34.7k
                                   + njs_number(value2));
669
34.7k
            pc += sizeof(njs_vmcode_3addr_t);
670
34.7k
            NEXT;
671
34.7k
        }
672
673
202k
        if (njs_is_string(value1)) {
674
47.5k
            s1 = value1;
675
47.5k
            s2 = &dst;
676
47.5k
            src = value2;
677
678
155k
        } else {
679
155k
            s1 = &dst;
680
155k
            s2 = value2;
681
155k
            src = value1;
682
155k
        }
683
684
202k
        if (njs_is_number(src)) {
685
163k
            size_t        size;
686
163k
            njs_string_t  sp;
687
163k
            char          buf[64];
688
689
            /* Alloc free path for "str" + int or int + "str" concatenation. */
690
691
163k
            num = njs_number(src);
692
693
163k
            if (isnan(num)) {
694
146
                njs_atom_to_value(vm, &dst, NJS_ATOM_STRING_NaN);
695
696
163k
            } else if (isinf(num)) {
697
698
0
                if (num < 0) {
699
0
                    njs_atom_to_value(vm, &dst, NJS_ATOM_STRING__Infinity);
700
701
0
                } else {
702
0
                    njs_atom_to_value(vm, &dst, NJS_ATOM_STRING_Infinity);
703
0
                }
704
705
163k
            } else {
706
163k
                size = njs_dtoa(num, buf);
707
708
163k
                sp.start = (u_char *) buf;
709
163k
                sp.size = size;
710
163k
                sp.length = size;
711
712
163k
                dst.string.data = &sp;
713
163k
            }
714
715
163k
            ret = njs_string_concat(vm, s1, s2, &name);
716
163k
            if (njs_slow_path(ret == NJS_ERROR)) {
717
0
                goto error;
718
0
            }
719
720
163k
        } else {
721
38.8k
            ret = njs_primitive_value_to_string(vm, &dst, src);
722
38.8k
            if (njs_slow_path(ret != NJS_OK)) {
723
0
                goto error;
724
0
            }
725
726
38.8k
            ret = njs_string_concat(vm, s1, s2, &name);
727
38.8k
            if (njs_slow_path(ret == NJS_ERROR)) {
728
0
                goto error;
729
0
            }
730
38.8k
        }
731
732
202k
        njs_value_assign(retval, &name);
733
734
202k
        BREAK;
735
736
202k
    CASE (NJS_VMCODE_EQUAL):
737
0
        njs_vmcode_debug_opcode();
738
739
0
        njs_vmcode_operand(vm, vmcode->operand3, value2);
740
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
741
742
0
        ret = njs_values_equal(vm, value1, value2);
743
0
        if (njs_slow_path(ret < 0)) {
744
0
            goto error;
745
0
        }
746
747
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
748
0
        njs_set_boolean(retval, ret);
749
750
0
        pc += sizeof(njs_vmcode_3addr_t);
751
0
        NEXT;
752
753
10.6k
    CASE (NJS_VMCODE_NOT_EQUAL):
754
10.6k
        njs_vmcode_debug_opcode();
755
756
10.6k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
757
10.6k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
758
759
10.6k
        ret = njs_values_equal(vm, value1, value2);
760
10.6k
        if (njs_slow_path(ret < 0)) {
761
0
            goto error;
762
0
        }
763
764
10.6k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
765
10.6k
        njs_set_boolean(retval, !ret);
766
767
10.6k
        pc += sizeof(njs_vmcode_3addr_t);
768
10.6k
        NEXT;
769
770
10.6k
#define NJS_PRE_NUMERIC                                                       \
771
10.6k
                                                                              \
772
408k
        if (njs_slow_path(!njs_is_numeric(value1))) {                         \
773
118k
            ret = njs_value_to_numeric(vm, value1, &numeric1);                \
774
118k
            if (njs_slow_path(ret != NJS_OK)) {                               \
775
0
                goto error;                                                   \
776
0
            }                                                                 \
777
118k
                                                                              \
778
118k
            value1 = &numeric1;                                               \
779
118k
        }                                                                     \
780
408k
                                                                              \
781
408k
        if (njs_slow_path(!njs_is_numeric(value2))) {                         \
782
155k
            ret = njs_value_to_numeric(vm, value2, &numeric2);                \
783
155k
            if (njs_slow_path(ret != NJS_OK)) {                               \
784
0
                goto error;                                                   \
785
0
            }                                                                 \
786
155k
                                                                              \
787
155k
            value2 = &numeric2;                                               \
788
155k
        }                                                                     \
789
408k
                                                                              \
790
408k
        num = njs_number(value1);                                             \
791
408k
                                                                              \
792
408k
        njs_vmcode_operand(vm, vmcode->operand1, retval);                     \
793
408k
        pc += sizeof(njs_vmcode_3addr_t)
794
795
147k
    CASE (NJS_VMCODE_SUBTRACTION):
796
147k
        njs_vmcode_debug_opcode();
797
798
147k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
799
147k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
800
801
591k
        NJS_PRE_NUMERIC;
802
803
591k
        num -= njs_number(value2);
804
805
591k
        njs_set_number(retval, num);
806
591k
        NEXT;
807
808
591k
    CASE (NJS_VMCODE_MULTIPLICATION):
809
34.7k
        njs_vmcode_debug_opcode();
810
811
34.7k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
812
34.7k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
813
814
139k
        NJS_PRE_NUMERIC;
815
816
139k
        num *= njs_number(value2);
817
818
139k
        njs_set_number(retval, num);
819
139k
        NEXT;
820
821
139k
    CASE (NJS_VMCODE_EXPONENTIATION):
822
26.0k
        njs_vmcode_debug_opcode();
823
824
26.0k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
825
26.0k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
826
827
104k
        NJS_PRE_NUMERIC;
828
829
104k
        exponent = njs_number(value2);
830
        /*
831
         * According to ES7:
832
         *  1. If exponent is NaN, the result should be NaN;
833
         *  2. The result of +/-1 ** +/-Infinity should be NaN.
834
         */
835
104k
        valid = njs_expect(1, fabs(num) != 1
836
104k
                              || (!isnan(exponent)
837
104k
                                  && !isinf(exponent)));
838
839
104k
        num = valid ? pow(num, exponent) : NAN;
840
841
104k
        njs_set_number(retval, num);
842
104k
        NEXT;
843
844
104k
    CASE (NJS_VMCODE_DIVISION):
845
39.1k
        njs_vmcode_debug_opcode();
846
847
39.1k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
848
39.1k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
849
850
156k
        NJS_PRE_NUMERIC;
851
852
156k
        num /= njs_number(value2);
853
854
156k
        njs_set_number(retval, num);
855
156k
        NEXT;
856
857
156k
    CASE (NJS_VMCODE_REMAINDER):
858
87.6k
        njs_vmcode_debug_opcode();
859
860
87.6k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
861
87.6k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
862
863
350k
        NJS_PRE_NUMERIC;
864
865
350k
        num = fmod(num, njs_number(value2));
866
867
350k
        njs_set_number(retval, num);
868
350k
        NEXT;
869
870
350k
    CASE (NJS_VMCODE_BITWISE_AND):
871
18.7k
        njs_vmcode_debug_opcode();
872
873
18.7k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
874
18.7k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
875
876
75.1k
        NJS_PRE_NUMERIC;
877
878
75.1k
        i32 = njs_number_to_int32(njs_number(value2));
879
75.1k
        i32 &= njs_number_to_int32(num);
880
881
75.1k
        njs_set_int32(retval, i32);
882
75.1k
        NEXT;
883
884
75.1k
    CASE (NJS_VMCODE_BITWISE_OR):
885
6.56k
        njs_vmcode_debug_opcode();
886
887
6.56k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
888
6.56k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
889
890
26.2k
        NJS_PRE_NUMERIC;
891
892
26.2k
        i32 = njs_number_to_int32(njs_number(value2));
893
26.2k
        i32 |= njs_number_to_int32(num);
894
895
26.2k
        njs_set_int32(retval, i32);
896
26.2k
        NEXT;
897
898
26.2k
    CASE (NJS_VMCODE_BITWISE_XOR):
899
26.1k
        njs_vmcode_debug_opcode();
900
901
26.1k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
902
26.1k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
903
904
104k
        NJS_PRE_NUMERIC;
905
906
104k
        i32 = njs_number_to_int32(njs_number(value2));
907
104k
        i32 ^= njs_number_to_int32(num);
908
909
104k
        njs_set_int32(retval, i32);
910
104k
        NEXT;
911
912
104k
    CASE (NJS_VMCODE_LEFT_SHIFT):
913
6
        njs_vmcode_debug_opcode();
914
915
6
        njs_vmcode_operand(vm, vmcode->operand3, value2);
916
6
        njs_vmcode_operand(vm, vmcode->operand2, value1);
917
918
24
        NJS_PRE_NUMERIC;
919
920
24
        u32 = njs_number_to_uint32(njs_number(value2)) & 0x1f;
921
24
        i32 = njs_number_to_int32(num);
922
923
        /* Shifting of negative numbers is undefined. */
924
24
        i32 = (uint32_t) i32 << u32;
925
926
24
        njs_set_int32(retval, i32);
927
24
        NEXT;
928
929
12.0k
    CASE (NJS_VMCODE_RIGHT_SHIFT):
930
12.0k
        njs_vmcode_debug_opcode();
931
932
12.0k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
933
12.0k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
934
935
48.2k
        NJS_PRE_NUMERIC;
936
937
48.2k
        u32 = njs_number_to_uint32(njs_number(value2)) & 0x1f;
938
48.2k
        i32 = njs_number_to_int32(num);
939
940
48.2k
        i32 >>= u32;
941
942
48.2k
        njs_set_int32(retval, i32);
943
48.2k
        NEXT;
944
945
48.2k
    CASE (NJS_VMCODE_UNSIGNED_RIGHT_SHIFT):
946
9.50k
        njs_vmcode_debug_opcode();
947
948
9.50k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
949
9.50k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
950
951
38.0k
        NJS_PRE_NUMERIC;
952
953
38.0k
        u32 = njs_number_to_uint32(njs_number(value2)) & 0x1f;
954
38.0k
        njs_set_uint32(retval, njs_number_to_uint32(num) >> u32);
955
38.0k
        NEXT;
956
957
117k
    CASE (NJS_VMCODE_TEMPLATE_LITERAL):
958
117k
        njs_vmcode_debug_opcode();
959
960
117k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
961
962
117k
        ret = njs_vmcode_template_literal(vm, retval);
963
964
117k
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
965
0
            goto error;
966
0
        }
967
968
117k
        BREAK;
969
970
117k
    CASE (NJS_VMCODE_PROPERTY_IN):
971
1
        njs_vmcode_debug_opcode();
972
973
1
        njs_vmcode_operand(vm, vmcode->operand3, value2);
974
1
        njs_vmcode_operand(vm, vmcode->operand2, value1);
975
1
        njs_vmcode_operand(vm, vmcode->operand1, retval);
976
977
1
        ret = njs_vmcode_property_in(vm, value1, value2, retval);
978
1
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
979
1
            goto error;
980
1
        }
981
982
0
        BREAK;
983
984
1.53k
    CASE (NJS_VMCODE_PROPERTY_DELETE):
985
1.53k
        njs_vmcode_debug_opcode();
986
987
1.53k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
988
1.53k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
989
990
1.53k
        if (njs_slow_path(!njs_is_index_or_key(value2))) {
991
0
            if (njs_slow_path(njs_is_null_or_undefined(value1))) {
992
0
                (void) njs_throw_cannot_property(vm, value1, value2, "delete");
993
0
                goto error;
994
0
            }
995
996
0
            ret = njs_value_to_key(vm, &primitive1, value2);
997
0
            if (njs_slow_path(ret != NJS_OK)) {
998
0
                goto error;
999
0
            }
1000
1001
0
            value2 = &primitive1;
1002
0
        }
1003
1004
1.53k
        ret = njs_value_property_val_delete(vm, value1, value2, NULL, 1);
1005
1.53k
        if (njs_slow_path(ret == NJS_ERROR)) {
1006
0
            goto error;
1007
0
        }
1008
1009
1.53k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1010
1.53k
        njs_value_assign(retval, &njs_value_true);
1011
1.53k
        ret = sizeof(njs_vmcode_3addr_t);
1012
1013
1.53k
        BREAK;
1014
1015
1.97k
    CASE (NJS_VMCODE_PROPERTY_FOREACH):
1016
1.97k
        njs_vmcode_debug_opcode();
1017
1018
1.97k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1019
1.97k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1020
1021
1.97k
        ret = njs_vmcode_property_foreach(vm, value1, pc, retval);
1022
1.97k
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1023
0
            goto error;
1024
0
        }
1025
1026
1.97k
        BREAK;
1027
1028
1.97k
    CASE (NJS_VMCODE_STRICT_EQUAL):
1029
0
        njs_vmcode_debug_opcode();
1030
1031
0
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1032
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1033
1034
0
        ret = njs_values_strict_equal(vm, value1, value2);
1035
1036
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1037
0
        njs_set_boolean(retval, ret);
1038
1039
0
        pc += sizeof(njs_vmcode_3addr_t);
1040
0
        NEXT;
1041
1042
10.3k
    CASE (NJS_VMCODE_STRICT_NOT_EQUAL):
1043
10.3k
        njs_vmcode_debug_opcode();
1044
1045
10.3k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1046
10.3k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1047
1048
10.3k
        ret = njs_values_strict_equal(vm, value1, value2);
1049
1050
10.3k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1051
10.3k
        njs_set_boolean(retval, !ret);
1052
1053
10.3k
        pc += sizeof(njs_vmcode_3addr_t);
1054
10.3k
        NEXT;
1055
1056
10.3k
    CASE (NJS_VMCODE_TEST_IF_TRUE):
1057
5
        njs_vmcode_debug_opcode();
1058
1059
5
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1060
1061
5
        ret = njs_is_true(value1);
1062
1063
5
        if (ret) {
1064
0
            test_jump = (njs_vmcode_test_jump_t *) pc;
1065
0
            ret = test_jump->offset;
1066
1067
5
        } else {
1068
5
            ret = sizeof(njs_vmcode_3addr_t);
1069
5
        }
1070
1071
5
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1072
5
        *retval = *value1;
1073
1074
5
        BREAK;
1075
1076
89
    CASE (NJS_VMCODE_TEST_IF_FALSE):
1077
89
        njs_vmcode_debug_opcode();
1078
1079
89
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1080
1081
89
        ret = !njs_is_true(value1);
1082
1083
89
        if (ret) {
1084
89
            test_jump = (njs_vmcode_test_jump_t *) pc;
1085
89
            ret = test_jump->offset;
1086
1087
89
        } else {
1088
0
            ret = sizeof(njs_vmcode_3addr_t);
1089
0
        }
1090
1091
89
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1092
89
        *retval = *value1;
1093
1094
89
        BREAK;
1095
1096
89
    CASE (NJS_VMCODE_COALESCE):
1097
0
        njs_vmcode_debug_opcode();
1098
1099
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1100
1101
0
        ret = !njs_is_null_or_undefined(value1);
1102
1103
0
        if (ret) {
1104
0
            test_jump = (njs_vmcode_test_jump_t *) pc;
1105
0
            ret = test_jump->offset;
1106
1107
0
        } else {
1108
0
            ret = sizeof(njs_vmcode_3addr_t);
1109
0
        }
1110
1111
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1112
0
        *retval = *value1;
1113
1114
0
        BREAK;
1115
1116
170
    CASE (NJS_VMCODE_OPTIONAL_CHAIN):
1117
170
        njs_vmcode_debug_opcode();
1118
1119
170
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1120
1121
170
        if (njs_is_null_or_undefined(value1)) {
1122
168
            njs_vmcode_operand(vm, vmcode->operand1, retval);
1123
168
            njs_set_undefined(retval);
1124
168
            test_jump = (njs_vmcode_test_jump_t *) pc;
1125
168
            ret = test_jump->offset;
1126
1127
168
        } else {
1128
2
            ret = sizeof(njs_vmcode_3addr_t);
1129
2
        }
1130
1131
170
        BREAK;
1132
1133
170
#define NJS_PRE_UNARY                                                         \
1134
62.6k
        if (njs_slow_path(!njs_is_numeric(value1))) {                         \
1135
42.3k
            ret = njs_value_to_numeric(vm, value1, &numeric1);                \
1136
42.3k
            if (njs_slow_path(ret != NJS_OK)) {                               \
1137
0
                goto error;                                                   \
1138
0
            }                                                                 \
1139
42.3k
                                                                              \
1140
42.3k
            value1 = &numeric1;                                               \
1141
42.3k
        }                                                                     \
1142
62.6k
                                                                              \
1143
62.6k
        num = njs_number(value1);                                             \
1144
62.6k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1145
1146
24.8k
    CASE (NJS_VMCODE_UNARY_NEGATION):
1147
24.8k
        njs_vmcode_debug_opcode();
1148
1149
24.8k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1150
1151
74.5k
        NJS_PRE_UNARY;
1152
1153
74.5k
        num = -num;
1154
1155
74.5k
        njs_set_number(retval, num);
1156
1157
74.5k
        pc += sizeof(njs_vmcode_2addr_t);
1158
74.5k
        NEXT;
1159
1160
74.5k
    CASE (NJS_VMCODE_UNARY_PLUS):
1161
2.33k
        njs_vmcode_debug_opcode();
1162
1163
2.33k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1164
1165
7.00k
        NJS_PRE_UNARY;
1166
1167
7.00k
        njs_set_number(retval, num);
1168
1169
7.00k
        pc += sizeof(njs_vmcode_2addr_t);
1170
7.00k
        NEXT;
1171
1172
35.4k
    CASE (NJS_VMCODE_BITWISE_NOT):
1173
35.4k
        njs_vmcode_debug_opcode();
1174
1175
35.4k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1176
1177
106k
        NJS_PRE_UNARY;
1178
1179
106k
        njs_set_int32(retval, ~njs_number_to_uint32(num));
1180
1181
106k
        pc += sizeof(njs_vmcode_2addr_t);
1182
106k
        NEXT;
1183
1184
106k
    CASE (NJS_VMCODE_LOGICAL_NOT):
1185
2.11k
        njs_vmcode_debug_opcode();
1186
1187
2.11k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1188
2.11k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1189
1190
2.11k
        njs_set_boolean(retval, !njs_is_true(value1));
1191
1192
2.11k
        pc += sizeof(njs_vmcode_2addr_t);
1193
2.11k
        NEXT;
1194
1195
5.22k
    CASE (NJS_VMCODE_OBJECT):
1196
5.22k
        njs_vmcode_debug_opcode();
1197
1198
5.22k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1199
1200
5.22k
        ret = njs_vmcode_object(vm, retval);
1201
5.22k
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1202
0
            goto error;
1203
0
        }
1204
1205
5.22k
        BREAK;
1206
1207
332k
    CASE (NJS_VMCODE_ARRAY):
1208
332k
        njs_vmcode_debug_opcode();
1209
1210
332k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1211
1212
332k
        ret = njs_vmcode_array(vm, pc, retval);
1213
332k
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1214
0
            goto error;
1215
0
        }
1216
1217
332k
        BREAK;
1218
1219
332k
    CASE (NJS_VMCODE_FUNCTION):
1220
109k
        njs_vmcode_debug_opcode();
1221
1222
109k
        ret = njs_vmcode_function(vm, pc);
1223
109k
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1224
0
            goto error;
1225
0
        }
1226
1227
109k
        BREAK;
1228
1229
109k
    CASE (NJS_VMCODE_REGEXP):
1230
24.0k
        njs_vmcode_debug_opcode();
1231
1232
24.0k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1233
1234
24.0k
        ret = njs_vmcode_regexp(vm, pc, retval);
1235
24.0k
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1236
0
            goto error;
1237
0
        }
1238
1239
24.0k
        BREAK;
1240
1241
24.0k
    CASE (NJS_VMCODE_INSTANCE_OF):
1242
0
        njs_vmcode_debug_opcode();
1243
1244
0
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1245
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1246
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1247
1248
0
        ret = njs_vmcode_instance_of(vm, value1, value2, retval);
1249
0
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1250
0
            goto error;
1251
0
        }
1252
1253
0
        BREAK;
1254
1255
0
    CASE (NJS_VMCODE_TYPEOF):
1256
0
        njs_vmcode_debug_opcode();
1257
1258
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1259
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1260
1261
0
        ret = njs_vmcode_typeof(vm, value1, retval);
1262
0
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1263
0
            goto error;
1264
0
        }
1265
1266
0
        BREAK;
1267
1268
721
    CASE (NJS_VMCODE_VOID):
1269
721
        njs_vmcode_debug_opcode();
1270
1271
721
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1272
1273
721
        njs_set_undefined(retval);
1274
1275
721
        ret = sizeof(njs_vmcode_2addr_t);
1276
1277
721
        BREAK;
1278
1279
721
    CASE (NJS_VMCODE_DELETE):
1280
0
        njs_vmcode_debug_opcode();
1281
1282
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1283
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1284
1285
0
        njs_set_boolean(retval, 1);
1286
1287
0
        ret = sizeof(njs_vmcode_2addr_t);
1288
1289
0
        BREAK;
1290
1291
0
    CASE (NJS_VMCODE_DEBUGGER):
1292
0
        njs_vmcode_debug_opcode();
1293
1294
0
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1295
1296
0
        ret = njs_vmcode_debugger(vm, retval);
1297
1298
0
        BREAK;
1299
1300
481k
    CASE (NJS_VMCODE_PUT_ARG):
1301
481k
        njs_vmcode_debug_opcode();
1302
1303
481k
        put_arg = (njs_vmcode_1addr_t *) pc;
1304
481k
        native = vm->top_frame;
1305
1306
481k
        value1 = &native->arguments[native->put_args++];
1307
481k
        njs_vmcode_operand(vm, put_arg->index, value2);
1308
1309
481k
        njs_value_assign(value1, value2);
1310
1311
481k
        ret = sizeof(njs_vmcode_1addr_t);
1312
481k
        BREAK;
1313
1314
481k
    CASE (NJS_VMCODE_STOP):
1315
254
        njs_vmcode_debug_opcode();
1316
1317
254
        njs_vmcode_operand(vm, vmcode->operand1, value2);
1318
254
        *rval = *value2;
1319
1320
254
        njs_vmcode_debug(vm, pc, "EXIT STOP");
1321
1322
254
        return NJS_OK;
1323
1324
137
    CASE (NJS_VMCODE_JUMP):
1325
137
        njs_vmcode_debug_opcode();
1326
1327
137
        ret = (njs_jump_off_t) vmcode->operand1;
1328
137
        BREAK;
1329
1330
5.57k
    CASE (NJS_VMCODE_PROPERTY_ATOM_SET):
1331
5.57k
        njs_vmcode_debug_opcode();
1332
1333
5.57k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1334
5.57k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1335
5.57k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1336
1337
5.57k
        ret = njs_value_property_set(vm, value1, value2->atom_id, retval);
1338
5.57k
        if (njs_slow_path(ret == NJS_ERROR)) {
1339
34
            goto error;
1340
34
        }
1341
1342
5.53k
        ret = sizeof(njs_vmcode_prop_set_t);
1343
5.53k
        BREAK;
1344
1345
18.3k
    CASE (NJS_VMCODE_PROPERTY_SET):
1346
18.3k
        njs_vmcode_debug_opcode();
1347
1348
18.3k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1349
18.3k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1350
18.3k
        njs_vmcode_operand(vm, vmcode->operand1, retval);
1351
1352
18.3k
        if (njs_slow_path(!njs_is_index_or_key(value2))) {
1353
0
            if (njs_slow_path(njs_is_null_or_undefined(value1))) {
1354
0
                (void) njs_throw_cannot_property(vm, value1, value2, "set");
1355
0
                goto error;
1356
0
            }
1357
1358
0
            njs_value_assign(&primitive1, value1);
1359
0
            ret = njs_value_to_key(vm, &primitive2, value2);
1360
0
            if (njs_slow_path(ret != NJS_OK)) {
1361
0
                goto error;
1362
0
            }
1363
1364
0
            value1 = &primitive1;
1365
0
            value2 = &primitive2;
1366
0
        }
1367
1368
18.3k
        if (value2->atom_id == NJS_ATOM_STRING_unknown) {
1369
0
            num = njs_number(value2);
1370
1371
0
            if (njs_fast_path(njs_number_is_atom_index(num, &u32))) {
1372
0
                value2->atom_id = njs_number_atom(u32);
1373
1374
0
            } else {
1375
0
                ret = njs_atom_atomize_key(vm, value2);
1376
0
                if (njs_slow_path(ret != NJS_OK)) {
1377
0
                    goto error;
1378
0
                }
1379
0
            }
1380
0
        }
1381
1382
18.3k
        ret = njs_value_property_set(vm, value1, value2->atom_id, retval);
1383
18.3k
        if (njs_slow_path(ret == NJS_ERROR)) {
1384
0
            goto error;
1385
0
        }
1386
1387
18.3k
        ret = sizeof(njs_vmcode_prop_set_t);
1388
18.3k
        BREAK;
1389
1390
18.3k
    CASE (NJS_VMCODE_PROPERTY_ACCESSOR):
1391
712
        njs_vmcode_debug_opcode();
1392
1393
712
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1394
712
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1395
1396
712
        accessor = (njs_vmcode_prop_accessor_t *) pc;
1397
712
        njs_vmcode_operand(vm, accessor->value, function);
1398
1399
712
        ret = njs_value_to_key(vm, &name, value2);
1400
712
        if (njs_slow_path(ret != NJS_OK)) {
1401
0
            njs_internal_error(vm, "failed conversion of type \"%s\" "
1402
0
                               "to string while property define",
1403
0
                               njs_type_string(value2->type));
1404
0
            goto error;
1405
0
        }
1406
1407
712
        ret = njs_object_prop_define_val(vm, value1, &name, function,
1408
712
                                         accessor->type);
1409
712
        if (njs_slow_path(ret != NJS_OK)) {
1410
0
            goto error;
1411
0
        }
1412
1413
712
        ret = sizeof(njs_vmcode_prop_accessor_t);
1414
712
        BREAK;
1415
1416
712
    CASE (NJS_VMCODE_IF_TRUE_JUMP):
1417
124
        njs_vmcode_debug_opcode();
1418
1419
124
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1420
124
        value2 = (njs_value_t *) vmcode->operand1;
1421
1422
124
        ret = njs_is_true(value1);
1423
1424
124
        ret = ret ? (njs_jump_off_t) value2
1425
124
                  : (njs_jump_off_t) sizeof(njs_vmcode_cond_jump_t);
1426
1427
124
        BREAK;
1428
1429
124
    CASE (NJS_VMCODE_IF_FALSE_JUMP):
1430
10
        njs_vmcode_debug_opcode();
1431
1432
10
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1433
10
        value2 = (njs_value_t *) vmcode->operand1;
1434
1435
10
        ret = njs_is_true(value1);
1436
1437
10
        ret = !ret ? (njs_jump_off_t) value2
1438
10
                   : (njs_jump_off_t) sizeof(njs_vmcode_cond_jump_t);
1439
1440
10
        BREAK;
1441
1442
10
    CASE (NJS_VMCODE_IF_EQUAL_JUMP):
1443
0
        njs_vmcode_debug_opcode();
1444
1445
0
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1446
0
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1447
1448
0
        if (njs_values_strict_equal(vm, value1, value2)) {
1449
0
            equal = (njs_vmcode_equal_jump_t *) pc;
1450
0
            ret = equal->offset;
1451
1452
0
        } else {
1453
0
            ret = sizeof(njs_vmcode_3addr_t);
1454
0
        }
1455
1456
0
        BREAK;
1457
1458
3.05k
    CASE (NJS_VMCODE_PROPERTY_INIT):
1459
3.05k
        njs_vmcode_debug_opcode();
1460
1461
3.05k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1462
3.05k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1463
1464
3.05k
        set = (njs_vmcode_prop_set_t *) pc;
1465
3.05k
        njs_vmcode_operand(vm, set->value, retval);
1466
3.05k
        ret = njs_vmcode_property_init(vm, value1, value2, retval);
1467
3.05k
        if (njs_slow_path(ret == NJS_ERROR)) {
1468
0
            goto error;
1469
0
        }
1470
1471
3.05k
        BREAK;
1472
1473
924k
    CASE (NJS_VMCODE_ARRAY_INIT):
1474
924k
        njs_vmcode_debug_opcode();
1475
1476
924k
        array_init = (njs_vmcode_array_init_t *) pc;
1477
1478
924k
        njs_vmcode_operand(vm, array_init->array, value1);
1479
924k
        njs_vmcode_operand(vm, array_init->value, value2);
1480
1481
924k
        ret = njs_vmcode_array_init(vm, pc, value1, value2);
1482
924k
        if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) {
1483
0
            goto error;
1484
0
        }
1485
1486
924k
        BREAK;
1487
1488
924k
    CASE (NJS_VMCODE_RETURN):
1489
38.0k
        njs_vmcode_debug_opcode();
1490
1491
38.0k
        value2 = (njs_value_t *) vmcode->operand1;
1492
1493
38.0k
        njs_vmcode_operand(vm, (njs_index_t) value2, value2);
1494
1495
38.0k
        njs_vmcode_debug(vm, pc, "EXIT RETURN");
1496
1497
38.0k
        njs_vmcode_return(vm, rval, value2);
1498
1499
38.0k
        return NJS_OK;
1500
1501
211k
    CASE (NJS_VMCODE_FUNCTION_FRAME):
1502
211k
        njs_vmcode_debug_opcode();
1503
1504
211k
        value2 = (njs_value_t *) vmcode->operand1;
1505
211k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1506
1507
211k
        function_frame = (njs_vmcode_function_frame_t *) pc;
1508
1509
211k
        ret = njs_function_frame_create(vm, value1, &njs_value_undefined,
1510
211k
                                        (uintptr_t) value2,
1511
211k
                                        function_frame->ctor);
1512
1513
211k
        if (njs_slow_path(ret != NJS_OK)) {
1514
48
            goto error;
1515
48
        }
1516
1517
211k
        ret = sizeof(njs_vmcode_function_frame_t);
1518
211k
        BREAK;
1519
1520
211k
    CASE (NJS_VMCODE_METHOD_FRAME):
1521
167k
        njs_vmcode_debug_opcode();
1522
1523
167k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1524
167k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1525
1526
167k
        method_frame = (njs_vmcode_method_frame_t *) pc;
1527
1528
167k
        ret = njs_function_frame_create(vm, value1, value2,
1529
167k
                                        method_frame->nargs,
1530
167k
                                        method_frame->ctor);
1531
1532
167k
        if (njs_slow_path(ret != NJS_OK)) {
1533
7
            goto error;
1534
7
        }
1535
1536
167k
        ret = sizeof(njs_vmcode_method_frame_t);
1537
167k
        BREAK;
1538
1539
378k
    CASE (NJS_VMCODE_FUNCTION_CALL):
1540
378k
        njs_vmcode_debug_opcode();
1541
1542
378k
        value2 = (njs_value_t *) vmcode->operand1;
1543
1544
378k
        vm->active_frame->native.pc = pc;
1545
1546
378k
        njs_vmcode_operand(vm, (njs_index_t) value2, value2);
1547
1548
378k
        ret = njs_function_frame_invoke(vm, value2);
1549
378k
        if (njs_slow_path(ret == NJS_ERROR)) {
1550
57.7k
            goto error;
1551
57.7k
        }
1552
1553
320k
        njs_vmcode_debug(vm, pc, "RESUME");
1554
1555
320k
        ret = sizeof(njs_vmcode_function_call_t);
1556
320k
        BREAK;
1557
1558
320k
    CASE (NJS_VMCODE_PROPERTY_NEXT):
1559
289k
        njs_vmcode_debug_opcode();
1560
1561
289k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1562
289k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1563
1564
289k
        pnext = (njs_vmcode_prop_next_t *) pc;
1565
289k
        retval = njs_scope_value(vm, pnext->retval);
1566
1567
289k
        njs_assert(njs_is_data(value2, NJS_DATA_TAG_FOREACH_NEXT));
1568
289k
        next = njs_data(value2);
1569
1570
289k
        if (next->index < next->array->length) {
1571
287k
            *retval = next->array->start[next->index++];
1572
1573
287k
            ret = pnext->offset;
1574
287k
            BREAK;
1575
287k
        }
1576
1577
289k
        njs_mp_free(vm->mem_pool, next);
1578
1579
289k
        ret = sizeof(njs_vmcode_prop_next_t);
1580
289k
        BREAK;
1581
1582
289k
    CASE (NJS_VMCODE_ARGUMENTS):
1583
3
        njs_vmcode_debug_opcode();
1584
1585
3
        ret = njs_vmcode_arguments(vm, pc);
1586
3
        if (njs_slow_path(ret == NJS_ERROR)) {
1587
0
            goto error;
1588
0
        }
1589
1590
3
        BREAK;
1591
1592
1.83k
    CASE (NJS_VMCODE_TO_PROPERTY_KEY):
1593
1.83k
        njs_vmcode_debug_opcode();
1594
1595
1.83k
        value2 = (njs_value_t *) vmcode->operand1;
1596
1.83k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1597
1598
1.83k
        njs_vmcode_operand(vm, (njs_index_t) value2, retval);
1599
1600
1.83k
        ret = njs_value_to_key(vm, retval, value1);
1601
1.83k
        if (njs_fast_path(ret == NJS_ERROR)) {
1602
0
            goto error;
1603
0
        }
1604
1605
1.83k
        ret = sizeof(njs_vmcode_2addr_t);
1606
1.83k
        BREAK;
1607
1608
18.3k
    CASE (NJS_VMCODE_TO_PROPERTY_KEY_CHK):
1609
18.3k
        njs_vmcode_debug_opcode();
1610
1611
18.3k
        value2 = (njs_value_t *) vmcode->operand1;
1612
18.3k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1613
1614
18.3k
        njs_vmcode_operand(vm, (njs_index_t) value2, retval);
1615
18.3k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1616
1617
18.3k
        if (njs_slow_path(njs_is_null_or_undefined(value2))) {
1618
0
            (void) njs_throw_cannot_property(vm, value2, value1, "get");
1619
0
            goto error;
1620
0
        }
1621
1622
18.3k
        ret = njs_value_to_key(vm, retval, value1);
1623
18.3k
        if (njs_fast_path(ret == NJS_ERROR)) {
1624
0
            goto error;
1625
0
        }
1626
1627
18.3k
        ret = sizeof(njs_vmcode_3addr_t);
1628
18.3k
        BREAK;
1629
1630
18.3k
    CASE (NJS_VMCODE_SET_FUNCTION_NAME):
1631
1.83k
        njs_vmcode_debug_opcode();
1632
1633
1.83k
        value2 = (njs_value_t *) vmcode->operand1;
1634
1.83k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1635
1636
1.83k
        njs_vmcode_operand(vm, (njs_index_t) value2, value2);
1637
1638
1.83k
        njs_assert(njs_is_function(value2));
1639
1640
1.83k
        ret = njs_function_name_set(vm, njs_function(value2), value1, NULL);
1641
1.83k
        if (njs_slow_path(ret == NJS_ERROR)) {
1642
0
            goto error;
1643
0
        }
1644
1645
1.83k
        ret = sizeof(njs_vmcode_2addr_t);
1646
1.83k
        BREAK;
1647
1648
1649
1.83k
    CASE (NJS_VMCODE_PROTO_INIT):
1650
1.12k
        njs_vmcode_debug_opcode();
1651
1652
1.12k
        njs_vmcode_operand(vm, vmcode->operand3, value2);
1653
1.12k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1654
1655
1.12k
        set = (njs_vmcode_prop_set_t *) pc;
1656
1.12k
        njs_vmcode_operand(vm, set->value, retval);
1657
1.12k
        ret = njs_vmcode_proto_init(vm, value1, value2, retval);
1658
1.12k
        if (njs_slow_path(ret == NJS_ERROR)) {
1659
0
            goto error;
1660
0
        }
1661
1662
1.12k
        BREAK;
1663
1664
1.12k
    CASE (NJS_VMCODE_IMPORT):
1665
0
        njs_vmcode_debug_opcode();
1666
1667
0
        import = (njs_vmcode_import_t *) pc;
1668
0
        retval = njs_scope_value(vm, import->retval);
1669
0
        ret = njs_vmcode_import(vm, import->module, retval);
1670
0
        if (njs_slow_path(ret == NJS_ERROR)) {
1671
0
            goto error;
1672
0
        }
1673
1674
0
        BREAK;
1675
1676
5.71k
    CASE (NJS_VMCODE_AWAIT):
1677
5.71k
        njs_vmcode_debug_opcode();
1678
1679
5.71k
        await = (njs_vmcode_await_t *) pc;
1680
1681
5.71k
        ret = njs_vmcode_await(vm, await, rval, promise_cap, async_ctx);
1682
1683
5.71k
        njs_vmcode_debug(vm, pc, "EXIT AWAIT");
1684
1685
5.71k
        if (njs_slow_path(ret == NJS_ERROR)) {
1686
0
            goto error;
1687
0
        }
1688
1689
5.71k
        return ret;
1690
1691
76.1k
    CASE (NJS_VMCODE_TRY_START):
1692
76.1k
        njs_vmcode_debug_opcode();
1693
1694
76.1k
        value2 = (njs_value_t *) vmcode->operand1;
1695
76.1k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1696
1697
76.1k
        ret = njs_vmcode_try_start(vm, value1, value2, pc);
1698
76.1k
        if (njs_slow_path(ret == NJS_ERROR)) {
1699
0
            goto error;
1700
0
        }
1701
1702
76.1k
        BREAK;
1703
1704
76.1k
    CASE (NJS_VMCODE_THROW):
1705
3
        njs_vmcode_debug_opcode();
1706
1707
3
        value2 = (njs_value_t *) vmcode->operand1;
1708
1709
3
        njs_vmcode_operand(vm, (njs_index_t) value2, value2);
1710
3
        njs_vm_throw(vm, value2);
1711
1712
3
        goto error;
1713
1714
0
    CASE (NJS_VMCODE_TRY_BREAK):
1715
0
        njs_vmcode_debug_opcode();
1716
1717
0
        value2 = (njs_value_t *) vmcode->operand1;
1718
1719
0
        try_trampoline = (njs_vmcode_try_trampoline_t *) pc;
1720
0
        value1 = njs_scope_value(vm, try_trampoline->exit_value);
1721
1722
0
        ret = njs_vmcode_try_break(vm, value1, value2);
1723
0
        BREAK;
1724
1725
6
    CASE (NJS_VMCODE_TRY_CONTINUE):
1726
6
        njs_vmcode_debug_opcode();
1727
1728
6
        value2 = (njs_value_t *) vmcode->operand1;
1729
1730
6
        try_trampoline = (njs_vmcode_try_trampoline_t *) pc;
1731
6
        value1 = njs_scope_value(vm, try_trampoline->exit_value);
1732
1733
6
        ret = njs_vmcode_try_continue(vm, value1, value2);
1734
6
        BREAK;
1735
1736
2.05k
    CASE (NJS_VMCODE_TRY_END):
1737
2.05k
        njs_vmcode_debug_opcode();
1738
1739
2.05k
        ret = njs_vmcode_try_end(vm, NULL, (njs_value_t *) vmcode->operand1);
1740
2.05k
        BREAK;
1741
1742
    /*
1743
     * njs_vmcode_catch() is set on the start of a "catch" block to
1744
     * store exception and to remove a "try" block if there is no
1745
     * "finally" block or to update a catch address to the start of
1746
     * a "finally" block.
1747
     * njs_vmcode_catch() is set on the start of a "finally" block
1748
     * to store uncaught exception and to remove a "try" block.
1749
     */
1750
74.6k
    CASE (NJS_VMCODE_CATCH):
1751
74.6k
        njs_vmcode_debug_opcode();
1752
1753
74.6k
        value2 = (njs_value_t *) vmcode->operand1;
1754
74.6k
        njs_vmcode_operand(vm, vmcode->operand2, value1);
1755
1756
74.6k
        *value1 = njs_vm_exception(vm);
1757
1758
74.6k
        if ((njs_jump_off_t) value2 == sizeof(njs_vmcode_catch_t)) {
1759
74.1k
            ret = njs_vmcode_try_end(vm, value1, value2);
1760
1761
74.1k
        } else {
1762
516
            frame = (njs_frame_t *) vm->top_frame;
1763
516
            frame->exception.catch = pc + (njs_jump_off_t) value2;
1764
516
            ret = sizeof(njs_vmcode_catch_t);
1765
516
        }
1766
1767
74.6k
        BREAK;
1768
1769
74.6k
    CASE (NJS_VMCODE_FINALLY):
1770
1.09k
        njs_vmcode_debug_opcode();
1771
1772
1.09k
        value2 = (njs_value_t *) vmcode->operand1;
1773
1774
1.09k
        ret = njs_vmcode_finally(vm, rval, value2, pc);
1775
1776
1.09k
        switch (ret) {
1777
0
        case NJS_OK:
1778
0
            njs_vmcode_debug(vm, pc, "EXIT FINALLY");
1779
1780
0
            return NJS_OK;
1781
516
        case NJS_ERROR:
1782
516
            goto error;
1783
1.09k
        }
1784
1785
578
        BREAK;
1786
1787
30.5k
    CASE (NJS_VMCODE_LET):
1788
30.5k
        njs_vmcode_debug_opcode();
1789
1790
30.5k
        var = (njs_vmcode_variable_t *) pc;
1791
30.5k
        value1 = njs_scope_value(vm, var->dst);
1792
1793
30.5k
        if (njs_is_valid(value1)) {
1794
27.7k
            value1 = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t));
1795
27.7k
            if (njs_slow_path(value1 == NULL)) {
1796
0
                njs_memory_error(vm);
1797
0
                goto error;
1798
0
            }
1799
1800
27.7k
            njs_scope_value_set(vm, var->dst, value1);
1801
27.7k
        }
1802
1803
30.5k
        njs_set_undefined(value1);
1804
1805
30.5k
        ret = sizeof(njs_vmcode_variable_t);
1806
30.5k
        BREAK;
1807
1808
52.2k
    CASE (NJS_VMCODE_LET_UPDATE):
1809
52.2k
        njs_vmcode_debug_opcode();
1810
1811
52.2k
        var = (njs_vmcode_variable_t *) pc;
1812
52.2k
        value2 = njs_scope_value(vm, var->dst);
1813
1814
52.2k
        value1 = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t));
1815
52.2k
        if (njs_slow_path(value1 == NULL)) {
1816
0
            njs_memory_error(vm);
1817
0
            goto error;
1818
0
        }
1819
1820
52.2k
        *value1 = *value2;
1821
1822
52.2k
        njs_scope_value_set(vm, var->dst, value1);
1823
1824
52.2k
        ret = sizeof(njs_vmcode_variable_t);
1825
52.2k
        BREAK;
1826
1827
52.2k
    CASE (NJS_VMCODE_INITIALIZATION_TEST):
1828
0
        njs_vmcode_debug_opcode();
1829
1830
0
        var = (njs_vmcode_variable_t *) pc;
1831
0
        value1 = njs_scope_value(vm, var->dst);
1832
1833
0
        if (njs_is_valid(value1)) {
1834
0
            ret = sizeof(njs_vmcode_variable_t);
1835
0
            BREAK;
1836
0
        }
1837
1838
0
        FALLTHROUGH;
1839
0
    CASE (NJS_VMCODE_NOT_INITIALIZED):
1840
0
        njs_vmcode_debug_opcode();
1841
1842
0
        njs_reference_error(vm, "cannot access variable before initialization");
1843
0
        goto error;
1844
1845
22.0k
    CASE (NJS_VMCODE_ERROR):
1846
22.0k
        njs_vmcode_debug_opcode();
1847
1848
22.0k
        njs_vmcode_error(vm, pc);
1849
22.0k
        goto error;
1850
1851
27.7k
    CASE (NJS_VMCODE_ASSIGNMENT_ERROR):
1852
27.7k
        njs_vmcode_debug_opcode();
1853
1854
27.7k
        njs_type_error(vm, "assignment to constant variable");
1855
27.7k
        goto error;
1856
1857
0
    }
1858
1859
108k
error:
1860
1861
108k
    if (njs_is_error(&vm->exception)) {
1862
108k
        vm->active_frame->native.pc = pc;
1863
1864
108k
        njs_error_stack_attach(vm, vm->exception, 0);
1865
108k
    }
1866
1867
161k
    for ( ;; ) {
1868
161k
        native = vm->top_frame;
1869
1870
161k
        if (!native->native) {
1871
108k
            frame = (njs_frame_t *) native;
1872
108k
            catch = frame->exception.catch;
1873
1874
108k
            if (catch != NULL) {
1875
74.6k
                pc = catch;
1876
1877
74.6k
                NEXT;
1878
74.6k
            }
1879
108k
        }
1880
1881
161k
        previous = native->previous;
1882
161k
        if (previous == NULL) {
1883
192
            break;
1884
192
        }
1885
1886
160k
        lambda_call = (native == &vm->active_frame->native);
1887
1888
160k
        njs_vm_scopes_restore(vm, native);
1889
1890
160k
        if (native->size != 0) {
1891
27
            vm->spare_stack_size += native->size;
1892
27
            njs_mp_free(vm->mem_pool, native);
1893
27
        }
1894
1895
160k
        if (lambda_call) {
1896
33.3k
            break;
1897
33.3k
        }
1898
160k
    }
1899
1900
108k
    njs_vmcode_debug(vm, pc, "EXIT ERROR");
1901
1902
108k
    return NJS_ERROR;
1903
0
}
1904
1905
1906
static njs_jump_off_t
1907
njs_vmcode_object(njs_vm_t *vm, njs_value_t *retval)
1908
5.22k
{
1909
5.22k
    njs_object_t  *object;
1910
1911
5.22k
    object = njs_object_alloc(vm);
1912
1913
5.22k
    if (njs_fast_path(object != NULL)) {
1914
5.22k
        njs_set_object(retval, object);
1915
1916
5.22k
        return sizeof(njs_vmcode_object_t);
1917
5.22k
    }
1918
1919
0
    return NJS_ERROR;
1920
5.22k
}
1921
1922
1923
static njs_jump_off_t
1924
njs_vmcode_array(njs_vm_t *vm, u_char *pc, njs_value_t *retval)
1925
332k
{
1926
332k
    uint32_t            length;
1927
332k
    njs_array_t         *array;
1928
332k
    njs_value_t         *value;
1929
332k
    njs_vmcode_array_t  *code;
1930
1931
332k
    code = (njs_vmcode_array_t *) pc;
1932
1933
332k
    array = njs_array_alloc(vm, code->flat, code->length, NJS_ARRAY_SPARE);
1934
1935
332k
    if (njs_fast_path(array != NULL)) {
1936
1937
332k
        if (code->ctor) {
1938
            /* Array of the form [,,,], [1,,]. */
1939
9.40k
            if (array->object.fast_array) {
1940
9.39k
                value = array->start;
1941
9.39k
                length = array->length;
1942
1943
39.8k
                do {
1944
39.8k
                    njs_set_invalid(value);
1945
39.8k
                    value++;
1946
39.8k
                    length--;
1947
39.8k
                } while (length != 0);
1948
9.39k
            }
1949
1950
322k
        } else {
1951
            /* Array of the form [], [,,1], [1,2,3]. */
1952
322k
            array->length = 0;
1953
322k
        }
1954
1955
332k
        njs_set_array(retval, array);
1956
1957
332k
        return sizeof(njs_vmcode_array_t);
1958
332k
    }
1959
1960
0
    return NJS_ERROR;
1961
332k
}
1962
1963
1964
static njs_jump_off_t
1965
njs_vmcode_function(njs_vm_t *vm, u_char *pc)
1966
109k
{
1967
109k
    njs_function_t         *function;
1968
109k
    njs_vmcode_function_t  *code;
1969
109k
    njs_function_lambda_t  *lambda;
1970
1971
109k
    code = (njs_vmcode_function_t *) pc;
1972
109k
    lambda = code->lambda;
1973
1974
109k
    function = njs_function_alloc(vm, lambda, code->async);
1975
109k
    if (njs_slow_path(function == NULL)) {
1976
0
        return NJS_ERROR;
1977
0
    }
1978
1979
109k
    if (njs_function_capture_closure(vm, function, lambda) != NJS_OK) {
1980
0
        return NJS_ERROR;
1981
0
    }
1982
1983
109k
    function->args_count = lambda->nargs - lambda->rest_parameters;
1984
1985
109k
    njs_set_function(njs_scope_value(vm, code->retval), function);
1986
1987
109k
    return sizeof(njs_vmcode_function_t);
1988
109k
}
1989
1990
1991
static njs_jump_off_t
1992
njs_vmcode_arguments(njs_vm_t *vm, u_char *pc)
1993
3
{
1994
3
    njs_frame_t             *frame;
1995
3
    njs_value_t             *value;
1996
3
    njs_jump_off_t          ret;
1997
3
    njs_vmcode_arguments_t  *code;
1998
1999
3
    frame = (njs_frame_t *) vm->active_frame;
2000
2001
3
    if (frame->native.arguments_object == NULL) {
2002
3
        ret = njs_function_arguments_object_init(vm, &frame->native);
2003
3
        if (njs_slow_path(ret != NJS_OK)) {
2004
0
            return NJS_ERROR;
2005
0
        }
2006
3
    }
2007
2008
3
    code = (njs_vmcode_arguments_t *) pc;
2009
2010
3
    value = njs_scope_valid_value(vm, code->dst);
2011
3
    if (njs_slow_path(value == NULL)) {
2012
0
        return NJS_ERROR;
2013
0
    }
2014
2015
3
    njs_set_object(value, frame->native.arguments_object);
2016
2017
3
    return sizeof(njs_vmcode_arguments_t);
2018
3
}
2019
2020
2021
static njs_jump_off_t
2022
njs_vmcode_regexp(njs_vm_t *vm, u_char *pc, njs_value_t *retval)
2023
24.0k
{
2024
24.0k
    njs_regexp_t         *regexp;
2025
24.0k
    njs_vmcode_regexp_t  *code;
2026
2027
24.0k
    code = (njs_vmcode_regexp_t *) pc;
2028
2029
24.0k
    regexp = njs_regexp_alloc(vm, code->pattern);
2030
2031
24.0k
    if (njs_fast_path(regexp != NULL)) {
2032
24.0k
        njs_set_regexp(retval, regexp);
2033
2034
24.0k
        return sizeof(njs_vmcode_regexp_t);
2035
24.0k
    }
2036
2037
0
    return NJS_ERROR;
2038
24.0k
}
2039
2040
2041
static njs_jump_off_t
2042
njs_vmcode_template_literal(njs_vm_t *vm, njs_value_t *retval)
2043
117k
{
2044
117k
    njs_array_t     *array;
2045
117k
    njs_jump_off_t  ret;
2046
117k
    njs_value_t     arguments[1];
2047
2048
117k
    static const njs_function_t  concat = {
2049
117k
          .native = 1,
2050
117k
          .u.native = njs_string_prototype_concat
2051
117k
    };
2052
2053
117k
    njs_assert(njs_is_array(retval));
2054
2055
117k
    array = njs_array(retval);
2056
2057
117k
    njs_set_empty_string(vm, &arguments[0]);
2058
2059
117k
    ret = njs_function_call(vm, (njs_function_t *) &concat, &arguments[0],
2060
117k
                            array->start, array->length, retval);
2061
117k
    if (njs_slow_path(ret != NJS_OK)) {
2062
0
        return ret;
2063
0
    }
2064
2065
117k
    njs_array_destroy(vm, array);
2066
2067
117k
    return sizeof(njs_vmcode_template_literal_t);
2068
117k
}
2069
2070
2071
static njs_jump_off_t
2072
njs_vmcode_array_init(njs_vm_t *vm, u_char *pc, njs_value_t *value,
2073
    njs_value_t *init)
2074
924k
{
2075
924k
    uint32_t                 index, size;
2076
924k
    njs_array_t              *array;
2077
924k
    njs_value_t              *entry;
2078
924k
    njs_object_prop_t        *prop;
2079
924k
    njs_vmcode_array_init_t  *code;
2080
2081
924k
    code = (njs_vmcode_array_init_t *) pc;
2082
924k
    index = code->index;
2083
2084
924k
    if (njs_slow_path(!njs_is_array(value))) {
2085
0
        njs_internal_error(vm, "array initialization target is not an array");
2086
0
        return NJS_ERROR;
2087
0
    }
2088
2089
924k
    array = njs_array(value);
2090
2091
924k
    if (njs_fast_path(array->object.fast_array)) {
2092
506k
        njs_assert(index < array->size);
2093
2094
506k
        if (index >= array->length) {
2095
483k
            entry = &array->start[array->length];
2096
483k
            size = index - array->length;
2097
2098
539k
            while (size != 0) {
2099
55.6k
                njs_set_invalid(entry);
2100
55.6k
                entry++;
2101
55.6k
                size--;
2102
55.6k
            }
2103
2104
483k
            array->length = index + 1;
2105
483k
        }
2106
2107
506k
        njs_value_assign(&array->start[index], init);
2108
2109
506k
    } else {
2110
418k
        prop = njs_object_property_add(vm, value, njs_number_atom(index), 0);
2111
418k
        if (njs_slow_path(prop == NULL)) {
2112
0
            return NJS_ERROR;
2113
0
        }
2114
2115
418k
        njs_value_assign(njs_prop_value(prop), init);
2116
418k
    }
2117
2118
924k
    return sizeof(njs_vmcode_array_init_t);
2119
924k
}
2120
2121
2122
static njs_jump_off_t
2123
njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *key,
2124
    njs_value_t *init)
2125
3.05k
{
2126
3.05k
    njs_int_t            ret;
2127
3.05k
    njs_value_t          name;
2128
3.05k
    njs_object_prop_t    *prop;
2129
3.05k
    njs_flathsh_query_t  fhq;
2130
2131
3.05k
    switch (value->type) {
2132
3.05k
    case NJS_OBJECT:
2133
3.05k
        if (key->type == NJS_STRING) {
2134
1.02k
            if (key->atom_id == NJS_ATOM_STRING_unknown) {
2135
0
                ret = njs_atom_atomize_key(vm, key);
2136
0
                if (ret != NJS_OK) {
2137
0
                    return ret;
2138
0
                }
2139
0
            }
2140
1.02k
        }
2141
2142
3.05k
        ret = njs_value_to_key(vm, &name, key);
2143
3.05k
        if (njs_slow_path(ret != NJS_OK)) {
2144
0
            return NJS_ERROR;
2145
0
        }
2146
2147
3.05k
        if (name.atom_id == NJS_ATOM_STRING_unknown) {
2148
2.03k
            ret = njs_atom_atomize_key(vm, &name);
2149
2.03k
            if (ret != NJS_OK) {
2150
0
                return ret;
2151
0
            }
2152
2.03k
        }
2153
2154
3.05k
        fhq.key_hash = name.atom_id;
2155
3.05k
        fhq.replace = 1;
2156
3.05k
        fhq.pool = vm->mem_pool;
2157
3.05k
        fhq.proto = &njs_object_hash_proto;
2158
2159
3.05k
        ret = njs_flathsh_unique_insert(njs_object_hash(value), &fhq);
2160
3.05k
        if (njs_slow_path(ret != NJS_OK)) {
2161
0
            njs_internal_error(vm, "flathsh insert/replace failed");
2162
0
            return NJS_ERROR;
2163
0
        }
2164
2165
3.05k
        prop = fhq.value;
2166
2167
3.05k
        prop->type = NJS_PROPERTY;
2168
3.05k
        prop->enumerable = 1;
2169
3.05k
        prop->configurable = 1;
2170
3.05k
        prop->writable = 1;
2171
3.05k
        prop->u.value = *init;
2172
2173
3.05k
        break;
2174
2175
0
    default:
2176
0
        njs_internal_error(vm, "unexpected object type \"%s\" "
2177
0
                           "while property initialization",
2178
0
                           njs_type_string(value->type));
2179
2180
0
        return NJS_ERROR;
2181
3.05k
    }
2182
2183
3.05k
    return sizeof(njs_vmcode_prop_set_t);
2184
3.05k
}
2185
2186
2187
static njs_jump_off_t
2188
njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *unused,
2189
    njs_value_t *init)
2190
1.12k
{
2191
1.12k
    njs_object_t         *obj;
2192
1.12k
    njs_value_t          retval;
2193
1.12k
    njs_jump_off_t       ret;
2194
1.12k
    njs_object_prop_t    *prop;
2195
1.12k
    njs_flathsh_query_t  fhq;
2196
2197
1.12k
    fhq.key_hash = NJS_ATOM_STRING___proto__;
2198
1.12k
    fhq.proto = &njs_object_hash_proto;
2199
1.12k
    fhq.pool = vm->mem_pool;
2200
2201
1.12k
    obj = njs_object(value);
2202
2203
1.12k
    ret = njs_flathsh_unique_find(&obj->__proto__->shared_hash, &fhq);
2204
1.12k
    if (njs_slow_path(ret != NJS_OK)) {
2205
0
        goto fail;
2206
0
    }
2207
2208
1.12k
    prop = fhq.value;
2209
2210
1.12k
    if (prop->type != NJS_PROPERTY_HANDLER) {
2211
0
        goto fail;
2212
0
    }
2213
2214
1.12k
    ret = njs_prop_handler(prop)(vm, prop, fhq.key_hash, value, init, &retval);
2215
1.12k
    if (njs_slow_path(ret != NJS_OK)) {
2216
0
        goto fail;
2217
0
    }
2218
2219
1.12k
    return sizeof(njs_vmcode_prop_set_t);
2220
2221
0
fail:
2222
2223
0
    njs_internal_error(vm, "\"__proto__\" init failed");
2224
0
    return NJS_ERROR;
2225
1.12k
}
2226
2227
2228
static njs_jump_off_t
2229
njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *key,
2230
    njs_value_t *retval)
2231
1
{
2232
1
    njs_int_t             ret;
2233
1
    njs_value_t           primitive;
2234
1
    njs_property_query_t  pq;
2235
2236
1
    if (njs_slow_path(njs_is_primitive(value))) {
2237
1
        njs_type_error(vm, "property \"in\" on primitive %s type",
2238
1
                       njs_type_string(value->type));
2239
1
        return NJS_ERROR;
2240
1
    }
2241
2242
0
    if (njs_slow_path(!njs_is_index_or_key(key))) {
2243
0
        ret = njs_value_to_key(vm, &primitive, key);
2244
0
        if (njs_slow_path(ret != NJS_OK)) {
2245
0
            return NJS_ERROR;
2246
0
        }
2247
2248
0
        key = &primitive;
2249
0
    }
2250
2251
0
    njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0);
2252
2253
0
    ret = njs_property_query_val(vm, &pq, value, key);
2254
0
    if (njs_slow_path(ret == NJS_ERROR)) {
2255
0
        return ret;
2256
0
    }
2257
2258
0
    njs_set_boolean(retval, ret == NJS_OK);
2259
2260
0
    return sizeof(njs_vmcode_3addr_t);
2261
0
}
2262
2263
2264
static njs_jump_off_t
2265
njs_vmcode_property_foreach(njs_vm_t *vm, njs_value_t *object,
2266
    u_char *pc, njs_value_t *retval)
2267
1.97k
{
2268
1.97k
    njs_property_next_t        *next;
2269
1.97k
    njs_vmcode_prop_foreach_t  *code;
2270
2271
1.97k
    next = njs_mp_alloc(vm->mem_pool, sizeof(njs_property_next_t));
2272
1.97k
    if (njs_slow_path(next == NULL)) {
2273
0
        njs_memory_error(vm);
2274
0
        return NJS_ERROR;
2275
0
    }
2276
2277
1.97k
    next->index = 0;
2278
1.97k
    next->array = njs_value_enumerate(vm, object,
2279
1.97k
                                      NJS_ENUM_KEYS
2280
1.97k
                                      | NJS_ENUM_STRING
2281
1.97k
                                      | NJS_ENUM_ENUMERABLE_ONLY);
2282
1.97k
    if (njs_slow_path(next->array == NULL)) {
2283
0
        njs_memory_error(vm);
2284
0
        return NJS_ERROR;
2285
0
    }
2286
2287
1.97k
    njs_set_data(retval, next, NJS_DATA_TAG_FOREACH_NEXT);
2288
2289
1.97k
    code = (njs_vmcode_prop_foreach_t *) pc;
2290
2291
1.97k
    return code->offset;
2292
1.97k
}
2293
2294
2295
static njs_jump_off_t
2296
njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
2297
    njs_value_t *constructor, njs_value_t *retval)
2298
0
{
2299
0
    njs_value_t     value, bound;
2300
0
    njs_object_t    *prototype, *proto;
2301
0
    njs_function_t  *function;
2302
0
    njs_jump_off_t  ret;
2303
2304
0
    if (!njs_is_function(constructor)) {
2305
0
        njs_type_error(vm, "right argument is not callable");
2306
0
        return NJS_ERROR;
2307
0
    }
2308
2309
0
    function = njs_function(constructor);
2310
2311
0
    if (function->bound != NULL) {
2312
0
        function = function->context;
2313
0
        njs_set_function(&bound, function);
2314
0
        constructor = &bound;
2315
0
    }
2316
2317
0
    if (njs_is_object(object)) {
2318
0
        ret = njs_value_property(vm, constructor, NJS_ATOM_STRING_prototype,
2319
0
                                 &value);
2320
2321
0
        if (njs_slow_path(ret == NJS_ERROR)) {
2322
0
            return ret;
2323
0
        }
2324
2325
0
        if (njs_fast_path(ret == NJS_OK)) {
2326
0
            if (njs_slow_path(!njs_is_object(&value))) {
2327
0
                njs_type_error(vm, "Function has non-object prototype "
2328
0
                               "in instanceof");
2329
0
                return NJS_ERROR;
2330
0
            }
2331
2332
0
            prototype = njs_object(&value);
2333
0
            proto = njs_object(object);
2334
2335
0
            do {
2336
0
                proto = proto->__proto__;
2337
2338
0
                if (proto == prototype) {
2339
0
                    njs_value_assign(retval, &njs_value_true);
2340
0
                    return sizeof(njs_vmcode_instance_of_t);
2341
0
                }
2342
2343
0
            } while (proto != NULL);
2344
0
        }
2345
0
    }
2346
2347
0
    njs_value_assign(retval, &njs_value_false);
2348
2349
0
    return sizeof(njs_vmcode_instance_of_t);
2350
0
}
2351
2352
2353
static njs_jump_off_t
2354
njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval)
2355
0
{
2356
    /* ECMAScript 5.1: null, array and regexp are objects. */
2357
2358
0
    static const uint32_t  types[NJS_VALUE_TYPE_MAX] = {
2359
0
        NJS_ATOM_STRING_object,
2360
0
        NJS_ATOM_STRING_undefined,
2361
0
        NJS_ATOM_STRING_boolean,
2362
0
        NJS_ATOM_STRING_number,
2363
0
        NJS_ATOM_STRING_symbol,
2364
0
        NJS_ATOM_STRING_string,
2365
0
        NJS_ATOM_STRING_data,
2366
0
        NJS_ATOM_STRING_external,
2367
0
        NJS_ATOM_STRING_unknown,
2368
0
        NJS_ATOM_STRING_undefined,
2369
0
        NJS_ATOM_STRING_undefined,
2370
0
        NJS_ATOM_STRING_undefined,
2371
0
        NJS_ATOM_STRING_undefined,
2372
0
        NJS_ATOM_STRING_undefined,
2373
0
        NJS_ATOM_STRING_undefined,
2374
0
        NJS_ATOM_STRING_undefined,
2375
2376
0
        NJS_ATOM_STRING_object,
2377
0
        NJS_ATOM_STRING_object,
2378
0
        NJS_ATOM_STRING_function,
2379
0
        NJS_ATOM_STRING_object,
2380
0
        NJS_ATOM_STRING_object,
2381
0
        NJS_ATOM_STRING_object,
2382
0
        NJS_ATOM_STRING_object,
2383
0
        NJS_ATOM_STRING_object,
2384
0
        NJS_ATOM_STRING_object,
2385
0
        NJS_ATOM_STRING_object,
2386
0
    };
2387
2388
0
    njs_atom_to_value(vm, retval, types[value->type]);
2389
2390
0
    return sizeof(njs_vmcode_2addr_t);
2391
0
}
2392
2393
2394
static njs_jump_off_t
2395
njs_vmcode_debugger(njs_vm_t *vm, njs_value_t *retval)
2396
0
{
2397
    /*
2398
     * HOW TO DEBUG JS CODE:
2399
     * 1) put debugger instruction when certain condition is met
2400
     *    in the JS code:
2401
     *    function test() {
2402
     *      if (<>) debugger;
2403
     *    }
2404
     * 2) set a breakpoint to njs_vmcode_debugger() in gdb.
2405
     *
2406
     * To see the values of certain indices:
2407
     * 1) use njs -d test.js to dump the byte code
2408
     * 2) find an appropriate index around DEBUGGER instruction
2409
     * 3) in gdb: p *njs_scope_value_get(vm, <index as a hex literal>)
2410
     **/
2411
2412
0
    njs_set_undefined(retval);
2413
2414
0
    return sizeof(njs_vmcode_debugger_t);
2415
0
}
2416
2417
2418
static njs_jump_off_t
2419
njs_string_concat(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2,
2420
    njs_value_t *retval)
2421
167k
{
2422
167k
    u_char             *start;
2423
167k
    size_t             size, length;
2424
167k
    njs_string_prop_t  string1, string2;
2425
2426
167k
    (void) njs_string_prop(vm, &string1, val1);
2427
167k
    (void) njs_string_prop(vm, &string2, val2);
2428
2429
167k
    length = string1.length + string2.length;
2430
167k
    size = string1.size + string2.size;
2431
2432
167k
    start = njs_string_alloc(vm, retval, size, length);
2433
167k
    if (njs_slow_path(start == NULL)) {
2434
0
        return NJS_ERROR;
2435
0
    }
2436
2437
167k
    (void) memcpy(start, string1.start, string1.size);
2438
167k
    (void) memcpy(start + string1.size, string2.start, string2.size);
2439
2440
167k
    return sizeof(njs_vmcode_3addr_t);
2441
167k
}
2442
2443
2444
static njs_jump_off_t
2445
njs_values_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
2446
10.6k
{
2447
10.6k
    njs_int_t    ret;
2448
10.6k
    njs_bool_t   nv1, nv2;
2449
10.6k
    njs_value_t  primitive;
2450
10.6k
    njs_value_t  *hv, *lv;
2451
2452
10.6k
again:
2453
2454
10.6k
    nv1 = njs_is_null_or_undefined(val1);
2455
10.6k
    nv2 = njs_is_null_or_undefined(val2);
2456
2457
    /* Void and null are equal and not comparable with anything else. */
2458
10.6k
    if (nv1 || nv2) {
2459
283
        return (nv1 && nv2);
2460
283
    }
2461
2462
10.3k
    if (njs_is_numeric(val1) && njs_is_numeric(val2)) {
2463
        /* NaNs and Infinities are handled correctly by comparision. */
2464
10.3k
        return (njs_number(val1) == njs_number(val2));
2465
10.3k
    }
2466
2467
0
    if (val1->type == val2->type) {
2468
2469
0
        if (njs_is_string(val1)) {
2470
0
            return njs_string_eq(vm, val1, val2);
2471
0
        }
2472
2473
0
        if (njs_is_symbol(val1)) {
2474
0
            return njs_symbol_eq(val1, val2);
2475
0
        }
2476
2477
0
        return (njs_object(val1) == njs_object(val2));
2478
0
    }
2479
2480
    /* Sort values as: numeric < symbol < string < objects. */
2481
2482
0
    if (val1->type > val2->type) {
2483
0
        hv = val1;
2484
0
        lv = val2;
2485
2486
0
    } else {
2487
0
        hv = val2;
2488
0
        lv = val1;
2489
0
    }
2490
2491
    /* If "lv" is an object then "hv" can only be another object. */
2492
0
    if (njs_is_object(lv)) {
2493
0
        return 0;
2494
0
    }
2495
2496
    /* If "hv" is a symbol then "lv" can only be a numeric. */
2497
0
    if (njs_is_symbol(hv)) {
2498
0
        return 0;
2499
0
    }
2500
2501
    /* If "hv" is a string then "lv" can be a numeric or symbol. */
2502
0
    if (njs_is_string(hv)) {
2503
0
        return !njs_is_symbol(lv)
2504
0
            && (njs_number(lv) == njs_string_to_number(vm, hv));
2505
0
    }
2506
2507
    /* "hv" is an object and "lv" is either a string or a symbol or a numeric. */
2508
2509
0
    ret = njs_value_to_primitive(vm, &primitive, hv, NJS_HINT_NONE);
2510
0
    if (ret != NJS_OK) {
2511
0
        return ret;
2512
0
    }
2513
2514
0
    val1 = &primitive;
2515
0
    val2 = lv;
2516
2517
0
    goto again;
2518
0
}
2519
2520
2521
/*
2522
 * ECMAScript 5.1: 11.8.5
2523
 * njs_primitive_values_compare() returns
2524
 *   1 if val1 is less than val2,
2525
 *   0 if val1 is greater than or equal to val2,
2526
 *  -1 if the values are not comparable.
2527
 */
2528
2529
static njs_jump_off_t
2530
njs_primitive_values_compare(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2)
2531
88.2k
{
2532
88.2k
    double   num1, num2;
2533
2534
88.2k
    if (njs_fast_path(njs_is_numeric(val1))) {
2535
27.3k
        num1 = njs_number(val1);
2536
2537
27.3k
        if (njs_fast_path(njs_is_numeric(val2))) {
2538
23.5k
            num2 = njs_number(val2);
2539
2540
23.5k
        } else {
2541
3.87k
            num2 = njs_string_to_number(vm, val2);
2542
3.87k
        }
2543
2544
60.8k
    } else if (njs_is_numeric(val2)) {
2545
30.4k
        num1 = njs_string_to_number(vm, val1);
2546
30.4k
        num2 = njs_number(val2);
2547
2548
30.4k
    } else {
2549
30.3k
        return (njs_string_cmp(vm, val1, val2) < 0) ? 1 : 0;
2550
30.3k
    }
2551
2552
    /* NaN and void values are not comparable with anything. */
2553
57.8k
    if (isnan(num1) || isnan(num2)) {
2554
57.4k
        return -1;
2555
57.4k
    }
2556
2557
    /* Infinities are handled correctly by comparision. */
2558
443
    return (num1 < num2);
2559
57.8k
}
2560
2561
2562
static njs_jump_off_t
2563
njs_function_frame_create(njs_vm_t *vm, njs_value_t *value,
2564
    const njs_value_t *this, uintptr_t nargs, njs_bool_t ctor)
2565
378k
{
2566
378k
    njs_int_t       ret;
2567
378k
    njs_value_t     new_target, *args;
2568
378k
    njs_object_t    *object;
2569
378k
    njs_function_t  *function, *target;
2570
2571
378k
    if (njs_fast_path(njs_is_function(value))) {
2572
2573
378k
        function = njs_function(value);
2574
378k
        target = function;
2575
378k
        args = NULL;
2576
2577
378k
        if (ctor) {
2578
117k
            if (function->bound != NULL) {
2579
0
                target = function->context;
2580
0
                nargs += function->bound_args;
2581
2582
0
                args = njs_mp_alloc(vm->mem_pool, nargs * sizeof(njs_value_t));
2583
0
                if (njs_slow_path(args == NULL)) {
2584
0
                    njs_memory_error(vm);
2585
0
                    return NJS_ERROR;
2586
0
                }
2587
2588
0
                memcpy(args, &function->bound[1],
2589
0
                       function->bound_args * sizeof(njs_value_t));
2590
0
            }
2591
2592
117k
            if (!target->ctor) {
2593
0
                njs_type_error(vm, "%s is not a constructor",
2594
0
                               njs_type_string(value->type));
2595
0
                return NJS_ERROR;
2596
0
            }
2597
2598
117k
            if (!target->native) {
2599
0
                object = njs_function_new_object(vm, value);
2600
0
                if (njs_slow_path(object == NULL)) {
2601
0
                    return NJS_ERROR;
2602
0
                }
2603
2604
0
                njs_set_object(&new_target, object);
2605
0
                this = &new_target;
2606
0
            }
2607
117k
        }
2608
2609
378k
        ret = njs_function_frame(vm, target, this, args, nargs, ctor);
2610
2611
378k
        if (args != NULL) {
2612
0
            vm->top_frame->put_args = function->bound_args;
2613
0
            njs_mp_free(vm->mem_pool, args);
2614
0
        }
2615
2616
378k
        return ret;
2617
378k
    }
2618
2619
55
    njs_type_error(vm, "%s is not a function", njs_type_string(value->type));
2620
2621
55
    return NJS_ERROR;
2622
378k
}
2623
2624
2625
njs_object_t *
2626
njs_function_new_object(njs_vm_t *vm, njs_value_t *constructor)
2627
52.5k
{
2628
52.5k
    njs_value_t     proto, bound;
2629
52.5k
    njs_object_t    *object;
2630
52.5k
    njs_function_t  *function;
2631
52.5k
    njs_jump_off_t  ret;
2632
2633
52.5k
    object = njs_object_alloc(vm);
2634
52.5k
    if (njs_slow_path(object == NULL)) {
2635
0
        return NULL;
2636
0
    }
2637
2638
52.5k
    njs_assert(njs_is_function(constructor));
2639
2640
52.5k
    function = njs_function(constructor);
2641
2642
52.5k
    if (function->bound != NULL) {
2643
0
        function = function->context;
2644
0
        njs_set_function(&bound, function);
2645
0
        constructor = &bound;
2646
0
    }
2647
2648
52.5k
    ret = njs_value_property(vm, constructor, NJS_ATOM_STRING_prototype, &proto);
2649
2650
52.5k
    if (njs_slow_path(ret == NJS_ERROR)) {
2651
0
        return NULL;
2652
0
    }
2653
2654
52.5k
    if (njs_fast_path(njs_is_object(&proto))) {
2655
52.5k
        object->__proto__ = njs_object(&proto);
2656
52.5k
    }
2657
2658
52.5k
    return object;
2659
52.5k
}
2660
2661
2662
static void
2663
njs_vmcode_return(njs_vm_t *vm, njs_value_t *dst, njs_value_t *retval)
2664
43.7k
{
2665
43.7k
    njs_frame_t  *frame;
2666
2667
43.7k
    frame = (njs_frame_t *) vm->top_frame;
2668
2669
43.7k
    if (frame->native.ctor) {
2670
0
        if (!njs_is_object(retval)) {
2671
0
            retval = frame->native.local[0];
2672
0
        }
2673
0
    }
2674
2675
43.7k
    njs_vm_scopes_restore(vm, &frame->native);
2676
2677
43.7k
    *dst = *retval;
2678
2679
43.7k
    njs_function_frame_free(vm, &frame->native);
2680
43.7k
}
2681
2682
2683
static njs_jump_off_t
2684
njs_vmcode_import(njs_vm_t *vm, njs_mod_t *module, njs_value_t *retval)
2685
0
{
2686
0
    njs_int_t  ret;
2687
0
    njs_mod_t  *m;
2688
2689
0
    m = njs_module_find(vm, &module->name, 0);
2690
0
    if (njs_slow_path(m == NULL)) {
2691
0
        if (!njs_is_valid(&vm->exception)) {
2692
0
            njs_error(vm, "Cannot load module \"%V\"", &module->name);
2693
0
        }
2694
2695
0
        return NJS_ERROR;
2696
0
    }
2697
2698
0
    if (!njs_is_null(&m->value)) {
2699
0
        njs_value_assign(retval, &m->value);
2700
0
        return sizeof(njs_vmcode_import_t);
2701
0
    }
2702
2703
0
    njs_set_invalid(&m->value);
2704
2705
0
    ret = njs_vm_invoke(vm, &m->function, NULL, 0, &m->value);
2706
0
    if (ret == NJS_ERROR) {
2707
0
        return ret;
2708
0
    }
2709
2710
0
    njs_value_assign(retval, &m->value);
2711
2712
0
    return sizeof(njs_vmcode_import_t);
2713
0
}
2714
2715
2716
static njs_int_t
2717
njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
2718
    njs_value_t *dst, njs_promise_capability_t *pcap, njs_async_ctx_t *ctx)
2719
5.71k
{
2720
5.71k
    size_t              size;
2721
5.71k
    njs_int_t           ret;
2722
5.71k
    njs_value_t         ctor, val, on_fulfilled, on_rejected, *value, retval;
2723
5.71k
    njs_function_t      *fulfilled, *rejected;
2724
5.71k
    njs_native_frame_t  *active;
2725
2726
5.71k
    active = &vm->active_frame->native;
2727
2728
5.71k
    value = njs_scope_valid_value(vm, await->retval);
2729
5.71k
    if (njs_slow_path(value == NULL)) {
2730
0
        njs_internal_error(vm, "await->retval is invalid");
2731
0
        return NJS_ERROR;
2732
0
    }
2733
2734
5.71k
    njs_set_function(&ctor, &njs_vm_ctor(vm, NJS_OBJ_TYPE_PROMISE));
2735
2736
5.71k
    ret = njs_promise_resolve(vm, &ctor, value, &val);
2737
5.71k
    if (njs_slow_path(ret != NJS_OK)) {
2738
0
        return NJS_ERROR;
2739
0
    }
2740
2741
5.71k
    if (ctx == NULL) {
2742
253
        ctx = njs_mp_alloc(vm->mem_pool, sizeof(njs_async_ctx_t));
2743
253
        if (njs_slow_path(ctx == NULL)) {
2744
0
            njs_memory_error(vm);
2745
0
            return NJS_ERROR;
2746
0
        }
2747
2748
253
        size = njs_function_frame_size(active);
2749
2750
253
        fulfilled = njs_promise_create_function(vm, size);
2751
253
        if (njs_slow_path(fulfilled == NULL)) {
2752
0
            return NJS_ERROR;
2753
0
        }
2754
2755
253
        ctx->await = fulfilled->context;
2756
253
        ctx->capability = pcap;
2757
2758
253
        ret = njs_function_frame_save(vm, ctx->await, NULL);
2759
253
        if (njs_slow_path(ret != NJS_OK)) {
2760
0
            return NJS_ERROR;
2761
0
        }
2762
2763
5.46k
    } else {
2764
5.46k
        fulfilled = njs_promise_create_function(vm, 0);
2765
5.46k
        if (njs_slow_path(fulfilled == NULL)) {
2766
0
            return NJS_ERROR;
2767
0
        }
2768
5.46k
    }
2769
2770
5.71k
    ctx->pc = (u_char *) await + sizeof(njs_vmcode_await_t);
2771
5.71k
    ctx->index = await->retval;
2772
5.71k
    ctx->throw_flag = 0;
2773
2774
5.71k
    fulfilled->context = ctx;
2775
5.71k
    fulfilled->args_count = 1;
2776
5.71k
    fulfilled->u.native = njs_await_fulfilled;
2777
2778
5.71k
    rejected = njs_promise_create_function(vm, 0);
2779
5.71k
    if (njs_slow_path(rejected == NULL)) {
2780
0
        return NJS_ERROR;
2781
0
    }
2782
2783
5.71k
    rejected->context = ctx;
2784
5.71k
    rejected->args_count = 1;
2785
5.71k
    rejected->u.native = njs_await_rejected;
2786
2787
5.71k
    njs_set_function(&on_fulfilled, fulfilled);
2788
5.71k
    njs_set_function(&on_rejected, rejected);
2789
2790
5.71k
    ret = njs_promise_perform_then(vm, &val, &on_fulfilled, &on_rejected, NULL,
2791
5.71k
                                   &retval);
2792
5.71k
    if (njs_slow_path(ret != NJS_OK)) {
2793
0
        return NJS_ERROR;
2794
0
    }
2795
2796
5.71k
    njs_vmcode_return(vm, dst, &retval);
2797
2798
5.71k
    return NJS_AGAIN;
2799
5.71k
}
2800
2801
2802
/*
2803
 * njs_vmcode_try_start() is set on the start of a "try" block to create
2804
 * a "try" block, to set a catch address to the start of a "catch" or
2805
 * "finally" blocks and to initialize a value to track uncaught exception.
2806
 */
2807
2808
static njs_jump_off_t
2809
njs_vmcode_try_start(njs_vm_t *vm, njs_value_t *exception_value,
2810
    njs_value_t *offset, u_char *pc)
2811
76.1k
{
2812
76.1k
    njs_value_t             *exit_value;
2813
76.1k
    njs_frame_t             *frame;
2814
76.1k
    njs_exception_t         *e;
2815
76.1k
    njs_vmcode_try_start_t  *try_start;
2816
2817
76.1k
    frame = (njs_frame_t *) vm->top_frame;
2818
2819
76.1k
    if (frame->exception.catch != NULL) {
2820
2.05k
        e = njs_mp_alloc(vm->mem_pool, sizeof(njs_exception_t));
2821
2.05k
        if (njs_slow_path(e == NULL)) {
2822
0
            njs_memory_error(vm);
2823
0
            return NJS_ERROR;
2824
0
        }
2825
2826
2.05k
        *e = frame->exception;
2827
2.05k
        frame->exception.next = e;
2828
2.05k
    }
2829
2830
76.1k
    frame->exception.catch = pc + (njs_jump_off_t) offset;
2831
2832
76.1k
    njs_set_invalid(exception_value);
2833
2834
76.1k
    try_start = (njs_vmcode_try_start_t *) pc;
2835
76.1k
    exit_value = njs_scope_value(vm, try_start->exit_value);
2836
2837
76.1k
    njs_set_invalid(exit_value);
2838
76.1k
    njs_number(exit_value) = 0;
2839
2840
76.1k
    return sizeof(njs_vmcode_try_start_t);
2841
76.1k
}
2842
2843
2844
/*
2845
 * njs_vmcode_try_break() sets exit_value to INVALID 1, and jumps to
2846
 * the nearest try_end block. The exit_value is checked by njs_vmcode_finally().
2847
 */
2848
2849
static njs_jump_off_t
2850
njs_vmcode_try_break(njs_vm_t *vm, njs_value_t *exit_value,
2851
    njs_value_t *offset)
2852
0
{
2853
    /* exit_value can contain valid value set by vmcode_try_return. */
2854
0
    if (!njs_is_valid(exit_value)) {
2855
0
        njs_number(exit_value) = 1;
2856
0
    }
2857
2858
0
    return (njs_jump_off_t) offset;
2859
0
}
2860
2861
2862
/*
2863
 * njs_vmcode_try_continue() sets exit_value to INVALID -1, and jumps to
2864
 * the nearest try_end block. The exit_value is checked by njs_vmcode_finally().
2865
 */
2866
2867
static njs_jump_off_t
2868
njs_vmcode_try_continue(njs_vm_t *vm, njs_value_t *exit_value,
2869
    njs_value_t *offset)
2870
6
{
2871
6
    njs_number(exit_value) = -1;
2872
2873
6
    return (njs_jump_off_t) offset;
2874
6
}
2875
2876
2877
/*
2878
 * njs_vmcode_try_end() is set on the end of a "try" block to remove the block.
2879
 * It is also set on the end of a "catch" block followed by a "finally" block.
2880
 */
2881
2882
static njs_jump_off_t
2883
njs_vmcode_try_end(njs_vm_t *vm, njs_value_t *invld, njs_value_t *offset)
2884
76.1k
{
2885
76.1k
    njs_frame_t      *frame;
2886
76.1k
    njs_exception_t  *e;
2887
2888
76.1k
    frame = (njs_frame_t *) vm->top_frame;
2889
76.1k
    e = frame->exception.next;
2890
2891
76.1k
    if (e == NULL) {
2892
74.1k
        frame->exception.catch = NULL;
2893
2894
74.1k
    } else {
2895
2.05k
        frame->exception = *e;
2896
2.05k
        njs_mp_free(vm->mem_pool, e);
2897
2.05k
    }
2898
2899
76.1k
    return (njs_jump_off_t) offset;
2900
76.1k
}
2901
2902
2903
/*
2904
 * njs_vmcode_finally() is set on the end of a "finally" or a "catch" block.
2905
 *   1) to throw uncaught exception.
2906
 *   2) to make a jump to an enslosing loop exit if "continue" or "break"
2907
 *      statement was used inside try block.
2908
 *   3) to finalize "return" instruction from "try" block.
2909
 */
2910
2911
static njs_jump_off_t
2912
njs_vmcode_finally(njs_vm_t *vm, njs_value_t *dst, njs_value_t *retval,
2913
    u_char *pc)
2914
1.09k
{
2915
1.09k
    njs_value_t           *exception_value, *exit_value;
2916
1.09k
    njs_jump_off_t        offset;
2917
1.09k
    njs_vmcode_finally_t  *finally;
2918
2919
1.09k
    exception_value = njs_scope_value(vm, (njs_index_t) retval);
2920
2921
1.09k
    if (njs_is_valid(exception_value)) {
2922
516
        njs_vm_throw(vm, exception_value);
2923
2924
516
        return NJS_ERROR;
2925
516
    }
2926
2927
578
    finally = (njs_vmcode_finally_t *) pc;
2928
2929
578
    exit_value = njs_scope_value(vm, finally->exit_value);
2930
2931
    /*
2932
     * exit_value is set by:
2933
     *   vmcode_try_start to INVALID 0
2934
     *   vmcode_try_break to INVALID 1
2935
     *   vmcode_try_continue to INVALID -1
2936
     *   vmcode_try_return to a valid return value
2937
     */
2938
2939
578
    if (njs_is_valid(exit_value)) {
2940
0
        njs_vmcode_return(vm, dst, exit_value);
2941
2942
0
        return NJS_OK;
2943
2944
578
    } else if (njs_number(exit_value) != 0) {
2945
6
        offset = (njs_number(exit_value) > 0) ? finally->break_offset
2946
6
                                              : finally->continue_offset;
2947
2948
6
        if (njs_slow_path(offset
2949
6
                          < (njs_jump_off_t) sizeof(njs_vmcode_finally_t)))
2950
0
        {
2951
0
            njs_internal_error(vm, "unset %s offset for FINALLY block",
2952
0
                               (njs_number(exit_value) > 0) ? "exit"
2953
0
                                                            : "continuaion");
2954
0
            return NJS_ERROR;
2955
0
        }
2956
2957
6
        return offset;
2958
6
    }
2959
2960
572
    return sizeof(njs_vmcode_finally_t);
2961
578
}
2962
2963
2964
static void
2965
njs_vmcode_error(njs_vm_t *vm, u_char *pc)
2966
22.0k
{
2967
22.0k
    njs_vmcode_error_t  *err;
2968
2969
22.0k
    err = (njs_vmcode_error_t *) pc;
2970
2971
22.0k
    if (err->type == NJS_OBJ_TYPE_REF_ERROR) {
2972
22.0k
        njs_reference_error(vm, "\"%V\" is not defined", &err->u.name);
2973
2974
22.0k
    } else {
2975
0
        njs_throw_error(vm, err->type, "%V", &err->u.message);
2976
0
    }
2977
22.0k
}
2978
2979
2980
static njs_int_t
2981
njs_throw_cannot_property(njs_vm_t *vm, njs_value_t *object, njs_value_t *key,
2982
    const char *what)
2983
0
{
2984
0
    njs_int_t    ret;
2985
0
    njs_str_t    string;
2986
0
    njs_value_t  dst;
2987
2988
0
    ret = njs_value_to_key2(vm, &dst, key, 0);
2989
0
    if (njs_slow_path(ret != NJS_OK)) {
2990
0
        return NJS_ERROR;
2991
0
    }
2992
2993
0
    njs_key_string_get(vm, &dst, &string);
2994
2995
0
    njs_type_error(vm, "cannot %s property \"%V\" of %s", what,
2996
0
                   &string, njs_is_null(object) ? "null" : "undefined");
2997
2998
0
    return NJS_OK;
2999
0
}