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/jspandafile/program_object-inl.h"
20 #include "ecmascript/cpu_profiler/cpu_profiler.h"
21 #include "ecmascript/jspandafile/program_object-inl.h"
22 #include "ecmascript/ecma_string.h"
23 #include "ecmascript/ecma_vm.h"
24 #include "ecmascript/global_env.h"
25 #include "ecmascript/ic/ic_runtime_stub-inl.h"
26 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
27 #include "ecmascript/interpreter/interpreter.h"
28 #include "ecmascript/interpreter/interpreter_assembly.h"
29 #include "ecmascript/interpreter/frame_handler.h"
30 #include "ecmascript/interpreter/slow_runtime_stub.h"
31 #include "ecmascript/js_generator_object.h"
32 #include "ecmascript/js_tagged_value.h"
33 #include "ecmascript/literal_data_extractor.h"
34 #include "ecmascript/mem/concurrent_marker.h"
35 #include "ecmascript/runtime_call_id.h"
36 #include "ecmascript/template_string.h"
37 #include "ecmascript/tooling/interface/js_debugger_manager.h"
38 #include "libpandafile/code_data_accessor.h"
39 #include "libpandafile/file.h"
40 #include "libpandafile/method_data_accessor.h"
41
42 namespace panda::ecmascript {
43 #if defined(__clang__)
44 #pragma clang diagnostic push
45 #pragma clang diagnostic ignored "-Wvoid-ptr-dereference"
46 #pragma clang diagnostic ignored "-Wgnu-label-as-value"
47 #elif defined(__GNUC__)
48 #pragma GCC diagnostic push
49 #pragma GCC diagnostic ignored "-Wpedantic"
50 #endif
51
52 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
53 #define LOG_INST() LOG(DEBUG, INTERPRETER) << ": "
54
55 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
56 #define HANDLE_OPCODE(handle_opcode) \
57 handle_opcode: // NOLINT(clang-diagnostic-gnu-label-as-value, cppcoreguidelines-macro-usage)
58
59 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
60 #define ADVANCE_PC(offset) \
61 pc += (offset); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic, cppcoreguidelines-macro-usage)
62
63 #define GOTO_NEXT() // NOLINT(clang-diagnostic-gnu-label-as-value, cppcoreguidelines-macro-usage)
64
65 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
66 #define DISPATCH(format) \
67 do { \
68 ADVANCE_PC(BytecodeInstruction::Size(format)) \
69 opcode = READ_INST_OP(); goto * dispatchTable[opcode]; \
70 } while (false)
71
72 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
73 #define DISPATCH_OFFSET(offset) \
74 do { \
75 ADVANCE_PC(offset) \
76 opcode = READ_INST_OP(); goto * dispatchTable[opcode]; \
77 } while (false)
78
79 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
80 #define GET_FRAME(CurrentSp) \
81 (reinterpret_cast<InterpretedFrame *>(CurrentSp) - 1) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
82 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
83 #define SAVE_PC() (GET_FRAME(sp)->pc = pc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
84 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
85 #define SAVE_ACC() (GET_FRAME(sp)->acc = acc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
86 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
87 #define RESTORE_ACC() (acc = GET_FRAME(sp)->acc) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
88
89 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
90 #define INTERPRETER_GOTO_EXCEPTION_HANDLER() \
91 do { \
92 SAVE_PC(); \
93 goto *dispatchTable[EcmaOpcode::LAST_OPCODE]; \
94 } while (false)
95
96 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
97 #define INTERPRETER_HANDLE_RETURN() \
98 do { \
99 size_t jumpSize = GetJumpSizeAfterCall(pc); \
100 DISPATCH_OFFSET(jumpSize); \
101 } while (false)
102
103 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
104 #define CHECK_SWITCH_TO_DEBUGGER_TABLE() \
105 if (ecmaVm->GetJsDebuggerManager()->IsDebugMode()) { \
106 dispatchTable = debugDispatchTable; \
107 }
108
109 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
110 #define REAL_GOTO_DISPATCH_OPCODE(opcode) \
111 do { \
112 goto *instDispatchTable[opcode]; \
113 } while (false)
114
115 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
116 #define REAL_GOTO_EXCEPTION_HANDLER() \
117 do { \
118 SAVE_PC(); \
119 goto *instDispatchTable[EcmaOpcode::LAST_OPCODE]; \
120 } while (false)
121
122 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
123 #define INTERPRETER_RETURN_IF_ABRUPT(result) \
124 do { \
125 if (result.IsException()) { \
126 INTERPRETER_GOTO_EXCEPTION_HANDLER(); \
127 } \
128 } while (false)
129
130 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
131 #define NOTIFY_DEBUGGER_EVENT() \
132 do { \
133 SAVE_ACC(); \
134 SAVE_PC(); \
135 NotifyBytecodePcChanged(thread); \
136 RESTORE_ACC(); \
137 } while (false)
138
139 /*
140 * reasons of set acc with hole:
141 * 1. acc will become illegal when new error
142 * 2. debugger logic will save acc, so illegal acc will set to frame
143 * 3. when debugger trigger gc, will mark an invalid acc and crash
144 * 4. acc will set to exception later, so it can set to hole template
145 */
146 #define NOTIFY_DEBUGGER_EXCEPTION_EVENT() \
147 do { \
148 SET_ACC(JSTaggedValue::Hole()); \
149 NOTIFY_DEBUGGER_EVENT(); \
150 } while (false)
151
152 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
153 #define CALL_INITIALIZE() \
154 do { \
155 SAVE_PC(); \
156 thread->CheckSafepoint(); \
157 funcTagged = sp[funcReg]; \
158 JSTaggedValue funcValue(funcTagged); \
159 if (!funcValue.IsCallable()) { \
160 { \
161 [[maybe_unused]] EcmaHandleScope handleScope(thread); \
162 JSHandle<JSObject> error = factory->GetJSError( \
163 ErrorType::TYPE_ERROR, "is not callable"); \
164 thread->SetException(error.GetTaggedValue()); \
165 } \
166 INTERPRETER_GOTO_EXCEPTION_HANDLER(); \
167 } \
168 funcObject = ECMAObject::Cast(funcValue.GetTaggedObject()); \
169 method = funcObject->GetCallTarget(); \
170 newSp = sp - FRAME_STATE_SIZE; \
171 } while (false)
172
173 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
174 #define CALL_PUSH_UNDEFINED(n) \
175 do { \
176 for (int i = 0; i < (n); i++) { \
177 *(--newSp) = JSTaggedValue::VALUE_UNDEFINED; \
178 } \
179 } while (false)
180
181 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
182 #define CALL_PUSH_ARGS_0() \
183 do { \
184 /* do nothing when 0 arg */ \
185 } while (false)
186
187 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
188 #define CALL_PUSH_ARGS_1() \
189 do { \
190 *(--newSp) = sp[a0]; \
191 } while (false)
192
193 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
194 #define CALL_PUSH_ARGS_2() \
195 do { \
196 *(--newSp) = sp[a1]; \
197 CALL_PUSH_ARGS_1(); \
198 } while (false)
199
200 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
201 #define CALL_PUSH_ARGS_3() \
202 do { \
203 *(--newSp) = sp[a2]; \
204 CALL_PUSH_ARGS_2(); \
205 } while (false)
206
207 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
208 #define CALL_PUSH_ARGS_I() \
209 do { \
210 for (int i = actualNumArgs; i > 0; i--) { \
211 *(--newSp) = sp[funcReg + i]; \
212 } \
213 } while (false)
214
215 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
216 #define CALL_PUSH_ARGS_I_THIS() \
217 do { \
218 /* 1: skip this */ \
219 for (int i = actualNumArgs + 1; i > 1; i--) { \
220 *(--newSp) = sp[funcReg + i]; \
221 } \
222 } while (false)
223
224 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
225 #define CALL_PUSH_ARGS_0_NO_EXTRA() \
226 do { \
227 /* do nothing when 0 arg */ \
228 } while (false)
229
230 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
231 #define CALL_PUSH_ARGS_1_NO_EXTRA() \
232 do { \
233 if (declaredNumArgs >= ActualNumArgsOfCall::CALLARG1) { \
234 *(--newSp) = sp[a0]; \
235 } \
236 } while (false)
237
238 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
239 #define CALL_PUSH_ARGS_2_NO_EXTRA() \
240 do { \
241 if (declaredNumArgs >= ActualNumArgsOfCall::CALLARGS2) { \
242 *(--newSp) = sp[a1]; \
243 } \
244 CALL_PUSH_ARGS_1_NO_EXTRA(); \
245 } while (false)
246
247 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
248 #define CALL_PUSH_ARGS_3_NO_EXTRA() \
249 do { \
250 if (declaredNumArgs >= ActualNumArgsOfCall::CALLARGS3) { \
251 *(--newSp) = sp[a2]; \
252 } \
253 CALL_PUSH_ARGS_2_NO_EXTRA(); \
254 } while (false)
255
256 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
257 #define CALL_PUSH_ARGS_I_NO_EXTRA() \
258 do { \
259 for (int i = std::min(actualNumArgs, declaredNumArgs); i > 0; i--) { \
260 *(--newSp) = sp[funcReg + i]; \
261 } \
262 } while (false)
263
264 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
265 #define CALL_PUSH_ARGS_I_THIS_NO_EXTRA() \
266 do { \
267 /* 1: skip this */ \
268 for (int i = std::min(actualNumArgs, declaredNumArgs) + 1; i > 1; i--) { \
269 *(--newSp) = sp[funcReg + i]; \
270 } \
271 } while (false)
272
273 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
274 #define CALL_PUSH_ARGS(ARG_TYPE) \
275 do { \
276 if (method->IsNativeWithCallField()) { \
277 /* native, just push all args directly */ \
278 CALL_PUSH_ARGS_##ARG_TYPE(); \
279 goto setVregsAndFrameNative; \
280 } \
281 int32_t declaredNumArgs = static_cast<int32_t>( \
282 method->GetNumArgsWithCallField()); \
283 if (actualNumArgs == declaredNumArgs) { \
284 /* fast path, just push all args directly */ \
285 CALL_PUSH_ARGS_##ARG_TYPE(); \
286 goto setVregsAndFrameNotNative; \
287 } \
288 /* slow path */ \
289 if (!method->HaveExtraWithCallField()) { \
290 /* push length = declaredNumArgs, may push undefined */ \
291 CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs); \
292 CALL_PUSH_ARGS_##ARG_TYPE##_NO_EXTRA(); \
293 } else { \
294 /* push actualNumArgs in the end, then all args, may push undefined */ \
295 *(--newSp) = JSTaggedValue(actualNumArgs).GetRawData(); \
296 CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs); \
297 CALL_PUSH_ARGS_##ARG_TYPE(); \
298 } \
299 goto setVregsAndFrameNotNative; \
300 } while (false)
301
302 #if ECMASCRIPT_ENABLE_IC
303 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
304 #define UPDATE_HOTNESS_COUNTER_NON_ACC(offset) (UpdateHotnessCounter(thread, sp, acc, offset))
305
306 #define UPDATE_HOTNESS_COUNTER(offset) \
307 do { \
308 if (UpdateHotnessCounter(thread, sp, acc, offset)) { \
309 RESTORE_ACC(); \
310 } \
311 } while (false)
312 #else
313 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
314 #define UPDATE_HOTNESS_COUNTER(offset) static_cast<void>(0)
315 #define UPDATE_HOTNESS_COUNTER_NON_ACC(offset) static_cast<void>(0)
316 #endif
317
318 #define READ_INST_OP() READ_INST_8(0) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
319 #define READ_INST_4_0() (READ_INST_8(1) & 0xf) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
320 #define READ_INST_4_1() (READ_INST_8(1) >> 4 & 0xf) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
321 #define READ_INST_4_2() (READ_INST_8(2) & 0xf) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
322 #define READ_INST_4_3() (READ_INST_8(2) >> 4 & 0xf) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
323 #define READ_INST_8_0() READ_INST_8(1) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
324 #define READ_INST_8_1() READ_INST_8(2) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
325 #define READ_INST_8_2() READ_INST_8(3) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
326 #define READ_INST_8_3() READ_INST_8(4) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
327 #define READ_INST_8_4() READ_INST_8(5) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
328 #define READ_INST_8_5() READ_INST_8(6) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
329 #define READ_INST_8_6() READ_INST_8(7) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
330 #define READ_INST_8_7() READ_INST_8(8) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
331 #define READ_INST_8_8() READ_INST_8(9) // NOLINT(hicpp-signed-bitwise, cppcoreguidelines-macro-usage)
332 #define READ_INST_8(offset) (*(pc + (offset)))
333 #define MOVE_AND_READ_INST_8(currentInst, offset) \
334 currentInst <<= 8; \
335 currentInst += READ_INST_8(offset); \
336
337 #define READ_INST_16_0() READ_INST_16(2)
338 #define READ_INST_16_1() READ_INST_16(3)
339 #define READ_INST_16_2() READ_INST_16(4)
340 #define READ_INST_16_3() READ_INST_16(5)
341 #define READ_INST_16_5() READ_INST_16(7)
342 #define READ_INST_16(offset) \
343 ({ \
344 uint16_t currentInst = READ_INST_8(offset); \
345 MOVE_AND_READ_INST_8(currentInst, offset - 1) \
346 })
347
348 #define READ_INST_32_0() READ_INST_32(4)
349 #define READ_INST_32_1() READ_INST_32(5)
350 #define READ_INST_32_2() READ_INST_32(6)
351 #define READ_INST_32(offset) \
352 ({ \
353 uint32_t currentInst = READ_INST_8(offset); \
354 MOVE_AND_READ_INST_8(currentInst, offset - 1) \
355 MOVE_AND_READ_INST_8(currentInst, offset - 2) \
356 MOVE_AND_READ_INST_8(currentInst, offset - 3) \
357 })
358
359 #define READ_INST_64_0() \
360 ({ \
361 uint64_t currentInst = READ_INST_8(8); \
362 MOVE_AND_READ_INST_8(currentInst, 7) \
363 MOVE_AND_READ_INST_8(currentInst, 6) \
364 MOVE_AND_READ_INST_8(currentInst, 5) \
365 MOVE_AND_READ_INST_8(currentInst, 4) \
366 MOVE_AND_READ_INST_8(currentInst, 3) \
367 MOVE_AND_READ_INST_8(currentInst, 2) \
368 MOVE_AND_READ_INST_8(currentInst, 1) \
369 })
370
371 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
372 #define GET_VREG(idx) (sp[idx]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
373 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
374 #define GET_VREG_VALUE(idx) (JSTaggedValue(sp[idx])) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
375 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
376 #define SET_VREG(idx, val) (sp[idx] = (val)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
377 #define GET_ACC() (acc) // NOLINT(cppcoreguidelines-macro-usage)
378 #define SET_ACC(val) (acc = val); // NOLINT(cppcoreguidelines-macro-usage)
379
ExecuteNative(JSThread * thread,const CallParams & params)380 JSTaggedValue EcmaInterpreter::ExecuteNative(JSThread *thread, const CallParams& params)
381 {
382 INTERPRETER_TRACE(thread, ExecuteNative);
383 JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
384
385 JSMethod *method = params.callTarget->GetCallTarget();
386 ASSERT(method->GetNumVregsWithCallField() == 0);
387 uint32_t numActualArgs = params.argc + RESERVED_CALL_ARGCOUNT;
388 // Tags and values of thread, new_tgt and argv_length are put into frames too for native frames
389 // NOLINTNEXTLINE(hicpp-signed-bitwise)
390 size_t frameSize = FRAME_STATE_SIZE + numActualArgs;
391 JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
392 if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) {
393 return JSTaggedValue::Undefined();
394 }
395
396 EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, numActualArgs, reinterpret_cast<JSTaggedValue *>(newSp));
397 newSp[RESERVED_INDEX_CALL_TARGET] = reinterpret_cast<JSTaggedType>(params.callTarget);
398 newSp[RESERVED_INDEX_NEW_TARGET] = params.newTarget;
399 newSp[RESERVED_INDEX_THIS] = params.thisArg;
400 for (size_t i = 0; i < params.argc; i++) {
401 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
402 newSp[i + RESERVED_CALL_ARGCOUNT] = params.argv[i];
403 }
404
405 InterpretedFrame *state = GET_FRAME(newSp);
406 state->base.prev = sp;
407 state->base.type = FrameType::INTERPRETER_FRAME;
408 state->pc = nullptr;
409 state->sp = newSp;
410 state->function = JSTaggedValue(params.callTarget);
411 thread->SetCurrentSPFrame(newSp);
412 #if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER
413 CpuProfiler::IsNeedAndGetStack(thread);
414 #endif
415 thread->CheckSafepoint();
416 LOG(DEBUG, INTERPRETER) << "Entry: Runtime Call.";
417 JSTaggedValue tagged =
418 reinterpret_cast<EcmaEntrypoint>(const_cast<void *>(method->GetNativePointer()))(&ecmaRuntimeCallInfo);
419 LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call.";
420 thread->SetCurrentSPFrame(sp);
421 #if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER
422 CpuProfiler::IsNeedAndGetStack(thread);
423 #endif
424 return tagged;
425 }
426
GetCurrentFrameState(JSTaggedType * sp)427 JSTaggedType* EcmaInterpreter::GetCurrentFrameState(JSTaggedType *sp)
428 {
429 return sp - FRAME_STATE_SIZE;
430 }
431
Execute(JSThread * thread,const CallParams & params)432 JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, const CallParams& params)
433 {
434 INTERPRETER_TRACE(thread, Execute);
435 JSMethod *method = params.callTarget->GetCallTarget();
436 if (method->IsNativeWithCallField()) {
437 return EcmaInterpreter::ExecuteNative(thread, params);
438 }
439 JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
440 JSTaggedType *newSp = GetCurrentFrameState(sp);
441 // push break state
442 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
443 if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) {
444 return JSTaggedValue::Undefined();
445 }
446 InterpretedFrame *breakState = GET_FRAME(newSp);
447 breakState->pc = nullptr;
448 breakState->sp = nullptr;
449 breakState->function = JSTaggedValue::Hole();
450 breakState->base.prev = sp;
451 breakState->base.type = FrameType::INTERPRETER_FRAME;
452 JSTaggedType *prevSp = newSp;
453
454 int32_t actualNumArgs = static_cast<int32_t>(params.argc);
455 int32_t declaredNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
456 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
457 newSp -= FRAME_STATE_SIZE;
458 // push args
459 if (actualNumArgs == declaredNumArgs) {
460 // fast path, just push all args directly
461 for (int i = actualNumArgs - 1; i >= 0; i--) {
462 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
463 *(--newSp) = params.argv[i];
464 }
465 } else {
466 // slow path
467 if (!method->HaveExtraWithCallField()) {
468 // push length = declaredNumArgs, may push undefined
469 CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs);
470 for (int i = std::min(actualNumArgs, declaredNumArgs) - 1; i >= 0; i--) {
471 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
472 *(--newSp) = params.argv[i];
473 }
474 } else {
475 // push actualNumArgs in the end, then all args, may push undefined
476 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
477 *(--newSp) = JSTaggedValue(actualNumArgs).GetRawData();
478 CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs);
479 for (int i = actualNumArgs - 1; i >= 0; i--) {
480 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
481 *(--newSp) = params.argv[i];
482 }
483 }
484 }
485 uint64_t callField = method->GetCallField();
486 if ((callField & CALL_TYPE_MASK) != 0) {
487 // not normal call type, setting func/newTarget/this cannot be skipped
488 if (method->HaveThisWithCallField()) {
489 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
490 *(--newSp) = params.thisArg; // push this
491 }
492 if (method->HaveNewTargetWithCallField()) {
493 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
494 *(--newSp) = params.newTarget; // push new target
495 }
496 if (method->HaveFuncWithCallField()) {
497 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
498 *(--newSp) = reinterpret_cast<JSTaggedType>(params.callTarget); // push func
499 }
500 }
501 int32_t numVregs = static_cast<int32_t>(method->GetNumVregsWithCallField());
502 // push vregs
503 CALL_PUSH_UNDEFINED(numVregs);
504 if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) {
505 return JSTaggedValue::Undefined();
506 }
507
508 const uint8_t *pc = method->GetBytecodeArray();
509 InterpretedFrame *state = GET_FRAME(newSp);
510 state->pc = pc;
511 state->sp = newSp;
512 state->function = JSTaggedValue(params.callTarget);
513 state->acc = JSTaggedValue::Hole();
514 JSHandle<JSTaggedValue> callTargetHandle(thread, params.callTarget);
515 JSHandle<JSFunction> thisFunc = JSHandle<JSFunction>::Cast(callTargetHandle);
516 JSTaggedValue constpool = thisFunc->GetConstantPool();
517 state->constpool = constpool;
518 state->profileTypeInfo = thisFunc->GetProfileTypeInfo();
519 state->base.prev = prevSp;
520 state->base.type = FrameType::INTERPRETER_FRAME;
521
522 JSTaggedValue env = thisFunc->GetLexicalEnv();
523 state->env = env;
524 thread->SetCurrentSPFrame(newSp);
525 #if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER
526 CpuProfiler::IsNeedAndGetStack(thread);
527 #endif
528 thread->CheckSafepoint();
529 LOG(DEBUG, INTERPRETER) << "break Entry: Runtime Call " << std::hex << reinterpret_cast<uintptr_t>(newSp) << " "
530 << std::hex << reinterpret_cast<uintptr_t>(pc);
531
532 #if ECMASCRIPT_ENABLE_INTERPRETER_ASM
533 InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), pc, newSp);
534 #else
535 EcmaInterpreter::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), pc, newSp);
536 #endif
537
538 // NOLINTNEXTLINE(readability-identifier-naming)
539 const JSTaggedValue resAcc = state->acc;
540 // pop frame
541 thread->SetCurrentSPFrame(sp);
542 #if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER
543 CpuProfiler::IsNeedAndGetStack(thread);
544 #endif
545 return resAcc;
546 }
547
GeneratorReEnterInterpreter(JSThread * thread,JSHandle<GeneratorContext> context)548 JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSHandle<GeneratorContext> context)
549 {
550 [[maybe_unused]] EcmaHandleScope handleScope(thread);
551 JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(JSHandle<JSTaggedValue>(thread, context->GetMethod()));
552 JSMethod *method = func->GetCallTarget();
553
554 JSTaggedType *currentSp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
555
556 // push break frame
557 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
558 JSTaggedType *breakSp = currentSp - FRAME_STATE_SIZE;
559 if (thread->DoStackOverflowCheck(breakSp) || thread->HasPendingException()) {
560 return JSTaggedValue::Exception();
561 }
562 InterpretedFrame *breakState = GET_FRAME(breakSp);
563 breakState->pc = nullptr;
564 breakState->sp = nullptr;
565 breakState->function = JSTaggedValue::Hole();
566 breakState->base.prev = currentSp;
567 breakState->base.type = FrameType::INTERPRETER_FRAME;
568
569 // create new frame and resume sp and pc
570 uint32_t nregs = context->GetNRegs();
571 size_t newFrameSize = FRAME_STATE_SIZE + nregs;
572 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic
573 JSTaggedType *newSp = breakSp - newFrameSize;
574 if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) {
575 return JSTaggedValue::Exception();
576 }
577 JSHandle<TaggedArray> regsArray(thread, context->GetRegsArray());
578 for (size_t i = 0; i < nregs; i++) {
579 newSp[i] = regsArray->Get(i).GetRawData(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
580 }
581 JSTaggedValue constpool = func->GetConstantPool();
582 uint32_t pcOffset = context->GetBCOffset();
583 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
584 const uint8_t *resumePc = method->GetBytecodeArray() + pcOffset +
585 BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8);
586
587 InterpretedFrame *state = GET_FRAME(newSp);
588 state->pc = resumePc;
589 state->sp = newSp;
590 state->function = func.GetTaggedValue();
591 state->constpool = constpool;
592 state->profileTypeInfo = func->GetProfileTypeInfo();
593 state->acc = context->GetAcc();
594 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
595 state->base.prev = breakSp;
596 state->base.type = FrameType::INTERPRETER_FRAME;
597 JSTaggedValue env = context->GetLexicalEnv();
598 state->env = env;
599 // execute interpreter
600 thread->SetCurrentSPFrame(newSp);
601
602 #if ECMASCRIPT_ENABLE_INTERPRETER_ASM
603 InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), resumePc, newSp);
604 #else
605 EcmaInterpreter::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), resumePc, newSp);
606 #endif
607
608 JSTaggedValue res = state->acc;
609 // pop frame
610 thread->SetCurrentSPFrame(currentSp);
611 return res;
612 }
613
ChangeGenContext(JSThread * thread,JSHandle<GeneratorContext> context)614 void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandle<GeneratorContext> context)
615 {
616 [[maybe_unused]] EcmaHandleScope handleScope(thread);
617 JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(JSHandle<JSTaggedValue>(thread, context->GetMethod()));
618 JSMethod *method = func->GetCallTarget();
619
620 JSTaggedType *currentSp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
621
622 // push break frame
623 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
624 JSTaggedType *breakSp = currentSp - FRAME_STATE_SIZE;
625 if (thread->DoStackOverflowCheck(breakSp) || thread->HasPendingException()) {
626 return;
627 }
628 InterpretedFrame *breakState = GET_FRAME(breakSp);
629 breakState->pc = nullptr;
630 breakState->sp = nullptr;
631 breakState->function = JSTaggedValue::Hole();
632 breakState->base.prev = currentSp;
633 breakState->base.type = FrameType::INTERPRETER_FRAME;
634
635 // create new frame and resume sp and pc
636 uint32_t nregs = context->GetNRegs();
637 size_t newFrameSize = FRAME_STATE_SIZE + nregs;
638
639 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic
640 JSTaggedType *newSp = breakSp - newFrameSize;
641 if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) {
642 return;
643 }
644 JSHandle<TaggedArray> regsArray(thread, context->GetRegsArray());
645 for (size_t i = 0; i < nregs; i++) {
646 newSp[i] = regsArray->Get(i).GetRawData(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
647 }
648 JSTaggedValue constpool = func->GetConstantPool();
649 uint32_t pcOffset = context->GetBCOffset();
650 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
651 const uint8_t *pc = method->GetBytecodeArray() + pcOffset;
652
653 InterpretedFrame *state = GET_FRAME(newSp);
654 state->pc = pc;
655 state->sp = newSp;
656 state->function = func.GetTaggedValue();
657 state->constpool = constpool;
658 state->profileTypeInfo = func->GetProfileTypeInfo();
659 state->acc = context->GetAcc();
660 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
661 state->base.prev = breakSp;
662 state->base.type = FrameType::INTERPRETER_FRAME;
663 state->env = context->GetLexicalEnv();
664
665 thread->SetCurrentSPFrame(newSp);
666 }
667
ResumeContext(JSThread * thread)668 void EcmaInterpreter::ResumeContext(JSThread *thread)
669 {
670 JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
671 InterpretedFrame *state = GET_FRAME(sp);
672 thread->SetCurrentSPFrame(state->base.prev);
673 }
674
NotifyBytecodePcChanged(JSThread * thread)675 void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread)
676 {
677 InterpretedFrameHandler frameHandler(thread);
678 for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) {
679 if (frameHandler.IsBreakFrame()) {
680 continue;
681 }
682 JSMethod *method = frameHandler.GetMethod();
683 // Skip builtins method
684 if (method->IsNative()) {
685 continue;
686 }
687 auto bcOffset = frameHandler.GetBytecodeOffset();
688 auto *debuggerMgr = thread->GetEcmaVM()->GetJsDebuggerManager();
689 debuggerMgr->GetNotificationManager()->BytecodePcChangedEvent(thread, method, bcOffset);
690 return;
691 }
692 }
693
694 // NOLINTNEXTLINE(readability-function-size)
RunInternal(JSThread * thread,ConstantPool * constpool,const uint8_t * pc,JSTaggedType * sp)695 NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool *constpool, const uint8_t *pc,
696 JSTaggedType *sp)
697 {
698 INTERPRETER_TRACE(thread, RunInternal);
699 uint8_t opcode = READ_INST_OP();
700 JSTaggedValue acc = JSTaggedValue::Hole();
701 EcmaVM *ecmaVm = thread->GetEcmaVM();
702 JSHandle<GlobalEnv> globalEnv = ecmaVm->GetGlobalEnv();
703 JSTaggedValue globalObj = globalEnv->GetGlobalObject();
704 ObjectFactory *factory = ecmaVm->GetFactory();
705
706 constexpr size_t numOps = 0x100;
707 static std::array<const void *, numOps> instDispatchTable{
708 #include "templates/instruction_dispatch.inl"
709 };
710
711 static std::array<const void *, numOps> debugDispatchTable{
712 #include "templates/debugger_instruction_dispatch.inl"
713 };
714
715 std::array<const void *, numOps> dispatchTable = instDispatchTable;
716 CHECK_SWITCH_TO_DEBUGGER_TABLE();
717 goto *dispatchTable[opcode];
718
719 HANDLE_OPCODE(HANDLE_MOV_V4_V4) {
720 uint16_t vdst = READ_INST_4_0();
721 uint16_t vsrc = READ_INST_4_1();
722 LOG_INST() << "mov v" << vdst << ", v" << vsrc;
723 uint64_t value = GET_VREG(vsrc);
724 SET_VREG(vdst, value)
725 DISPATCH(BytecodeInstruction::Format::V4_V4);
726 }
727
728 HANDLE_OPCODE(HANDLE_MOV_DYN_V8_V8) {
729 uint16_t vdst = READ_INST_8_0();
730 uint16_t vsrc = READ_INST_8_1();
731 LOG_INST() << "mov.dyn v" << vdst << ", v" << vsrc;
732 uint64_t value = GET_VREG(vsrc);
733 SET_VREG(vdst, value)
734 DISPATCH(BytecodeInstruction::Format::V8_V8);
735 }
736 HANDLE_OPCODE(HANDLE_MOV_DYN_V16_V16) {
737 uint16_t vdst = READ_INST_16_0();
738 uint16_t vsrc = READ_INST_16_2();
739 LOG_INST() << "mov.dyn v" << vdst << ", v" << vsrc;
740 uint64_t value = GET_VREG(vsrc);
741 SET_VREG(vdst, value)
742 DISPATCH(BytecodeInstruction::Format::V16_V16);
743 }
744 HANDLE_OPCODE(HANDLE_LDA_STR_ID32) {
745 uint32_t stringId = READ_INST_32_0();
746 LOG_INST() << "lda.str " << std::hex << stringId;
747 SET_ACC(constpool->GetObjectFromCache(stringId));
748 DISPATCH(BytecodeInstruction::Format::ID32);
749 }
750 HANDLE_OPCODE(HANDLE_JMP_IMM8) {
751 int8_t offset = READ_INST_8_0();
752 UPDATE_HOTNESS_COUNTER(offset);
753 LOG_INST() << "jmp " << std::hex << static_cast<int32_t>(offset);
754 DISPATCH_OFFSET(offset);
755 }
756 HANDLE_OPCODE(HANDLE_JMP_IMM16) {
757 int16_t offset = READ_INST_16_0();
758 UPDATE_HOTNESS_COUNTER(offset);
759 LOG_INST() << "jmp " << std::hex << static_cast<int32_t>(offset);
760 DISPATCH_OFFSET(offset);
761 }
762 HANDLE_OPCODE(HANDLE_JMP_IMM32) {
763 int32_t offset = READ_INST_32_0();
764 UPDATE_HOTNESS_COUNTER(offset);
765 LOG_INST() << "jmp " << std::hex << offset;
766 DISPATCH_OFFSET(offset);
767 }
768 HANDLE_OPCODE(HANDLE_JEQZ_IMM8) {
769 int8_t offset = READ_INST_8_0();
770 LOG_INST() << "jeqz ->\t"
771 << "cond jmpz " << std::hex << static_cast<int32_t>(offset);
772 if (GET_ACC() == JSTaggedValue::False() || (GET_ACC().IsInt() && GET_ACC().GetInt() == 0) ||
773 (GET_ACC().IsDouble() && GET_ACC().GetDouble() == 0)) {
774 UPDATE_HOTNESS_COUNTER(offset);
775 DISPATCH_OFFSET(offset);
776 } else {
777 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
778 }
779 }
780 HANDLE_OPCODE(HANDLE_JEQZ_IMM16) {
781 int16_t offset = READ_INST_16_0();
782 LOG_INST() << "jeqz ->\t"
783 << "cond jmpz " << std::hex << static_cast<int32_t>(offset);
784 if (GET_ACC() == JSTaggedValue::False() || (GET_ACC().IsInt() && GET_ACC().GetInt() == 0) ||
785 (GET_ACC().IsDouble() && GET_ACC().GetDouble() == 0)) {
786 UPDATE_HOTNESS_COUNTER(offset);
787 DISPATCH_OFFSET(offset);
788 } else {
789 DISPATCH(BytecodeInstruction::Format::IMM16);
790 }
791 }
792 HANDLE_OPCODE(HANDLE_JNEZ_IMM8) {
793 int8_t offset = READ_INST_8_0();
794 LOG_INST() << "jnez ->\t"
795 << "cond jmpz " << std::hex << static_cast<int32_t>(offset);
796 if (GET_ACC() == JSTaggedValue::True() || (GET_ACC().IsInt() && GET_ACC().GetInt() != 0) ||
797 (GET_ACC().IsDouble() && GET_ACC().GetDouble() != 0)) {
798 UPDATE_HOTNESS_COUNTER(offset);
799 DISPATCH_OFFSET(offset);
800 } else {
801 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
802 }
803 }
804 HANDLE_OPCODE(HANDLE_JNEZ_IMM16) {
805 int16_t offset = READ_INST_16_0();
806 LOG_INST() << "jnez ->\t"
807 << "cond jmpz " << std::hex << static_cast<int32_t>(offset);
808 if (GET_ACC() == JSTaggedValue::True() || (GET_ACC().IsInt() && GET_ACC().GetInt() != 0) ||
809 (GET_ACC().IsDouble() && GET_ACC().GetDouble() != 0)) {
810 UPDATE_HOTNESS_COUNTER(offset);
811 DISPATCH_OFFSET(offset);
812 } else {
813 DISPATCH(BytecodeInstruction::Format::IMM16);
814 }
815 }
816 HANDLE_OPCODE(HANDLE_LDA_DYN_V8) {
817 uint16_t vsrc = READ_INST_8_0();
818 LOG_INST() << "lda.dyn v" << vsrc;
819 uint64_t value = GET_VREG(vsrc);
820 SET_ACC(JSTaggedValue(value))
821 DISPATCH(BytecodeInstruction::Format::V8);
822 }
823 HANDLE_OPCODE(HANDLE_STA_DYN_V8) {
824 uint16_t vdst = READ_INST_8_0();
825 LOG_INST() << "sta.dyn v" << vdst;
826 SET_VREG(vdst, GET_ACC().GetRawData())
827 DISPATCH(BytecodeInstruction::Format::V8);
828 }
829 HANDLE_OPCODE(HANDLE_LDAI_DYN_IMM32) {
830 int32_t imm = READ_INST_32_0();
831 LOG_INST() << "ldai.dyn " << std::hex << imm;
832 SET_ACC(JSTaggedValue(imm))
833 DISPATCH(BytecodeInstruction::Format::IMM32);
834 }
835
836 HANDLE_OPCODE(HANDLE_FLDAI_DYN_IMM64) {
837 auto imm = bit_cast<double>(READ_INST_64_0());
838 LOG_INST() << "fldai.dyn " << imm;
839 SET_ACC(JSTaggedValue(imm))
840 DISPATCH(BytecodeInstruction::Format::IMM64);
841 }
842 {
843 int32_t actualNumArgs;
844 uint32_t funcReg;
845 JSTaggedType funcTagged;
846 ECMAObject *funcObject;
847 JSMethod *method;
848 JSTaggedType *newSp;
849 bool callThis;
850
851 HANDLE_OPCODE(HANDLE_CALLARG0DYN_PREF_V8) {
852 actualNumArgs = ActualNumArgsOfCall::CALLARG0;
853 funcReg = READ_INST_8_1();
854 LOG_INST() << "callarg0.dyn "
855 << "v" << funcReg;
856 CALL_INITIALIZE();
857 callThis = false;
858 CALL_PUSH_ARGS(0);
859 }
860 HANDLE_OPCODE(HANDLE_CALLARG1DYN_PREF_V8_V8) {
861 actualNumArgs = ActualNumArgsOfCall::CALLARG1;
862 funcReg = READ_INST_8_1();
863 uint8_t a0 = READ_INST_8_2();
864 LOG_INST() << "callarg1.dyn "
865 << "v" << funcReg << ", v" << a0;
866 CALL_INITIALIZE();
867 callThis = false;
868 CALL_PUSH_ARGS(1);
869 }
870 HANDLE_OPCODE(HANDLE_CALLARGS2DYN_PREF_V8_V8_V8) {
871 actualNumArgs = ActualNumArgsOfCall::CALLARGS2;
872 funcReg = READ_INST_8_1();
873 uint8_t a0 = READ_INST_8_2();
874 uint8_t a1 = READ_INST_8_3();
875 LOG_INST() << "callargs2.dyn "
876 << "v" << funcReg << ", v" << a0 << ", v" << a1;
877 CALL_INITIALIZE();
878 callThis = false;
879 CALL_PUSH_ARGS(2);
880 }
881 HANDLE_OPCODE(HANDLE_CALLARGS3DYN_PREF_V8_V8_V8_V8) {
882 actualNumArgs = ActualNumArgsOfCall::CALLARGS3;
883 funcReg = READ_INST_8_1();
884 uint8_t a0 = READ_INST_8_2();
885 uint8_t a1 = READ_INST_8_3();
886 uint8_t a2 = READ_INST_8_4();
887 LOG_INST() << "callargs3.dyn "
888 << "v" << funcReg << ", v" << a0 << ", v" << a1 << ", v" << a2;
889 CALL_INITIALIZE();
890 callThis = false;
891 CALL_PUSH_ARGS(3);
892 }
893 HANDLE_OPCODE(HANDLE_CALLITHISRANGEDYN_PREF_IMM16_V8) {
894 actualNumArgs = READ_INST_16_1() - 1; // 1: exclude this
895 funcReg = READ_INST_8_3();
896 LOG_INST() << "calli.dyn.this.range " << actualNumArgs << ", v" << funcReg;
897 CALL_INITIALIZE();
898 callThis = true;
899 CALL_PUSH_ARGS(I_THIS);
900 }
901 HANDLE_OPCODE(HANDLE_CALLSPREADDYN_PREF_V8_V8_V8) {
902 uint16_t v0 = READ_INST_8_1();
903 uint16_t v1 = READ_INST_8_2();
904 uint16_t v2 = READ_INST_8_3();
905 LOG_INST() << "intrinsics::callspreaddyn"
906 << " v" << v0 << " v" << v1 << " v" << v2;
907 JSTaggedValue func = GET_VREG_VALUE(v0);
908 JSTaggedValue obj = GET_VREG_VALUE(v1);
909 JSTaggedValue array = GET_VREG_VALUE(v2);
910
911 SAVE_PC();
912 JSTaggedValue res = SlowRuntimeStub::CallSpreadDyn(thread, func, obj, array);
913 INTERPRETER_RETURN_IF_ABRUPT(res);
914 SET_ACC(res);
915
916 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8_V8);
917 }
918 HANDLE_OPCODE(HANDLE_CALLIRANGEDYN_PREF_IMM16_V8) {
919 actualNumArgs = READ_INST_16_1();
920 funcReg = READ_INST_8_3();
921 LOG_INST() << "calli.rangedyn " << actualNumArgs << ", v" << funcReg;
922 CALL_INITIALIZE();
923 callThis = false;
924 CALL_PUSH_ARGS(I);
925 }
926 setVregsAndFrameNative: {
927 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
928 *(--newSp) = (callThis ? sp[funcReg + callThis] : JSTaggedValue::VALUE_UNDEFINED); // push this
929 *(--newSp) = JSTaggedValue::VALUE_UNDEFINED; // push new target
930 *(--newSp) = static_cast<JSTaggedType>(ToUintPtr(funcObject)); // push func
931 ASSERT(method->GetNumVregsWithCallField() == 0); // no need to push vregs
932 if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) {
933 INTERPRETER_GOTO_EXCEPTION_HANDLER();
934 }
935 EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS,
936 reinterpret_cast<JSTaggedValue *>(newSp));
937
938 InterpretedFrame *state = GET_FRAME(newSp);
939 state->base.prev = sp;
940 state->base.type = FrameType::INTERPRETER_FRAME;
941 state->pc = nullptr;
942 state->sp = newSp;
943 state->function = JSTaggedValue(funcTagged);
944 thread->SetCurrentSPFrame(newSp);
945 LOG(DEBUG, INTERPRETER) << "Entry: Runtime Call.";
946 JSTaggedValue retValue = reinterpret_cast<EcmaEntrypoint>(
947 const_cast<void *>(method->GetNativePointer()))(&ecmaRuntimeCallInfo);
948
949 thread->SetCurrentSPFrame(sp);
950 if (UNLIKELY(thread->HasPendingException())) {
951 INTERPRETER_GOTO_EXCEPTION_HANDLER();
952 }
953 LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call.";
954 SET_ACC(retValue);
955 INTERPRETER_HANDLE_RETURN();
956 }
957 setVregsAndFrameNotNative: {
958 if (JSFunction::Cast(funcObject)->IsClassConstructor()) {
959 {
960 [[maybe_unused]] EcmaHandleScope handleScope(thread);
961 JSHandle<JSObject> error =
962 factory->GetJSError(ErrorType::TYPE_ERROR, "class constructor cannot called without 'new'");
963 thread->SetException(error.GetTaggedValue());
964 }
965 INTERPRETER_GOTO_EXCEPTION_HANDLER();
966 }
967 uint64_t callField = method->GetCallField();
968 if ((callField & CALL_TYPE_MASK) != 0) {
969 // not normal call type, setting func/newTarget/this cannot be skipped
970 if (method->HaveThisWithCallField()) {
971 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
972 *(--newSp) = (callThis ? sp[funcReg + callThis] : JSTaggedValue::VALUE_UNDEFINED); // push this
973 }
974 if (method->HaveNewTargetWithCallField()) {
975 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
976 *(--newSp) = JSTaggedValue::VALUE_UNDEFINED; // push new target
977 }
978 if (method->HaveFuncWithCallField()) {
979 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
980 *(--newSp) = static_cast<JSTaggedType>(ToUintPtr(funcObject)); // push func
981 }
982 }
983 int32_t numVregs = static_cast<int32_t>(method->GetNumVregsWithCallField());
984 // push vregs
985 CALL_PUSH_UNDEFINED(numVregs);
986 SAVE_PC();
987 if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) {
988 INTERPRETER_GOTO_EXCEPTION_HANDLER();
989 }
990
991 InterpretedFrame *state = GET_FRAME(newSp);
992 state->base.prev = sp;
993 state->base.type = FrameType::INTERPRETER_FRAME;
994 state->pc = pc = JSMethod::Cast(method)->GetBytecodeArray();
995 state->sp = sp = newSp;
996 state->function = JSTaggedValue(funcTagged);
997 state->acc = JSTaggedValue::Hole();
998 state->constpool = JSFunction::Cast(funcObject)->GetConstantPool();
999 constpool = ConstantPool::Cast(state->constpool.GetTaggedObject());
1000 state->profileTypeInfo = JSFunction::Cast(funcObject)->GetProfileTypeInfo();
1001 JSTaggedValue env = JSFunction::Cast(funcObject)->GetLexicalEnv();
1002 state->env = env;
1003 thread->SetCurrentSPFrame(newSp);
1004 LOG(DEBUG, INTERPRETER) << "Entry: Runtime Call " << std::hex << reinterpret_cast<uintptr_t>(sp) << " "
1005 << std::hex << reinterpret_cast<uintptr_t>(pc);
1006 DISPATCH_OFFSET(0);
1007 }
1008 }
1009 HANDLE_OPCODE(HANDLE_RETURN_DYN) {
1010 LOG_INST() << "returnla ";
1011 InterpretedFrame *state = GET_FRAME(sp);
1012 LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call " << std::hex << reinterpret_cast<uintptr_t>(state->sp) << " "
1013 << std::hex << reinterpret_cast<uintptr_t>(state->pc);
1014 JSMethod *method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod();
1015 [[maybe_unused]] auto fistPC = method->GetInstructions();
1016 UPDATE_HOTNESS_COUNTER(-(pc - fistPC));
1017 JSTaggedType *currentSp = sp;
1018 sp = state->base.prev;
1019 ASSERT(sp != nullptr);
1020 InterpretedFrame *prevState = GET_FRAME(sp);
1021 pc = prevState->pc;
1022
1023 // break frame
1024 if (pc == nullptr) {
1025 state->acc = acc;
1026 return;
1027 }
1028 thread->SetCurrentSPFrame(sp);
1029
1030 constpool = ConstantPool::Cast(prevState->constpool.GetTaggedObject());
1031
1032 if (IsFastNewFrameExit(currentSp)) {
1033 JSFunction *func = JSFunction::Cast(GetThisFunction(currentSp).GetTaggedObject());
1034 if (acc.IsECMAObject()) {
1035 INTERPRETER_HANDLE_RETURN();
1036 }
1037
1038 if (func->IsBase()) {
1039 JSTaggedValue thisObject = GetThisObjectFromFastNewFrame(currentSp);
1040 SET_ACC(thisObject);
1041 INTERPRETER_HANDLE_RETURN();
1042 }
1043
1044 if (!acc.IsUndefined()) {
1045 {
1046 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1047 JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR,
1048 "Derived constructor must return object or undefined");
1049 thread->SetException(error.GetTaggedValue());
1050 }
1051 INTERPRETER_GOTO_EXCEPTION_HANDLER();
1052 }
1053
1054 JSTaggedValue thisObject = GetThisObjectFromFastNewFrame(currentSp);
1055 SET_ACC(thisObject);
1056 INTERPRETER_HANDLE_RETURN();
1057 }
1058
1059 INTERPRETER_HANDLE_RETURN();
1060 }
1061 HANDLE_OPCODE(HANDLE_RETURNUNDEFINED_PREF) {
1062 LOG_INST() << "return.undefined";
1063 InterpretedFrame *state = GET_FRAME(sp);
1064 LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call " << std::hex << reinterpret_cast<uintptr_t>(sp) << " "
1065 << std::hex << reinterpret_cast<uintptr_t>(state->pc);
1066 JSMethod *method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod();
1067 [[maybe_unused]] auto fistPC = method->GetInstructions();
1068 UPDATE_HOTNESS_COUNTER_NON_ACC(-(pc - fistPC));
1069 JSTaggedType *currentSp = sp;
1070 sp = state->base.prev;
1071 ASSERT(sp != nullptr);
1072 InterpretedFrame *prevState = GET_FRAME(sp);
1073 pc = prevState->pc;
1074
1075 // break frame
1076 if (pc == nullptr) {
1077 state->acc = JSTaggedValue::Undefined();
1078 return;
1079 }
1080 thread->SetCurrentSPFrame(sp);
1081
1082 constpool = ConstantPool::Cast(prevState->constpool.GetTaggedObject());
1083
1084 if (IsFastNewFrameExit(currentSp)) {
1085 JSFunction *func = JSFunction::Cast(GetThisFunction(currentSp).GetTaggedObject());
1086 if (func->IsBase()) {
1087 JSTaggedValue thisObject = GetThisObjectFromFastNewFrame(currentSp);
1088 SET_ACC(thisObject);
1089 INTERPRETER_HANDLE_RETURN();
1090 }
1091
1092 if (!acc.IsUndefined()) {
1093 {
1094 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1095 JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR,
1096 "Derived constructor must return object or undefined");
1097 thread->SetException(error.GetTaggedValue());
1098 }
1099 INTERPRETER_GOTO_EXCEPTION_HANDLER();
1100 }
1101
1102 JSTaggedValue thisObject = GetThisObjectFromFastNewFrame(currentSp);
1103 SET_ACC(thisObject);
1104 INTERPRETER_HANDLE_RETURN();
1105 } else {
1106 SET_ACC(JSTaggedValue::Undefined());
1107 }
1108 INTERPRETER_HANDLE_RETURN();
1109 }
1110 HANDLE_OPCODE(HANDLE_LDNAN_PREF) {
1111 LOG_INST() << "intrinsics::ldnan";
1112 SET_ACC(JSTaggedValue(base::NAN_VALUE));
1113 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1114 }
1115 HANDLE_OPCODE(HANDLE_LDINFINITY_PREF) {
1116 LOG_INST() << "intrinsics::ldinfinity";
1117 SET_ACC(JSTaggedValue(base::POSITIVE_INFINITY));
1118 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1119 }
1120 HANDLE_OPCODE(HANDLE_LDGLOBALTHIS_PREF) {
1121 LOG_INST() << "intrinsics::ldglobalthis";
1122 SET_ACC(globalObj)
1123 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1124 }
1125 HANDLE_OPCODE(HANDLE_LDUNDEFINED_PREF) {
1126 LOG_INST() << "intrinsics::ldundefined";
1127 SET_ACC(JSTaggedValue::Undefined())
1128 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1129 }
1130 HANDLE_OPCODE(HANDLE_LDNULL_PREF) {
1131 LOG_INST() << "intrinsics::ldnull";
1132 SET_ACC(JSTaggedValue::Null())
1133 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1134 }
1135 HANDLE_OPCODE(HANDLE_LDSYMBOL_PREF) {
1136 LOG_INST() << "intrinsics::ldsymbol";
1137 SET_ACC(globalEnv->GetSymbolFunction().GetTaggedValue());
1138 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1139 }
1140 HANDLE_OPCODE(HANDLE_LDGLOBAL_PREF) {
1141 LOG_INST() << "intrinsics::ldglobal";
1142 SET_ACC(globalObj)
1143 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1144 }
1145 HANDLE_OPCODE(HANDLE_LDTRUE_PREF) {
1146 LOG_INST() << "intrinsics::ldtrue";
1147 SET_ACC(JSTaggedValue::True())
1148 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1149 }
1150 HANDLE_OPCODE(HANDLE_LDFALSE_PREF) {
1151 LOG_INST() << "intrinsics::ldfalse";
1152 SET_ACC(JSTaggedValue::False())
1153 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1154 }
1155 HANDLE_OPCODE(HANDLE_LDLEXENVDYN_PREF) {
1156 LOG_INST() << "intrinsics::ldlexenvDyn ";
1157 InterpretedFrame *state = GET_FRAME(sp);
1158 JSTaggedValue currentLexenv = state->env;
1159 SET_ACC(currentLexenv);
1160 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1161 }
1162 HANDLE_OPCODE(HANDLE_GETUNMAPPEDARGS_PREF) {
1163 LOG_INST() << "intrinsics::getunmappedargs";
1164
1165 uint32_t startIdx = 0;
1166 uint32_t actualNumArgs = GetNumArgs(sp, 0, startIdx);
1167
1168 SAVE_PC();
1169 JSTaggedValue res = SlowRuntimeStub::GetUnmapedArgs(thread, sp, actualNumArgs, startIdx);
1170 INTERPRETER_RETURN_IF_ABRUPT(res);
1171 SET_ACC(res);
1172 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1173 }
1174 HANDLE_OPCODE(HANDLE_ASYNCFUNCTIONENTER_PREF) {
1175 LOG_INST() << "intrinsics::asyncfunctionenter";
1176 SAVE_PC();
1177 JSTaggedValue res = SlowRuntimeStub::AsyncFunctionEnter(thread);
1178 INTERPRETER_RETURN_IF_ABRUPT(res);
1179 SET_ACC(res);
1180 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1181 }
1182 HANDLE_OPCODE(HANDLE_TONUMBER_PREF_V8) {
1183 uint16_t v0 = READ_INST_8_1();
1184
1185 LOG_INST() << "intrinsics::tonumber"
1186 << " v" << v0;
1187 JSTaggedValue value = GET_VREG_VALUE(v0);
1188 if (value.IsNumber() || value.IsBigInt()) {
1189 // fast path
1190 SET_ACC(value);
1191 } else {
1192 // slow path
1193 SAVE_PC();
1194 JSTaggedValue res = SlowRuntimeStub::ToNumber(thread, value);
1195 INTERPRETER_RETURN_IF_ABRUPT(res);
1196 SET_ACC(res);
1197 }
1198 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1199 }
1200 HANDLE_OPCODE(HANDLE_NEGDYN_PREF_V8) {
1201 uint16_t v0 = READ_INST_8_1();
1202 LOG_INST() << "intrinsics::negdyn"
1203 << " v" << v0;
1204 JSTaggedValue value = GET_VREG_VALUE(v0);
1205 // fast path
1206 if (value.IsInt()) {
1207 if (value.GetInt() == 0) {
1208 SET_ACC(JSTaggedValue(-0.0));
1209 } else {
1210 SET_ACC(JSTaggedValue(-value.GetInt()));
1211 }
1212 } else if (value.IsDouble()) {
1213 SET_ACC(JSTaggedValue(-value.GetDouble()));
1214 } else { // slow path
1215 SAVE_PC();
1216 JSTaggedValue res = SlowRuntimeStub::NegDyn(thread, value);
1217 INTERPRETER_RETURN_IF_ABRUPT(res);
1218 SET_ACC(res);
1219 }
1220 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1221 }
1222 HANDLE_OPCODE(HANDLE_NOTDYN_PREF_V8) {
1223 uint16_t v0 = READ_INST_8_1();
1224
1225 LOG_INST() << "intrinsics::notdyn"
1226 << " v" << v0;
1227 JSTaggedValue value = GET_VREG_VALUE(v0);
1228 int32_t number;
1229 // number, fast path
1230 if (value.IsInt()) {
1231 number = static_cast<int32_t>(value.GetInt());
1232 SET_ACC(JSTaggedValue(~number)); // NOLINT(hicpp-signed-bitwise)
1233 } else if (value.IsDouble()) {
1234 number = base::NumberHelper::DoubleToInt(value.GetDouble(), base::INT32_BITS);
1235 SET_ACC(JSTaggedValue(~number)); // NOLINT(hicpp-signed-bitwise)
1236 } else {
1237 // slow path
1238 SAVE_PC();
1239 JSTaggedValue res = SlowRuntimeStub::NotDyn(thread, value);
1240 INTERPRETER_RETURN_IF_ABRUPT(res);
1241 SET_ACC(res);
1242 }
1243 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1244 }
1245 HANDLE_OPCODE(HANDLE_INCDYN_PREF_V8) {
1246 uint16_t v0 = READ_INST_8_1();
1247
1248 LOG_INST() << "intrinsics::incdyn"
1249 << " v" << v0;
1250
1251 JSTaggedValue value = GET_VREG_VALUE(v0);
1252 // number fast path
1253 if (value.IsInt()) {
1254 int32_t a0 = value.GetInt();
1255 if (UNLIKELY(a0 == INT32_MAX)) {
1256 auto ret = static_cast<double>(a0) + 1.0;
1257 SET_ACC(JSTaggedValue(ret))
1258 } else {
1259 SET_ACC(JSTaggedValue(a0 + 1))
1260 }
1261 } else if (value.IsDouble()) {
1262 SET_ACC(JSTaggedValue(value.GetDouble() + 1.0))
1263 } else {
1264 // slow path
1265 SAVE_PC();
1266 JSTaggedValue res = SlowRuntimeStub::IncDyn(thread, value);
1267 INTERPRETER_RETURN_IF_ABRUPT(res);
1268 SET_ACC(res);
1269 }
1270 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1271 }
1272 HANDLE_OPCODE(HANDLE_DECDYN_PREF_V8) {
1273 uint16_t v0 = READ_INST_8_1();
1274 LOG_INST() << "intrinsics::decdyn"
1275 << " v" << v0;
1276
1277 JSTaggedValue value = GET_VREG_VALUE(v0);
1278 // number, fast path
1279 if (value.IsInt()) {
1280 int32_t a0 = value.GetInt();
1281 if (UNLIKELY(a0 == INT32_MIN)) {
1282 auto ret = static_cast<double>(a0) - 1.0;
1283 SET_ACC(JSTaggedValue(ret))
1284 } else {
1285 SET_ACC(JSTaggedValue(a0 - 1))
1286 }
1287 } else if (value.IsDouble()) {
1288 SET_ACC(JSTaggedValue(value.GetDouble() - 1.0))
1289 } else {
1290 // slow path
1291 SAVE_PC();
1292 JSTaggedValue res = SlowRuntimeStub::DecDyn(thread, value);
1293 INTERPRETER_RETURN_IF_ABRUPT(res);
1294 SET_ACC(res);
1295 }
1296 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1297 }
1298 HANDLE_OPCODE(HANDLE_THROWDYN_PREF) {
1299 LOG_INST() << "intrinsics::throwdyn";
1300 SAVE_PC();
1301 SlowRuntimeStub::ThrowDyn(thread, GET_ACC());
1302 INTERPRETER_GOTO_EXCEPTION_HANDLER();
1303 }
1304 HANDLE_OPCODE(HANDLE_TYPEOFDYN_PREF) {
1305 LOG_INST() << "intrinsics::typeofdyn";
1306 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
1307 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(FastTypeOf));
1308 typedef JSTaggedType (*PFFastTypeOf)(uintptr_t, JSTaggedType);
1309 auto fastTypeOfPtr = reinterpret_cast<PFFastTypeOf>(stubAddr);
1310 JSTaggedValue res = JSTaggedValue(fastTypeOfPtr(thread->GetGlueAddr(), GET_ACC().GetRawData()));
1311 #else
1312 JSTaggedValue res = FastRuntimeStub::FastTypeOf(thread, GET_ACC());
1313 #endif
1314 SET_ACC(res);
1315 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1316 }
1317 HANDLE_OPCODE(HANDLE_GETPROPITERATOR_PREF) {
1318 LOG_INST() << "intrinsics::getpropiterator";
1319 SAVE_PC();
1320 JSTaggedValue res = SlowRuntimeStub::GetPropIterator(thread, GET_ACC());
1321 INTERPRETER_RETURN_IF_ABRUPT(res);
1322 SET_ACC(res);
1323 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1324 }
1325 HANDLE_OPCODE(HANDLE_RESUMEGENERATOR_PREF_V8) {
1326 LOG_INST() << "intrinsics::resumegenerator";
1327 uint16_t vs = READ_INST_8_1();
1328 JSGeneratorObject *obj = JSGeneratorObject::Cast(GET_VREG_VALUE(vs).GetTaggedObject());
1329 SET_ACC(obj->GetResumeResult());
1330 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1331 }
1332 HANDLE_OPCODE(HANDLE_GETRESUMEMODE_PREF_V8) {
1333 LOG_INST() << "intrinsics::getresumemode";
1334 uint16_t vs = READ_INST_8_1();
1335 JSGeneratorObject *obj = JSGeneratorObject::Cast(GET_VREG_VALUE(vs).GetTaggedObject());
1336 SET_ACC(JSTaggedValue(static_cast<int>(obj->GetResumeMode())));
1337 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1338 }
1339 HANDLE_OPCODE(HANDLE_GETITERATOR_PREF) {
1340 LOG_INST() << "intrinsics::getiterator";
1341 JSTaggedValue obj = GET_ACC();
1342
1343 // fast path: Generator obj is already store in acc
1344 if (!obj.IsGeneratorObject()) {
1345 // slow path
1346 SAVE_PC();
1347 JSTaggedValue res = SlowRuntimeStub::GetIterator(thread, obj);
1348 INTERPRETER_RETURN_IF_ABRUPT(res);
1349 SET_ACC(res);
1350 }
1351 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
1352 }
1353 HANDLE_OPCODE(HANDLE_THROWCONSTASSIGNMENT_PREF_V8) {
1354 uint16_t v0 = READ_INST_8_1();
1355 LOG_INST() << "throwconstassignment"
1356 << " v" << v0;
1357 SAVE_PC();
1358 SlowRuntimeStub::ThrowConstAssignment(thread, GET_VREG_VALUE(v0));
1359 INTERPRETER_GOTO_EXCEPTION_HANDLER();
1360 }
1361 HANDLE_OPCODE(HANDLE_THROWTHROWNOTEXISTS_PREF) {
1362 LOG_INST() << "throwthrownotexists";
1363
1364 SAVE_PC();
1365 SlowRuntimeStub::ThrowThrowNotExists(thread);
1366 INTERPRETER_GOTO_EXCEPTION_HANDLER();
1367 }
1368 HANDLE_OPCODE(HANDLE_THROWPATTERNNONCOERCIBLE_PREF) {
1369 LOG_INST() << "throwpatternnoncoercible";
1370
1371 SAVE_PC();
1372 SlowRuntimeStub::ThrowPatternNonCoercible(thread);
1373 INTERPRETER_GOTO_EXCEPTION_HANDLER();
1374 }
1375 HANDLE_OPCODE(HANDLE_THROWIFNOTOBJECT_PREF_V8) {
1376 LOG_INST() << "throwifnotobject";
1377 uint16_t v0 = READ_INST_8_1();
1378
1379 JSTaggedValue value = GET_VREG_VALUE(v0);
1380 // fast path
1381 if (value.IsECMAObject()) {
1382 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1383 }
1384
1385 // slow path
1386 SAVE_PC();
1387 SlowRuntimeStub::ThrowIfNotObject(thread);
1388 INTERPRETER_GOTO_EXCEPTION_HANDLER();
1389 }
1390 HANDLE_OPCODE(HANDLE_ITERNEXT_PREF_V8) {
1391 uint16_t v0 = READ_INST_8_1();
1392 LOG_INST() << "intrinsics::iternext"
1393 << " v" << v0;
1394 SAVE_PC();
1395 JSTaggedValue iter = GET_VREG_VALUE(v0);
1396 JSTaggedValue res = SlowRuntimeStub::IterNext(thread, iter);
1397 INTERPRETER_RETURN_IF_ABRUPT(res);
1398 SET_ACC(res);
1399 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1400 }
1401 HANDLE_OPCODE(HANDLE_CLOSEITERATOR_PREF_V8) {
1402 uint16_t v0 = READ_INST_8_1();
1403 LOG_INST() << "intrinsics::closeiterator"
1404 << " v" << v0;
1405 SAVE_PC();
1406 JSTaggedValue iter = GET_VREG_VALUE(v0);
1407 JSTaggedValue res = SlowRuntimeStub::CloseIterator(thread, iter);
1408 INTERPRETER_RETURN_IF_ABRUPT(res);
1409 SET_ACC(res);
1410 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1411 }
1412 HANDLE_OPCODE(HANDLE_ADD2DYN_PREF_V8) {
1413 uint16_t v0 = READ_INST_8_1();
1414 LOG_INST() << "intrinsics::add2dyn"
1415 << " v" << v0;
1416 int32_t a0;
1417 int32_t a1;
1418 JSTaggedValue left = GET_VREG_VALUE(v0);
1419 JSTaggedValue right = GET_ACC();
1420 // number, fast path
1421 if (left.IsInt() && right.IsInt()) {
1422 a0 = left.GetInt();
1423 a1 = right.GetInt();
1424 if ((a0 > 0 && a1 > INT32_MAX - a0) || (a0 < 0 && a1 < INT32_MIN - a0)) {
1425 auto ret = static_cast<double>(a0) + static_cast<double>(a1);
1426 SET_ACC(JSTaggedValue(ret))
1427 } else {
1428 SET_ACC(JSTaggedValue(a0 + a1))
1429 }
1430 } else if (left.IsNumber() && right.IsNumber()) {
1431 double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble();
1432 double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble();
1433 double ret = a0Double + a1Double;
1434 SET_ACC(JSTaggedValue(ret))
1435 } else {
1436 // one or both are not number, slow path
1437 SAVE_PC();
1438 JSTaggedValue res = SlowRuntimeStub::Add2Dyn(thread, ecmaVm, left, right);
1439 INTERPRETER_RETURN_IF_ABRUPT(res);
1440 SET_ACC(res);
1441 }
1442 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1443 }
1444 HANDLE_OPCODE(HANDLE_SUB2DYN_PREF_V8) {
1445 uint16_t v0 = READ_INST_8_1();
1446 LOG_INST() << "intrinsics::sub2dyn"
1447 << " v" << v0;
1448 int32_t a0;
1449 int32_t a1;
1450 JSTaggedValue left = GET_VREG_VALUE(v0);
1451 JSTaggedValue right = GET_ACC();
1452 if (left.IsInt() && right.IsInt()) {
1453 a0 = left.GetInt();
1454 a1 = -right.GetInt();
1455 if ((a0 > 0 && a1 > INT32_MAX - a0) || (a0 < 0 && a1 < INT32_MIN - a0)) {
1456 auto ret = static_cast<double>(a0) + static_cast<double>(a1);
1457 SET_ACC(JSTaggedValue(ret))
1458 } else {
1459 SET_ACC(JSTaggedValue(a0 + a1))
1460 }
1461 } else if (left.IsNumber() && right.IsNumber()) {
1462 double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble();
1463 double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble();
1464 double ret = a0Double - a1Double;
1465 SET_ACC(JSTaggedValue(ret))
1466 } else {
1467 // one or both are not number, slow path
1468 SAVE_PC();
1469 JSTaggedValue res = SlowRuntimeStub::Sub2Dyn(thread, left, right);
1470 INTERPRETER_RETURN_IF_ABRUPT(res);
1471 SET_ACC(res);
1472 }
1473 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1474 }
1475 HANDLE_OPCODE(HANDLE_MUL2DYN_PREF_V8) {
1476 uint16_t v0 = READ_INST_8_1();
1477 LOG_INST() << "intrinsics::mul2dyn"
1478 << " v" << v0;
1479 JSTaggedValue left = GET_VREG_VALUE(v0);
1480 JSTaggedValue right = acc;
1481 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
1482 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(FastMul));
1483 typedef JSTaggedType (*PFFastMul)(JSTaggedType, JSTaggedType);
1484 auto fastMulPtr = reinterpret_cast<PFFastMul>(stubAddr);
1485 JSTaggedValue value = JSTaggedValue(fastMulPtr(left.GetRawData(), right.GetRawData()));
1486 #else
1487 JSTaggedValue value = FastRuntimeStub::FastMul(left, right);
1488 #endif
1489 if (!value.IsHole()) {
1490 SET_ACC(value);
1491 } else {
1492 // slow path
1493 SAVE_PC();
1494 JSTaggedValue res = SlowRuntimeStub::Mul2Dyn(thread, left, right);
1495 INTERPRETER_RETURN_IF_ABRUPT(res);
1496 SET_ACC(res);
1497 }
1498 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1499 }
1500 HANDLE_OPCODE(HANDLE_DIV2DYN_PREF_V8) {
1501 uint16_t v0 = READ_INST_8_1();
1502 LOG_INST() << "intrinsics::div2dyn"
1503 << " v" << v0;
1504 JSTaggedValue left = GET_VREG_VALUE(v0);
1505 JSTaggedValue right = acc;
1506 // fast path
1507 JSTaggedValue res = FastRuntimeStub::FastDiv(left, right);
1508 if (!res.IsHole()) {
1509 SET_ACC(res);
1510 } else {
1511 // slow path
1512 SAVE_PC();
1513 JSTaggedValue slowRes = SlowRuntimeStub::Div2Dyn(thread, left, right);
1514 INTERPRETER_RETURN_IF_ABRUPT(slowRes);
1515 SET_ACC(slowRes);
1516 }
1517 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1518 }
1519 HANDLE_OPCODE(HANDLE_MOD2DYN_PREF_V8) {
1520 uint16_t vs = READ_INST_8_1();
1521 LOG_INST() << "intrinsics::mod2dyn"
1522 << " v" << vs;
1523 JSTaggedValue left = GET_VREG_VALUE(vs);
1524 JSTaggedValue right = GET_ACC();
1525
1526 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
1527 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(FastMod));
1528 typedef JSTaggedType (*PFFastMod)(uintptr_t, JSTaggedType, JSTaggedType);
1529 auto fastModPtr = reinterpret_cast<PFFastMod>(stubAddr);
1530 JSTaggedValue res = JSTaggedValue(fastModPtr(thread->GetGlueAddr(), left.GetRawData(), right.GetRawData()));
1531 #else
1532 JSTaggedValue res = FastRuntimeStub::FastMod(left, right);
1533 #endif
1534 if (!res.IsHole()) {
1535 SET_ACC(res);
1536 } else {
1537 // slow path
1538 SAVE_PC();
1539 JSTaggedValue slowRes = SlowRuntimeStub::Mod2Dyn(thread, left, right);
1540 INTERPRETER_RETURN_IF_ABRUPT(slowRes);
1541 SET_ACC(slowRes);
1542 }
1543 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1544 }
1545 HANDLE_OPCODE(HANDLE_EQDYN_PREF_V8) {
1546 uint16_t v0 = READ_INST_8_1();
1547
1548 LOG_INST() << "intrinsics::eqdyn"
1549 << " v" << v0;
1550 JSTaggedValue left = GET_VREG_VALUE(v0);
1551 JSTaggedValue right = acc;
1552 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
1553 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(FastEqual));
1554 typedef JSTaggedType (*PFFastEqual)(JSTaggedType, JSTaggedType);
1555 auto fastEqualPtr = reinterpret_cast<PFFastEqual>(stubAddr);
1556 JSTaggedValue res = JSTaggedValue(fastEqualPtr(left.GetRawData(), right.GetRawData()));
1557 #else
1558 JSTaggedValue res = FastRuntimeStub::FastEqual(left, right);
1559 #endif
1560 if (!res.IsHole()) {
1561 SET_ACC(res);
1562 } else {
1563 // slow path
1564 SAVE_PC();
1565 res = SlowRuntimeStub::EqDyn(thread, left, right);
1566 INTERPRETER_RETURN_IF_ABRUPT(res);
1567 SET_ACC(res);
1568 }
1569
1570 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1571 }
1572 HANDLE_OPCODE(HANDLE_NOTEQDYN_PREF_V8) {
1573 uint16_t v0 = READ_INST_8_1();
1574
1575 LOG_INST() << "intrinsics::noteqdyn"
1576 << " v" << v0;
1577 JSTaggedValue left = GET_VREG_VALUE(v0);
1578 JSTaggedValue right = acc;
1579
1580 JSTaggedValue res = FastRuntimeStub::FastEqual(left, right);
1581 if (!res.IsHole()) {
1582 res = res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True();
1583 SET_ACC(res);
1584 } else {
1585 // slow path
1586 SAVE_PC();
1587 res = SlowRuntimeStub::NotEqDyn(thread, left, right);
1588 INTERPRETER_RETURN_IF_ABRUPT(res);
1589 SET_ACC(res);
1590 }
1591 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1592 }
1593 HANDLE_OPCODE(HANDLE_LESSDYN_PREF_V8) {
1594 uint16_t v0 = READ_INST_8_1();
1595
1596 LOG_INST() << "intrinsics::lessdyn"
1597 << " v" << v0;
1598 JSTaggedValue left = GET_VREG_VALUE(v0);
1599 JSTaggedValue right = GET_ACC();
1600 if (left.IsNumber() && right.IsNumber()) {
1601 // fast path
1602 double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
1603 double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
1604 bool ret = JSTaggedValue::StrictNumberCompare(valueA, valueB) == ComparisonResult::LESS;
1605 SET_ACC(ret ? JSTaggedValue::True() : JSTaggedValue::False())
1606 } else if (left.IsBigInt() && right.IsBigInt()) {
1607 bool result = BigInt::LessThan(left, right);
1608 SET_ACC(JSTaggedValue(result));
1609 } else {
1610 // slow path
1611 SAVE_PC();
1612 JSTaggedValue res = SlowRuntimeStub::LessDyn(thread, left, right);
1613 INTERPRETER_RETURN_IF_ABRUPT(res);
1614 SET_ACC(res);
1615 }
1616 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1617 }
1618 HANDLE_OPCODE(HANDLE_LESSEQDYN_PREF_V8) {
1619 uint16_t vs = READ_INST_8_1();
1620 LOG_INST() << "intrinsics::lesseqdyn "
1621 << " v" << vs;
1622 JSTaggedValue left = GET_VREG_VALUE(vs);
1623 JSTaggedValue right = GET_ACC();
1624 if (left.IsNumber() && right.IsNumber()) {
1625 // fast path
1626 double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
1627 double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
1628 bool ret = JSTaggedValue::StrictNumberCompare(valueA, valueB) <= ComparisonResult::EQUAL;
1629 SET_ACC(ret ? JSTaggedValue::True() : JSTaggedValue::False())
1630 } else if (left.IsBigInt() && right.IsBigInt()) {
1631 bool result = BigInt::LessThan(left, right) || BigInt::Equal(left, right);
1632 SET_ACC(JSTaggedValue(result));
1633 } else {
1634 // slow path
1635 SAVE_PC();
1636 JSTaggedValue res = SlowRuntimeStub::LessEqDyn(thread, left, right);
1637 INTERPRETER_RETURN_IF_ABRUPT(res);
1638 SET_ACC(res);
1639 }
1640 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1641 }
1642 HANDLE_OPCODE(HANDLE_GREATERDYN_PREF_V8) {
1643 uint16_t v0 = READ_INST_8_1();
1644
1645 LOG_INST() << "intrinsics::greaterdyn"
1646 << " v" << v0;
1647 JSTaggedValue left = GET_VREG_VALUE(v0);
1648 JSTaggedValue right = acc;
1649 if (left.IsNumber() && right.IsNumber()) {
1650 // fast path
1651 double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
1652 double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
1653 bool ret = JSTaggedValue::StrictNumberCompare(valueA, valueB) == ComparisonResult::GREAT;
1654 SET_ACC(ret ? JSTaggedValue::True() : JSTaggedValue::False())
1655 } else if (left.IsBigInt() && right.IsBigInt()) {
1656 bool result = BigInt::LessThan(right, left);
1657 SET_ACC(JSTaggedValue(result));
1658 } else {
1659 // slow path
1660 SAVE_PC();
1661 JSTaggedValue res = SlowRuntimeStub::GreaterDyn(thread, left, right);
1662 INTERPRETER_RETURN_IF_ABRUPT(res);
1663 SET_ACC(res);
1664 }
1665 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1666 }
1667 HANDLE_OPCODE(HANDLE_GREATEREQDYN_PREF_V8) {
1668 uint16_t vs = READ_INST_8_1();
1669 LOG_INST() << "intrinsics::greateqdyn "
1670 << " v" << vs;
1671 JSTaggedValue left = GET_VREG_VALUE(vs);
1672 JSTaggedValue right = GET_ACC();
1673 if (left.IsNumber() && right.IsNumber()) {
1674 // fast path
1675 double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
1676 double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
1677 ComparisonResult comparison = JSTaggedValue::StrictNumberCompare(valueA, valueB);
1678 bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL);
1679 SET_ACC(ret ? JSTaggedValue::True() : JSTaggedValue::False())
1680 } else if (left.IsBigInt() && right.IsBigInt()) {
1681 bool result = BigInt::LessThan(right, left) || BigInt::Equal(right, left);
1682 SET_ACC(JSTaggedValue(result))
1683 } else {
1684 // slow path
1685 SAVE_PC();
1686 JSTaggedValue res = SlowRuntimeStub::GreaterEqDyn(thread, left, right);
1687 INTERPRETER_RETURN_IF_ABRUPT(res);
1688 SET_ACC(res);
1689 }
1690 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1691 }
1692 HANDLE_OPCODE(HANDLE_SHL2DYN_PREF_V8) {
1693 uint16_t v0 = READ_INST_8_1();
1694
1695 LOG_INST() << "intrinsics::shl2dyn"
1696 << " v" << v0;
1697 JSTaggedValue left = GET_VREG_VALUE(v0);
1698 JSTaggedValue right = GET_ACC();
1699 // both number, fast path
1700 if (left.IsInt() && right.IsInt()) {
1701 int32_t opNumber0 = left.GetInt();
1702 int32_t opNumber1 = right.GetInt();
1703 uint32_t shift =
1704 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1705 using unsigned_type = std::make_unsigned_t<int32_t>;
1706 auto ret =
1707 static_cast<int32_t>(static_cast<unsigned_type>(opNumber0) << shift); // NOLINT(hicpp-signed-bitwise)
1708 SET_ACC(JSTaggedValue(ret))
1709 } else if (left.IsNumber() && right.IsNumber()) {
1710 int32_t opNumber0 =
1711 left.IsInt() ? left.GetInt() : base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS);
1712 int32_t opNumber1 =
1713 right.IsInt() ? right.GetInt() : base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS);
1714 uint32_t shift =
1715 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1716 using unsigned_type = std::make_unsigned_t<int32_t>;
1717 auto ret =
1718 static_cast<int32_t>(static_cast<unsigned_type>(opNumber0) << shift); // NOLINT(hicpp-signed-bitwise)
1719 SET_ACC(JSTaggedValue(ret))
1720 } else {
1721 // slow path
1722 SAVE_PC();
1723 JSTaggedValue res = SlowRuntimeStub::Shl2Dyn(thread, left, right);
1724 INTERPRETER_RETURN_IF_ABRUPT(res);
1725 SET_ACC(res);
1726 }
1727 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1728 }
1729 HANDLE_OPCODE(HANDLE_SHR2DYN_PREF_V8) {
1730 uint16_t v0 = READ_INST_8_1();
1731
1732 LOG_INST() << "intrinsics::shr2dyn"
1733 << " v" << v0;
1734 JSTaggedValue left = GET_VREG_VALUE(v0);
1735 JSTaggedValue right = GET_ACC();
1736 // both number, fast path
1737 if (left.IsInt() && right.IsInt()) {
1738 int32_t opNumber0 = left.GetInt();
1739 int32_t opNumber1 = right.GetInt();
1740 uint32_t shift =
1741 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1742 auto ret = static_cast<int32_t>(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise)
1743 SET_ACC(JSTaggedValue(ret))
1744 } else if (left.IsNumber() && right.IsNumber()) {
1745 int32_t opNumber0 =
1746 left.IsInt() ? left.GetInt() : base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS);
1747 int32_t opNumber1 =
1748 right.IsInt() ? right.GetInt() : base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS);
1749 uint32_t shift =
1750 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1751 auto ret = static_cast<int32_t>(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise)
1752 SET_ACC(JSTaggedValue(ret))
1753 } else {
1754 // slow path
1755 SAVE_PC();
1756 JSTaggedValue res = SlowRuntimeStub::Shr2Dyn(thread, left, right);
1757 INTERPRETER_RETURN_IF_ABRUPT(res);
1758 SET_ACC(res);
1759 }
1760 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1761 }
1762 HANDLE_OPCODE(HANDLE_ASHR2DYN_PREF_V8) {
1763 uint16_t v0 = READ_INST_8_1();
1764
1765 LOG_INST() << "intrinsics::ashr2dyn"
1766 << " v" << v0;
1767 JSTaggedValue left = GET_VREG_VALUE(v0);
1768 JSTaggedValue right = GET_ACC();
1769 if (left.IsInt() && right.IsInt()) {
1770 int32_t opNumber0 = left.GetInt();
1771 int32_t opNumber1 = right.GetInt();
1772 uint32_t shift =
1773 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1774 using unsigned_type = std::make_unsigned_t<uint32_t>;
1775 auto ret =
1776 static_cast<uint32_t>(static_cast<unsigned_type>(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise)
1777 SET_ACC(JSTaggedValue(ret))
1778 } else if (left.IsNumber() && right.IsNumber()) {
1779 int32_t opNumber0 =
1780 left.IsInt() ? left.GetInt() : base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS);
1781 int32_t opNumber1 =
1782 right.IsInt() ? right.GetInt() : base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS);
1783 uint32_t shift =
1784 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1785 using unsigned_type = std::make_unsigned_t<uint32_t>;
1786 auto ret =
1787 static_cast<uint32_t>(static_cast<unsigned_type>(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise)
1788 SET_ACC(JSTaggedValue(ret))
1789 } else {
1790 // slow path
1791 SAVE_PC();
1792 JSTaggedValue res = SlowRuntimeStub::Ashr2Dyn(thread, left, right);
1793 INTERPRETER_RETURN_IF_ABRUPT(res);
1794 SET_ACC(res);
1795 }
1796 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1797 }
1798 HANDLE_OPCODE(HANDLE_AND2DYN_PREF_V8) {
1799 uint16_t v0 = READ_INST_8_1();
1800
1801 LOG_INST() << "intrinsics::and2dyn"
1802 << " v" << v0;
1803 JSTaggedValue left = GET_VREG_VALUE(v0);
1804 JSTaggedValue right = GET_ACC();
1805 // both number, fast path
1806 if (left.IsInt() && right.IsInt()) {
1807 int32_t opNumber0 = left.GetInt();
1808 int32_t opNumber1 = right.GetInt();
1809 // NOLINT(hicpp-signed-bitwise)
1810 auto ret = static_cast<uint32_t>(opNumber0) & static_cast<uint32_t>(opNumber1);
1811 SET_ACC(JSTaggedValue(static_cast<int32_t>(ret)))
1812 } else if (left.IsNumber() && right.IsNumber()) {
1813 int32_t opNumber0 =
1814 left.IsInt() ? left.GetInt() : base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS);
1815 int32_t opNumber1 =
1816 right.IsInt() ? right.GetInt() : base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS);
1817 // NOLINT(hicpp-signed-bitwise)
1818 auto ret = static_cast<uint32_t>(opNumber0) & static_cast<uint32_t>(opNumber1);
1819 SET_ACC(JSTaggedValue(static_cast<int32_t>(ret)))
1820 } else {
1821 // slow path
1822 SAVE_PC();
1823 JSTaggedValue res = SlowRuntimeStub::And2Dyn(thread, left, right);
1824 INTERPRETER_RETURN_IF_ABRUPT(res);
1825 SET_ACC(res);
1826 }
1827 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1828 }
1829 HANDLE_OPCODE(HANDLE_OR2DYN_PREF_V8) {
1830 uint16_t v0 = READ_INST_8_1();
1831
1832 LOG_INST() << "intrinsics::or2dyn"
1833 << " v" << v0;
1834 JSTaggedValue left = GET_VREG_VALUE(v0);
1835 JSTaggedValue right = GET_ACC();
1836 // both number, fast path
1837 if (left.IsInt() && right.IsInt()) {
1838 int32_t opNumber0 = left.GetInt();
1839 int32_t opNumber1 = right.GetInt();
1840 // NOLINT(hicpp-signed-bitwise)
1841 auto ret = static_cast<uint32_t>(opNumber0) | static_cast<uint32_t>(opNumber1);
1842 SET_ACC(JSTaggedValue(static_cast<int32_t>(ret)))
1843 } else if (left.IsNumber() && right.IsNumber()) {
1844 int32_t opNumber0 =
1845 left.IsInt() ? left.GetInt() : base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS);
1846 int32_t opNumber1 =
1847 right.IsInt() ? right.GetInt() : base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS);
1848 // NOLINT(hicpp-signed-bitwise)
1849 auto ret = static_cast<uint32_t>(opNumber0) | static_cast<uint32_t>(opNumber1);
1850 SET_ACC(JSTaggedValue(static_cast<int32_t>(ret)))
1851 } else {
1852 // slow path
1853 SAVE_PC();
1854 JSTaggedValue res = SlowRuntimeStub::Or2Dyn(thread, left, right);
1855 INTERPRETER_RETURN_IF_ABRUPT(res);
1856 SET_ACC(res);
1857 }
1858 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1859 }
1860 HANDLE_OPCODE(HANDLE_XOR2DYN_PREF_V8) {
1861 uint16_t v0 = READ_INST_8_1();
1862
1863 LOG_INST() << "intrinsics::xor2dyn"
1864 << " v" << v0;
1865 JSTaggedValue left = GET_VREG_VALUE(v0);
1866 JSTaggedValue right = GET_ACC();
1867 // both number, fast path
1868 if (left.IsInt() && right.IsInt()) {
1869 int32_t opNumber0 = left.GetInt();
1870 int32_t opNumber1 = right.GetInt();
1871 // NOLINT(hicpp-signed-bitwise)
1872 auto ret = static_cast<uint32_t>(opNumber0) ^ static_cast<uint32_t>(opNumber1);
1873 SET_ACC(JSTaggedValue(static_cast<int32_t>(ret)))
1874 } else if (left.IsNumber() && right.IsNumber()) {
1875 int32_t opNumber0 =
1876 left.IsInt() ? left.GetInt() : base::NumberHelper::DoubleToInt(left.GetDouble(), base::INT32_BITS);
1877 int32_t opNumber1 =
1878 right.IsInt() ? right.GetInt() : base::NumberHelper::DoubleToInt(right.GetDouble(), base::INT32_BITS);
1879 // NOLINT(hicpp-signed-bitwise)
1880 auto ret = static_cast<uint32_t>(opNumber0) ^ static_cast<uint32_t>(opNumber1);
1881 SET_ACC(JSTaggedValue(static_cast<int32_t>(ret)))
1882 } else {
1883 // slow path
1884 SAVE_PC();
1885 JSTaggedValue res = SlowRuntimeStub::Xor2Dyn(thread, left, right);
1886 INTERPRETER_RETURN_IF_ABRUPT(res);
1887 SET_ACC(res);
1888 }
1889 DISPATCH(BytecodeInstruction::Format::PREF_V8);
1890 }
1891 HANDLE_OPCODE(HANDLE_DELOBJPROP_PREF_V8_V8) {
1892 uint16_t v0 = READ_INST_8_1();
1893 uint16_t v1 = READ_INST_8_2();
1894 LOG_INST() << "intrinsics::delobjprop"
1895 << " v0" << v0 << " v1" << v1;
1896
1897 JSTaggedValue obj = GET_VREG_VALUE(v0);
1898 JSTaggedValue prop = GET_VREG_VALUE(v1);
1899 SAVE_PC();
1900 JSTaggedValue res = SlowRuntimeStub::DelObjProp(thread, obj, prop);
1901 INTERPRETER_RETURN_IF_ABRUPT(res);
1902 SET_ACC(res);
1903
1904 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
1905 }
1906 HANDLE_OPCODE(HANDLE_DEFINEFUNCDYN_PREF_ID16_IMM16_V8) {
1907 uint16_t methodId = READ_INST_16_1();
1908 uint16_t length = READ_INST_16_3();
1909 uint16_t v0 = READ_INST_8_5();
1910 LOG_INST() << "intrinsics::definefuncDyn length: " << length
1911 << " v" << v0;
1912 JSFunction *result = JSFunction::Cast(constpool->GetObjectFromCache(methodId).GetTaggedObject());
1913 ASSERT(result != nullptr);
1914 if (result->GetResolved()) {
1915 SAVE_PC();
1916 auto res = SlowRuntimeStub::DefinefuncDyn(thread, result);
1917 INTERPRETER_RETURN_IF_ABRUPT(res);
1918 result = JSFunction::Cast(res.GetTaggedObject());
1919 result->SetConstantPool(thread, JSTaggedValue(constpool));
1920 } else {
1921 result->SetResolved(true);
1922 }
1923
1924 result->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
1925 JSTaggedValue envHandle = GET_VREG_VALUE(v0);
1926 result->SetLexicalEnv(thread, envHandle);
1927 SET_ACC(JSTaggedValue(result))
1928
1929 DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_V8);
1930 }
1931 HANDLE_OPCODE(HANDLE_DEFINENCFUNCDYN_PREF_ID16_IMM16_V8) {
1932 uint16_t methodId = READ_INST_16_1();
1933 uint16_t length = READ_INST_16_3();
1934 uint16_t v0 = READ_INST_8_5();
1935 JSTaggedValue homeObject = GET_ACC();
1936 LOG_INST() << "intrinsics::definencfuncDyn length: " << length
1937 << " v" << v0;
1938 JSFunction *result = JSFunction::Cast(constpool->GetObjectFromCache(methodId).GetTaggedObject());
1939 ASSERT(result != nullptr);
1940 if (result->GetResolved()) {
1941 SAVE_ACC();
1942 SAVE_PC();
1943 auto res = SlowRuntimeStub::DefineNCFuncDyn(thread, result);
1944 INTERPRETER_RETURN_IF_ABRUPT(res);
1945 result = JSFunction::Cast(res.GetTaggedObject());
1946 result->SetConstantPool(thread, JSTaggedValue(constpool));
1947 RESTORE_ACC();
1948 homeObject = GET_ACC();
1949 } else {
1950 result->SetResolved(true);
1951 }
1952
1953 result->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
1954 JSTaggedValue env = GET_VREG_VALUE(v0);
1955 result->SetLexicalEnv(thread, env);
1956 result->SetHomeObject(thread, homeObject);
1957 SET_ACC(JSTaggedValue(result));
1958
1959 DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_V8);
1960 }
1961 HANDLE_OPCODE(HANDLE_DEFINEMETHOD_PREF_ID16_IMM16_V8) {
1962 uint16_t methodId = READ_INST_16_1();
1963 uint16_t length = READ_INST_16_3();
1964 uint16_t v0 = READ_INST_8_5();
1965 JSTaggedValue homeObject = GET_ACC();
1966 LOG_INST() << "intrinsics::definemethod length: " << length
1967 << " v" << v0;
1968 JSFunction *result = JSFunction::Cast(constpool->GetObjectFromCache(methodId).GetTaggedObject());
1969 ASSERT(result != nullptr);
1970 if (result->GetResolved()) {
1971 SAVE_PC();
1972 auto res = SlowRuntimeStub::DefineMethod(thread, result, homeObject);
1973 INTERPRETER_RETURN_IF_ABRUPT(res);
1974 result = JSFunction::Cast(res.GetTaggedObject());
1975 result->SetConstantPool(thread, JSTaggedValue(constpool));
1976 } else {
1977 result->SetHomeObject(thread, homeObject);
1978 result->SetResolved(true);
1979 }
1980
1981 result->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
1982 JSTaggedValue taggedCurEnv = GET_VREG_VALUE(v0);
1983 result->SetLexicalEnv(thread, taggedCurEnv);
1984 SET_ACC(JSTaggedValue(result));
1985
1986 DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_V8);
1987 }
1988 HANDLE_OPCODE(HANDLE_NEWOBJDYNRANGE_PREF_IMM16_V8) {
1989 uint16_t numArgs = READ_INST_16_1();
1990 uint16_t firstArgRegIdx = READ_INST_8_3();
1991 LOG_INST() << "intrinsics::newobjDynrange " << numArgs << " v" << firstArgRegIdx;
1992 JSTaggedValue ctor = GET_VREG_VALUE(firstArgRegIdx);
1993 if (ctor.IsJSFunction() && ctor.IsConstructor()) {
1994 thread->CheckSafepoint();
1995 ctor = GET_VREG_VALUE(firstArgRegIdx); // may be moved by GC
1996 JSFunction *ctorFunc = JSFunction::Cast(ctor.GetTaggedObject());
1997 JSMethod *ctorMethod = ctorFunc->GetMethod();
1998 if (ctorFunc->IsBuiltinsConstructor()) {
1999 ASSERT(ctorMethod->GetNumVregsWithCallField() == 0);
2000 size_t frameSize = FRAME_STATE_SIZE + numArgs + 1; // +1 for this
2001 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2002 JSTaggedType *newSp = sp - frameSize;
2003 if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) {
2004 INTERPRETER_GOTO_EXCEPTION_HANDLER();
2005 }
2006 EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, numArgs + 1, reinterpret_cast<JSTaggedValue *>(newSp));
2007 // copy args
2008 uint32_t index = 0;
2009 // func
2010 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2011 newSp[index++] = GET_VREG(firstArgRegIdx);
2012 // newTarget
2013 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2014 newSp[index++] = GET_VREG(firstArgRegIdx + 1);
2015 // this
2016 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2017 newSp[index++] = JSTaggedValue::VALUE_UNDEFINED;
2018 for (size_t i = 2; i < numArgs; ++i) { // 2: func and newTarget
2019 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2020 newSp[index++] = GET_VREG(firstArgRegIdx + i);
2021 }
2022
2023 InterpretedFrame *state = GET_FRAME(newSp);
2024 state->base.prev = sp;
2025 state->base.type = FrameType::INTERPRETER_FRAME;
2026 state->pc = nullptr;
2027 state->sp = newSp;
2028 state->function = ctor;
2029 thread->SetCurrentSPFrame(newSp);
2030 LOG(DEBUG, INTERPRETER) << "Entry: Runtime New.";
2031 JSTaggedValue retValue = reinterpret_cast<EcmaEntrypoint>(
2032 const_cast<void *>(ctorMethod->GetNativePointer()))(&ecmaRuntimeCallInfo);
2033
2034 thread->SetCurrentSPFrame(sp);
2035 if (UNLIKELY(thread->HasPendingException())) {
2036 INTERPRETER_GOTO_EXCEPTION_HANDLER();
2037 }
2038 LOG(DEBUG, INTERPRETER) << "Exit: Runtime New.";
2039 SET_ACC(retValue);
2040 DISPATCH(BytecodeInstruction::Format::PREF_IMM16_V8);
2041 }
2042
2043 if (IsFastNewFrameEnter(ctorMethod)) {
2044 SAVE_PC();
2045 uint32_t numVregs = ctorMethod->GetNumVregsWithCallField();
2046 uint32_t numDeclaredArgs = ctorMethod->GetNumArgsWithCallField() + 1; // +1 for this
2047 // +1 for hidden this, explicit this may be overwritten after bc optimizer
2048 size_t frameSize = FRAME_STATE_SIZE + numVregs + numDeclaredArgs + 1;
2049 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2050 JSTaggedType *newSp = sp - frameSize;
2051 InterpretedFrame *state = GET_FRAME(newSp);
2052
2053 if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) {
2054 INTERPRETER_GOTO_EXCEPTION_HANDLER();
2055 }
2056
2057 uint32_t index = 0;
2058 // initialize vregs value
2059 for (size_t i = 0; i < numVregs; ++i) {
2060 newSp[index++] = JSTaggedValue::VALUE_UNDEFINED;
2061 }
2062
2063 // this
2064 JSTaggedValue thisObj;
2065 if (ctorFunc->IsBase()) {
2066 JSTaggedValue newTarget = GET_VREG_VALUE(firstArgRegIdx + 1);
2067 thisObj = FastRuntimeStub::NewThisObject(thread, ctor, newTarget, state);
2068 INTERPRETER_RETURN_IF_ABRUPT(thisObj);
2069 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2070 newSp[index++] = thisObj.GetRawData();
2071 } else {
2072 ASSERT(ctorFunc->IsDerivedConstructor());
2073 thisObj = JSTaggedValue::Undefined();
2074 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2075 newSp[index++] = thisObj.GetRawData();
2076
2077 state->function = ctor;
2078 state->constpool = ctorFunc->GetConstantPool();
2079 state->profileTypeInfo = ctorFunc->GetProfileTypeInfo();
2080 state->env = ctorFunc->GetLexicalEnv();
2081 }
2082
2083 // the second condition ensure not push extra args
2084 for (size_t i = 2; i < numArgs && index < numVregs + numDeclaredArgs; ++i) { // 2: func and newTarget
2085 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2086 newSp[index++] = GET_VREG(firstArgRegIdx + i);
2087 }
2088
2089 // set undefined to the extra prats of declare
2090 for (size_t i = index; i < numVregs + numDeclaredArgs; ++i) {
2091 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2092 newSp[index++] = JSTaggedValue::VALUE_UNDEFINED;
2093 }
2094
2095 // hidden this object
2096 newSp[index] = thisObj.GetRawData();
2097
2098 state->base.prev = sp;
2099 state->base.type = FrameType::INTERPRETER_FAST_NEW_FRAME;
2100 state->pc = pc = ctorMethod->GetBytecodeArray();
2101 state->sp = sp = newSp;
2102 state->acc = JSTaggedValue::Hole();
2103 constpool = ConstantPool::Cast(state->constpool.GetTaggedObject());
2104
2105 thread->SetCurrentSPFrame(newSp);
2106 LOG(DEBUG, INTERPRETER) << "Entry: Runtime New " << std::hex << reinterpret_cast<uintptr_t>(sp) << " "
2107 << std::hex << reinterpret_cast<uintptr_t>(pc);
2108 DISPATCH_OFFSET(0);
2109 }
2110 }
2111
2112 // bound function, proxy, other call types, enter slow path
2113 constexpr uint16_t firstArgOffset = 2;
2114 JSTaggedValue newTarget = GET_VREG_VALUE(firstArgRegIdx + 1);
2115 // Exclude func and newTarget
2116 uint16_t firstArgIdx = firstArgRegIdx + firstArgOffset;
2117 uint16_t length = numArgs - firstArgOffset;
2118
2119 SAVE_PC();
2120 JSTaggedValue res = SlowRuntimeStub::NewObjDynRange(thread, ctor, newTarget, firstArgIdx, length);
2121 INTERPRETER_RETURN_IF_ABRUPT(res);
2122 SET_ACC(res);
2123 DISPATCH(BytecodeInstruction::Format::PREF_IMM16_V8);
2124 }
2125 HANDLE_OPCODE(HANDLE_EXPDYN_PREF_V8) {
2126 uint16_t v0 = READ_INST_8_1();
2127 LOG_INST() << "intrinsics::expdyn"
2128 << " v" << v0;
2129 JSTaggedValue base = GET_VREG_VALUE(v0);
2130 JSTaggedValue exponent = GET_ACC();
2131 if (base.IsNumber() && exponent.IsNumber()) {
2132 // fast path
2133 double doubleBase = base.IsInt() ? base.GetInt() : base.GetDouble();
2134 double doubleExponent = exponent.IsInt() ? exponent.GetInt() : exponent.GetDouble();
2135 if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) {
2136 SET_ACC(JSTaggedValue(base::NAN_VALUE));
2137 }
2138 if ((doubleBase == 0 &&
2139 ((bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
2140 std::isfinite(doubleExponent) && base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent &&
2141 base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF == // 2 : half
2142 (doubleExponent / 2)) { // 2 : half
2143 if (doubleExponent > 0) {
2144 SET_ACC(JSTaggedValue(-0.0));
2145 }
2146 if (doubleExponent < 0) {
2147 SET_ACC(JSTaggedValue(-base::POSITIVE_INFINITY));
2148 }
2149 }
2150 SET_ACC(JSTaggedValue(std::pow(doubleBase, doubleExponent)));
2151 } else {
2152 // slow path
2153 SAVE_PC();
2154 JSTaggedValue res = SlowRuntimeStub::ExpDyn(thread, base, exponent);
2155 INTERPRETER_RETURN_IF_ABRUPT(res);
2156 SET_ACC(res);
2157 }
2158 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2159 }
2160 HANDLE_OPCODE(HANDLE_ISINDYN_PREF_V8) {
2161 uint16_t v0 = READ_INST_8_1();
2162 LOG_INST() << "intrinsics::isindyn"
2163 << " v" << v0;
2164 JSTaggedValue prop = GET_VREG_VALUE(v0);
2165 JSTaggedValue obj = GET_ACC();
2166 SAVE_PC();
2167 JSTaggedValue res = SlowRuntimeStub::IsInDyn(thread, prop, obj);
2168 INTERPRETER_RETURN_IF_ABRUPT(res);
2169 SET_ACC(res);
2170 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2171 }
2172 HANDLE_OPCODE(HANDLE_INSTANCEOFDYN_PREF_V8) {
2173 uint16_t v0 = READ_INST_8_1();
2174 LOG_INST() << "intrinsics::instanceofdyn"
2175 << " v" << v0;
2176 JSTaggedValue obj = GET_VREG_VALUE(v0);
2177 JSTaggedValue target = GET_ACC();
2178 SAVE_PC();
2179 JSTaggedValue res = SlowRuntimeStub::InstanceofDyn(thread, obj, target);
2180 INTERPRETER_RETURN_IF_ABRUPT(res);
2181 SET_ACC(res);
2182 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2183 }
2184 HANDLE_OPCODE(HANDLE_STRICTNOTEQDYN_PREF_V8) {
2185 uint16_t v0 = READ_INST_8_1();
2186 LOG_INST() << "intrinsics::strictnoteq"
2187 << " v" << v0;
2188 JSTaggedValue left = GET_VREG_VALUE(v0);
2189 JSTaggedValue right = GET_ACC();
2190 bool res = FastRuntimeStub::FastStrictEqual(left, right);
2191 SET_ACC(JSTaggedValue(!res));
2192 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2193 }
2194 HANDLE_OPCODE(HANDLE_STRICTEQDYN_PREF_V8) {
2195 uint16_t v0 = READ_INST_8_1();
2196 LOG_INST() << "intrinsics::stricteq"
2197 << " v" << v0;
2198 JSTaggedValue left = GET_VREG_VALUE(v0);
2199 JSTaggedValue right = GET_ACC();
2200 bool res = FastRuntimeStub::FastStrictEqual(left, right);
2201 SET_ACC(JSTaggedValue(res));
2202 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2203 }
2204 HANDLE_OPCODE(HANDLE_LDLEXVARDYN_PREF_IMM16_IMM16) {
2205 uint16_t level = READ_INST_16_1();
2206 uint16_t slot = READ_INST_16_3();
2207
2208 LOG_INST() << "intrinsics::ldlexvardyn"
2209 << " level:" << level << " slot:" << slot;
2210 InterpretedFrame *state = GET_FRAME(sp);
2211 JSTaggedValue currentLexenv = state->env;
2212 JSTaggedValue env(currentLexenv);
2213 for (int i = 0; i < level; i++) {
2214 JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
2215 ASSERT(!taggedParentEnv.IsUndefined());
2216 env = taggedParentEnv;
2217 }
2218 SET_ACC(LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot));
2219 DISPATCH(BytecodeInstruction::Format::PREF_IMM16_IMM16);
2220 }
2221 HANDLE_OPCODE(HANDLE_LDLEXVARDYN_PREF_IMM8_IMM8) {
2222 uint16_t level = READ_INST_8_1();
2223 uint16_t slot = READ_INST_8_2();
2224
2225 LOG_INST() << "intrinsics::ldlexvardyn"
2226 << " level:" << level << " slot:" << slot;
2227 InterpretedFrame *state = GET_FRAME(sp);
2228 JSTaggedValue currentLexenv = state->env;
2229 JSTaggedValue env(currentLexenv);
2230 for (int i = 0; i < level; i++) {
2231 JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
2232 ASSERT(!taggedParentEnv.IsUndefined());
2233 env = taggedParentEnv;
2234 }
2235 SET_ACC(LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot));
2236 DISPATCH(BytecodeInstruction::Format::PREF_IMM8_IMM8);
2237 }
2238 HANDLE_OPCODE(HANDLE_LDLEXVARDYN_PREF_IMM4_IMM4) {
2239 uint16_t level = READ_INST_4_2();
2240 uint16_t slot = READ_INST_4_3();
2241
2242 LOG_INST() << "intrinsics::ldlexvardyn"
2243 << " level:" << level << " slot:" << slot;
2244 InterpretedFrame *state = GET_FRAME(sp);
2245 JSTaggedValue currentLexenv = state->env;
2246 JSTaggedValue env(currentLexenv);
2247 for (int i = 0; i < level; i++) {
2248 JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
2249 ASSERT(!taggedParentEnv.IsUndefined());
2250 env = taggedParentEnv;
2251 }
2252 SET_ACC(LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot));
2253 DISPATCH(BytecodeInstruction::Format::PREF_IMM4_IMM4);
2254 }
2255 HANDLE_OPCODE(HANDLE_STLEXVARDYN_PREF_IMM16_IMM16_V8) {
2256 uint16_t level = READ_INST_16_1();
2257 uint16_t slot = READ_INST_16_3();
2258 uint16_t v0 = READ_INST_8_5();
2259 LOG_INST() << "intrinsics::stlexvardyn"
2260 << " level:" << level << " slot:" << slot << " v" << v0;
2261
2262 JSTaggedValue value = GET_VREG_VALUE(v0);
2263 InterpretedFrame *state = GET_FRAME(sp);
2264 JSTaggedValue env = state->env;
2265 for (int i = 0; i < level; i++) {
2266 JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
2267 ASSERT(!taggedParentEnv.IsUndefined());
2268 env = taggedParentEnv;
2269 }
2270 LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(thread, slot, value);
2271
2272 DISPATCH(BytecodeInstruction::Format::PREF_IMM16_IMM16_V8);
2273 }
2274 HANDLE_OPCODE(HANDLE_NEWLEXENVWITHNAMEDYN_PREF_IMM16_IMM16) {
2275 uint16_t numVars = READ_INST_16_1();
2276 uint16_t scopeId = READ_INST_16_3();
2277 LOG_INST() << "intrinsics::newlexenvwithnamedyn"
2278 << " numVars " << numVars << " scopeId " << scopeId;
2279
2280 SAVE_PC();
2281 JSTaggedValue res = SlowRuntimeStub::NewLexicalEnvWithNameDyn(thread, numVars, scopeId);
2282 INTERPRETER_RETURN_IF_ABRUPT(res);
2283
2284 SET_ACC(res);
2285 GET_FRAME(sp)->env = res;
2286 DISPATCH(BytecodeInstruction::Format::PREF_IMM16_IMM16);
2287 }
2288 HANDLE_OPCODE(HANDLE_STLEXVARDYN_PREF_IMM8_IMM8_V8) {
2289 uint16_t level = READ_INST_8_1();
2290 uint16_t slot = READ_INST_8_2();
2291 uint16_t v0 = READ_INST_8_3();
2292 LOG_INST() << "intrinsics::stlexvardyn"
2293 << " level:" << level << " slot:" << slot << " v" << v0;
2294
2295 JSTaggedValue value = GET_VREG_VALUE(v0);
2296 InterpretedFrame *state = GET_FRAME(sp);
2297 JSTaggedValue env = state->env;
2298 for (int i = 0; i < level; i++) {
2299 JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
2300 ASSERT(!taggedParentEnv.IsUndefined());
2301 env = taggedParentEnv;
2302 }
2303 LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(thread, slot, value);
2304
2305 DISPATCH(BytecodeInstruction::Format::PREF_IMM8_IMM8_V8);
2306 }
2307 HANDLE_OPCODE(HANDLE_STLEXVARDYN_PREF_IMM4_IMM4_V8) {
2308 uint16_t level = READ_INST_4_2();
2309 uint16_t slot = READ_INST_4_3();
2310 uint16_t v0 = READ_INST_8_2();
2311 LOG_INST() << "intrinsics::stlexvardyn"
2312 << " level:" << level << " slot:" << slot << " v" << v0;
2313
2314 JSTaggedValue value = GET_VREG_VALUE(v0);
2315 InterpretedFrame *state = GET_FRAME(sp);
2316 JSTaggedValue env = state->env;
2317 for (int i = 0; i < level; i++) {
2318 JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
2319 ASSERT(!taggedParentEnv.IsUndefined());
2320 env = taggedParentEnv;
2321 }
2322 LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(thread, slot, value);
2323
2324 DISPATCH(BytecodeInstruction::Format::PREF_IMM4_IMM4_V8);
2325 }
2326 HANDLE_OPCODE(HANDLE_NEWLEXENVDYN_PREF_IMM16) {
2327 uint16_t numVars = READ_INST_16_1();
2328 LOG_INST() << "intrinsics::newlexenvdyn"
2329 << " imm " << numVars;
2330
2331 JSTaggedValue res = FastRuntimeStub::NewLexicalEnvDyn(thread, factory, numVars);
2332 if (res.IsHole()) {
2333 SAVE_PC();
2334 res = SlowRuntimeStub::NewLexicalEnvDyn(thread, numVars);
2335 INTERPRETER_RETURN_IF_ABRUPT(res);
2336 }
2337 SET_ACC(res);
2338 GET_FRAME(sp)->env = res;
2339 DISPATCH(BytecodeInstruction::Format::PREF_IMM16);
2340 }
2341 HANDLE_OPCODE(HANDLE_POPLEXENVDYN_PREF) {
2342 InterpretedFrame *state = GET_FRAME(sp);
2343 JSTaggedValue currentLexenv = state->env;
2344 JSTaggedValue parentLexenv = LexicalEnv::Cast(currentLexenv.GetTaggedObject())->GetParentEnv();
2345 GET_FRAME(sp)->env = parentLexenv;
2346 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
2347 }
2348 HANDLE_OPCODE(HANDLE_CREATEITERRESULTOBJ_PREF_V8_V8) {
2349 uint16_t v0 = READ_INST_8_1();
2350 uint16_t v1 = READ_INST_8_2();
2351 LOG_INST() << "intrinsics::createiterresultobj"
2352 << " v" << v0 << " v" << v1;
2353 JSTaggedValue value = GET_VREG_VALUE(v0);
2354 JSTaggedValue flag = GET_VREG_VALUE(v1);
2355 SAVE_PC();
2356 JSTaggedValue res = SlowRuntimeStub::CreateIterResultObj(thread, value, flag);
2357 INTERPRETER_RETURN_IF_ABRUPT(res);
2358 SET_ACC(res);
2359 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2360 }
2361 HANDLE_OPCODE(HANDLE_SUSPENDGENERATOR_PREF_V8_V8) {
2362 uint16_t v0 = READ_INST_8_1();
2363 uint16_t v1 = READ_INST_8_2();
2364 LOG_INST() << "intrinsics::suspendgenerator"
2365 << " v" << v0 << " v" << v1;
2366 JSTaggedValue genObj = GET_VREG_VALUE(v0);
2367 JSTaggedValue value = GET_VREG_VALUE(v1);
2368 // suspend will record bytecode offset
2369 SAVE_PC();
2370 SAVE_ACC();
2371 JSTaggedValue res = SlowRuntimeStub::SuspendGenerator(thread, genObj, value);
2372 INTERPRETER_RETURN_IF_ABRUPT(res);
2373 SET_ACC(res);
2374
2375 InterpretedFrame *state = GET_FRAME(sp);
2376 JSMethod *method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod();
2377 [[maybe_unused]] auto fistPC = method->GetInstructions();
2378 UPDATE_HOTNESS_COUNTER(-(pc - fistPC));
2379 LOG(DEBUG, INTERPRETER) << "Exit: SuspendGenerator " << std::hex << reinterpret_cast<uintptr_t>(sp) << " "
2380 << std::hex << reinterpret_cast<uintptr_t>(state->pc);
2381 sp = state->base.prev;
2382 ASSERT(sp != nullptr);
2383 InterpretedFrame *prevState = GET_FRAME(sp);
2384 pc = prevState->pc;
2385
2386 // break frame
2387 if (pc == nullptr) {
2388 state->acc = acc;
2389 return;
2390 }
2391 thread->SetCurrentSPFrame(sp);
2392 constpool = ConstantPool::Cast(prevState->constpool.GetTaggedObject());
2393
2394 INTERPRETER_HANDLE_RETURN();
2395 }
2396 HANDLE_OPCODE(HANDLE_ASYNCFUNCTIONAWAITUNCAUGHT_PREF_V8_V8) {
2397 uint16_t v0 = READ_INST_8_1();
2398 uint16_t v1 = READ_INST_8_2();
2399 LOG_INST() << "intrinsics::asyncfunctionawaituncaught"
2400 << " v" << v0 << " v" << v1;
2401 JSTaggedValue asyncFuncObj = GET_VREG_VALUE(v0);
2402 JSTaggedValue value = GET_VREG_VALUE(v1);
2403 SAVE_PC();
2404 JSTaggedValue res = SlowRuntimeStub::AsyncFunctionAwaitUncaught(thread, asyncFuncObj, value);
2405 INTERPRETER_RETURN_IF_ABRUPT(res);
2406 SET_ACC(res);
2407 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2408 }
2409 HANDLE_OPCODE(HANDLE_ASYNCFUNCTIONRESOLVE_PREF_V8_V8_V8) {
2410 uint16_t v0 = READ_INST_8_1();
2411 [[maybe_unused]] uint16_t v1 = READ_INST_8_2();
2412 uint16_t v2 = READ_INST_8_3();
2413 LOG_INST() << "intrinsics::asyncfunctionresolve"
2414 << " v" << v0 << " v" << v1 << " v" << v2;
2415
2416 JSTaggedValue asyncFuncObj = GET_VREG_VALUE(v0);
2417 JSTaggedValue value = GET_VREG_VALUE(v2);
2418 SAVE_PC();
2419 JSTaggedValue res = SlowRuntimeStub::AsyncFunctionResolveOrReject(thread, asyncFuncObj, value, true);
2420 INTERPRETER_RETURN_IF_ABRUPT(res);
2421 SET_ACC(res);
2422 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8_V8);
2423 }
2424 HANDLE_OPCODE(HANDLE_ASYNCFUNCTIONREJECT_PREF_V8_V8_V8) {
2425 uint16_t v0 = READ_INST_8_1();
2426 [[maybe_unused]] uint16_t v1 = READ_INST_8_2();
2427 uint16_t v2 = READ_INST_8_3();
2428 LOG_INST() << "intrinsics::asyncfunctionreject"
2429 << " v" << v0 << " v" << v1 << " v" << v2;
2430
2431 JSTaggedValue asyncFuncObj = GET_VREG_VALUE(v0);
2432 JSTaggedValue value = GET_VREG_VALUE(v2);
2433 SAVE_ACC();
2434 SAVE_PC();
2435 JSTaggedValue res = SlowRuntimeStub::AsyncFunctionResolveOrReject(thread, asyncFuncObj, value, false);
2436 INTERPRETER_RETURN_IF_ABRUPT(res);
2437 RESTORE_ACC();
2438 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8_V8);
2439 }
2440 HANDLE_OPCODE(HANDLE_NEWOBJSPREADDYN_PREF_V8_V8) {
2441 uint16_t v0 = READ_INST_8_1();
2442 uint16_t v1 = READ_INST_8_2();
2443 LOG_INST() << "intrinsic::newobjspearddyn"
2444 << " v" << v0 << " v" << v1;
2445 JSTaggedValue func = GET_VREG_VALUE(v0);
2446 JSTaggedValue newTarget = GET_VREG_VALUE(v1);
2447 JSTaggedValue array = GET_ACC();
2448 SAVE_PC();
2449 JSTaggedValue res = SlowRuntimeStub::NewObjSpreadDyn(thread, func, newTarget, array);
2450 INTERPRETER_RETURN_IF_ABRUPT(res);
2451 SET_ACC(res);
2452 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2453 }
2454 HANDLE_OPCODE(HANDLE_THROWUNDEFINEDIFHOLE_PREF_V8_V8) {
2455 uint16_t v0 = READ_INST_8_1();
2456 uint16_t v1 = READ_INST_8_2();
2457 LOG_INST() << "intrinsic::throwundefinedifhole"
2458 << " v" << v0 << " v" << v1;
2459 JSTaggedValue hole = GET_VREG_VALUE(v0);
2460 if (!hole.IsHole()) {
2461 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2462 }
2463 JSTaggedValue obj = GET_VREG_VALUE(v1);
2464 ASSERT(obj.IsString());
2465 SAVE_PC();
2466 SlowRuntimeStub::ThrowUndefinedIfHole(thread, obj);
2467 INTERPRETER_GOTO_EXCEPTION_HANDLER();
2468 }
2469 HANDLE_OPCODE(HANDLE_STOWNBYNAME_PREF_ID32_V8) {
2470 uint32_t stringId = READ_INST_32_1();
2471 uint32_t v0 = READ_INST_8_5();
2472 LOG_INST() << "intrinsics::stownbyname "
2473 << "v" << v0 << " stringId:" << stringId;
2474
2475 JSTaggedValue receiver = GET_VREG_VALUE(v0);
2476 if (receiver.IsJSObject() && !receiver.IsClassConstructor() && !receiver.IsClassPrototype()) {
2477 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
2478 JSTaggedValue value = GET_ACC();
2479 // fast path
2480 SAVE_ACC();
2481 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
2482 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByNameWithOwn));
2483 typedef JSTaggedType (*PFSetPropertyByName)(uintptr_t, JSTaggedType, JSTaggedType, JSTaggedType);
2484 auto setPropertyByNamePtr = reinterpret_cast<PFSetPropertyByName>(stubAddr);
2485 JSTaggedValue res = JSTaggedValue(setPropertyByNamePtr(thread->GetGlueAddr(),
2486 receiver.GetRawData(), propKey.GetRawData(), value.GetRawData()));
2487 #else
2488 JSTaggedValue res = FastRuntimeStub::SetPropertyByName<true>(thread, receiver, propKey, value);
2489 #endif
2490 if (!res.IsHole()) {
2491 INTERPRETER_RETURN_IF_ABRUPT(res);
2492 RESTORE_ACC();
2493 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
2494 }
2495 RESTORE_ACC();
2496 }
2497
2498 SAVE_ACC();
2499 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
2500 auto propKey = constpool->GetObjectFromCache(stringId); // Maybe moved by GC
2501 auto value = GET_ACC(); // Maybe moved by GC
2502 SAVE_PC();
2503 JSTaggedValue res = SlowRuntimeStub::StOwnByName(thread, receiver, propKey, value);
2504 RESTORE_ACC();
2505 INTERPRETER_RETURN_IF_ABRUPT(res);
2506 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
2507 }
2508 HANDLE_OPCODE(HANDLE_CREATEEMPTYARRAY_PREF) {
2509 LOG_INST() << "intrinsics::createemptyarray";
2510 SAVE_PC();
2511 JSTaggedValue res = SlowRuntimeStub::CreateEmptyArray(thread, factory, globalEnv);
2512 SET_ACC(res);
2513 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
2514 }
2515 HANDLE_OPCODE(HANDLE_CREATEEMPTYOBJECT_PREF) {
2516 LOG_INST() << "intrinsics::createemptyobject";
2517 SAVE_PC();
2518 JSTaggedValue res = SlowRuntimeStub::CreateEmptyObject(thread, factory, globalEnv);
2519 SET_ACC(res);
2520 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
2521 }
2522 HANDLE_OPCODE(HANDLE_CREATEOBJECTWITHBUFFER_PREF_IMM16) {
2523 uint16_t imm = READ_INST_16_1();
2524 LOG_INST() << "intrinsics::createobjectwithbuffer"
2525 << " imm:" << imm;
2526 JSObject *result = JSObject::Cast(constpool->GetObjectFromCache(imm).GetTaggedObject());
2527
2528 SAVE_PC();
2529 JSTaggedValue res = SlowRuntimeStub::CreateObjectWithBuffer(thread, factory, result);
2530 INTERPRETER_RETURN_IF_ABRUPT(res);
2531 SET_ACC(res);
2532 DISPATCH(BytecodeInstruction::Format::PREF_IMM16);
2533 }
2534 HANDLE_OPCODE(HANDLE_SETOBJECTWITHPROTO_PREF_V8_V8) {
2535 uint16_t v0 = READ_INST_8_1();
2536 uint16_t v1 = READ_INST_8_2();
2537 LOG_INST() << "intrinsics::setobjectwithproto"
2538 << " v" << v0 << " v" << v1;
2539 JSTaggedValue proto = GET_VREG_VALUE(v0);
2540 JSTaggedValue obj = GET_VREG_VALUE(v1);
2541 SAVE_ACC();
2542 SAVE_PC();
2543 JSTaggedValue res = SlowRuntimeStub::SetObjectWithProto(thread, proto, obj);
2544 INTERPRETER_RETURN_IF_ABRUPT(res);
2545 RESTORE_ACC();
2546 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2547 }
2548 HANDLE_OPCODE(HANDLE_CREATEARRAYWITHBUFFER_PREF_IMM16) {
2549 uint16_t imm = READ_INST_16_1();
2550 LOG_INST() << "intrinsics::createarraywithbuffer"
2551 << " imm:" << imm;
2552 JSArray *result = JSArray::Cast(constpool->GetObjectFromCache(imm).GetTaggedObject());
2553 SAVE_PC();
2554 JSTaggedValue res = SlowRuntimeStub::CreateArrayWithBuffer(thread, factory, result);
2555 INTERPRETER_RETURN_IF_ABRUPT(res);
2556 SET_ACC(res);
2557 DISPATCH(BytecodeInstruction::Format::PREF_IMM16);
2558 }
2559 HANDLE_OPCODE(HANDLE_IMPORTMODULE_PREF_ID32) {
2560 uint32_t stringId = READ_INST_32_1();
2561 auto prop = constpool->GetObjectFromCache(stringId);
2562
2563 LOG_INST() << "intrinsics::importmodule "
2564 << "stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(prop.GetTaggedObject()));
2565
2566 JSTaggedValue moduleRef = SlowRuntimeStub::ImportModule(thread, prop);
2567 SET_ACC(moduleRef);
2568 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
2569 }
2570 HANDLE_OPCODE(HANDLE_STMODULEVAR_PREF_ID32) {
2571 uint32_t stringId = READ_INST_32_1();
2572 auto prop = constpool->GetObjectFromCache(stringId);
2573
2574 LOG_INST() << "intrinsics::stmodulevar "
2575 << "stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(prop.GetTaggedObject()));
2576
2577 JSTaggedValue value = GET_ACC();
2578
2579 SAVE_ACC();
2580 SlowRuntimeStub::StModuleVar(thread, prop, value);
2581 RESTORE_ACC();
2582 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
2583 }
2584 HANDLE_OPCODE(HANDLE_COPYMODULE_PREF_V8) {
2585 uint16_t v0 = READ_INST_8_1();
2586 JSTaggedValue srcModule = GET_VREG_VALUE(v0);
2587
2588 LOG_INST() << "intrinsics::copymodule ";
2589
2590 SAVE_ACC();
2591 SlowRuntimeStub::CopyModule(thread, srcModule);
2592 RESTORE_ACC();
2593 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2594 }
2595 HANDLE_OPCODE(HANDLE_LDMODVARBYNAME_PREF_ID32_V8) {
2596 uint32_t stringId = READ_INST_32_1();
2597 uint32_t v0 = READ_INST_8_5();
2598
2599 JSTaggedValue itemName = constpool->GetObjectFromCache(stringId);
2600 JSTaggedValue moduleObj = GET_VREG_VALUE(v0);
2601 LOG_INST() << "intrinsics::ldmodvarbyname "
2602 << "string_id:" << stringId << ", "
2603 << "itemName: " << ConvertToString(EcmaString::Cast(itemName.GetTaggedObject()));
2604
2605 JSTaggedValue moduleVar = SlowRuntimeStub::LdModvarByName(thread, moduleObj, itemName);
2606 SET_ACC(moduleVar);
2607 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
2608 }
2609 HANDLE_OPCODE(HANDLE_CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8) {
2610 uint32_t stringId = READ_INST_32_1();
2611 JSTaggedValue pattern = constpool->GetObjectFromCache(stringId);
2612 uint8_t flags = READ_INST_8_5();
2613 LOG_INST() << "intrinsics::createregexpwithliteral "
2614 << "stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(pattern.GetTaggedObject()))
2615 << ", flags:" << flags;
2616 SAVE_PC();
2617 JSTaggedValue res = SlowRuntimeStub::CreateRegExpWithLiteral(thread, pattern, flags);
2618 INTERPRETER_RETURN_IF_ABRUPT(res);
2619 SET_ACC(res);
2620 DISPATCH(BytecodeInstruction::Format::PREF_ID32_IMM8);
2621 }
2622 HANDLE_OPCODE(HANDLE_GETTEMPLATEOBJECT_PREF_V8) {
2623 uint16_t v0 = READ_INST_8_1();
2624 LOG_INST() << "intrinsic::gettemplateobject"
2625 << " v" << v0;
2626
2627 JSTaggedValue literal = GET_VREG_VALUE(v0);
2628 SAVE_PC();
2629 JSTaggedValue res = SlowRuntimeStub::GetTemplateObject(thread, literal);
2630 INTERPRETER_RETURN_IF_ABRUPT(res);
2631 SET_ACC(res);
2632 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2633 }
2634 HANDLE_OPCODE(HANDLE_GETNEXTPROPNAME_PREF_V8) {
2635 uint16_t v0 = READ_INST_8_1();
2636 LOG_INST() << "intrinsic::getnextpropname"
2637 << " v" << v0;
2638 JSTaggedValue iter = GET_VREG_VALUE(v0);
2639 SAVE_PC();
2640 JSTaggedValue res = SlowRuntimeStub::GetNextPropName(thread, iter);
2641 INTERPRETER_RETURN_IF_ABRUPT(res);
2642 SET_ACC(res);
2643 DISPATCH(BytecodeInstruction::Format::PREF_V8);
2644 }
2645 HANDLE_OPCODE(HANDLE_COPYDATAPROPERTIES_PREF_V8_V8) {
2646 uint16_t v0 = READ_INST_8_1();
2647 uint16_t v1 = READ_INST_8_2();
2648 LOG_INST() << "intrinsic::copydataproperties"
2649 << " v" << v0 << " v" << v1;
2650 JSTaggedValue dst = GET_VREG_VALUE(v0);
2651 JSTaggedValue src = GET_VREG_VALUE(v1);
2652 SAVE_PC();
2653 JSTaggedValue res = SlowRuntimeStub::CopyDataProperties(thread, dst, src);
2654 INTERPRETER_RETURN_IF_ABRUPT(res);
2655 SET_ACC(res);
2656 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2657 }
2658 HANDLE_OPCODE(HANDLE_STOWNBYINDEX_PREF_V8_IMM32) {
2659 uint32_t v0 = READ_INST_8_1();
2660 uint32_t index = READ_INST_32_2();
2661 LOG_INST() << "intrinsics::stownbyindex"
2662 << " v" << v0 << " imm" << index;
2663 JSTaggedValue receiver = GET_VREG_VALUE(v0);
2664 // fast path
2665 if (receiver.IsHeapObject() && !receiver.IsClassConstructor() && !receiver.IsClassPrototype()) {
2666 SAVE_ACC();
2667 JSTaggedValue value = GET_ACC();
2668 // fast path
2669 JSTaggedValue res =
2670 FastRuntimeStub::SetPropertyByIndex<true>(thread, receiver, index, value);
2671 if (!res.IsHole()) {
2672 INTERPRETER_RETURN_IF_ABRUPT(res);
2673 RESTORE_ACC();
2674 DISPATCH(BytecodeInstruction::Format::PREF_V8_IMM32);
2675 }
2676 RESTORE_ACC();
2677 }
2678 SAVE_ACC();
2679 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
2680 auto value = GET_ACC(); // Maybe moved by GC
2681 SAVE_PC();
2682 JSTaggedValue res = SlowRuntimeStub::StOwnByIndex(thread, receiver, index, value);
2683 INTERPRETER_RETURN_IF_ABRUPT(res);
2684 RESTORE_ACC();
2685 DISPATCH(BytecodeInstruction::Format::PREF_V8_IMM32);
2686 }
2687 HANDLE_OPCODE(HANDLE_STOWNBYVALUE_PREF_V8_V8) {
2688 uint32_t v0 = READ_INST_8_1();
2689 uint32_t v1 = READ_INST_8_2();
2690 LOG_INST() << "intrinsics::stownbyvalue"
2691 << " v" << v0 << " v" << v1;
2692
2693 JSTaggedValue receiver = GET_VREG_VALUE(v0);
2694 if (receiver.IsHeapObject() && !receiver.IsClassConstructor() && !receiver.IsClassPrototype()) {
2695 SAVE_ACC();
2696 JSTaggedValue propKey = GET_VREG_VALUE(v1);
2697 JSTaggedValue value = GET_ACC();
2698 // fast path
2699 JSTaggedValue res = FastRuntimeStub::SetPropertyByValue<true>(thread, receiver, propKey, value);
2700
2701 // SetPropertyByValue maybe gc need update the value
2702 RESTORE_ACC();
2703 propKey = GET_VREG_VALUE(v1);
2704 value = GET_ACC();
2705 if (!res.IsHole()) {
2706 INTERPRETER_RETURN_IF_ABRUPT(res);
2707 RESTORE_ACC();
2708 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2709 }
2710 }
2711
2712 // slow path
2713 SAVE_ACC();
2714 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
2715 auto propKey = GET_VREG_VALUE(v1); // Maybe moved by GC
2716 auto value = GET_ACC(); // Maybe moved by GC
2717 SAVE_PC();
2718 JSTaggedValue res = SlowRuntimeStub::StOwnByValue(thread, receiver, propKey, value);
2719 RESTORE_ACC();
2720 INTERPRETER_RETURN_IF_ABRUPT(res);
2721 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2722 }
2723 HANDLE_OPCODE(HANDLE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8) {
2724 uint16_t numKeys = READ_INST_16_1();
2725 uint16_t v0 = READ_INST_8_3();
2726 uint16_t firstArgRegIdx = READ_INST_8_4();
2727 LOG_INST() << "intrinsics::createobjectwithexcludedkeys " << numKeys << " v" << firstArgRegIdx;
2728
2729 JSTaggedValue obj = GET_VREG_VALUE(v0);
2730
2731 SAVE_PC();
2732 JSTaggedValue res = SlowRuntimeStub::CreateObjectWithExcludedKeys(thread, numKeys, obj, firstArgRegIdx);
2733 INTERPRETER_RETURN_IF_ABRUPT(res);
2734 SET_ACC(res);
2735 DISPATCH(BytecodeInstruction::Format::PREF_IMM16_V8_V8);
2736 }
2737 HANDLE_OPCODE(HANDLE_DEFINEGENERATORFUNC_PREF_ID16_IMM16_V8) {
2738 uint16_t methodId = READ_INST_16_1();
2739 uint16_t length = READ_INST_16_3();
2740 uint16_t v0 = READ_INST_8_5();
2741 LOG_INST() << "define gengerator function length: " << length
2742 << " v" << v0;
2743 JSFunction *result = JSFunction::Cast(constpool->GetObjectFromCache(methodId).GetTaggedObject());
2744 ASSERT(result != nullptr);
2745 if (result->GetResolved()) {
2746 SAVE_PC();
2747 auto res = SlowRuntimeStub::DefineGeneratorFunc(thread, result);
2748 INTERPRETER_RETURN_IF_ABRUPT(res);
2749 result = JSFunction::Cast(res.GetTaggedObject());
2750 result->SetConstantPool(thread, JSTaggedValue(constpool));
2751 } else {
2752 result->SetResolved(true);
2753 }
2754
2755 result->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
2756 JSTaggedValue env = GET_VREG_VALUE(v0);
2757 result->SetLexicalEnv(thread, env);
2758 SET_ACC(JSTaggedValue(result))
2759 DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_V8);
2760 }
2761 HANDLE_OPCODE(HANDLE_DEFINEASYNCFUNC_PREF_ID16_IMM16_V8) {
2762 uint16_t methodId = READ_INST_16_1();
2763 uint16_t length = READ_INST_16_3();
2764 uint16_t v0 = READ_INST_8_5();
2765 LOG_INST() << "define async function length: " << length
2766 << " v" << v0;
2767 JSFunction *result = JSFunction::Cast(constpool->GetObjectFromCache(methodId).GetTaggedObject());
2768 ASSERT(result != nullptr);
2769 if (result->GetResolved()) {
2770 SAVE_PC();
2771 auto res = SlowRuntimeStub::DefineAsyncFunc(thread, result);
2772 INTERPRETER_RETURN_IF_ABRUPT(res);
2773 result = JSFunction::Cast(res.GetTaggedObject());
2774 result->SetConstantPool(thread, JSTaggedValue(constpool));
2775 } else {
2776 result->SetResolved(true);
2777 }
2778
2779 result->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
2780 JSTaggedValue env = GET_VREG_VALUE(v0);
2781 result->SetLexicalEnv(thread, env);
2782 SET_ACC(JSTaggedValue(result))
2783 DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_V8);
2784 }
2785 HANDLE_OPCODE(HANDLE_LDHOLE_PREF) {
2786 LOG_INST() << "intrinsic::ldhole";
2787 SET_ACC(JSTaggedValue::Hole());
2788 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
2789 }
2790 HANDLE_OPCODE(HANDLE_COPYRESTARGS_PREF_IMM16) {
2791 uint16_t restIdx = READ_INST_16_1();
2792 LOG_INST() << "intrinsics::copyrestargs"
2793 << " index: " << restIdx;
2794
2795 uint32_t startIdx = 0;
2796 uint32_t restNumArgs = GetNumArgs(sp, restIdx, startIdx);
2797
2798 SAVE_PC();
2799 JSTaggedValue res = SlowRuntimeStub::CopyRestArgs(thread, sp, restNumArgs, startIdx);
2800 INTERPRETER_RETURN_IF_ABRUPT(res);
2801 SET_ACC(res);
2802 DISPATCH(BytecodeInstruction::Format::PREF_IMM16);
2803 }
2804 HANDLE_OPCODE(HANDLE_DEFINEGETTERSETTERBYVALUE_PREF_V8_V8_V8_V8) {
2805 uint16_t v0 = READ_INST_8_1();
2806 uint16_t v1 = READ_INST_8_2();
2807 uint16_t v2 = READ_INST_8_3();
2808 uint16_t v3 = READ_INST_8_4();
2809 LOG_INST() << "intrinsics::definegettersetterbyvalue"
2810 << " v" << v0 << " v" << v1 << " v" << v2 << " v" << v3;
2811
2812 JSTaggedValue obj = GET_VREG_VALUE(v0);
2813 JSTaggedValue prop = GET_VREG_VALUE(v1);
2814 JSTaggedValue getter = GET_VREG_VALUE(v2);
2815 JSTaggedValue setter = GET_VREG_VALUE(v3);
2816 JSTaggedValue flag = GET_ACC();
2817 SAVE_PC();
2818 JSTaggedValue res =
2819 SlowRuntimeStub::DefineGetterSetterByValue(thread, obj, prop, getter, setter, flag.ToBoolean());
2820 INTERPRETER_RETURN_IF_ABRUPT(res);
2821 SET_ACC(res);
2822 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8_V8_V8);
2823 }
2824 HANDLE_OPCODE(HANDLE_LDOBJBYINDEX_PREF_V8_IMM32) {
2825 uint16_t v0 = READ_INST_8_1();
2826 uint32_t idx = READ_INST_32_2();
2827 LOG_INST() << "intrinsics::ldobjbyindex"
2828 << " v" << v0 << " imm" << idx;
2829
2830 JSTaggedValue receiver = GET_VREG_VALUE(v0);
2831 // fast path
2832 if (LIKELY(receiver.IsHeapObject())) {
2833 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
2834 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex));
2835 typedef JSTaggedType (*PFGetPropertyByIndex)(uintptr_t, JSTaggedType, uint32_t);
2836 auto getPropertyByIndex = reinterpret_cast<PFGetPropertyByIndex>(stubAddr);
2837 JSTaggedValue res = JSTaggedValue(getPropertyByIndex(thread->GetGlueAddr(), receiver.GetRawData(), idx));
2838 #else
2839 JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, receiver, idx);
2840 #endif
2841 if (!res.IsHole()) {
2842 INTERPRETER_RETURN_IF_ABRUPT(res);
2843 SET_ACC(res);
2844 DISPATCH(BytecodeInstruction::Format::PREF_V8_IMM32);
2845 }
2846 }
2847 // not meet fast condition or fast path return hole, walk slow path
2848 // slow stub not need receiver
2849 SAVE_PC();
2850 JSTaggedValue res = SlowRuntimeStub::LdObjByIndex(thread, receiver, idx, false, JSTaggedValue::Undefined());
2851 INTERPRETER_RETURN_IF_ABRUPT(res);
2852 SET_ACC(res);
2853 DISPATCH(BytecodeInstruction::Format::PREF_V8_IMM32);
2854 }
2855 HANDLE_OPCODE(HANDLE_STOBJBYINDEX_PREF_V8_IMM32) {
2856 uint16_t v0 = READ_INST_8_1();
2857 uint32_t index = READ_INST_32_2();
2858 LOG_INST() << "intrinsics::stobjbyindex"
2859 << " v" << v0 << " imm" << index;
2860
2861 JSTaggedValue receiver = GET_VREG_VALUE(v0);
2862 if (receiver.IsHeapObject()) {
2863 SAVE_ACC();
2864 JSTaggedValue value = GET_ACC();
2865 // fast path
2866 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
2867 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex));
2868 typedef JSTaggedType (*PFSetPropertyByIndex)(uintptr_t, JSTaggedType, uint32_t, JSTaggedType);
2869 auto setPropertyByIndex = reinterpret_cast<PFSetPropertyByIndex>(stubAddr);
2870 JSTaggedValue res = JSTaggedValue(setPropertyByIndex(thread->GetGlueAddr(),
2871 receiver.GetRawData(), index, value.GetRawData()));
2872 #else
2873 JSTaggedValue res = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value);
2874 #endif
2875 if (!res.IsHole()) {
2876 INTERPRETER_RETURN_IF_ABRUPT(res);
2877 RESTORE_ACC();
2878 DISPATCH(BytecodeInstruction::Format::PREF_V8_IMM32);
2879 }
2880 RESTORE_ACC();
2881 }
2882 // slow path
2883 SAVE_ACC();
2884 SAVE_PC();
2885 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
2886 JSTaggedValue value = GET_ACC(); // Maybe moved by GC
2887 JSTaggedValue res = SlowRuntimeStub::StObjByIndex(thread, receiver, index, value);
2888 INTERPRETER_RETURN_IF_ABRUPT(res);
2889 RESTORE_ACC();
2890 DISPATCH(BytecodeInstruction::Format::PREF_V8_IMM32);
2891 }
2892 HANDLE_OPCODE(HANDLE_LDOBJBYVALUE_PREF_V8_V8) {
2893 uint32_t v0 = READ_INST_8_1();
2894 uint32_t v1 = READ_INST_8_2();
2895 LOG_INST() << "intrinsics::Ldobjbyvalue"
2896 << " v" << v0 << " v" << v1;
2897
2898 JSTaggedValue receiver = GET_VREG_VALUE(v0);
2899 JSTaggedValue propKey = GET_VREG_VALUE(v1);
2900
2901 #if ECMASCRIPT_ENABLE_IC
2902 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
2903 if (!profileTypeInfo.IsUndefined()) {
2904 uint16_t slotId = READ_INST_8_0();
2905 auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
2906 JSTaggedValue firstValue = profileTypeArray->Get(slotId);
2907 JSTaggedValue res = JSTaggedValue::Hole();
2908
2909 if (LIKELY(firstValue.IsHeapObject())) {
2910 JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1);
2911 res = ICRuntimeStub::TryLoadICByValue(thread, receiver, propKey, firstValue, secondValue);
2912 }
2913 // IC miss and not enter the megamorphic state, store as polymorphic
2914 if (res.IsHole() && !firstValue.IsHole()) {
2915 res = ICRuntimeStub::LoadICByValue(thread,
2916 profileTypeArray,
2917 receiver, propKey, slotId);
2918 }
2919
2920 if (LIKELY(!res.IsHole())) {
2921 INTERPRETER_RETURN_IF_ABRUPT(res);
2922 SET_ACC(res);
2923 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2924 }
2925 }
2926 #endif
2927 // fast path
2928 if (LIKELY(receiver.IsHeapObject())) {
2929 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
2930 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByValue));
2931 typedef JSTaggedType (*PFGetPropertyByValue)(uintptr_t, JSTaggedType, JSTaggedType);
2932 auto getPropertyByValuePtr = reinterpret_cast<PFGetPropertyByValue>(stubAddr);
2933 JSTaggedValue res = JSTaggedValue(getPropertyByValuePtr(thread->GetGlueAddr(),
2934 receiver.GetRawData(), propKey.GetRawData()));
2935 #else
2936 JSTaggedValue res = FastRuntimeStub::GetPropertyByValue(thread, receiver, propKey);
2937 #endif
2938 if (!res.IsHole()) {
2939 ASSERT(!res.IsAccessor());
2940 INTERPRETER_RETURN_IF_ABRUPT(res);
2941 SET_ACC(res);
2942 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2943 }
2944 }
2945 // slow path
2946 SAVE_PC();
2947 JSTaggedValue res = SlowRuntimeStub::LdObjByValue(thread, receiver, propKey, false, JSTaggedValue::Undefined());
2948 INTERPRETER_RETURN_IF_ABRUPT(res);
2949 SET_ACC(res);
2950 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2951 }
2952 HANDLE_OPCODE(HANDLE_STOBJBYVALUE_PREF_V8_V8) {
2953 uint32_t v0 = READ_INST_8_1();
2954 uint32_t v1 = READ_INST_8_2();
2955
2956 LOG_INST() << "intrinsics::stobjbyvalue"
2957 << " v" << v0 << " v" << v1;
2958
2959 JSTaggedValue receiver = GET_VREG_VALUE(v0);
2960 #if ECMASCRIPT_ENABLE_IC
2961 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
2962 if (!profileTypeInfo.IsUndefined()) {
2963 uint16_t slotId = READ_INST_8_0();
2964 auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
2965 JSTaggedValue firstValue = profileTypeArray->Get(slotId);
2966 JSTaggedValue propKey = GET_VREG_VALUE(v1);
2967 JSTaggedValue value = GET_ACC();
2968 JSTaggedValue res = JSTaggedValue::Hole();
2969 SAVE_ACC();
2970
2971 if (LIKELY(firstValue.IsHeapObject())) {
2972 JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1);
2973 res = ICRuntimeStub::TryStoreICByValue(thread, receiver, propKey, firstValue, secondValue, value);
2974 }
2975 // IC miss and not enter the megamorphic state, store as polymorphic
2976 if (res.IsHole() && !firstValue.IsHole()) {
2977 res = ICRuntimeStub::StoreICByValue(thread,
2978 profileTypeArray,
2979 receiver, propKey, value, slotId);
2980 }
2981
2982 if (LIKELY(!res.IsHole())) {
2983 INTERPRETER_RETURN_IF_ABRUPT(res);
2984 RESTORE_ACC();
2985 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2986 }
2987 }
2988 #endif
2989 if (receiver.IsHeapObject()) {
2990 SAVE_ACC();
2991 JSTaggedValue propKey = GET_VREG_VALUE(v1);
2992 JSTaggedValue value = GET_ACC();
2993 // fast path
2994 JSTaggedValue res = FastRuntimeStub::SetPropertyByValue(thread, receiver, propKey, value);
2995 if (!res.IsHole()) {
2996 INTERPRETER_RETURN_IF_ABRUPT(res);
2997 RESTORE_ACC();
2998 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
2999 }
3000 RESTORE_ACC();
3001 }
3002 {
3003 // slow path
3004 SAVE_ACC();
3005 SAVE_PC();
3006 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
3007 JSTaggedValue propKey = GET_VREG_VALUE(v1); // Maybe moved by GC
3008 JSTaggedValue value = GET_ACC(); // Maybe moved by GC
3009 JSTaggedValue res = SlowRuntimeStub::StObjByValue(thread, receiver, propKey, value);
3010 INTERPRETER_RETURN_IF_ABRUPT(res);
3011 RESTORE_ACC();
3012 }
3013 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
3014 }
3015 HANDLE_OPCODE(HANDLE_LDSUPERBYVALUE_PREF_V8_V8) {
3016 uint32_t v0 = READ_INST_8_1();
3017 uint32_t v1 = READ_INST_8_2();
3018 LOG_INST() << "intrinsics::Ldsuperbyvalue"
3019 << " v" << v0 << " v" << v1;
3020
3021 JSTaggedValue receiver = GET_VREG_VALUE(v0);
3022 JSTaggedValue propKey = GET_VREG_VALUE(v1);
3023
3024 // slow path
3025 SAVE_PC();
3026 JSTaggedValue thisFunc = GetThisFunction(sp);
3027 JSTaggedValue res = SlowRuntimeStub::LdSuperByValue(thread, receiver, propKey, thisFunc);
3028 INTERPRETER_RETURN_IF_ABRUPT(res);
3029 SET_ACC(res);
3030 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
3031 }
3032 HANDLE_OPCODE(HANDLE_STSUPERBYVALUE_PREF_V8_V8) {
3033 uint32_t v0 = READ_INST_8_1();
3034 uint32_t v1 = READ_INST_8_2();
3035
3036 LOG_INST() << "intrinsics::stsuperbyvalue"
3037 << " v" << v0 << " v" << v1;
3038 JSTaggedValue receiver = GET_VREG_VALUE(v0);
3039 JSTaggedValue propKey = GET_VREG_VALUE(v1);
3040 JSTaggedValue value = GET_ACC();
3041
3042 // slow path
3043 SAVE_ACC();
3044 SAVE_PC();
3045 JSTaggedValue thisFunc = GetThisFunction(sp);
3046 JSTaggedValue res = SlowRuntimeStub::StSuperByValue(thread, receiver, propKey, value, thisFunc);
3047 INTERPRETER_RETURN_IF_ABRUPT(res);
3048 RESTORE_ACC();
3049 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
3050 }
3051 HANDLE_OPCODE(HANDLE_TRYLDGLOBALBYNAME_PREF_ID32) {
3052 uint32_t stringId = READ_INST_32_1();
3053 auto prop = constpool->GetObjectFromCache(stringId);
3054
3055 LOG_INST() << "intrinsics::tryldglobalbyname "
3056 << "stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(prop.GetTaggedObject()));
3057
3058 #if ECMASCRIPT_ENABLE_IC
3059 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
3060 if (!profileTypeInfo.IsUndefined()) {
3061 uint16_t slotId = READ_INST_8_0();
3062 JSTaggedValue res = ICRuntimeStub::LoadGlobalICByName(thread,
3063 ProfileTypeInfo::Cast(
3064 profileTypeInfo.GetTaggedObject()),
3065 globalObj, prop, slotId);
3066 INTERPRETER_RETURN_IF_ABRUPT(res);
3067 SET_ACC(res);
3068 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3069 }
3070 #endif
3071
3072 // order: 1. global record 2. global object
3073 JSTaggedValue result = SlowRuntimeStub::LdGlobalRecord(thread, prop);
3074 if (!result.IsUndefined()) {
3075 SET_ACC(PropertyBox::Cast(result.GetTaggedObject())->GetValue());
3076 } else {
3077 JSTaggedValue globalResult = FastRuntimeStub::GetGlobalOwnProperty(thread, globalObj, prop);
3078 if (!globalResult.IsHole()) {
3079 SET_ACC(globalResult);
3080 } else {
3081 // slow path
3082 SAVE_PC();
3083 JSTaggedValue res = SlowRuntimeStub::TryLdGlobalByName(thread, globalObj, prop);
3084 INTERPRETER_RETURN_IF_ABRUPT(res);
3085 SET_ACC(res);
3086 }
3087 }
3088
3089 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3090 }
3091 HANDLE_OPCODE(HANDLE_TRYSTGLOBALBYNAME_PREF_ID32) {
3092 uint32_t stringId = READ_INST_32_1();
3093 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3094 LOG_INST() << "intrinsics::trystglobalbyname"
3095 << " stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject()));
3096
3097 #if ECMASCRIPT_ENABLE_IC
3098 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
3099 if (!profileTypeInfo.IsUndefined()) {
3100 uint16_t slotId = READ_INST_8_0();
3101 JSTaggedValue value = GET_ACC();
3102 SAVE_ACC();
3103 JSTaggedValue res = ICRuntimeStub::StoreGlobalICByName(thread,
3104 ProfileTypeInfo::Cast(
3105 profileTypeInfo.GetTaggedObject()),
3106 globalObj, propKey, value, slotId);
3107 INTERPRETER_RETURN_IF_ABRUPT(res);
3108 RESTORE_ACC();
3109 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3110 }
3111 #endif
3112
3113 auto recordResult = SlowRuntimeStub::LdGlobalRecord(thread, propKey);
3114 SAVE_PC();
3115 // 1. find from global record
3116 if (!recordResult.IsUndefined()) {
3117 JSTaggedValue value = GET_ACC();
3118 SAVE_ACC();
3119 JSTaggedValue res = SlowRuntimeStub::TryUpdateGlobalRecord(thread, propKey, value);
3120 INTERPRETER_RETURN_IF_ABRUPT(res);
3121 RESTORE_ACC();
3122 } else {
3123 // 2. find from global object
3124 auto globalResult = FastRuntimeStub::GetGlobalOwnProperty(thread, globalObj, propKey);
3125 if (globalResult.IsHole()) {
3126 auto result = SlowRuntimeStub::ThrowReferenceError(thread, propKey, " is not defined");
3127 INTERPRETER_RETURN_IF_ABRUPT(result);
3128 }
3129 JSTaggedValue value = GET_ACC();
3130 SAVE_ACC();
3131 JSTaggedValue res = SlowRuntimeStub::StGlobalVar(thread, propKey, value);
3132 INTERPRETER_RETURN_IF_ABRUPT(res);
3133 RESTORE_ACC();
3134 }
3135 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3136 }
3137
3138 HANDLE_OPCODE(HANDLE_STCONSTTOGLOBALRECORD_PREF_ID32) {
3139 uint32_t stringId = READ_INST_32_1();
3140 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3141 LOG_INST() << "intrinsics::stconsttoglobalrecord"
3142 << " stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject()));
3143
3144 JSTaggedValue value = GET_ACC();
3145 SAVE_ACC();
3146 SAVE_PC();
3147 JSTaggedValue res = SlowRuntimeStub::StGlobalRecord(thread, propKey, value, true);
3148 INTERPRETER_RETURN_IF_ABRUPT(res);
3149 RESTORE_ACC();
3150 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3151 }
3152
3153 HANDLE_OPCODE(HANDLE_STLETTOGLOBALRECORD_PREF_ID32) {
3154 uint32_t stringId = READ_INST_32_1();
3155 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3156 LOG_INST() << "intrinsics::stlettoglobalrecord"
3157 << " stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject()));
3158
3159 JSTaggedValue value = GET_ACC();
3160 SAVE_ACC();
3161 SAVE_PC();
3162 JSTaggedValue res = SlowRuntimeStub::StGlobalRecord(thread, propKey, value, false);
3163 INTERPRETER_RETURN_IF_ABRUPT(res);
3164 RESTORE_ACC();
3165 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3166 }
3167
3168 HANDLE_OPCODE(HANDLE_STCLASSTOGLOBALRECORD_PREF_ID32) {
3169 uint32_t stringId = READ_INST_32_1();
3170 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3171 LOG_INST() << "intrinsics::stclasstoglobalrecord"
3172 << " stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject()));
3173
3174 JSTaggedValue value = GET_ACC();
3175 SAVE_ACC();
3176 SAVE_PC();
3177 JSTaggedValue res = SlowRuntimeStub::StGlobalRecord(thread, propKey, value, false);
3178 INTERPRETER_RETURN_IF_ABRUPT(res);
3179 RESTORE_ACC();
3180 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3181 }
3182
3183 HANDLE_OPCODE(HANDLE_STOWNBYVALUEWITHNAMESET_PREF_V8_V8) {
3184 uint32_t v0 = READ_INST_8_1();
3185 uint32_t v1 = READ_INST_8_2();
3186 LOG_INST() << "intrinsics::stownbyvaluewithnameset"
3187 << " v" << v0 << " v" << v1;
3188 JSTaggedValue receiver = GET_VREG_VALUE(v0);
3189 if (receiver.IsHeapObject() && !receiver.IsClassConstructor() && !receiver.IsClassPrototype()) {
3190 SAVE_ACC();
3191 JSTaggedValue propKey = GET_VREG_VALUE(v1);
3192 JSTaggedValue value = GET_ACC();
3193 // fast path
3194 JSTaggedValue res = FastRuntimeStub::SetPropertyByValue<true>(thread, receiver, propKey, value);
3195
3196 // SetPropertyByValue maybe gc need update the value
3197 RESTORE_ACC();
3198 propKey = GET_VREG_VALUE(v1);
3199 value = GET_ACC();
3200 if (!res.IsHole()) {
3201 INTERPRETER_RETURN_IF_ABRUPT(res);
3202 JSFunction::SetFunctionNameNoPrefix(thread, JSFunction::Cast(value.GetTaggedObject()), propKey);
3203 RESTORE_ACC();
3204 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
3205 }
3206 }
3207
3208 // slow path
3209 SAVE_ACC();
3210 SAVE_PC();
3211 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
3212 auto propKey = GET_VREG_VALUE(v1); // Maybe moved by GC
3213 auto value = GET_ACC(); // Maybe moved by GC
3214 JSTaggedValue res = SlowRuntimeStub::StOwnByValueWithNameSet(thread, receiver, propKey, value);
3215 RESTORE_ACC();
3216 INTERPRETER_RETURN_IF_ABRUPT(res);
3217 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
3218 }
3219 HANDLE_OPCODE(HANDLE_STOWNBYNAMEWITHNAMESET_PREF_ID32_V8) {
3220 uint32_t stringId = READ_INST_32_1();
3221 uint32_t v0 = READ_INST_8_5();
3222 LOG_INST() << "intrinsics::stownbynamewithnameset "
3223 << "v" << v0 << " stringId:" << stringId;
3224
3225 JSTaggedValue receiver = GET_VREG_VALUE(v0);
3226 if (receiver.IsJSObject() && !receiver.IsClassConstructor() && !receiver.IsClassPrototype()) {
3227 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3228 JSTaggedValue value = GET_ACC();
3229 // fast path
3230 SAVE_ACC();
3231 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
3232 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByNameWithOwn));
3233 typedef JSTaggedType (*PFSetPropertyByName)(uintptr_t, JSTaggedType, JSTaggedType, JSTaggedType);
3234 auto setPropertyByNamePtr = reinterpret_cast<PFSetPropertyByName>(stubAddr);
3235 JSTaggedValue res = JSTaggedValue(setPropertyByNamePtr(thread->GetGlueAddr(), receiver.GetRawData(),
3236 propKey.GetRawData(), value.GetRawData()));
3237 #else
3238 JSTaggedValue res = FastRuntimeStub::SetPropertyByName<true>(thread, receiver, propKey, value);
3239 #endif
3240 if (!res.IsHole()) {
3241 INTERPRETER_RETURN_IF_ABRUPT(res);
3242 JSFunction::SetFunctionNameNoPrefix(thread, JSFunction::Cast(value.GetTaggedObject()), propKey);
3243 RESTORE_ACC();
3244 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3245 }
3246 RESTORE_ACC();
3247 }
3248
3249 SAVE_ACC();
3250 SAVE_PC();
3251 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
3252 auto propKey = constpool->GetObjectFromCache(stringId); // Maybe moved by GC
3253 auto value = GET_ACC(); // Maybe moved by GC
3254 JSTaggedValue res = SlowRuntimeStub::StOwnByNameWithNameSet(thread, receiver, propKey, value);
3255 RESTORE_ACC();
3256 INTERPRETER_RETURN_IF_ABRUPT(res);
3257 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3258 }
3259
3260 HANDLE_OPCODE(HANDLE_LDGLOBALVAR_PREF_ID32) {
3261 uint32_t stringId = READ_INST_32_1();
3262 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3263
3264 #if ECMASCRIPT_ENABLE_IC
3265 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
3266 if (!profileTypeInfo.IsUndefined()) {
3267 uint16_t slotId = READ_INST_8_0();
3268 JSTaggedValue res = ICRuntimeStub::LoadGlobalICByName(thread,
3269 ProfileTypeInfo::Cast(
3270 profileTypeInfo.GetTaggedObject()),
3271 globalObj, propKey, slotId);
3272 INTERPRETER_RETURN_IF_ABRUPT(res);
3273 SET_ACC(res);
3274 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3275 }
3276 #endif
3277 JSTaggedValue result = FastRuntimeStub::GetGlobalOwnProperty(thread, globalObj, propKey);
3278 if (!result.IsHole()) {
3279 SET_ACC(result);
3280 } else {
3281 // slow path
3282 SAVE_PC();
3283 JSTaggedValue res = SlowRuntimeStub::LdGlobalVar(thread, globalObj, propKey);
3284 INTERPRETER_RETURN_IF_ABRUPT(res);
3285 SET_ACC(res);
3286 }
3287 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3288 }
3289 HANDLE_OPCODE(HANDLE_LDOBJBYNAME_PREF_ID32_V8) {
3290 uint32_t v0 = READ_INST_8_5();
3291 JSTaggedValue receiver = GET_VREG_VALUE(v0);
3292
3293 #if ECMASCRIPT_ENABLE_IC
3294 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
3295 if (!profileTypeInfo.IsUndefined()) {
3296 uint16_t slotId = READ_INST_8_0();
3297 auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
3298 JSTaggedValue firstValue = profileTypeArray->Get(slotId);
3299 JSTaggedValue res = JSTaggedValue::Hole();
3300
3301 if (LIKELY(firstValue.IsHeapObject())) {
3302 JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1);
3303 res = ICRuntimeStub::TryLoadICByName(thread, receiver, firstValue, secondValue);
3304 }
3305 if (LIKELY(!res.IsHole())) {
3306 INTERPRETER_RETURN_IF_ABRUPT(res);
3307 SET_ACC(res);
3308 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3309 } else if (!firstValue.IsHole()) { // IC miss and not enter the megamorphic state, store as polymorphic
3310 uint32_t stringId = READ_INST_32_1();
3311 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3312 res = ICRuntimeStub::LoadICByName(thread,
3313 profileTypeArray,
3314 receiver, propKey, slotId);
3315 INTERPRETER_RETURN_IF_ABRUPT(res);
3316 SET_ACC(res);
3317 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3318 }
3319 }
3320 #endif
3321 uint32_t stringId = READ_INST_32_1();
3322 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3323 LOG_INST() << "intrinsics::ldobjbyname "
3324 << "v" << v0 << " stringId:" << stringId << ", "
3325 << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject())) << ", obj:" << receiver.GetRawData();
3326
3327 if (LIKELY(receiver.IsHeapObject())) {
3328 // fast path
3329 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
3330 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName));
3331 typedef JSTaggedType (*PFGetPropertyByName)(uintptr_t, JSTaggedType, JSTaggedType);
3332 auto getPropertyByNamePtr = reinterpret_cast<PFGetPropertyByName>(stubAddr);
3333 JSTaggedValue res = JSTaggedValue(getPropertyByNamePtr(thread->GetGlueAddr(), receiver.GetRawData(),
3334 propKey.GetRawData()));
3335 #else
3336 JSTaggedValue res = FastRuntimeStub::GetPropertyByName(thread, receiver, propKey);
3337 #endif
3338 if (!res.IsHole()) {
3339 ASSERT(!res.IsAccessor());
3340 INTERPRETER_RETURN_IF_ABRUPT(res);
3341 SET_ACC(res);
3342 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3343 }
3344 }
3345 // not meet fast condition or fast path return hole, walk slow path
3346 // slow stub not need receiver
3347 SAVE_PC();
3348 JSTaggedValue res = SlowRuntimeStub::LdObjByName(thread, receiver, propKey, false, JSTaggedValue::Undefined());
3349 INTERPRETER_RETURN_IF_ABRUPT(res);
3350 SET_ACC(res);
3351 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3352 }
3353 HANDLE_OPCODE(HANDLE_STOBJBYNAME_PREF_ID32_V8) {
3354 uint32_t v0 = READ_INST_8_5();
3355 JSTaggedValue receiver = GET_VREG_VALUE(v0);
3356 JSTaggedValue value = GET_ACC();
3357 #if ECMASCRIPT_ENABLE_IC
3358 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
3359 if (!profileTypeInfo.IsUndefined()) {
3360 uint16_t slotId = READ_INST_8_0();
3361 auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
3362 JSTaggedValue firstValue = profileTypeArray->Get(slotId);
3363 JSTaggedValue res = JSTaggedValue::Hole();
3364 SAVE_ACC();
3365
3366 if (LIKELY(firstValue.IsHeapObject())) {
3367 JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1);
3368 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
3369 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(TryStoreICByName));
3370 typedef JSTaggedType (*PFTryStoreICByName)(uintptr_t,
3371 JSTaggedType, JSTaggedType, JSTaggedType, JSTaggedType);
3372 auto tryStoreICByNamePtr = reinterpret_cast<PFTryStoreICByName>(stubAddr);
3373 res = JSTaggedValue(
3374 tryStoreICByNamePtr(thread->GetGlueAddr(), receiver.GetRawData(),
3375 firstValue.GetRawData(), secondValue.GetRawData(), value.GetRawData()));
3376 #else
3377 res = ICRuntimeStub::TryStoreICByName(thread, receiver, firstValue, secondValue, value);
3378 #endif
3379 }
3380 if (LIKELY(!res.IsHole())) {
3381 INTERPRETER_RETURN_IF_ABRUPT(res);
3382 RESTORE_ACC();
3383 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3384 } else if (!firstValue.IsHole()) { // IC miss and not enter the megamorphic state, store as polymorphic
3385 uint32_t stringId = READ_INST_32_1();
3386 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3387 res = ICRuntimeStub::StoreICByName(thread,
3388 profileTypeArray,
3389 receiver, propKey, value, slotId);
3390 INTERPRETER_RETURN_IF_ABRUPT(res);
3391 RESTORE_ACC();
3392 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3393 }
3394 }
3395 #endif
3396 uint32_t stringId = READ_INST_32_1();
3397 LOG_INST() << "intrinsics::stobjbyname "
3398 << "v" << v0 << " stringId:" << stringId;
3399 if (receiver.IsHeapObject()) {
3400 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3401 value = GET_ACC();
3402 // fast path
3403 SAVE_ACC();
3404 #ifdef ECMASCRIPT_ENABLE_STUB_AOT
3405 auto stubAddr = thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByName));
3406 typedef JSTaggedType (*PFSetPropertyByName)(uintptr_t, JSTaggedType, JSTaggedType, JSTaggedType);
3407 auto setPropertyByNamePtr = reinterpret_cast<PFSetPropertyByName>(stubAddr);
3408 JSTaggedValue res = JSTaggedValue(setPropertyByNamePtr(thread->GetGlueAddr(),
3409 receiver.GetRawData(), propKey.GetRawData(), value.GetRawData()));
3410 #else
3411 JSTaggedValue res = FastRuntimeStub::SetPropertyByName(thread, receiver, propKey, value);
3412 #endif
3413 if (!res.IsHole()) {
3414 INTERPRETER_RETURN_IF_ABRUPT(res);
3415 RESTORE_ACC();
3416 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3417 }
3418 RESTORE_ACC();
3419 }
3420 // slow path
3421 SAVE_ACC();
3422 SAVE_PC();
3423 receiver = GET_VREG_VALUE(v0); // Maybe moved by GC
3424 auto propKey = constpool->GetObjectFromCache(stringId); // Maybe moved by GC
3425 value = GET_ACC(); // Maybe moved by GC
3426 JSTaggedValue res = SlowRuntimeStub::StObjByName(thread, receiver, propKey, value);
3427 INTERPRETER_RETURN_IF_ABRUPT(res);
3428 RESTORE_ACC();
3429 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3430 }
3431 HANDLE_OPCODE(HANDLE_LDSUPERBYNAME_PREF_ID32_V8) {
3432 uint32_t stringId = READ_INST_32_1();
3433 uint32_t v0 = READ_INST_8_5();
3434 JSTaggedValue obj = GET_VREG_VALUE(v0);
3435 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3436
3437 LOG_INST() << "intrinsics::ldsuperbyname"
3438 << "v" << v0 << " stringId:" << stringId << ", "
3439 << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject())) << ", obj:" << obj.GetRawData();
3440
3441 SAVE_PC();
3442 JSTaggedValue thisFunc = GetThisFunction(sp);
3443 JSTaggedValue res = SlowRuntimeStub::LdSuperByValue(thread, obj, propKey, thisFunc);
3444
3445 INTERPRETER_RETURN_IF_ABRUPT(res);
3446 SET_ACC(res);
3447 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3448 }
3449 HANDLE_OPCODE(HANDLE_STSUPERBYNAME_PREF_ID32_V8) {
3450 uint32_t stringId = READ_INST_32_1();
3451 uint32_t v0 = READ_INST_8_5();
3452
3453 JSTaggedValue obj = GET_VREG_VALUE(v0);
3454 JSTaggedValue propKey = constpool->GetObjectFromCache(stringId);
3455 JSTaggedValue value = GET_ACC();
3456
3457 LOG_INST() << "intrinsics::stsuperbyname"
3458 << "v" << v0 << " stringId:" << stringId << ", "
3459 << ConvertToString(EcmaString::Cast(propKey.GetTaggedObject())) << ", obj:" << obj.GetRawData()
3460 << ", value:" << value.GetRawData();
3461
3462 // slow path
3463 SAVE_ACC();
3464 SAVE_PC();
3465 JSTaggedValue thisFunc = GetThisFunction(sp);
3466 JSTaggedValue res = SlowRuntimeStub::StSuperByValue(thread, obj, propKey, value, thisFunc);
3467 INTERPRETER_RETURN_IF_ABRUPT(res);
3468 RESTORE_ACC();
3469 DISPATCH(BytecodeInstruction::Format::PREF_ID32_V8);
3470 }
3471 HANDLE_OPCODE(HANDLE_STGLOBALVAR_PREF_ID32) {
3472 uint32_t stringId = READ_INST_32_1();
3473 JSTaggedValue prop = constpool->GetObjectFromCache(stringId);
3474 JSTaggedValue value = GET_ACC();
3475
3476 LOG_INST() << "intrinsics::stglobalvar "
3477 << "stringId:" << stringId << ", " << ConvertToString(EcmaString::Cast(prop.GetTaggedObject()))
3478 << ", value:" << value.GetRawData();
3479 #if ECMASCRIPT_ENABLE_IC
3480 auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
3481 if (!profileTypeInfo.IsUndefined()) {
3482 uint16_t slotId = READ_INST_8_0();
3483 SAVE_ACC();
3484 JSTaggedValue res = ICRuntimeStub::StoreGlobalICByName(thread,
3485 ProfileTypeInfo::Cast(
3486 profileTypeInfo.GetTaggedObject()),
3487 globalObj, prop, value, slotId);
3488 INTERPRETER_RETURN_IF_ABRUPT(res);
3489 RESTORE_ACC();
3490 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3491 }
3492 #endif
3493 SAVE_ACC();
3494 SAVE_PC();
3495 JSTaggedValue res = SlowRuntimeStub::StGlobalVar(thread, prop, value);
3496 INTERPRETER_RETURN_IF_ABRUPT(res);
3497 RESTORE_ACC();
3498 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3499 }
3500 HANDLE_OPCODE(HANDLE_CREATEGENERATOROBJ_PREF_V8) {
3501 uint16_t v0 = READ_INST_8_1();
3502 LOG_INST() << "intrinsics::creategeneratorobj"
3503 << " v" << v0;
3504 SAVE_PC();
3505 JSTaggedValue genFunc = GET_VREG_VALUE(v0);
3506 JSTaggedValue res = SlowRuntimeStub::CreateGeneratorObj(thread, genFunc);
3507 INTERPRETER_RETURN_IF_ABRUPT(res);
3508 SET_ACC(res);
3509 DISPATCH(BytecodeInstruction::Format::PREF_V8);
3510 }
3511 HANDLE_OPCODE(HANDLE_STARRAYSPREAD_PREF_V8_V8) {
3512 uint16_t v0 = READ_INST_8_1();
3513 uint16_t v1 = READ_INST_8_2();
3514 LOG_INST() << "ecmascript::intrinsics::starrayspread"
3515 << " v" << v0 << " v" << v1 << "acc";
3516 JSTaggedValue dst = GET_VREG_VALUE(v0);
3517 JSTaggedValue index = GET_VREG_VALUE(v1);
3518 JSTaggedValue src = GET_ACC();
3519 SAVE_PC();
3520 JSTaggedValue res = SlowRuntimeStub::StArraySpread(thread, dst, index, src);
3521 INTERPRETER_RETURN_IF_ABRUPT(res);
3522 SET_ACC(res);
3523 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
3524 }
3525 HANDLE_OPCODE(HANDLE_GETITERATORNEXT_PREF_V8_V8) {
3526 uint16_t v0 = READ_INST_8_1();
3527 uint16_t v1 = READ_INST_8_2();
3528 LOG_INST() << "intrinsic::getiteratornext"
3529 << " v" << v0 << " v" << v1;
3530 JSTaggedValue obj = GET_VREG_VALUE(v0);
3531 JSTaggedValue method = GET_VREG_VALUE(v1);
3532 SAVE_PC();
3533 JSTaggedValue res = SlowRuntimeStub::GetIteratorNext(thread, obj, method);
3534 INTERPRETER_RETURN_IF_ABRUPT(res);
3535 SET_ACC(res);
3536 DISPATCH(BytecodeInstruction::Format::PREF_V8_V8);
3537 }
3538 HANDLE_OPCODE(HANDLE_DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8) {
3539 uint16_t methodId = READ_INST_16_1();
3540 uint16_t imm = READ_INST_16_3();
3541 uint16_t length = READ_INST_16_5();
3542 uint16_t v0 = READ_INST_8_7();
3543 uint16_t v1 = READ_INST_8_8();
3544 LOG_INST() << "intrinsics::defineclasswithbuffer"
3545 << " method id:" << methodId << " literal id:" << imm << " lexenv: v" << v0 << " parent: v" << v1;
3546 JSFunction *classTemplate = JSFunction::Cast(constpool->GetObjectFromCache(methodId).GetTaggedObject());
3547 ASSERT(classTemplate != nullptr);
3548
3549 JSTaggedValue lexenv = GET_VREG_VALUE(v0);
3550 JSTaggedValue proto = GET_VREG_VALUE(v1);
3551
3552 JSTaggedValue res;
3553 SAVE_PC();
3554 res = SlowRuntimeStub::CloneClassFromTemplate(thread, JSTaggedValue(classTemplate), proto, lexenv, constpool);
3555 INTERPRETER_RETURN_IF_ABRUPT(res);
3556 ASSERT(res.IsClassConstructor());
3557 JSFunction *cls = JSFunction::Cast(res.GetTaggedObject());
3558
3559 lexenv = GET_VREG_VALUE(v0); // slow runtime may gc
3560 cls->SetLexicalEnv(thread, lexenv);
3561
3562 SlowRuntimeStub::SetClassConstructorLength(thread, res, JSTaggedValue(length));
3563
3564 SET_ACC(res);
3565 DISPATCH(BytecodeInstruction::Format::PREF_ID16_IMM16_IMM16_V8_V8);
3566 }
3567 HANDLE_OPCODE(HANDLE_LDFUNCTION_PREF) {
3568 LOG_INST() << "intrinsic::ldfunction";
3569 SET_ACC(GetThisFunction(sp));
3570 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
3571 }
3572 HANDLE_OPCODE(HANDLE_LDBIGINT_PREF_ID32) {
3573 uint32_t stringId = READ_INST_32_1();
3574 LOG_INST() << "intrinsic::ldbigint";
3575 JSTaggedValue numberBigInt = constpool->GetObjectFromCache(stringId);
3576 SAVE_PC();
3577 JSTaggedValue res = SlowRuntimeStub::LdBigInt(thread, numberBigInt);
3578 INTERPRETER_RETURN_IF_ABRUPT(res);
3579 SET_ACC(res);
3580 DISPATCH(BytecodeInstruction::Format::PREF_ID32);
3581 }
3582 HANDLE_OPCODE(HANDLE_SUPERCALL_PREF_IMM16_V8) {
3583 uint16_t range = READ_INST_16_1();
3584 uint16_t v0 = READ_INST_8_3();
3585 LOG_INST() << "intrinsics::supercall"
3586 << " range: " << range << " v" << v0;
3587
3588 JSTaggedValue thisFunc = GET_ACC();
3589 JSTaggedValue newTarget = GetNewTarget(sp);
3590
3591 SAVE_PC();
3592 JSTaggedValue res = SlowRuntimeStub::SuperCall(thread, thisFunc, newTarget, v0, range);
3593 INTERPRETER_RETURN_IF_ABRUPT(res);
3594 SET_ACC(res);
3595 DISPATCH(BytecodeInstruction::Format::PREF_IMM16_V8);
3596 }
3597 HANDLE_OPCODE(HANDLE_SUPERCALLSPREAD_PREF_V8) {
3598 uint16_t v0 = READ_INST_8_1();
3599 LOG_INST() << "intrinsic::supercallspread"
3600 << " array: v" << v0;
3601
3602 JSTaggedValue thisFunc = GET_ACC();
3603 JSTaggedValue newTarget = GetNewTarget(sp);
3604 JSTaggedValue array = GET_VREG_VALUE(v0);
3605
3606 SAVE_PC();
3607 JSTaggedValue res = SlowRuntimeStub::SuperCallSpread(thread, thisFunc, newTarget, array);
3608 INTERPRETER_RETURN_IF_ABRUPT(res);
3609 SET_ACC(res);
3610 DISPATCH(BytecodeInstruction::Format::PREF_V8);
3611 }
3612 HANDLE_OPCODE(HANDLE_CREATEOBJECTHAVINGMETHOD_PREF_IMM16) {
3613 uint16_t imm = READ_INST_16_1();
3614 LOG_INST() << "intrinsics::createobjecthavingmethod"
3615 << " imm:" << imm;
3616 JSObject *result = JSObject::Cast(constpool->GetObjectFromCache(imm).GetTaggedObject());
3617 JSTaggedValue env = GET_ACC();
3618
3619 SAVE_PC();
3620 JSTaggedValue res = SlowRuntimeStub::CreateObjectHavingMethod(thread, factory, result, env, constpool);
3621 INTERPRETER_RETURN_IF_ABRUPT(res);
3622 SET_ACC(res);
3623 DISPATCH(BytecodeInstruction::Format::PREF_IMM16);
3624 }
3625 HANDLE_OPCODE(HANDLE_THROWIFSUPERNOTCORRECTCALL_PREF_IMM16) {
3626 uint16_t imm = READ_INST_16_1();
3627 JSTaggedValue thisValue = GET_ACC();
3628 LOG_INST() << "intrinsic::throwifsupernotcorrectcall"
3629 << " imm:" << imm;
3630 SAVE_PC();
3631 JSTaggedValue res = SlowRuntimeStub::ThrowIfSuperNotCorrectCall(thread, imm, thisValue);
3632 INTERPRETER_RETURN_IF_ABRUPT(res);
3633 DISPATCH(BytecodeInstruction::Format::PREF_IMM16);
3634 }
3635 HANDLE_OPCODE(HANDLE_LDHOMEOBJECT_PREF) {
3636 LOG_INST() << "intrinsics::ldhomeobject";
3637
3638 JSTaggedValue thisFunc = GetThisFunction(sp);
3639 JSTaggedValue homeObject = JSFunction::Cast(thisFunc.GetTaggedObject())->GetHomeObject();
3640
3641 SET_ACC(homeObject);
3642 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
3643 }
3644 HANDLE_OPCODE(HANDLE_THROWDELETESUPERPROPERTY_PREF) {
3645 LOG_INST() << "throwdeletesuperproperty";
3646
3647 SAVE_PC();
3648 SlowRuntimeStub::ThrowDeleteSuperProperty(thread);
3649 INTERPRETER_GOTO_EXCEPTION_HANDLER();
3650 }
3651 HANDLE_OPCODE(HANDLE_DEBUGGER_PREF) {
3652 LOG_INST() << "intrinsics::debugger";
3653 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
3654 }
3655 HANDLE_OPCODE(HANDLE_ISTRUE_PREF) {
3656 LOG_INST() << "intrinsics::istrue";
3657 if (GET_ACC().ToBoolean()) {
3658 SET_ACC(JSTaggedValue::True());
3659 } else {
3660 SET_ACC(JSTaggedValue::False());
3661 }
3662 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
3663 }
3664 HANDLE_OPCODE(HANDLE_ISFALSE_PREF) {
3665 LOG_INST() << "intrinsics::isfalse";
3666 if (!GET_ACC().ToBoolean()) {
3667 SET_ACC(JSTaggedValue::True());
3668 } else {
3669 SET_ACC(JSTaggedValue::False());
3670 }
3671 DISPATCH(BytecodeInstruction::Format::PREF_NONE);
3672 }
3673 HANDLE_OPCODE(EXCEPTION_HANDLER) {
3674 InterpretedFrameHandler frameHandler(sp);
3675 uint32_t pcOffset = panda_file::INVALID_OFFSET;
3676 for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) {
3677 if (frameHandler.IsBreakFrame()) {
3678 return;
3679 }
3680 auto method = frameHandler.GetMethod();
3681 pcOffset = FindCatchBlock(method, frameHandler.GetBytecodeOffset());
3682 if (pcOffset != panda_file::INVALID_OFFSET) {
3683 sp = frameHandler.GetSp();
3684 constpool = frameHandler.GetConstpool();
3685 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3686 pc = method->GetBytecodeArray() + pcOffset;
3687 break;
3688 }
3689 }
3690 if (pcOffset == panda_file::INVALID_OFFSET) {
3691 return;
3692 }
3693
3694 auto exception = thread->GetException();
3695 SET_ACC(exception);
3696 thread->ClearException();
3697 thread->SetCurrentSPFrame(sp);
3698 DISPATCH_OFFSET(0);
3699 }
3700 HANDLE_OPCODE(HANDLE_OVERFLOW) {
3701 LOG(FATAL, INTERPRETER) << "opcode overflow";
3702 }
3703 #include "templates/debugger_instruction_handler.inl"
3704 }
3705
InitStackFrame(JSThread * thread)3706 void EcmaInterpreter::InitStackFrame(JSThread *thread)
3707 {
3708 uint64_t *prevSp = const_cast<uint64_t *>(thread->GetCurrentSPFrame());
3709 InterpretedFrame *state = GET_FRAME(prevSp);
3710 state->pc = nullptr;
3711 state->sp = nullptr;
3712 state->function = JSTaggedValue::Hole();
3713 state->acc = JSTaggedValue::Hole();
3714 state->constpool = JSTaggedValue::Hole();
3715 state->profileTypeInfo = JSTaggedValue::Undefined();
3716 state->base.type = FrameType::INTERPRETER_FRAME;
3717 state->base.prev = nullptr;
3718 }
3719
FindCatchBlock(JSMethod * caller,uint32_t pc)3720 uint32_t EcmaInterpreter::FindCatchBlock(JSMethod *caller, uint32_t pc)
3721 {
3722 auto *pandaFile = caller->GetPandaFile();
3723 panda_file::MethodDataAccessor mda(*pandaFile, caller->GetFileId());
3724 panda_file::CodeDataAccessor cda(*pandaFile, mda.GetCodeId().value());
3725
3726 uint32_t pcOffset = panda_file::INVALID_OFFSET;
3727 cda.EnumerateTryBlocks([&pcOffset, pc](panda_file::CodeDataAccessor::TryBlock &try_block) {
3728 if ((try_block.GetStartPc() <= pc) && ((try_block.GetStartPc() + try_block.GetLength()) > pc)) {
3729 try_block.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catch_block) {
3730 pcOffset = catch_block.GetHandlerPc();
3731 return false;
3732 });
3733 }
3734 return pcOffset == panda_file::INVALID_OFFSET;
3735 });
3736 return pcOffset;
3737 }
3738
GetThisFunction(JSTaggedType * sp)3739 JSTaggedValue EcmaInterpreter::GetThisFunction(JSTaggedType *sp)
3740 {
3741 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3742 InterpretedFrame *state = reinterpret_cast<InterpretedFrame *>(sp) - 1;
3743 return state->function;
3744 }
3745
GetNewTarget(JSTaggedType * sp)3746 JSTaggedValue EcmaInterpreter::GetNewTarget(JSTaggedType *sp)
3747 {
3748 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3749 InterpretedFrame *state = reinterpret_cast<InterpretedFrame *>(sp) - 1;
3750 JSMethod *method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod();
3751 ASSERT(method->HaveNewTargetWithCallField());
3752 uint32_t numVregs = method->GetNumVregsWithCallField();
3753 bool haveFunc = method->HaveFuncWithCallField();
3754 return JSTaggedValue(sp[numVregs + haveFunc]);
3755 }
3756
GetNumArgs(JSTaggedType * sp,uint32_t restIdx,uint32_t & startIdx)3757 uint32_t EcmaInterpreter::GetNumArgs(JSTaggedType *sp, uint32_t restIdx, uint32_t &startIdx)
3758 {
3759 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3760 InterpretedFrame *state = reinterpret_cast<InterpretedFrame *>(sp) - 1;
3761 JSMethod *method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod();
3762 ASSERT(method->HaveExtraWithCallField());
3763 uint32_t numVregs = method->GetNumVregsWithCallField();
3764 bool haveFunc = method->HaveFuncWithCallField();
3765 bool haveNewTarget = method->HaveNewTargetWithCallField();
3766 bool haveThis = method->HaveThisWithCallField();
3767 uint32_t copyArgs = haveFunc + haveNewTarget + haveThis;
3768 uint32_t numArgs = method->GetNumArgsWithCallField();
3769 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3770 JSTaggedType *lastFrame = state->base.prev - FRAME_STATE_SIZE;
3771 if (lastFrame - sp > numVregs + copyArgs + numArgs) {
3772 // In this case, actualNumArgs is in the end
3773 // If not, then actualNumArgs == declaredNumArgs, therefore do nothing
3774 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3775 numArgs = JSTaggedValue(*(lastFrame - 1)).GetInt();
3776 }
3777 startIdx = numVregs + copyArgs + restIdx;
3778 return ((numArgs > restIdx) ? (numArgs - restIdx) : 0);
3779 }
3780
GetJumpSizeAfterCall(const uint8_t * prevPc)3781 size_t EcmaInterpreter::GetJumpSizeAfterCall(const uint8_t *prevPc)
3782 {
3783 uint8_t op = *prevPc;
3784 size_t jumpSize;
3785 switch (op) {
3786 case (EcmaOpcode::CALLARG0DYN_PREF_V8):
3787 jumpSize = BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8);
3788 break;
3789 case (EcmaOpcode::CALLARG1DYN_PREF_V8_V8):
3790 jumpSize = BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8);
3791 break;
3792 case (EcmaOpcode::CALLARGS2DYN_PREF_V8_V8_V8):
3793 jumpSize = BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8);
3794 break;
3795 case (EcmaOpcode::CALLARGS3DYN_PREF_V8_V8_V8_V8):
3796 jumpSize = BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8_V8);
3797 break;
3798 case (EcmaOpcode::CALLIRANGEDYN_PREF_IMM16_V8):
3799 jumpSize = BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8);
3800 break;
3801 case (EcmaOpcode::CALLITHISRANGEDYN_PREF_IMM16_V8):
3802 case (EcmaOpcode::NEWOBJDYNRANGE_PREF_IMM16_V8):
3803 jumpSize = BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8);
3804 break;
3805 default:
3806 UNREACHABLE();
3807 }
3808
3809 return jumpSize;
3810 }
3811
GetRuntimeProfileTypeInfo(JSTaggedType * sp)3812 JSTaggedValue EcmaInterpreter::GetRuntimeProfileTypeInfo(JSTaggedType *sp)
3813 {
3814 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3815 InterpretedFrame *state = reinterpret_cast<InterpretedFrame *>(sp) - 1;
3816 return state->profileTypeInfo;
3817 }
3818
UpdateHotnessCounter(JSThread * thread,JSTaggedType * sp,JSTaggedValue acc,int32_t offset)3819 bool EcmaInterpreter::UpdateHotnessCounter(JSThread* thread, JSTaggedType *sp, JSTaggedValue acc, int32_t offset)
3820 {
3821 InterpretedFrame *state = GET_FRAME(sp);
3822 auto method = JSFunction::Cast(state->function.GetTaggedObject())->GetMethod();
3823 auto hotnessCounter = static_cast<int32_t>(method->GetHotnessCounter());
3824
3825 hotnessCounter += offset;
3826 if (UNLIKELY(hotnessCounter <= 0)) {
3827 bool needRestoreAcc = false;
3828 SAVE_ACC();
3829 needRestoreAcc = thread->CheckSafepoint();
3830 RESTORE_ACC();
3831 if (state->profileTypeInfo == JSTaggedValue::Undefined()) {
3832 state->acc = acc;
3833 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3834 auto thisFunc = state->function;
3835 auto res = SlowRuntimeStub::NotifyInlineCache(
3836 thread, JSFunction::Cast(thisFunc.GetHeapObject()), method);
3837 state->profileTypeInfo = res;
3838 method->SetHotnessCounter(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD);
3839 return true;
3840 } else {
3841 method->SetHotnessCounter(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD);
3842 return needRestoreAcc;
3843 }
3844 }
3845 method->SetHotnessCounter(static_cast<uint32_t>(hotnessCounter));
3846 return false;
3847 }
3848
3849 // only use for fast new, not universal API
GetThisObjectFromFastNewFrame(JSTaggedType * sp)3850 JSTaggedValue EcmaInterpreter::GetThisObjectFromFastNewFrame(JSTaggedType *sp)
3851 {
3852 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
3853 InterpretedFrame *state = reinterpret_cast<InterpretedFrame *>(sp) - 1;
3854 JSMethod *method = ECMAObject::Cast(state->function.GetTaggedObject())->GetCallTarget();
3855 ASSERT(method->OnlyHaveThisWithCallField());
3856 uint32_t numVregs = method->GetNumVregsWithCallField();
3857 uint32_t numDeclaredArgs = method->GetNumArgsWithCallField() + 1; // 1: explict this object
3858 uint32_t hiddenThisObjectIndex = numVregs + numDeclaredArgs; // hidden this object in the end of fast new frame
3859 return JSTaggedValue(sp[hiddenThisObjectIndex]);
3860 }
3861
IsFastNewFrameEnter(JSMethod * method)3862 bool EcmaInterpreter::IsFastNewFrameEnter(JSMethod *method)
3863 {
3864 if (method->IsNativeWithCallField()) {
3865 return false;
3866 }
3867
3868 return method->OnlyHaveThisWithCallField();
3869 }
3870
IsFastNewFrameExit(JSTaggedType * sp)3871 bool EcmaInterpreter::IsFastNewFrameExit(JSTaggedType *sp)
3872 {
3873 return GET_FRAME(sp)->base.type == FrameType::INTERPRETER_FAST_NEW_FRAME;
3874 }
3875
GetEcmaOpcodeStr(EcmaOpcode opcode)3876 std::string GetEcmaOpcodeStr(EcmaOpcode opcode)
3877 {
3878 const std::map<EcmaOpcode, const char *> strMap = {
3879 {LDNAN_PREF, "LDNAN"},
3880 {LDINFINITY_PREF, "LDINFINITY"},
3881 {LDGLOBALTHIS_PREF, "LDGLOBALTHIS"},
3882 {LDUNDEFINED_PREF, "LDUNDEFINED"},
3883 {LDNULL_PREF, "LDNULL"},
3884 {LDSYMBOL_PREF, "LDSYMBOL"},
3885 {LDGLOBAL_PREF, "LDGLOBAL"},
3886 {LDTRUE_PREF, "LDTRUE"},
3887 {LDFALSE_PREF, "LDFALSE"},
3888 {THROWDYN_PREF, "THROWDYN"},
3889 {TYPEOFDYN_PREF, "TYPEOFDYN"},
3890 {LDLEXENVDYN_PREF, "LDLEXENVDYN"},
3891 {POPLEXENVDYN_PREF, "POPLEXENVDYN"},
3892 {GETUNMAPPEDARGS_PREF, "GETUNMAPPEDARGS"},
3893 {GETPROPITERATOR_PREF, "GETPROPITERATOR"},
3894 {ASYNCFUNCTIONENTER_PREF, "ASYNCFUNCTIONENTER"},
3895 {LDHOLE_PREF, "LDHOLE"},
3896 {RETURNUNDEFINED_PREF, "RETURNUNDEFINED"},
3897 {CREATEEMPTYOBJECT_PREF, "CREATEEMPTYOBJECT"},
3898 {CREATEEMPTYARRAY_PREF, "CREATEEMPTYARRAY"},
3899 {GETITERATOR_PREF, "GETITERATOR"},
3900 {THROWTHROWNOTEXISTS_PREF, "THROWTHROWNOTEXISTS"},
3901 {THROWPATTERNNONCOERCIBLE_PREF, "THROWPATTERNNONCOERCIBLE"},
3902 {LDHOMEOBJECT_PREF, "LDHOMEOBJECT"},
3903 {THROWDELETESUPERPROPERTY_PREF, "THROWDELETESUPERPROPERTY"},
3904 {DEBUGGER_PREF, "DEBUGGER"},
3905 {ADD2DYN_PREF_V8, "ADD2DYN"},
3906 {SUB2DYN_PREF_V8, "SUB2DYN"},
3907 {MUL2DYN_PREF_V8, "MUL2DYN"},
3908 {DIV2DYN_PREF_V8, "DIV2DYN"},
3909 {MOD2DYN_PREF_V8, "MOD2DYN"},
3910 {EQDYN_PREF_V8, "EQDYN"},
3911 {NOTEQDYN_PREF_V8, "NOTEQDYN"},
3912 {LESSDYN_PREF_V8, "LESSDYN"},
3913 {LESSEQDYN_PREF_V8, "LESSEQDYN"},
3914 {GREATERDYN_PREF_V8, "GREATERDYN"},
3915 {GREATEREQDYN_PREF_V8, "GREATEREQDYN"},
3916 {SHL2DYN_PREF_V8, "SHL2DYN"},
3917 {SHR2DYN_PREF_V8, "SHR2DYN"},
3918 {ASHR2DYN_PREF_V8, "ASHR2DYN"},
3919 {AND2DYN_PREF_V8, "AND2DYN"},
3920 {OR2DYN_PREF_V8, "OR2DYN"},
3921 {XOR2DYN_PREF_V8, "XOR2DYN"},
3922 {TONUMBER_PREF_V8, "TONUMBER"},
3923 {NEGDYN_PREF_V8, "NEGDYN"},
3924 {NOTDYN_PREF_V8, "NOTDYN"},
3925 {INCDYN_PREF_V8, "INCDYN"},
3926 {DECDYN_PREF_V8, "DECDYN"},
3927 {EXPDYN_PREF_V8, "EXPDYN"},
3928 {ISINDYN_PREF_V8, "ISINDYN"},
3929 {INSTANCEOFDYN_PREF_V8, "INSTANCEOFDYN"},
3930 {STRICTNOTEQDYN_PREF_V8, "STRICTNOTEQDYN"},
3931 {STRICTEQDYN_PREF_V8, "STRICTEQDYN"},
3932 {RESUMEGENERATOR_PREF_V8, "RESUMEGENERATOR"},
3933 {GETRESUMEMODE_PREF_V8, "GETRESUMEMODE"},
3934 {CREATEGENERATOROBJ_PREF_V8, "CREATEGENERATOROBJ"},
3935 {THROWCONSTASSIGNMENT_PREF_V8, "THROWCONSTASSIGNMENT"},
3936 {GETTEMPLATEOBJECT_PREF_V8, "GETTEMPLATEOBJECT"},
3937 {GETNEXTPROPNAME_PREF_V8, "GETNEXTPROPNAME"},
3938 {CALLARG0DYN_PREF_V8, "CALLARG0DYN"},
3939 {THROWIFNOTOBJECT_PREF_V8, "THROWIFNOTOBJECT"},
3940 {ITERNEXT_PREF_V8, "ITERNEXT"},
3941 {CLOSEITERATOR_PREF_V8, "CLOSEITERATOR"},
3942 {COPYMODULE_PREF_V8, "COPYMODULE"},
3943 {SUPERCALLSPREAD_PREF_V8, "SUPERCALLSPREAD"},
3944 {DELOBJPROP_PREF_V8_V8, "DELOBJPROP"},
3945 {NEWOBJSPREADDYN_PREF_V8_V8, "NEWOBJSPREADDYN"},
3946 {CREATEITERRESULTOBJ_PREF_V8_V8, "CREATEITERRESULTOBJ"},
3947 {SUSPENDGENERATOR_PREF_V8_V8, "SUSPENDGENERATOR"},
3948 {ASYNCFUNCTIONAWAITUNCAUGHT_PREF_V8_V8, "ASYNCFUNCTIONAWAITUNCAUGHT"},
3949 {THROWUNDEFINEDIFHOLE_PREF_V8_V8, "THROWUNDEFINEDIFHOLE"},
3950 {CALLARG1DYN_PREF_V8_V8, "CALLARG1DYN"},
3951 {COPYDATAPROPERTIES_PREF_V8_V8, "COPYDATAPROPERTIES"},
3952 {STARRAYSPREAD_PREF_V8_V8, "STARRAYSPREAD"},
3953 {GETITERATORNEXT_PREF_V8_V8, "GETITERATORNEXT"},
3954 {SETOBJECTWITHPROTO_PREF_V8_V8, "SETOBJECTWITHPROTO"},
3955 {LDOBJBYVALUE_PREF_V8_V8, "LDOBJBYVALUE"},
3956 {STOBJBYVALUE_PREF_V8_V8, "STOBJBYVALUE"},
3957 {STOWNBYVALUE_PREF_V8_V8, "STOWNBYVALUE"},
3958 {LDSUPERBYVALUE_PREF_V8_V8, "LDSUPERBYVALUE"},
3959 {STSUPERBYVALUE_PREF_V8_V8, "STSUPERBYVALUE"},
3960 {LDOBJBYINDEX_PREF_V8_IMM32, "LDOBJBYINDEX"},
3961 {STOBJBYINDEX_PREF_V8_IMM32, "STOBJBYINDEX"},
3962 {STOWNBYINDEX_PREF_V8_IMM32, "STOWNBYINDEX"},
3963 {CALLSPREADDYN_PREF_V8_V8_V8, "CALLSPREADDYN"},
3964 {ASYNCFUNCTIONRESOLVE_PREF_V8_V8_V8, "ASYNCFUNCTIONRESOLVE"},
3965 {ASYNCFUNCTIONREJECT_PREF_V8_V8_V8, "ASYNCFUNCTIONREJECT"},
3966 {CALLARGS2DYN_PREF_V8_V8_V8, "CALLARGS2DYN"},
3967 {CALLARGS3DYN_PREF_V8_V8_V8_V8, "CALLARGS3DYN"},
3968 {DEFINEGETTERSETTERBYVALUE_PREF_V8_V8_V8_V8, "DEFINEGETTERSETTERBYVALUE"},
3969 {NEWOBJDYNRANGE_PREF_IMM16_V8, "NEWOBJDYNRANGE"},
3970 {CALLIRANGEDYN_PREF_IMM16_V8, "CALLIRANGEDYN"},
3971 {CALLITHISRANGEDYN_PREF_IMM16_V8, "CALLITHISRANGEDYN"},
3972 {SUPERCALL_PREF_IMM16_V8, "SUPERCALL"},
3973 {CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8, "CREATEOBJECTWITHEXCLUDEDKEYS"},
3974 {DEFINEFUNCDYN_PREF_ID16_IMM16_V8, "DEFINEFUNCDYN"},
3975 {DEFINENCFUNCDYN_PREF_ID16_IMM16_V8, "DEFINENCFUNCDYN"},
3976 {DEFINEGENERATORFUNC_PREF_ID16_IMM16_V8, "DEFINEGENERATORFUNC"},
3977 {DEFINEASYNCFUNC_PREF_ID16_IMM16_V8, "DEFINEASYNCFUNC"},
3978 {DEFINEMETHOD_PREF_ID16_IMM16_V8, "DEFINEMETHOD"},
3979 {NEWLEXENVDYN_PREF_IMM16, "NEWLEXENVDYN"},
3980 {COPYRESTARGS_PREF_IMM16, "COPYRESTARGS"},
3981 {CREATEARRAYWITHBUFFER_PREF_IMM16, "CREATEARRAYWITHBUFFER"},
3982 {CREATEOBJECTHAVINGMETHOD_PREF_IMM16, "CREATEOBJECTHAVINGMETHOD"},
3983 {THROWIFSUPERNOTCORRECTCALL_PREF_IMM16, "THROWIFSUPERNOTCORRECTCALL"},
3984 {CREATEOBJECTWITHBUFFER_PREF_IMM16, "CREATEOBJECTWITHBUFFER"},
3985 {LDLEXVARDYN_PREF_IMM4_IMM4, "LDLEXVARDYN"},
3986 {LDLEXVARDYN_PREF_IMM8_IMM8, "LDLEXVARDYN"},
3987 {LDLEXVARDYN_PREF_IMM16_IMM16, "LDLEXVARDYN"},
3988 {STLEXVARDYN_PREF_IMM4_IMM4_V8, "STLEXVARDYN"},
3989 {STLEXVARDYN_PREF_IMM8_IMM8_V8, "STLEXVARDYN"},
3990 {STLEXVARDYN_PREF_IMM16_IMM16_V8, "STLEXVARDYN"},
3991 {NEWLEXENVWITHNAMEDYN_PREF_IMM16_IMM16, "NEWLEXENVWITHNAMEDYN"},
3992 {DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8, "DEFINECLASSWITHBUFFER"},
3993 {IMPORTMODULE_PREF_ID32, "IMPORTMODULE"},
3994 {STMODULEVAR_PREF_ID32, "STMODULEVAR"},
3995 {TRYLDGLOBALBYNAME_PREF_ID32, "TRYLDGLOBALBYNAME"},
3996 {TRYSTGLOBALBYNAME_PREF_ID32, "TRYSTGLOBALBYNAME"},
3997 {LDGLOBALVAR_PREF_ID32, "LDGLOBALVAR"},
3998 {STGLOBALVAR_PREF_ID32, "STGLOBALVAR"},
3999 {LDOBJBYNAME_PREF_ID32_V8, "LDOBJBYNAME"},
4000 {STOBJBYNAME_PREF_ID32_V8, "STOBJBYNAME"},
4001 {STOWNBYNAME_PREF_ID32_V8, "STOWNBYNAME"},
4002 {LDSUPERBYNAME_PREF_ID32_V8, "LDSUPERBYNAME"},
4003 {STSUPERBYNAME_PREF_ID32_V8, "STSUPERBYNAME"},
4004 {LDMODVARBYNAME_PREF_ID32_V8, "LDMODVARBYNAME"},
4005 {CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8, "CREATEREGEXPWITHLITERAL"},
4006 {ISTRUE_PREF, "ISTRUE"},
4007 {ISFALSE_PREF, "ISFALSE"},
4008 {STCONSTTOGLOBALRECORD_PREF_ID32, "STCONSTTOGLOBALRECORD"},
4009 {STLETTOGLOBALRECORD_PREF_ID32, "STLETTOGLOBALRECORD"},
4010 {STCLASSTOGLOBALRECORD_PREF_ID32, "STCLASSTOGLOBALRECORD"},
4011 {STOWNBYVALUEWITHNAMESET_PREF_V8_V8, "STOWNBYVALUEWITHNAMESET"},
4012 {STOWNBYNAMEWITHNAMESET_PREF_ID32_V8, "STOWNBYNAMEWITHNAMESET"},
4013 {LDFUNCTION_PREF, "LDFUNCTION"},
4014 {LDBIGINT_PREF_ID32, "LDBIGINT"},
4015 {MOV_DYN_V8_V8, "MOV_DYN"},
4016 {MOV_DYN_V16_V16, "MOV_DYN"},
4017 {LDA_STR_ID32, "LDA_STR"},
4018 {LDAI_DYN_IMM32, "LDAI_DYN"},
4019 {FLDAI_DYN_IMM64, "FLDAI_DYN"},
4020 {JMP_IMM8, "JMP"},
4021 {JMP_IMM16, "JMP"},
4022 {JMP_IMM32, "JMP"},
4023 {JEQZ_IMM8, "JEQZ"},
4024 {JEQZ_IMM16, "JEQZ"},
4025 {LDA_DYN_V8, "LDA_DYN"},
4026 {STA_DYN_V8, "STA_DYN"},
4027 {RETURN_DYN, "RETURN_DYN"},
4028 {MOV_V4_V4, "MOV"},
4029 {JNEZ_IMM8, "JNEZ"},
4030 {JNEZ_IMM16, "JNEZ"},
4031 {LAST_OPCODE, "LAST_OPCODE"},
4032 };
4033 if (strMap.count(opcode) > 0) {
4034 return strMap.at(opcode);
4035 }
4036 return "bytecode-" + std::to_string(opcode);
4037 }
4038 #if defined(__clang__)
4039 #pragma clang diagnostic pop
4040 #elif defined(__GNUC__)
4041 #pragma GCC diagnostic pop
4042 #endif
4043 } // namespace panda::ecmascript
4044 #endif // ECMASCRIPT_INTERPRETER_INTERPRETER_INL_H
4045