1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ECMASCRIPT_INTERPRETER_INTERPRETER_INL_H
17#define ECMASCRIPT_INTERPRETER_INTERPRETER_INL_H
18
19#include "ecmascript/debugger/js_debugger_manager.h"
20#include "ecmascript/ecma_context.h"
21#include "ecmascript/ecma_string.h"
22#include "ecmascript/ecma_vm.h"
23#include "ecmascript/global_env.h"
24#include "ecmascript/ic/ic_runtime_stub-inl.h"
25#include "ecmascript/interpreter/fast_runtime_stub-inl.h"
26#include "ecmascript/interpreter/interpreter.h"
27#include "ecmascript/interpreter/interpreter_assembly.h"
28#include "ecmascript/interpreter/frame_handler.h"
29#include "ecmascript/interpreter/slow_runtime_stub.h"
30#include "ecmascript/jspandafile/literal_data_extractor.h"
31#include "ecmascript/jspandafile/program_object.h"
32#include "ecmascript/js_async_generator_object.h"
33#include "ecmascript/js_generator_object.h"
34#include "ecmascript/js_tagged_value.h"
35#include "ecmascript/jit/jit_task.h"
36#include "ecmascript/mem/concurrent_marker.h"
37#include "ecmascript/module/js_module_manager.h"
38#include "ecmascript/module/js_module_source_text.h"
39#include "ecmascript/runtime_call_id.h"
40#include "ecmascript/stubs/runtime_stubs.h"
41#include "ecmascript/sendable_env.h"
42#include "ecmascript/template_string.h"
43#include "ecmascript/checkpoint/thread_state_transition.h"
44#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
45#include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
46#endif
47
48namespace panda::ecmascript {
49using CommonStubCSigns = kungfu::CommonStubCSigns;
50#if defined(__clang__)
51#pragma clang diagnostic push
52#pragma clang diagnostic ignored "-Wvoid-ptr-dereference"
53#pragma clang diagnostic ignored "-Wgnu-label-as-value"
54#elif defined(__GNUC__)
55#pragma GCC diagnostic push
56#pragma GCC diagnostic ignored "-Wpedantic"
57#endif
58
59#if ECMASCRIPT_ENABLE_INTERPRETER_LOG
60#define HANDLE_OPCODE(opcode)                                           \
61    HANDLE_##opcode:                                                    \
62    {                                                                   \
63        RuntimeStubs::DebugPrintInstruction(thread->GetGlueAddr(), pc); \
64    }
65#else
66#define HANDLE_OPCODE(opcode)       \
67    HANDLE_##opcode:
68#endif
69
70#define NOPRINT_HANDLE_OPCODE(opcode) \
71    HANDLE_##opcode:
72
73#define LOG_INST() false && LOG_INTERPRETER(DEBUG)
74
75#define DEBUG_HANDLE_OPCODE(opcode) \
76    DEBUG_HANDLE_##opcode:
77
78// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
79#define ADVANCE_PC(offset) \
80    pc += (offset);  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic, cppcoreguidelines-macro-usage)
81
82#define GOTO_NEXT()  // NOLINT(clang-diagnostic-gnu-label-as-value, cppcoreguidelines-macro-usage)
83
84// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
85#define DISPATCH(curOpcode)                                       \
86    do {                                                          \
87        ADVANCE_PC(BytecodeInstruction::Size(EcmaOpcode::curOpcode))  \
88        opcode = READ_INST_OP(); goto *dispatchTable[opcode];     \
89    } while (false)
90
91// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
92#define DISPATCH_OFFSET(offset)                               \
93    do {                                                      \
94        ADVANCE_PC(offset)                                    \
95        opcode = READ_INST_OP(); goto *dispatchTable[opcode]; \
96    } while (false)
97
98#define DISPATCH_THROW()                  \
99    do {                                  \
100        opcode = *(pc + 1);               \
101        goto *throwDispatchTable[opcode]; \
102    } while (false)
103
104#define DISPATCH_WIDE()                  \
105    do {                                 \
106        opcode = *(pc + 1);              \
107        goto *wideDispatchTable[opcode]; \
108    } while (false)
109
110#define DISPATCH_DEPRECATED()                  \
111    do {                                       \
112        opcode = *(pc + 1);                    \
113        goto *deprecatedDispatchTable[opcode]; \
114    } while (false)
115
116#define DISPATCH_CALLRUNTIME()                  \
117    do {                                        \
118        opcode = *(pc + 1);                     \
119        goto *callRuntimeDispatchTable[opcode]; \
120    } while (false)
121
122// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
123#define GET_FRAME(CurrentSp) \
124    (reinterpret_cast<InterpretedFrame *>(CurrentSp) - 1)  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
125// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
126#define GET_ENTRY_FRAME(sp) \
127    (reinterpret_cast<InterpretedEntryFrame *>(sp) - 1)  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
128#define GET_BUILTIN_FRAME(sp) \
129    (reinterpret_cast<InterpretedBuiltinFrame *>(sp) - 1)  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
130// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
131#define SAVE_PC() (GET_FRAME(sp)->pc = pc)  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
132// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
133#define SAVE_ACC() (GET_FRAME(sp)->acc = acc)  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
134// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
135#define RESTORE_ACC() (acc = GET_FRAME(sp)->acc)  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
136// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
137#define GET_VREG(idx) (sp[idx])  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
138// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
139#define GET_VREG_VALUE(idx) (JSTaggedValue(sp[idx]))  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
140// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
141#define SET_VREG(idx, val) (sp[idx] = (val));  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
142#define GET_ACC() (acc)                        // NOLINT(cppcoreguidelines-macro-usage)
143#define SET_ACC(val) (acc = val)               // NOLINT(cppcoreguidelines-macro-usage)
144
145#define GET_METHOD_FROM_CACHE(index) \
146    ConstantPool::GetMethodFromCache(thread, constpool, index)
147
148#define GET_STR_FROM_CACHE(index) \
149    ConstantPool::GetStringFromCache(thread, constpool, index)
150
151#define GET_LITERA_FROM_CACHE(index, type, module) \
152    ConstantPool::GetLiteralFromCache<type>(thread, constpool, index, module)
153
154// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
155#define INTERPRETER_GOTO_EXCEPTION_HANDLER()          \
156    do {                                              \
157        SAVE_PC();                                    \
158        goto *dispatchTable[EXCEPTION_OPCODE]; \
159    } while (false)
160
161// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
162#define INTERPRETER_HANDLE_RETURN()                                                     \
163    do {                                                                                \
164        size_t jumpSize = GetJumpSizeAfterCall(pc);                                     \
165        DISPATCH_OFFSET(jumpSize);                                                      \
166    } while (false)
167
168// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
169#define CHECK_SWITCH_TO_DEBUGGER_TABLE()                 \
170    if (ecmaVm->GetJsDebuggerManager()->IsDebugMode()) { \
171        dispatchTable = debugDispatchTable.data();       \
172    }
173
174// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
175#define REAL_GOTO_DISPATCH_OPCODE(opcode)                       \
176    do {                                                        \
177        ASSERT(static_cast<uint16_t>(opcode) <= 0xff);          \
178        goto *instDispatchTable[static_cast<uint8_t>(opcode)];  \
179    } while (false)
180
181// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
182#define REAL_GOTO_EXCEPTION_HANDLER()                     \
183    do {                                                  \
184        SAVE_PC();                                        \
185        goto *instDispatchTable[EXCEPTION_OPCODE]; \
186    } while (false)
187
188// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
189#define INTERPRETER_RETURN_IF_ABRUPT(result)      \
190    do {                                          \
191        if (result.IsException()) {               \
192            INTERPRETER_GOTO_EXCEPTION_HANDLER(); \
193        }                                         \
194    } while (false)
195
196// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
197#define HANDLE_EXCEPTION_IF_ABRUPT_COMPLETION(_thread)    \
198    do {                                                  \
199        if (UNLIKELY((_thread)->HasPendingException())) { \
200            INTERPRETER_GOTO_EXCEPTION_HANDLER();         \
201        }                                                 \
202    } while (false)
203
204#define JUMP_IF_ENTRYFRAME_PENDING()                \
205    do {                                            \
206        if (thread->IsEntryFrameDroppedPending()) { \
207            thread->ResetEntryFrameDroppedState();  \
208            DROPFRAME_JUMP();                       \
209        }                                           \
210    } while (false)
211
212#define DROPFRAME_JUMP()                                              \
213    do {                                                              \
214        thread->ResetFrameDroppedState();                             \
215        sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()); \
216        InterpretedFrame *state = GET_FRAME(sp);                      \
217        pc = state->pc;                                               \
218        RESTORE_ACC();                                                \
219        DISPATCH_OFFSET(0);                                           \
220    } while (false)
221
222#define RESET_AND_JUMP_IF_DROPFRAME()                \
223    do {                                             \
224        if (thread->IsFrameDropped()) {              \
225            if (thread->IsEntryFrameDroppedTrue()) { \
226                return;                              \
227            }                                        \
228            DROPFRAME_JUMP();                        \
229        }                                            \
230    } while (false)
231
232// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
233#define NOTIFY_DEBUGGER_EVENT()          \
234    do {                                 \
235        JUMP_IF_ENTRYFRAME_PENDING();    \
236        SAVE_ACC();                      \
237        SAVE_PC();                       \
238        NotifyBytecodePcChanged(thread); \
239        RESET_AND_JUMP_IF_DROPFRAME();   \
240        RESTORE_ACC();                   \
241    } while (false)
242
243/*
244 * reasons of set acc with hole:
245 * 1. acc will become illegal when new error
246 * 2. debugger logic will save acc, so illegal acc will set to frame
247 * 3. when debugger trigger gc, will mark an invalid acc and crash
248 * 4. acc will set to exception later, so it can set to hole template
249 */
250#define NOTIFY_DEBUGGER_EXCEPTION_EVENT() \
251    do {                                  \
252        SET_ACC(JSTaggedValue::Hole());   \
253        NOTIFY_DEBUGGER_EVENT();          \
254    } while (false)
255
256// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
257#define DEPRECATED_CALL_INITIALIZE()                                            \
258    do {                                                                        \
259        SAVE_PC();                                                              \
260        thread->CheckSafepoint();                                               \
261        funcTagged = sp[startReg];                                              \
262        JSTaggedValue funcValue(funcTagged);                                    \
263        if (!funcValue.IsCallable()) {                                          \
264            {                                                                   \
265                [[maybe_unused]] EcmaHandleScope handleScope(thread);           \
266                JSHandle<JSObject> error = factory->GetJSError(                 \
267                    ErrorType::TYPE_ERROR, "is not callable", StackCheck::NO);  \
268                thread->SetException(error.GetTaggedValue());                   \
269            }                                                                   \
270            INTERPRETER_GOTO_EXCEPTION_HANDLER();                               \
271        }                                                                       \
272        funcObject = ECMAObject::Cast(funcValue.GetTaggedObject());             \
273        methodHandle.Update(JSTaggedValue(funcObject->GetCallTarget()));        \
274        newSp = sp - InterpretedFrame::NumOfMembers();                          \
275    } while (false)
276
277#define CALL_INITIALIZE()                                                       \
278    do {                                                                        \
279        SAVE_PC();                                                              \
280        SAVE_ACC();                                                             \
281        thread->CheckSafepoint();                                               \
282        RESTORE_ACC();                                                          \
283        funcTagged = acc.GetRawData();                                          \
284        JSTaggedValue funcValue = acc;                                          \
285        if (!funcValue.IsCallable()) {                                          \
286            {                                                                   \
287                [[maybe_unused]] EcmaHandleScope handleScope(thread);           \
288                JSHandle<JSObject> error = factory->GetJSError(                 \
289                    ErrorType::TYPE_ERROR, "is not callable", StackCheck::NO);  \
290                thread->SetException(error.GetTaggedValue());                   \
291            }                                                                   \
292            INTERPRETER_GOTO_EXCEPTION_HANDLER();                               \
293        }                                                                       \
294        funcObject = ECMAObject::Cast(funcValue.GetTaggedObject());             \
295        methodHandle.Update(JSTaggedValue(funcObject->GetCallTarget()));        \
296        newSp = sp - InterpretedFrame::NumOfMembers();                          \
297    } while (false)
298
299// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
300#define CALL_PUSH_UNDEFINED(n)                           \
301    do {                                                 \
302        for (int i = 0; i < (n); i++) {                  \
303            *(--newSp) = JSTaggedValue::VALUE_UNDEFINED; \
304        }                                                \
305    } while (false)
306
307// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
308#define CALL_PUSH_ARGS_0()          \
309    do {                            \
310        /* do nothing when 0 arg */ \
311    } while (false)
312
313// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
314#define DEPRECATED_CALL_PUSH_ARGS_0() CALL_PUSH_ARGS_0()
315
316// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
317#define CALL_PUSH_ARGS_1()   \
318    do {                     \
319        *(--newSp) = sp[a0]; \
320    } while (false)
321
322// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
323#define DEPRECATED_CALL_PUSH_ARGS_1() CALL_PUSH_ARGS_1()
324
325// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
326#define CALL_PUSH_ARGS_2()   \
327    do {                     \
328        *(--newSp) = sp[a1]; \
329        CALL_PUSH_ARGS_1();  \
330    } while (false)
331
332// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
333#define DEPRECATED_CALL_PUSH_ARGS_2() CALL_PUSH_ARGS_2()
334
335// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
336#define CALL_PUSH_ARGS_3()   \
337    do {                     \
338        *(--newSp) = sp[a2]; \
339        CALL_PUSH_ARGS_2();  \
340    } while (false)
341
342// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
343#define DEPRECATED_CALL_PUSH_ARGS_3() CALL_PUSH_ARGS_3()
344
345// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
346#define CALL_PUSH_ARGS_RANGE()                                               \
347    do {                                                                     \
348        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - actualNumArgs))) { \
349            INTERPRETER_GOTO_EXCEPTION_HANDLER();                            \
350        }                                                                    \
351        for (int i = actualNumArgs - 1; i >= 0; i--) {                           \
352            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];            \
353        }                                                                    \
354    } while (false)
355
356// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
357#define DEPRECATED_CALL_PUSH_ARGS_RANGE()                                               \
358    do {                                                                     \
359        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - actualNumArgs))) { \
360            INTERPRETER_GOTO_EXCEPTION_HANDLER();                            \
361        }                                                                    \
362        for (int i = actualNumArgs; i > 0; i--) {                            \
363            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];             \
364        }                                                                    \
365    } while (false)
366
367// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
368#define CALL_PUSH_ARGS_THISRANGE()                                          \
369    do {                                                                     \
370        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - actualNumArgs))) { \
371            INTERPRETER_GOTO_EXCEPTION_HANDLER();                            \
372        }                                                                    \
373        /* 1: skip this */                                                   \
374        for (int i = actualNumArgs; i > 0; i--) {                        \
375            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];             \
376        }                                                                    \
377    } while (false)
378
379// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
380#define DEPRECATED_CALL_PUSH_ARGS_THISRANGE()                                          \
381    do {                                                                     \
382        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - actualNumArgs))) { \
383            INTERPRETER_GOTO_EXCEPTION_HANDLER();                            \
384        }                                                                    \
385        /* 1: skip this */                                                   \
386        for (int i = actualNumArgs + 1; i > 1; i--) {                        \
387            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];             \
388        }                                                                    \
389    } while (false)
390
391// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
392#define CALL_PUSH_ARGS_0_NO_EXTRA() \
393    do {                            \
394        /* do nothing when 0 arg */ \
395    } while (false)
396
397// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
398#define DEPRECATED_CALL_PUSH_ARGS_0_NO_EXTRA() CALL_PUSH_ARGS_0_NO_EXTRA()
399
400// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
401#define CALL_PUSH_ARGS_1_NO_EXTRA()                             \
402    do {                                                        \
403        if (declaredNumArgs >= ActualNumArgsOfCall::CALLARG1) { \
404            *(--newSp) = sp[a0];                                \
405        }                                                       \
406    } while (false)
407
408// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
409#define DEPRECATED_CALL_PUSH_ARGS_1_NO_EXTRA() CALL_PUSH_ARGS_1_NO_EXTRA()
410
411// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
412#define CALL_PUSH_ARGS_2_NO_EXTRA()                              \
413    do {                                                         \
414        if (declaredNumArgs >= ActualNumArgsOfCall::CALLARGS2) { \
415            *(--newSp) = sp[a1];                                 \
416        }                                                        \
417        DEPRECATED_CALL_PUSH_ARGS_1_NO_EXTRA();                             \
418    } while (false)
419
420// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
421#define DEPRECATED_CALL_PUSH_ARGS_2_NO_EXTRA() CALL_PUSH_ARGS_2_NO_EXTRA()
422
423// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
424#define CALL_PUSH_ARGS_3_NO_EXTRA()                              \
425    do {                                                         \
426        if (declaredNumArgs >= ActualNumArgsOfCall::CALLARGS3) { \
427            *(--newSp) = sp[a2];                                 \
428        }                                                        \
429        DEPRECATED_CALL_PUSH_ARGS_2_NO_EXTRA();                             \
430    } while (false)
431
432// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
433#define DEPRECATED_CALL_PUSH_ARGS_3_NO_EXTRA() CALL_PUSH_ARGS_3_NO_EXTRA()
434
435// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
436#define CALL_PUSH_ARGS_RANGE_NO_EXTRA()                                      \
437    do {                                                                     \
438        int num = std::min(actualNumArgs, declaredNumArgs);                  \
439        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - num))) {           \
440            INTERPRETER_GOTO_EXCEPTION_HANDLER();                            \
441        }                                                                    \
442        for (int i = num - 1; i >= 0; i--) {                                 \
443            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];            \
444        }                                                                    \
445    } while (false)
446
447// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
448#define DEPRECATED_CALL_PUSH_ARGS_RANGE_NO_EXTRA()                           \
449    do {                                                                     \
450        int num = std::min(actualNumArgs, declaredNumArgs);                  \
451        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - num))) {           \
452            INTERPRETER_GOTO_EXCEPTION_HANDLER();                            \
453        }                                                                    \
454        for (int i = num; i > 0; i--) {                                      \
455            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];            \
456        }                                                                    \
457    } while (false)
458
459// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
460#define CALL_PUSH_ARGS_THISRANGE_NO_EXTRA()                                      \
461    do {                                                                         \
462        int num = std::min(actualNumArgs, declaredNumArgs);                      \
463        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - num))) {               \
464            INTERPRETER_GOTO_EXCEPTION_HANDLER();                                \
465        }                                                                        \
466        /* 1: skip this */                                                       \
467        for (int i = num; i > 0; i--) {                                          \
468            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];                \
469        }                                                                        \
470    } while (false)
471
472// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
473#define DEPRECATED_CALL_PUSH_ARGS_THISRANGE_NO_EXTRA()                                      \
474    do {                                                                         \
475        int num = std::min(actualNumArgs, declaredNumArgs);                      \
476        if (UNLIKELY(thread->DoStackOverflowCheck(newSp - num))) {               \
477            INTERPRETER_GOTO_EXCEPTION_HANDLER();                                \
478        }                                                                        \
479        /* 1: skip this */                                                       \
480        for (int i = num + 1; i > 1; i--) {                                      \
481            *(--newSp) = sp[startReg + static_cast<uint32_t>(i)];                 \
482        }                                                                        \
483    } while (false)
484
485// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
486#define CALL_PUSH_ARGS(ARG_TYPE)                                                   \
487    do {                                                                           \
488        if (methodHandle->IsNativeWithCallField()) {                               \
489            /* native, just push all args directly */                              \
490            CALL_PUSH_ARGS_##ARG_TYPE();                                           \
491            goto setVregsAndFrameNative;                                           \
492        }                                                                          \
493        int32_t declaredNumArgs =                                                  \
494            static_cast<int32_t>(methodHandle->GetNumArgsWithCallField());         \
495        if (actualNumArgs == declaredNumArgs) {                                    \
496            /* fast path, just push all args directly */                           \
497            CALL_PUSH_ARGS_##ARG_TYPE();                                           \
498            goto setVregsAndFrameNotNative;                                        \
499        }                                                                          \
500        /* slow path */                                                            \
501        if (!methodHandle->HaveExtraWithCallField()) {                             \
502            /* push length = declaredNumArgs, may push undefined */                \
503            CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs);                  \
504            CALL_PUSH_ARGS_##ARG_TYPE##_NO_EXTRA();                                \
505        } else {                                                                   \
506            /* push actualNumArgs in the end, then all args, may push undefined */ \
507            *(--newSp) = JSTaggedValue(actualNumArgs).GetRawData();                \
508            CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs);                  \
509            CALL_PUSH_ARGS_##ARG_TYPE();                                           \
510        }                                                                          \
511        goto setVregsAndFrameNotNative;                                            \
512    } while (false)
513
514// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
515#define DEPRECATED_CALL_PUSH_ARGS(ARG_TYPE)                                                   \
516    do {                                                                           \
517        if (methodHandle->IsNativeWithCallField()) {                                     \
518            /* native, just push all args directly */                              \
519            DEPRECATED_CALL_PUSH_ARGS_##ARG_TYPE();                                           \
520            goto deprecatedSetVregsAndFrameNative;                                           \
521        }                                                                          \
522        int32_t declaredNumArgs =                                                  \
523            static_cast<int32_t>(methodHandle->GetNumArgsWithCallField());               \
524        if (actualNumArgs == declaredNumArgs) {                                    \
525            /* fast path, just push all args directly */                           \
526            DEPRECATED_CALL_PUSH_ARGS_##ARG_TYPE();                                           \
527            goto deprecatedSetVregsAndFrameNotNative;                                        \
528        }                                                                          \
529        /* slow path */                                                            \
530        if (!methodHandle->HaveExtraWithCallField()) {                                   \
531            /* push length = declaredNumArgs, may push undefined */                \
532            CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs);                  \
533            DEPRECATED_CALL_PUSH_ARGS_##ARG_TYPE##_NO_EXTRA();                                \
534        } else {                                                                   \
535            /* push actualNumArgs in the end, then all args, may push undefined */ \
536            *(--newSp) = JSTaggedValue(actualNumArgs).GetRawData();                \
537            CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs);                  \
538            DEPRECATED_CALL_PUSH_ARGS_##ARG_TYPE();                                           \
539        }                                                                          \
540        goto deprecatedSetVregsAndFrameNotNative;                                            \
541    } while (false)
542
543#if ECMASCRIPT_ENABLE_IC
544// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
545#define UPDATE_HOTNESS_COUNTER_NON_ACC(offset)   (UpdateHotnessCounter(thread, sp, acc, offset))
546
547#define UPDATE_HOTNESS_COUNTER(offset)                       \
548    do {                                                     \
549        if (UpdateHotnessCounter(thread, sp, acc, offset)) { \
550            HANDLE_EXCEPTION_IF_ABRUPT_COMPLETION(thread);   \
551            RESTORE_ACC();                                   \
552        }                                                    \
553    } while (false)
554#else
555// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
556#define UPDATE_HOTNESS_COUNTER(offset) static_cast<void>(0)
557#define UPDATE_HOTNESS_COUNTER_NON_ACC(offset) static_cast<void>(0)
558#endif
559
560#define READ_INST_OP() READ_INST_8(0)               // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
561#define READ_INST_4_0() (READ_INST_8(1) & 0xf)      // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
562#define READ_INST_4_1() (READ_INST_8(1) >> 4 & 0xf) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
563#define READ_INST_4_2() (READ_INST_8(2) & 0xf)      // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
564#define READ_INST_4_3() (READ_INST_8(2) >> 4 & 0xf) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
565#define READ_INST_8_0() READ_INST_8(1)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
566#define READ_INST_8_1() READ_INST_8(2)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
567#define READ_INST_8_2() READ_INST_8(3)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
568#define READ_INST_8_3() READ_INST_8(4)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
569#define READ_INST_8_4() READ_INST_8(5)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
570#define READ_INST_8_5() READ_INST_8(6)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
571#define READ_INST_8_6() READ_INST_8(7)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
572#define READ_INST_8_7() READ_INST_8(8)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
573#define READ_INST_8_8() READ_INST_8(9)              // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
574#define READ_INST_8_9() READ_INST_8(10)             // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
575#define READ_INST_8(offset) (*(pc + (offset)))
576#define MOVE_AND_READ_INST_8(currentInst, offset) \
577    currentInst <<= 8;                            \
578    currentInst += READ_INST_8(offset);           \
579
580#define READ_INST_16_0() READ_INST_16(2)
581#define READ_INST_16_1() READ_INST_16(3)
582#define READ_INST_16_2() READ_INST_16(4)
583#define READ_INST_16_3() READ_INST_16(5)
584#define READ_INST_16_4() READ_INST_16(6)
585#define READ_INST_16_5() READ_INST_16(7)
586#define READ_INST_16_6() READ_INST_16(8)
587#define READ_INST_16_7() READ_INST_16(9)
588#define READ_INST_16(offset)                          \
589    ({                                                \
590        uint16_t currentInst = READ_INST_8(offset);   \
591        MOVE_AND_READ_INST_8(currentInst, offset - 1) \
592    })
593
594#define READ_INST_32_0() READ_INST_32(4)
595#define READ_INST_32_1() READ_INST_32(5)
596#define READ_INST_32_2() READ_INST_32(6)
597#define READ_INST_32(offset)                          \
598    ({                                                \
599        uint32_t currentInst = READ_INST_8(offset);   \
600        MOVE_AND_READ_INST_8(currentInst, offset - 1) \
601        MOVE_AND_READ_INST_8(currentInst, offset - 2) \
602        MOVE_AND_READ_INST_8(currentInst, offset - 3) \
603    })
604
605#define READ_INST_64_0()                       \
606    ({                                         \
607        uint64_t currentInst = READ_INST_8(8); \
608        MOVE_AND_READ_INST_8(currentInst, 7)   \
609        MOVE_AND_READ_INST_8(currentInst, 6)   \
610        MOVE_AND_READ_INST_8(currentInst, 5)   \
611        MOVE_AND_READ_INST_8(currentInst, 4)   \
612        MOVE_AND_READ_INST_8(currentInst, 3)   \
613        MOVE_AND_READ_INST_8(currentInst, 2)   \
614        MOVE_AND_READ_INST_8(currentInst, 1)   \
615    })
616
617#undef LOG_INST
618#undef HANDLE_OPCODE
619#undef ADVANCE_PC
620#undef GOTO_NEXT
621#undef DISPATCH
622#undef DISPATCH_OFFSET
623#undef GET_FRAME
624#undef GET_ENTRY_FRAME
625#undef SAVE_PC
626#undef SAVE_ACC
627#undef RESTORE_ACC
628#undef INTERPRETER_GOTO_EXCEPTION_HANDLER
629#undef CHECK_SWITCH_TO_DEBUGGER_TABLE
630#undef REAL_GOTO_DISPATCH_OPCODE
631#undef REAL_GOTO_EXCEPTION_HANDLER
632#undef INTERPRETER_RETURN_IF_ABRUPT
633#undef NOTIFY_DEBUGGER_EVENT
634#undef DEPRECATED_CALL_INITIALIZE
635#undef CALL_PUSH_UNDEFINED
636#undef DEPRECATED_CALL_PUSH_ARGS_0
637#undef DEPRECATED_CALL_PUSH_ARGS_1
638#undef DEPRECATED_CALL_PUSH_ARGS_2
639#undef DEPRECATED_CALL_PUSH_ARGS_3
640#undef DEPRECATED_CALL_PUSH_ARGS_RANGE
641#undef DEPRECATED_CALL_PUSH_ARGS_THISRANGE
642#undef DEPRECATED_CALL_PUSH_ARGS_0_NO_EXTRA
643#undef DEPRECATED_CALL_PUSH_ARGS_1_NO_EXTRA
644#undef DEPRECATED_CALL_PUSH_ARGS_2_NO_EXTRA
645#undef DEPRECATED_CALL_PUSH_ARGS_3_NO_EXTRA
646#undef DEPRECATED_CALL_PUSH_ARGS_RANGE_NO_EXTRA
647#undef DEPRECATED_CALL_PUSH_ARGS_THISRANGE_NO_EXTRA
648#undef DEPRECATED_CALL_PUSH_ARGS
649#undef UPDATE_HOTNESS_COUNTER_NON_ACC
650#undef UPDATE_HOTNESS_COUNTER
651#undef GET_VREG
652#undef GET_VREG_VALUE
653#undef SET_VREG
654#undef GET_ACC
655#undef SET_ACC
656#if defined(__clang__)
657#pragma clang diagnostic pop
658#elif defined(__GNUC__)
659#pragma GCC diagnostic pop
660#endif
661}  // namespace panda::ecmascript
662#endif  // ECMASCRIPT_INTERPRETER_INTERPRETER_INL_H
663