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