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 48 namespace panda::ecmascript { 49 using 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