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