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