1/*
2 * Copyright (c) 2021-2024 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#include "ecmascript/compiler/slowpath_lowering.h"
17
18#include "ecmascript/compiler/bytecodes.h"
19#include "ecmascript/compiler/circuit_builder.h"
20#include "ecmascript/compiler/share_gate_meta_data.h"
21#include "ecmascript/dfx/vm_thread_control.h"
22#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
23#include "ecmascript/js_async_generator_object.h"
24#include "ecmascript/js_generator_object.h"
25#include "ecmascript/js_thread.h"
26#include "ecmascript/jit/jit.h"
27#include "ecmascript/lexical_env.h"
28
29namespace panda::ecmascript::kungfu {
30using UseIterator = GateAccessor::UseIterator;
31
32#define CREATE_DOUBLE_EXIT(SuccessLabel, FailLabel)               \
33    StateDepend successControl;                                   \
34    StateDepend failControl;                                      \
35    builder_.Bind(&SuccessLabel);                                 \
36    {                                                             \
37        successControl.SetState(builder_.GetState());             \
38        successControl.SetDepend(builder_.GetDepend());           \
39    }                                                             \
40    builder_.Bind(&FailLabel);                                    \
41    {                                                             \
42        failControl.SetState(builder_.GetState());                \
43        failControl.SetDepend(builder_.GetDepend());              \
44    }
45
46void SlowPathLowering::CallRuntimeLowering()
47{
48    std::vector<GateRef> gateList;
49    circuit_->GetAllGates(gateList);
50
51    for (const auto &gate : gateList) {
52        auto op = acc_.GetOpCode(gate);
53        [[maybe_unused]] auto scopedGate = circuit_->VisitGateBegin(gate);
54        switch (op) {
55            case OpCode::JS_BYTECODE:
56                Lower(gate);
57                break;
58            case OpCode::GET_EXCEPTION: {
59                // initialize label manager
60                Environment env(gate, circuit_, &builder_);
61                LowerExceptionHandler(gate);
62                break;
63            }
64            case OpCode::CONSTRUCT:
65                LowerConstruct(gate);
66                break;
67            case OpCode::CALLINTERNAL:
68                LowerCallInternal(gate);
69                break;
70            case OpCode::CALL_NEW:
71                LowerCallNew(gate);
72                break;
73            case OpCode::TYPEDCALL:
74                LowerTypedCall(gate);
75                break;
76            case OpCode::TYPEDFASTCALL:
77                LowerTypedFastCall(gate);
78                break;
79            case OpCode::CHECK_SAFEPOINT_AND_STACKOVER:
80                LowerCheckSafePointAndStackOver(gate);
81                break;
82            case OpCode::GET_ENV:
83                LowerGetEnv(gate);
84                break;
85            case OpCode::LOOP_EXIT:
86                DeleteLoopExit(gate);
87                break;
88            case OpCode::LOOP_EXIT_VALUE:
89                DeleteLoopExitValue(gate);
90                break;
91            case OpCode::GET_UNSHARED_CONSTPOOL:
92                unsharedCP_.emplace_back(gate);
93                break;
94            default:
95                break;
96        }
97    }
98
99    // Make sure all IRs are lowered before lowering the constpool. If constpool is not used in CIR, it will be replaced
100    // by undefined.
101    for (const auto &gate : unsharedCP_) {
102        GateRef sharedConstPool = acc_.GetValueIn(gate, 0);
103        ASSERT(acc_.GetOpCode(sharedConstPool) == OpCode::GET_SHARED_CONSTPOOL);
104        LowerGetUnsharedConstPool(gate);
105        LowerGetSharedConstPool(sharedConstPool);
106    }
107
108    if (IsLogEnabled()) {
109        LOG_COMPILER(INFO) << " ";
110        LOG_COMPILER(INFO) << "\033[34m" << "================="
111                           << " After slowpath Lowering "
112                           << "[" << GetMethodName() << "] "
113                           << "=================" << "\033[0m";
114        circuit_->PrintAllGatesWithBytecode();
115        LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
116    }
117}
118
119void SlowPathLowering::LowerGetEnv(GateRef gate)
120{
121    GateRef jsFunc = acc_.GetValueIn(gate, 0);
122    GateRef envOffset = builder_.IntPtr(JSFunction::LEXICAL_ENV_OFFSET);
123    GateRef env = builder_.Load(VariableType::JS_ANY(), jsFunc, envOffset, acc_.GetDep(gate));
124    acc_.UpdateAllUses(gate, env);
125    acc_.DeleteGate(gate);
126}
127
128void SlowPathLowering::DeleteLoopExit(GateRef gate)
129{
130    auto state = acc_.GetState(gate);
131    acc_.ReplaceGate(gate, state, Circuit::NullGate(), Circuit::NullGate());
132}
133
134void SlowPathLowering::DeleteLoopExitValue(GateRef gate)
135{
136    auto state = acc_.GetState(gate);
137    auto value = acc_.GetValueIn(gate, 0);
138    acc_.ReplaceGate(gate, state, Circuit::NullGate(), value);
139}
140
141void SlowPathLowering::LowerToJSCall(GateRef hirGate, const std::vector<GateRef> &args,
142    const std::vector<GateRef> &argsFastCall)
143{
144    Label exit(&builder_);
145    DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
146    GateRef func = args[static_cast<size_t>(CommonArgIdx::FUNC)];
147    GateRef argc = args[static_cast<size_t>(CommonArgIdx::ACTUAL_ARGC)];
148    LowerFastCall(hirGate, glue_, func, argc, args, argsFastCall, &res, &exit, false);
149    builder_.Bind(&exit);
150    GateRef stateInGate = builder_.GetState();
151    GateRef depend = builder_.GetDepend();
152    ReplaceHirWithPendingException(hirGate, stateInGate, depend, *res);
153}
154
155void SlowPathLowering::ReplaceHirWithPendingException(GateRef hirGate,
156    GateRef state, GateRef depend, GateRef value)
157{
158    auto condition = builder_.HasPendingException(glue_);
159    GateRef ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
160    GateRef ifTrue = builder_.IfTrue(ifBranch);
161    GateRef ifFalse = builder_.IfFalse(ifBranch);
162    GateRef eDepend = builder_.DependRelay(ifTrue, depend);
163    GateRef sDepend = builder_.DependRelay(ifFalse, depend);
164
165    StateDepend success(ifFalse, sDepend);
166    StateDepend exception(ifTrue, eDepend);
167    acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
168}
169
170/*
171 * lower to slowpath call like this pattern:
172 * have throw:
173 * res = Call(...);
174 * if (res == VALUE_EXCEPTION) {
175 *     goto exception_handle;
176 * }
177 * Set(res);
178 *
179 * no throw:
180 * res = Call(...);
181 * Set(res);
182 */
183void SlowPathLowering::ReplaceHirWithValue(GateRef hirGate, GateRef value, bool noThrow)
184{
185    if (!noThrow) {
186        GateRef state = builder_.GetState();
187        // copy depend-wire of hirGate to value
188        GateRef depend = builder_.GetDepend();
189        // exception value
190        GateRef exceptionVal = builder_.ExceptionConstant();
191        // compare with trampolines result
192        GateRef equal = builder_.Equal(value, exceptionVal);
193        auto ifBranch = builder_.Branch(state, equal, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
194
195        GateRef ifTrue = builder_.IfTrue(ifBranch);
196        GateRef ifFalse = builder_.IfFalse(ifBranch);
197        GateRef eDepend = builder_.DependRelay(ifTrue, depend);
198        GateRef sDepend = builder_.DependRelay(ifFalse, depend);
199        StateDepend success(ifFalse, sDepend);
200        StateDepend exception(ifTrue, eDepend);
201        acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
202    } else {
203        acc_.ReplaceHirDirectly(hirGate, builder_.GetStateDepend(), value);
204    }
205}
206
207/*
208 * lower to throw call like this pattern:
209 * Call(...);
210 * goto exception_handle;
211 *
212 */
213void SlowPathLowering::ReplaceHirToThrowCall(GateRef hirGate, GateRef value)
214{
215    auto condition = builder_.HasPendingException(glue_);
216    GateRef state = builder_.GetState();
217    GateRef depend = builder_.GetDepend();
218    GateRef ifBranch = builder_.Branch(state, condition, BranchWeight::DEOPT_WEIGHT, 1, "checkException");
219    GateRef ifTrue = builder_.IfTrue(ifBranch);
220    GateRef ifFalse = builder_.IfFalse(ifBranch);
221    GateRef eDepend = builder_.DependRelay(ifTrue, depend);
222    GateRef sDepend = builder_.DependRelay(ifFalse, depend);
223
224    StateDepend success(ifFalse, sDepend);
225    StateDepend exception(ifTrue, eDepend);
226    acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
227}
228
229void SlowPathLowering::Lower(GateRef gate)
230{
231    EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
232    // initialize label manager
233    Environment env(gate, circuit_, &builder_);
234    AddProfiling(gate);
235    switch (ecmaOpcode) {
236        case EcmaOpcode::CALLARG0_IMM8:
237            LowerCallArg0(gate);
238            break;
239        case EcmaOpcode::CALLTHIS0_IMM8_V8:
240            LowerCallthis0Imm8V8(gate);
241            break;
242        case EcmaOpcode::CALLARG1_IMM8_V8:
243            LowerCallArg1Imm8V8(gate);
244            break;
245        case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
246            LowerWideCallrangePrefImm16V8(gate);
247            break;
248        case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
249            LowerCallThisArg1(gate);
250            break;
251        case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
252            LowerCallargs2Imm8V8V8(gate);
253            break;
254        case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
255            LowerCallthis2Imm8V8V8V8(gate);
256            break;
257        case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
258            LowerCallargs3Imm8V8V8(gate);
259            break;
260        case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
261            LowerCallthis3Imm8V8V8V8V8(gate);
262            break;
263        case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
264            LowerCallthisrangeImm8Imm8V8(gate);
265            break;
266        case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8:
267            LowerWideCallthisrangePrefImm16V8(gate);
268            break;
269        case EcmaOpcode::APPLY_IMM8_V8_V8:
270            LowerCallSpread(gate);
271            break;
272        case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
273            LowerCallrangeImm8Imm8V8(gate);
274            break;
275        case EcmaOpcode::GETUNMAPPEDARGS:
276            LowerGetUnmappedArgs(gate);
277            break;
278        case EcmaOpcode::ASYNCFUNCTIONENTER:
279            LowerAsyncFunctionEnter(gate);
280            break;
281        case EcmaOpcode::INC_IMM8:
282            LowerInc(gate);
283            break;
284        case EcmaOpcode::DEC_IMM8:
285            LowerDec(gate);
286            break;
287        case EcmaOpcode::GETPROPITERATOR:
288            LowerGetPropIterator(gate);
289            break;
290        case EcmaOpcode::RESUMEGENERATOR:
291            LowerResumeGenerator(gate);
292            break;
293        case EcmaOpcode::GETRESUMEMODE:
294            LowerGetResumeMode(gate);
295            break;
296        case EcmaOpcode::CLOSEITERATOR_IMM8_V8:
297        case EcmaOpcode::CLOSEITERATOR_IMM16_V8:
298            LowerCloseIterator(gate);
299            break;
300        case EcmaOpcode::ADD2_IMM8_V8:
301            LowerAdd2(gate);
302            break;
303        case EcmaOpcode::SUB2_IMM8_V8:
304            LowerSub2(gate);
305            break;
306        case EcmaOpcode::MUL2_IMM8_V8:
307            LowerMul2(gate);
308            break;
309        case EcmaOpcode::DIV2_IMM8_V8:
310            LowerDiv2(gate);
311            break;
312        case EcmaOpcode::MOD2_IMM8_V8:
313            LowerMod2(gate);
314            break;
315        case EcmaOpcode::EQ_IMM8_V8:
316            LowerEq(gate);
317            break;
318        case EcmaOpcode::NOTEQ_IMM8_V8:
319            LowerNotEq(gate);
320            break;
321        case EcmaOpcode::LESS_IMM8_V8:
322            LowerLess(gate);
323            break;
324        case EcmaOpcode::LESSEQ_IMM8_V8:
325            LowerLessEq(gate);
326            break;
327        case EcmaOpcode::GREATER_IMM8_V8:
328            LowerGreater(gate);
329            break;
330        case EcmaOpcode::GREATEREQ_IMM8_V8:
331            LowerGreaterEq(gate);
332            break;
333        case EcmaOpcode::CREATEITERRESULTOBJ_V8_V8:
334            LowerCreateIterResultObj(gate);
335            break;
336        case EcmaOpcode::SUSPENDGENERATOR_V8:
337            LowerSuspendGenerator(gate);
338            break;
339        case EcmaOpcode::ASYNCFUNCTIONAWAITUNCAUGHT_V8:
340            LowerAsyncFunctionAwaitUncaught(gate);
341            break;
342        case EcmaOpcode::ASYNCFUNCTIONRESOLVE_V8:
343            LowerAsyncFunctionResolve(gate);
344            break;
345        case EcmaOpcode::ASYNCFUNCTIONREJECT_V8:
346            LowerAsyncFunctionReject(gate);
347            break;
348        case EcmaOpcode::TRYLDGLOBALBYNAME_IMM8_ID16:
349        case EcmaOpcode::TRYLDGLOBALBYNAME_IMM16_ID16:
350            LowerTryLdGlobalByName(gate);
351            break;
352        case EcmaOpcode::STGLOBALVAR_IMM16_ID16:
353            LowerStGlobalVar(gate);
354            break;
355        case EcmaOpcode::GETITERATOR_IMM8:
356        case EcmaOpcode::GETITERATOR_IMM16:
357            LowerGetIterator(gate);
358            break;
359        case EcmaOpcode::GETASYNCITERATOR_IMM8:
360            LowerGetAsyncIterator(gate);
361            break;
362        case EcmaOpcode::NEWOBJAPPLY_IMM8_V8:
363        case EcmaOpcode::NEWOBJAPPLY_IMM16_V8:
364            LowerNewObjApply(gate);
365            break;
366        case EcmaOpcode::THROW_PREF_NONE:
367            LowerThrow(gate);
368            break;
369        case EcmaOpcode::TYPEOF_IMM8:
370        case EcmaOpcode::TYPEOF_IMM16:
371            LowerTypeof(gate);
372            break;
373        case EcmaOpcode::THROW_CONSTASSIGNMENT_PREF_V8:
374            LowerThrowConstAssignment(gate);
375            break;
376        case EcmaOpcode::THROW_NOTEXISTS_PREF_NONE:
377            LowerThrowThrowNotExists(gate);
378            break;
379        case EcmaOpcode::THROW_PATTERNNONCOERCIBLE_PREF_NONE:
380            LowerThrowPatternNonCoercible(gate);
381            break;
382        case EcmaOpcode::THROW_IFNOTOBJECT_PREF_V8:
383            LowerThrowIfNotObject(gate);
384            break;
385        case EcmaOpcode::THROW_UNDEFINEDIFHOLE_PREF_V8_V8:
386            LowerThrowUndefinedIfHole(gate);
387            break;
388        case EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16:
389            LowerThrowUndefinedIfHoleWithName(gate);
390            break;
391        case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM8:
392        case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM16:
393            LowerThrowIfSuperNotCorrectCall(gate);
394            break;
395        case EcmaOpcode::THROW_DELETESUPERPROPERTY_PREF_NONE:
396            LowerThrowDeleteSuperProperty(gate);
397            break;
398        case EcmaOpcode::LDSYMBOL:
399            LowerLdSymbol(gate);
400            break;
401        case EcmaOpcode::LDGLOBAL:
402            LowerLdGlobal(gate);
403            break;
404        case EcmaOpcode::TONUMBER_IMM8:
405            LowerToNumber(gate);
406            break;
407        case EcmaOpcode::NEG_IMM8:
408            LowerNeg(gate);
409            break;
410        case EcmaOpcode::NOT_IMM8:
411            LowerNot(gate);
412            break;
413        case EcmaOpcode::SHL2_IMM8_V8:
414            LowerShl2(gate);
415            break;
416        case EcmaOpcode::SHR2_IMM8_V8:
417            LowerShr2(gate);
418            break;
419        case EcmaOpcode::ASHR2_IMM8_V8:
420            LowerAshr2(gate);
421            break;
422        case EcmaOpcode::AND2_IMM8_V8:
423            LowerAnd2(gate);
424            break;
425        case EcmaOpcode::OR2_IMM8_V8:
426            LowerOr2(gate);
427            break;
428        case EcmaOpcode::XOR2_IMM8_V8:
429            LowerXor2(gate);
430            break;
431        case EcmaOpcode::DELOBJPROP_V8:
432            LowerDelObjProp(gate);
433            break;
434        case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8:
435        case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8:
436            LowerDefineMethod(gate);
437            break;
438        case EcmaOpcode::EXP_IMM8_V8:
439            LowerExp(gate);
440            break;
441        case EcmaOpcode::ISIN_IMM8_V8:
442            LowerIsIn(gate);
443            break;
444        case EcmaOpcode::INSTANCEOF_IMM8_V8:
445            LowerInstanceof(gate);
446            break;
447        case EcmaOpcode::STRICTNOTEQ_IMM8_V8:
448            LowerFastStrictNotEqual(gate);
449            break;
450        case EcmaOpcode::STRICTEQ_IMM8_V8:
451            LowerFastStrictEqual(gate);
452            break;
453        case EcmaOpcode::CREATEEMPTYARRAY_IMM8:
454        case EcmaOpcode::CREATEEMPTYARRAY_IMM16:
455            LowerCreateEmptyArray(gate);
456            break;
457        case EcmaOpcode::CREATEEMPTYOBJECT:
458            LowerCreateEmptyObject(gate);
459            break;
460        case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
461        case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
462            LowerCreateObjectWithBuffer(gate);
463            break;
464        case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
465        case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
466            LowerCreateArrayWithBuffer(gate);
467            break;
468        case EcmaOpcode::STMODULEVAR_IMM8:
469        case EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16:
470            LowerStModuleVar(gate);
471            break;
472        case EcmaOpcode::SETGENERATORSTATE_IMM8:
473            LowerSetGeneratorState(gate);
474            break;
475        case EcmaOpcode::GETTEMPLATEOBJECT_IMM8:
476        case EcmaOpcode::GETTEMPLATEOBJECT_IMM16:
477            LowerGetTemplateObject(gate);
478            break;
479        case EcmaOpcode::SETOBJECTWITHPROTO_IMM8_V8:
480        case EcmaOpcode::SETOBJECTWITHPROTO_IMM16_V8:
481            LowerSetObjectWithProto(gate);
482            break;
483        case EcmaOpcode::LDBIGINT_ID16:
484            LowerLdBigInt(gate);
485            break;
486        case EcmaOpcode::TONUMERIC_IMM8:
487            LowerToNumeric(gate);
488            break;
489        case EcmaOpcode::DYNAMICIMPORT:
490            LowerDynamicImport(gate);
491            break;
492        case EcmaOpcode::LDEXTERNALMODULEVAR_IMM8:
493        case EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16:
494            LowerExternalModule(gate);
495            break;
496        case EcmaOpcode::GETMODULENAMESPACE_IMM8:
497        case EcmaOpcode::WIDE_GETMODULENAMESPACE_PREF_IMM16:
498            LowerGetModuleNamespace(gate);
499            break;
500        case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8:
501        case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8:
502        case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8:
503            LowerNewObjRange(gate);
504            break;
505        case EcmaOpcode::JEQZ_IMM8:
506        case EcmaOpcode::JEQZ_IMM16:
507        case EcmaOpcode::JEQZ_IMM32:
508            LowerConditionJump(gate, true);
509            break;
510        case EcmaOpcode::JNEZ_IMM8:
511        case EcmaOpcode::JNEZ_IMM16:
512        case EcmaOpcode::JNEZ_IMM32:
513            LowerConditionJump(gate, false);
514            break;
515        case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
516        case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
517            LowerSuperCall(gate);
518            break;
519        case EcmaOpcode::SUPERCALLARROWRANGE_IMM8_IMM8_V8:
520        case EcmaOpcode::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8:
521            LowerSuperCallArrow(gate);
522            break;
523        case EcmaOpcode::SUPERCALLSPREAD_IMM8_V8:
524            LowerSuperCallSpread(gate);
525            break;
526        case EcmaOpcode::CALLRUNTIME_SUPERCALLFORWARDALLARGS_PREF_V8:
527            LowerSuperCallForwardAllArgs(gate);
528            break;
529        case EcmaOpcode::ISTRUE:
530        case EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8:
531            LowerIsTrueOrFalse(gate, true);
532            break;
533        case EcmaOpcode::ISFALSE:
534        case EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8:
535            LowerIsTrueOrFalse(gate, false);
536            break;
537        case EcmaOpcode::GETNEXTPROPNAME_V8:
538            LowerGetNextPropName(gate);
539            break;
540        case EcmaOpcode::COPYDATAPROPERTIES_V8:
541            LowerCopyDataProperties(gate);
542            break;
543        case EcmaOpcode::CREATEOBJECTWITHEXCLUDEDKEYS_IMM8_V8_V8:
544        case EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8:
545            LowerCreateObjectWithExcludedKeys(gate);
546            break;
547        case EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
548        case EcmaOpcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
549            LowerCreateRegExpWithLiteral(gate);
550            break;
551        case EcmaOpcode::STOWNBYVALUE_IMM8_V8_V8:
552        case EcmaOpcode::STOWNBYVALUE_IMM16_V8_V8:
553            LowerStOwnByValue(gate);
554            break;
555        case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16:
556        case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16:
557        case EcmaOpcode::WIDE_STOWNBYINDEX_PREF_V8_IMM32:
558            LowerStOwnByIndex(gate);
559            break;
560        case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8:
561        case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8:
562            LowerStOwnByName(gate);
563            break;
564        case EcmaOpcode::NEWLEXENV_IMM8:
565        case EcmaOpcode::WIDE_NEWLEXENV_PREF_IMM16:
566            LowerNewLexicalEnv(gate);
567            break;
568        case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16:
569        case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16:
570            LowerNewLexicalEnvWithName(gate);
571            break;
572        case EcmaOpcode::POPLEXENV:
573            LowerPopLexicalEnv(gate);
574            break;
575        case EcmaOpcode::LDSUPERBYVALUE_IMM8_V8:
576        case EcmaOpcode::LDSUPERBYVALUE_IMM16_V8:
577            LowerLdSuperByValue(gate);
578            break;
579        case EcmaOpcode::STSUPERBYVALUE_IMM16_V8_V8:
580        case EcmaOpcode::STSUPERBYVALUE_IMM8_V8_V8:
581            LowerStSuperByValue(gate);
582            break;
583        case EcmaOpcode::TRYSTGLOBALBYNAME_IMM8_ID16:
584        case EcmaOpcode::TRYSTGLOBALBYNAME_IMM16_ID16:
585            LowerTryStGlobalByName(gate);
586            break;
587        case EcmaOpcode::STCONSTTOGLOBALRECORD_IMM16_ID16:
588            LowerStConstToGlobalRecord(gate, true);
589            break;
590        case EcmaOpcode::STTOGLOBALRECORD_IMM16_ID16:
591            LowerStConstToGlobalRecord(gate, false);
592            break;
593        case EcmaOpcode::STOWNBYVALUEWITHNAMESET_IMM8_V8_V8:
594        case EcmaOpcode::STOWNBYVALUEWITHNAMESET_IMM16_V8_V8:
595            LowerStOwnByValueWithNameSet(gate);
596            break;
597        case EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
598        case EcmaOpcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8:
599            LowerStOwnByNameWithNameSet(gate);
600            break;
601        case EcmaOpcode::LDGLOBALVAR_IMM16_ID16:
602            LowerLdGlobalVar(gate);
603            break;
604        case EcmaOpcode::LDOBJBYNAME_IMM8_ID16:
605        case EcmaOpcode::LDOBJBYNAME_IMM16_ID16:
606            LowerLdObjByName(gate);
607            break;
608        case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
609        case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
610            LowerStObjByName(gate, false);
611            break;
612        case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8:
613            LowerDefineGetterSetterByValue(gate);
614            break;
615        case EcmaOpcode::LDOBJBYINDEX_IMM8_IMM16:
616        case EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16:
617        case EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32:
618            LowerLdObjByIndex(gate);
619            break;
620        case EcmaOpcode::STOBJBYINDEX_IMM8_V8_IMM16:
621        case EcmaOpcode::STOBJBYINDEX_IMM16_V8_IMM16:
622        case EcmaOpcode::WIDE_STOBJBYINDEX_PREF_V8_IMM32:
623            LowerStObjByIndex(gate);
624            break;
625        case EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
626        case EcmaOpcode::LDOBJBYVALUE_IMM16_V8:
627            LowerLdObjByValue(gate, false);
628            break;
629        case EcmaOpcode::LDTHISBYVALUE_IMM8:
630        case EcmaOpcode::LDTHISBYVALUE_IMM16:
631            LowerLdObjByValue(gate, true);
632            break;
633        case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8:
634        case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8:
635            LowerStObjByValue(gate, false);
636            break;
637        case EcmaOpcode::STTHISBYVALUE_IMM8_V8:
638        case EcmaOpcode::STTHISBYVALUE_IMM16_V8:
639            LowerStObjByValue(gate, true);
640            break;
641        case EcmaOpcode::LDSUPERBYNAME_IMM8_ID16:
642        case EcmaOpcode::LDSUPERBYNAME_IMM16_ID16:
643            LowerLdSuperByName(gate);
644            break;
645        case EcmaOpcode::STSUPERBYNAME_IMM8_ID16_V8:
646        case EcmaOpcode::STSUPERBYNAME_IMM16_ID16_V8:
647            LowerStSuperByName(gate);
648            break;
649        case EcmaOpcode::CREATEGENERATOROBJ_V8:
650            LowerCreateGeneratorObj(gate);
651            break;
652        case EcmaOpcode::CREATEASYNCGENERATOROBJ_V8:
653            LowerCreateAsyncGeneratorObj(gate);
654            break;
655        case EcmaOpcode::ASYNCGENERATORRESOLVE_V8_V8_V8:
656            LowerAsyncGeneratorResolve(gate);
657            break;
658        case EcmaOpcode::ASYNCGENERATORREJECT_V8:
659            LowerAsyncGeneratorReject(gate);
660            break;
661        case EcmaOpcode::STARRAYSPREAD_V8_V8:
662            LowerStArraySpread(gate);
663            break;
664        case EcmaOpcode::LDLEXVAR_IMM4_IMM4:
665        case EcmaOpcode::LDLEXVAR_IMM8_IMM8:
666        case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16:
667            LowerLdLexVar(gate);
668            break;
669        case EcmaOpcode::STLEXVAR_IMM4_IMM4:
670        case EcmaOpcode::STLEXVAR_IMM8_IMM8:
671        case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16:
672            LowerStLexVar(gate);
673            break;
674        case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:
675        case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8:
676            LowerDefineClassWithBuffer(gate);
677            break;
678        case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8:
679        case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8:
680            LowerDefineFunc(gate);
681            break;
682        case EcmaOpcode::COPYRESTARGS_IMM8:
683        case EcmaOpcode::WIDE_COPYRESTARGS_PREF_IMM16:
684            LowerCopyRestArgs(gate);
685            break;
686        case EcmaOpcode::WIDE_LDPATCHVAR_PREF_IMM16:
687            LowerWideLdPatchVar(gate);
688            break;
689        case EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16:
690            LowerWideStPatchVar(gate);
691            break;
692        case EcmaOpcode::LDLOCALMODULEVAR_IMM8:
693        case EcmaOpcode::WIDE_LDLOCALMODULEVAR_PREF_IMM16:
694            LowerLdLocalModuleVarByIndex(gate);
695            break;
696        case EcmaOpcode::DEBUGGER:
697        case EcmaOpcode::JSTRICTEQZ_IMM8:
698        case EcmaOpcode::JSTRICTEQZ_IMM16:
699        case EcmaOpcode::JNSTRICTEQZ_IMM8:
700        case EcmaOpcode::JNSTRICTEQZ_IMM16:
701        case EcmaOpcode::JEQNULL_IMM8:
702        case EcmaOpcode::JEQNULL_IMM16:
703        case EcmaOpcode::JNENULL_IMM8:
704        case EcmaOpcode::JNENULL_IMM16:
705        case EcmaOpcode::JSTRICTEQNULL_IMM8:
706        case EcmaOpcode::JSTRICTEQNULL_IMM16:
707        case EcmaOpcode::JNSTRICTEQNULL_IMM8:
708        case EcmaOpcode::JNSTRICTEQNULL_IMM16:
709        case EcmaOpcode::JEQUNDEFINED_IMM8:
710        case EcmaOpcode::JEQUNDEFINED_IMM16:
711        case EcmaOpcode::JNEUNDEFINED_IMM8:
712        case EcmaOpcode::JNEUNDEFINED_IMM16:
713        case EcmaOpcode::JSTRICTEQUNDEFINED_IMM8:
714        case EcmaOpcode::JSTRICTEQUNDEFINED_IMM16:
715        case EcmaOpcode::JNSTRICTEQUNDEFINED_IMM8:
716        case EcmaOpcode::JNSTRICTEQUNDEFINED_IMM16:
717        case EcmaOpcode::JEQ_V8_IMM8:
718        case EcmaOpcode::JEQ_V8_IMM16:
719        case EcmaOpcode::JNE_V8_IMM8:
720        case EcmaOpcode::JNE_V8_IMM16:
721        case EcmaOpcode::JSTRICTEQ_V8_IMM8:
722        case EcmaOpcode::JSTRICTEQ_V8_IMM16:
723        case EcmaOpcode::JNSTRICTEQ_V8_IMM8:
724        case EcmaOpcode::JNSTRICTEQ_V8_IMM16:
725            break;
726        case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
727        case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
728            LowerLdThisByName(gate);
729            break;
730        case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
731        case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
732            LowerStObjByName(gate, true);
733            break;
734        case EcmaOpcode::LDPRIVATEPROPERTY_IMM8_IMM16_IMM16:
735            LowerLdPrivateProperty(gate);
736            break;
737        case EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8:
738            LowerStPrivateProperty(gate);
739            break;
740        case EcmaOpcode::TESTIN_IMM8_IMM16_IMM16:
741            LowerTestIn(gate);
742            break;
743        case EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE:
744            LowerNotifyConcurrentResult(gate);
745            break;
746        case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
747        case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
748            LowerDefineFieldByName(gate);
749            break;
750        case EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYVALUE_PREF_IMM8_V8_V8:
751            LowerDefineFieldByValue(gate);
752            break;
753        case EcmaOpcode::CALLRUNTIME_DEFINEFIELDBYINDEX_PREF_IMM8_IMM32_V8:
754            LowerDefineFieldByIndex(gate);
755            break;
756        case EcmaOpcode::CALLRUNTIME_TOPROPERTYKEY_PREF_NONE:
757            LowerToPropertyKey(gate);
758            break;
759        case EcmaOpcode::CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16:
760            LowerCreatePrivateProperty(gate);
761            break;
762        case EcmaOpcode::CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8:
763            LowerDefinePrivateProperty(gate);
764            break;
765        case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8:
766            LowerCallInit(gate);
767            break;
768        case EcmaOpcode::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8:
769            LowerDefineSendableClass(gate);
770            break;
771        case EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16:
772            LowerLdSendableClass(gate);
773            break;
774        case EcmaOpcode::CALLRUNTIME_LDSENDABLEEXTERNALMODULEVAR_PREF_IMM8:
775        case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEEXTERNALMODULEVAR_PREF_IMM16:
776            LowerSendableExternalModule(gate);
777            break;
778        case EcmaOpcode::CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8:
779        case EcmaOpcode::CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16:
780            LowerNewSendableEnv(gate);
781            break;
782        case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4:
783        case EcmaOpcode::CALLRUNTIME_STSENDABLEVAR_PREF_IMM8_IMM8:
784        case EcmaOpcode::CALLRUNTIME_WIDESTSENDABLEVAR_PREF_IMM16_IMM16:
785            LowerStSendableVar(gate);
786            break;
787        case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4:
788        case EcmaOpcode::CALLRUNTIME_LDSENDABLEVAR_PREF_IMM8_IMM8:
789        case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16:
790            LowerLdSendableVar(gate);
791            break;
792        case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8:
793        case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16:
794            LowerLdLazyExternalModuleVar(gate);
795            break;
796        case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8:
797        case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16:
798            LowerLdLazySendableExternalModuleVar(gate);
799            break;
800        case EcmaOpcode::LDA_STR_ID16:
801            LowerLdStr(gate);
802            break;
803        default:
804            break;
805    }
806}
807
808void SlowPathLowering::LowerCallStubWithIC(GateRef gate, int sign, const std::vector<GateRef> &args)
809{
810    std::vector<GateRef> inputs { glue_ };
811    inputs.insert(inputs.end(), args.begin(), args.end());
812    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
813    GateRef slotId = builder_.ZExtInt16ToInt32(acc_.GetValueIn(gate, 0));
814    inputs.emplace_back(jsFunc);
815    inputs.emplace_back(slotId);
816
817    GateRef result = builder_.CallStub(glue_, gate, sign, inputs);
818    ReplaceHirWithValue(gate, result);
819}
820
821GateRef SlowPathLowering::LowerCallRuntime(GateRef gate, int index, const std::vector<GateRef> &args, bool useLabel)
822{
823    const std::string name = RuntimeStubCSigns::GetRTName(index);
824    if (useLabel) {
825        GateRef result = builder_.CallRuntime(glue_, index, Gate::InvalidGateRef, args, gate, name.c_str());
826        return result;
827    } else {
828        const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
829        GateRef target = builder_.IntPtr(index);
830        GateRef result = builder_.Call(cs, glue_, target, builder_.GetDepend(), args, gate, name.c_str());
831        return result;
832    }
833}
834
835GateRef SlowPathLowering::LowerCallNGCRuntime(GateRef gate, int index, const std::vector<GateRef> &args, bool useLabel)
836{
837    const std::string name = RuntimeStubCSigns::GetRTName(index);
838    if (useLabel) {
839        GateRef result = builder_.CallNGCRuntime(glue_, index, Gate::InvalidGateRef, args, gate, name.c_str());
840        return result;
841    } else {
842        const CallSignature *cs = RuntimeStubCSigns::Get(index);
843        GateRef target = builder_.IntPtr(index);
844        GateRef result = builder_.Call(cs, glue_, target, builder_.GetDepend(), args, gate, name.c_str());
845        return result;
846    }
847}
848
849void SlowPathLowering::LowerAdd2(GateRef gate)
850{
851    // 2: number of value inputs
852    ASSERT(acc_.GetNumValueIn(gate) == 2);
853    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Add,
854        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
855    ReplaceHirWithValue(gate, result);
856}
857
858void SlowPathLowering::LowerCreateIterResultObj(GateRef gate)
859{
860    const int id = RTSTUB_ID(CreateIterResultObj);
861    // 2: number of value inputs
862    ASSERT(acc_.GetNumValueIn(gate) == 2);
863    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)});
864    ReplaceHirWithValue(gate, newGate);
865}
866
867// When executing to SUSPENDGENERATOR instruction, save contextual information to GeneratorContext,
868// including registers, acc, etc.
869void SlowPathLowering::SaveFrameToContext(GateRef gate)
870{
871    GateRef genObj = acc_.GetValueIn(gate, 1);
872    GateRef saveRegister = acc_.GetDep(gate);
873    while (acc_.GetOpCode(saveRegister) != OpCode::SAVE_REGISTER) {
874        saveRegister = acc_.GetDep(saveRegister);
875    }
876    ASSERT(acc_.GetOpCode(saveRegister) == OpCode::SAVE_REGISTER);
877
878    acc_.SetDep(gate, acc_.GetDep(saveRegister));
879    builder_.SetDepend(acc_.GetDep(saveRegister));
880    GateRef context =
881        builder_.Load(VariableType::JS_POINTER(), genObj, builder_.IntPtr(JSGeneratorObject::GENERATOR_CONTEXT_OFFSET));
882    // new tagged array
883    auto method = methodLiteral_;
884    const size_t arrLength = method->GetNumberVRegs() + 1; // 1: env vreg
885    GateRef length = builder_.Int32(arrLength);
886    GateRef taggedLength = builder_.ToTaggedInt(builder_.ZExtInt32ToInt64(length));
887    const int arrayId = RTSTUB_ID(NewTaggedArray);
888    GateRef taggedArray = LowerCallRuntime(gate, arrayId, {taggedLength});
889    // setRegsArrays
890    auto hole = builder_.HoleConstant();
891    size_t numVreg = acc_.GetNumValueIn(saveRegister);
892    for (size_t idx = 0; idx < numVreg; idx++) {
893        GateRef tmpGate = acc_.GetValueIn(saveRegister, idx);
894        if (tmpGate != hole) {
895            builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, taggedArray, builder_.Int32(idx), tmpGate);
896        }
897    }
898    ASSERT(numVreg > 0);
899    GateRef lexicalEnvGate = acc_.GetValueIn(saveRegister, numVreg - 1);
900    acc_.DeleteGate(saveRegister);
901
902    // setRegsArrays
903    GateRef regsArrayOffset = builder_.IntPtr(GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET);
904    builder_.Store(VariableType::JS_POINTER(), glue_, context, regsArrayOffset, taggedArray);
905
906    // set this
907    GateRef thisOffset = builder_.IntPtr(GeneratorContext::GENERATOR_THIS_OFFSET);
908    GateRef thisObj = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
909    builder_.Store(VariableType::JS_ANY(), glue_, context, thisOffset, thisObj);
910
911    // set method
912    GateRef methodOffset = builder_.IntPtr(GeneratorContext::GENERATOR_METHOD_OFFSET);
913    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
914    builder_.Store(VariableType::JS_ANY(), glue_, context, methodOffset, jsFunc);
915
916    // set acc
917    ASSERT(acc_.GetNumValueIn(gate) > 0);
918    GateRef accOffset = builder_.IntPtr(GeneratorContext::GENERATOR_ACC_OFFSET);
919    GateRef curAccGate = acc_.GetValueIn(gate, acc_.GetNumValueIn(gate) - 1); // get current acc
920    builder_.Store(VariableType::JS_ANY(), glue_, context, accOffset, curAccGate);
921
922    // set generator object
923    GateRef generatorObjectOffset = builder_.IntPtr(GeneratorContext::GENERATOR_GENERATOR_OBJECT_OFFSET);
924    builder_.Store(VariableType::JS_ANY(), glue_, context, generatorObjectOffset, genObj);
925
926    // set lexical env
927    GateRef lexicalEnvOffset = builder_.IntPtr(GeneratorContext::GENERATOR_LEXICALENV_OFFSET);
928    builder_.Store(VariableType::JS_ANY(), glue_, context, lexicalEnvOffset, lexicalEnvGate);
929
930    // set nregs
931    GateRef nregsOffset = builder_.IntPtr(GeneratorContext::GENERATOR_NREGS_OFFSET);
932    builder_.Store(VariableType::INT32(), glue_, context, nregsOffset, length);
933
934    // set bc size
935    GateRef bcSizeOffset = builder_.IntPtr(GeneratorContext::GENERATOR_BC_OFFSET_OFFSET);
936    GateRef bcSizeGate = acc_.GetValueIn(gate, 0); // saved bc_offset
937    bcSizeGate = builder_.TruncInt64ToInt32(bcSizeGate);
938    builder_.Store(VariableType::INT32(), glue_, context, bcSizeOffset, bcSizeGate);
939
940    // set context to generator object
941    GateRef contextOffset = builder_.IntPtr(JSGeneratorObject::GENERATOR_CONTEXT_OFFSET);
942    builder_.Store(VariableType::JS_POINTER(), glue_, genObj, contextOffset, context);
943
944    // set generator object to context
945    builder_.Store(VariableType::JS_POINTER(), glue_, context, generatorObjectOffset, genObj);
946}
947
948void SlowPathLowering::LowerSuspendGenerator(GateRef gate)
949{
950    SaveFrameToContext(gate);
951    acc_.SetDep(gate, builder_.GetDepend());
952    AddProfiling(gate, false);
953    const int id = RTSTUB_ID(OptSuspendGenerator);
954    auto value = acc_.GetValueIn(gate, 2); // 2: acc
955    auto genObj = acc_.GetValueIn(gate, 1);
956    GateRef newGate = LowerCallRuntime(gate, id, { genObj, value });
957    ReplaceHirWithValue(gate, newGate);
958}
959
960void SlowPathLowering::LowerAsyncFunctionAwaitUncaught(GateRef gate)
961{
962    const int id = RTSTUB_ID(AsyncFunctionAwaitUncaught);
963    // 2: number of value inputs
964    ASSERT(acc_.GetNumValueIn(gate) == 2);
965    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)});
966    ReplaceHirWithValue(gate, newGate);
967}
968
969void SlowPathLowering::LowerAsyncFunctionResolve(GateRef gate)
970{
971    const int id = RTSTUB_ID(AsyncFunctionResolveOrReject);
972    // 2: number of value inputs
973    ASSERT(acc_.GetNumValueIn(gate) == 2);
974    GateRef taggedTrue = builder_.TaggedTrue();
975    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1), taggedTrue});
976    ReplaceHirWithValue(gate, newGate);
977}
978
979void SlowPathLowering::LowerAsyncFunctionReject(GateRef gate)
980{
981    const int id = RTSTUB_ID(AsyncFunctionResolveOrReject);
982    // 2: number of value inputs
983    ASSERT(acc_.GetNumValueIn(gate) == 2);
984    GateRef taggedFalse = builder_.TaggedFalse();
985    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1), taggedFalse});
986    ReplaceHirWithValue(gate, newGate);
987}
988
989void SlowPathLowering::LowerTryLdGlobalByName(GateRef gate)
990{
991    // 2: number of value inputs
992    ASSERT(acc_.GetNumValueIn(gate) == 2);
993    GateRef stringId = acc_.GetValueIn(gate, 1);  // 1: the second parameter
994    LowerCallStubWithIC(gate, CommonStubCSigns::TryLdGlobalByName, { stringId });
995}
996
997void SlowPathLowering::LowerStGlobalVar(GateRef gate)
998{
999    // 3: number of value inputs
1000    ASSERT(acc_.GetNumValueIn(gate) == 3);
1001    GateRef id = acc_.GetValueIn(gate, 1);  // 1: the second parameter
1002    GateRef value = acc_.GetValueIn(gate, 2);  // 2: the 2nd para is value
1003    LowerCallStubWithIC(gate, CommonStubCSigns::StGlobalVar, { id, value });
1004}
1005
1006void SlowPathLowering::LowerGetIterator(GateRef gate)
1007{
1008    auto result = LowerCallRuntime(gate, RTSTUB_ID(GetIterator), {acc_.GetValueIn(gate, 0)}, true);
1009    ReplaceHirWithValue(gate, result);
1010}
1011
1012void SlowPathLowering::LowerGetAsyncIterator(GateRef gate)
1013{
1014    auto result = LowerCallRuntime(gate, RTSTUB_ID(GetAsyncIterator), {acc_.GetValueIn(gate, 0)}, true);
1015    ReplaceHirWithValue(gate, result);
1016}
1017
1018void SlowPathLowering::LowerCallArg0(GateRef gate)
1019{
1020    // 1: number of value inputs
1021    ASSERT(acc_.GetNumValueIn(gate) == 1);
1022
1023    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
1024        EcmaOpcode::CALLARG0_IMM8));
1025    GateRef actualArgv = builder_.IntPtr(0);
1026    GateRef newTarget = builder_.Undefined();
1027    GateRef thisObj = builder_.Undefined();
1028    GateRef func = acc_.GetValueIn(gate, 0);
1029    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj}, {glue_, func, thisObj});
1030}
1031
1032void SlowPathLowering::LowerCallthisrangeImm8Imm8V8(GateRef gate)
1033{
1034    // this
1035    size_t fixedInputsNum = 1;
1036    size_t numIns = acc_.GetNumValueIn(gate);
1037    ASSERT(numIns >= fixedInputsNum);
1038    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
1039        EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8));
1040    GateRef actualArgv = builder_.IntPtr(0);
1041    const size_t callTargetIndex = 1;  // 1: acc
1042    GateRef callTarget = acc_.GetValueIn(gate, numIns - callTargetIndex); // acc
1043    GateRef thisObj = acc_.GetValueIn(gate, 0);
1044    GateRef newTarget = builder_.Undefined();
1045    std::vector<GateRef> vec { glue_, actualArgc, actualArgv, callTarget, newTarget, thisObj };
1046    // add common args
1047    for (size_t i = fixedInputsNum; i < numIns - callTargetIndex; i++) {
1048        vec.emplace_back(acc_.GetValueIn(gate, i));
1049    }
1050    std::vector<GateRef> vec1 { glue_, callTarget, thisObj };
1051    // add common args
1052    for (size_t i = fixedInputsNum; i < numIns - callTargetIndex; i++) {
1053        vec1.emplace_back(acc_.GetValueIn(gate, i));
1054    }
1055    LowerToJSCall(gate, vec, vec1);
1056}
1057
1058void SlowPathLowering::LowerWideCallthisrangePrefImm16V8(GateRef gate)
1059{
1060    // The first register input is thisobj, second is thisObj and other inputs are common args.
1061    size_t fixedInputsNum = 1; // 1: acc
1062    size_t numIns = acc_.GetNumValueIn(gate);
1063    ASSERT(numIns >= fixedInputsNum);
1064    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
1065        EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8));
1066    GateRef actualArgv = builder_.IntPtr(0);
1067    const size_t callTargetIndex = 1;
1068    GateRef callTarget = acc_.GetValueIn(gate, numIns - callTargetIndex);
1069    GateRef thisObj = acc_.GetValueIn(gate, 0);
1070    GateRef newTarget = builder_.Undefined();
1071    std::vector<GateRef> vec {glue_, actualArgc, actualArgv, callTarget, newTarget, thisObj};
1072    // add common args
1073    for (size_t i = fixedInputsNum; i < numIns - callTargetIndex; i++) {
1074        vec.emplace_back(acc_.GetValueIn(gate, i));
1075    }
1076    std::vector<GateRef> vec1 {glue_, callTarget, thisObj};
1077    // add common args
1078    for (size_t i = fixedInputsNum; i < numIns - callTargetIndex; i++) {
1079        vec1.emplace_back(acc_.GetValueIn(gate, i));
1080    }
1081    LowerToJSCall(gate, vec, vec1);
1082}
1083
1084void SlowPathLowering::LowerCallSpread(GateRef gate)
1085{
1086    // need to fixed in later
1087    const int id = RTSTUB_ID(CallSpread);
1088    // 3: number of value inputs
1089    ASSERT(acc_.GetNumValueIn(gate) == 3);
1090    GateRef stateInGate = builder_.GetState();
1091    GateRef newGate = LowerCallRuntime(gate, id,
1092        {acc_.GetValueIn(gate, 2), acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)});
1093    ReplaceHirWithPendingException(gate, stateInGate, newGate, newGate);
1094}
1095
1096void SlowPathLowering::LowerCallrangeImm8Imm8V8(GateRef gate)
1097{
1098    size_t numArgs = acc_.GetNumValueIn(gate);
1099    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
1100        EcmaOpcode::CALLRANGE_IMM8_IMM8_V8));
1101    GateRef actualArgv = builder_.IntPtr(0);
1102    const size_t callTargetIndex = 1; // acc
1103    ASSERT(numArgs > 0);
1104    GateRef callTarget = acc_.GetValueIn(gate, numArgs - callTargetIndex);
1105    GateRef newTarget = builder_.Undefined();
1106    GateRef thisObj = builder_.Undefined();
1107    std::vector<GateRef> vec {glue_, actualArgc, actualArgv, callTarget, newTarget, thisObj};
1108    for (size_t i = 0; i < numArgs - callTargetIndex; i++) { // 2: skip acc
1109        vec.emplace_back(acc_.GetValueIn(gate, i));
1110    }
1111    std::vector<GateRef> vec1 {glue_, callTarget, thisObj};
1112    for (size_t i = 0; i < numArgs - callTargetIndex; i++) { // 2: skip acc
1113        vec1.emplace_back(acc_.GetValueIn(gate, i));
1114    }
1115    LowerToJSCall(gate, vec, vec1);
1116}
1117
1118void SlowPathLowering::LowerNewObjApply(GateRef gate)
1119{
1120    const int id = RTSTUB_ID(NewObjApply);
1121    // 2: number of value inputs
1122    ASSERT(acc_.GetNumValueIn(gate) == 2);
1123    GateRef newGate = LowerCallRuntime(gate, id,
1124        {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1125    ReplaceHirWithValue(gate, newGate);
1126}
1127
1128void SlowPathLowering::LowerThrow(GateRef gate)
1129{
1130    GateRef exception = acc_.GetValueIn(gate, 0);
1131    GateRef exceptionOffset = builder_.Int64(JSThread::GlueData::GetExceptionOffset(false));
1132    builder_.Store(VariableType::INT64(), glue_, glue_, exceptionOffset, exception);
1133    // store gate value == depend
1134    GateRef result = builder_.GetDepend();
1135    ReplaceHirToThrowCall(gate, result);
1136}
1137
1138void SlowPathLowering::LowerThrowConstAssignment(GateRef gate)
1139{
1140    const int id = RTSTUB_ID(ThrowConstAssignment);
1141    // 1: number of value inputs
1142    ASSERT(acc_.GetNumValueIn(gate) == 1);
1143    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0)});
1144    ReplaceHirToThrowCall(gate, newGate);
1145}
1146
1147void SlowPathLowering::LowerThrowThrowNotExists(GateRef gate)
1148{
1149    const int id = RTSTUB_ID(ThrowThrowNotExists);
1150    GateRef newGate = LowerCallRuntime(gate, id, {});
1151    ReplaceHirToThrowCall(gate, newGate);
1152}
1153
1154void SlowPathLowering::LowerThrowPatternNonCoercible(GateRef gate)
1155{
1156    const int id = RTSTUB_ID(ThrowPatternNonCoercible);
1157    GateRef newGate = LowerCallRuntime(gate, id, {});
1158    ReplaceHirToThrowCall(gate, newGate);
1159}
1160
1161void SlowPathLowering::LowerThrowIfNotObject(GateRef gate)
1162{
1163    // 1: number of value inputs
1164    ASSERT(acc_.GetNumValueIn(gate) == 1);
1165    GateRef value = acc_.GetValueIn(gate, 0);
1166    Label successExit(&builder_);
1167    Label exceptionExit(&builder_);
1168    Label isEcmaObject(&builder_);
1169    Label notEcmaObject(&builder_);
1170    Label isHeapObject(&builder_);
1171    BRANCH_CIR(builder_.TaggedIsHeapObject(value), &isHeapObject, &notEcmaObject);
1172    builder_.Bind(&isHeapObject);
1173    BRANCH_CIR(builder_.TaggedObjectIsEcmaObject(value), &isEcmaObject, &notEcmaObject);
1174    builder_.Bind(&isEcmaObject);
1175    {
1176        builder_.Jump(&successExit);
1177    }
1178    builder_.Bind(&notEcmaObject);
1179    {
1180        LowerCallRuntime(gate, RTSTUB_ID(ThrowIfNotObject), {}, true);
1181        builder_.Jump(&exceptionExit);
1182    }
1183    CREATE_DOUBLE_EXIT(successExit, exceptionExit)
1184    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, Circuit::NullGate());
1185}
1186
1187void SlowPathLowering::LowerThrowUndefinedIfHole(GateRef gate)
1188{
1189    // 2: number of value inputs
1190    ASSERT(acc_.GetNumValueIn(gate) == 2);
1191    GateRef hole = acc_.GetValueIn(gate, 0);
1192    GateRef obj = acc_.GetValueIn(gate, 1);
1193    Label successExit(&builder_);
1194    Label exceptionExit(&builder_);
1195    Label isHole(&builder_);
1196    Label notHole(&builder_);
1197    BRANCH_CIR(builder_.TaggedIsHole(hole), &isHole, &notHole);
1198    builder_.Bind(&notHole);
1199    {
1200        builder_.Jump(&successExit);
1201    }
1202    builder_.Bind(&isHole);
1203    {
1204        LowerCallRuntime(gate, RTSTUB_ID(ThrowUndefinedIfHole), {obj}, true);
1205        builder_.Jump(&exceptionExit);
1206    }
1207    CREATE_DOUBLE_EXIT(successExit, exceptionExit)
1208    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, Circuit::NullGate());
1209}
1210
1211void SlowPathLowering::LowerThrowUndefinedIfHoleWithName(GateRef gate)
1212{
1213    // 2: number of value inputs
1214    ASSERT(acc_.GetNumValueIn(gate) == 2);
1215    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1216    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
1217    GateRef hole = acc_.GetValueIn(gate, 1);
1218    Label successExit(&builder_);
1219    Label exceptionExit(&builder_);
1220    Label isHole(&builder_);
1221    Label notHole(&builder_);
1222    BRANCH_CIR(builder_.TaggedIsHole(hole), &isHole, &notHole);
1223    builder_.Bind(&notHole);
1224    {
1225        builder_.Jump(&successExit);
1226    }
1227    builder_.Bind(&isHole);
1228    {
1229        GateRef module = builder_.GetModuleFromFunction(jsFunc);
1230        GateRef obj = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module,
1231                                                      builder_.ZExtInt16ToInt32(acc_.GetValueIn(gate, 0)),
1232                                                      ConstPoolType::STRING);
1233        LowerCallRuntime(gate, RTSTUB_ID(ThrowUndefinedIfHole), {obj}, true);
1234        builder_.Jump(&exceptionExit);
1235    }
1236    CREATE_DOUBLE_EXIT(successExit, exceptionExit)
1237    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, Circuit::NullGate());
1238}
1239
1240void SlowPathLowering::LowerThrowIfSuperNotCorrectCall(GateRef gate)
1241{
1242    // 2: number of value inputs
1243    ASSERT(acc_.GetNumValueIn(gate) == 2);
1244    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(ThrowIfSuperNotCorrectCall),
1245        {builder_.ToTaggedInt(acc_.GetValueIn(gate, 0)), acc_.GetValueIn(gate, 1)}, true);
1246    ReplaceHirWithValue(gate, result);
1247}
1248
1249void SlowPathLowering::LowerThrowDeleteSuperProperty(GateRef gate)
1250{
1251    const int id = RTSTUB_ID(ThrowDeleteSuperProperty);
1252    GateRef newGate = LowerCallRuntime(gate, id, {});
1253    ReplaceHirToThrowCall(gate, newGate);
1254}
1255
1256void SlowPathLowering::LowerExceptionHandler(GateRef hirGate)
1257{
1258    GateRef depend = acc_.GetDep(hirGate);
1259    GateRef exceptionOffset = builder_.Int64(JSThread::GlueData::GetExceptionOffset(false));
1260    GateRef val = builder_.Int64Add(glue_, exceptionOffset);
1261    auto bit = LoadStoreAccessor::ToValue(MemoryAttribute::Default());
1262    GateRef loadException = circuit_->NewGate(circuit_->Load(bit), VariableType::JS_ANY().GetMachineType(),
1263        { depend, val }, VariableType::JS_ANY().GetGateType());
1264    acc_.SetDep(loadException, depend);
1265    GateRef holeCst = builder_.HoleConstant();
1266    GateRef clearException = circuit_->NewGate(circuit_->Store(bit), MachineType::NOVALUE,
1267        { loadException, glue_, glue_, exceptionOffset, holeCst }, VariableType::INT64().GetGateType());
1268    auto uses = acc_.Uses(hirGate);
1269    for (auto it = uses.begin(); it != uses.end();) {
1270        if (acc_.GetOpCode(*it) != OpCode::VALUE_SELECTOR && acc_.IsDependIn(it)) {
1271            it = acc_.ReplaceIn(it, clearException);
1272        } else {
1273            it = acc_.ReplaceIn(it, loadException);
1274        }
1275    }
1276    acc_.DeleteGate(hirGate);
1277}
1278
1279void SlowPathLowering::LowerLdSymbol(GateRef gate)
1280{
1281    const int id = RTSTUB_ID(GetSymbolFunction);
1282    GateRef newGate = LowerCallRuntime(gate, id, {});
1283    ReplaceHirWithValue(gate, newGate);
1284}
1285
1286void SlowPathLowering::LowerLdGlobal(GateRef gate)
1287{
1288    GateRef offset = builder_.Int64(JSThread::GlueData::GetGlobalObjOffset(false));
1289    GateRef val = builder_.Int64Add(glue_, offset);
1290    auto bit = LoadStoreAccessor::ToValue(MemoryAttribute::Default());
1291    GateRef newGate = circuit_->NewGate(circuit_->Load(bit), VariableType::JS_ANY().GetMachineType(),
1292        { builder_.GetDepend(), val }, VariableType::JS_ANY().GetGateType());
1293    ReplaceHirWithValue(gate, newGate);
1294}
1295
1296void SlowPathLowering::LowerSub2(GateRef gate)
1297{
1298    // 2: number of value inputs
1299    ASSERT(acc_.GetNumValueIn(gate) == 2);
1300    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Sub,
1301        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1302    ReplaceHirWithValue(gate, result);
1303}
1304
1305void SlowPathLowering::LowerMul2(GateRef gate)
1306{
1307    // 2: number of value inputs
1308    ASSERT(acc_.GetNumValueIn(gate) == 2);
1309    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Mul,
1310        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1311    ReplaceHirWithValue(gate, result);
1312}
1313
1314void SlowPathLowering::LowerDiv2(GateRef gate)
1315{
1316    // 2: number of value inputs
1317    ASSERT(acc_.GetNumValueIn(gate) == 2);
1318    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Div,
1319        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1320    ReplaceHirWithValue(gate, result);
1321}
1322
1323void SlowPathLowering::LowerMod2(GateRef gate)
1324{
1325    // 2: number of value inputs
1326    ASSERT(acc_.GetNumValueIn(gate) == 2);
1327    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Mod,
1328        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1329    ReplaceHirWithValue(gate, result);
1330}
1331
1332void SlowPathLowering::LowerEq(GateRef gate)
1333{
1334    // 2: number of value inputs
1335    ASSERT(acc_.GetNumValueIn(gate) == 2);
1336    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Equal,
1337                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1338    ReplaceHirWithValue(gate, result);
1339}
1340
1341void SlowPathLowering::LowerNotEq(GateRef gate)
1342{
1343    // 2: number of value inputs
1344    ASSERT(acc_.GetNumValueIn(gate) == 2);
1345    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::NotEqual,
1346                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1347    ReplaceHirWithValue(gate, result);
1348}
1349
1350void SlowPathLowering::LowerLess(GateRef gate)
1351{
1352    // 2: number of value inputs
1353    ASSERT(acc_.GetNumValueIn(gate) == 2);
1354    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Less,
1355                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1356    ReplaceHirWithValue(gate, result);
1357}
1358
1359void SlowPathLowering::LowerLessEq(GateRef gate)
1360{
1361    // 2: number of value inputs
1362    ASSERT(acc_.GetNumValueIn(gate) == 2);
1363    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::LessEq,
1364                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1365    ReplaceHirWithValue(gate, result);
1366}
1367
1368void SlowPathLowering::LowerGreater(GateRef gate)
1369{
1370    // 2: number of value inputs
1371    ASSERT(acc_.GetNumValueIn(gate) == 2);
1372    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Greater,
1373                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1374    ReplaceHirWithValue(gate, result);
1375}
1376
1377void SlowPathLowering::LowerGreaterEq(GateRef gate)
1378{
1379    // 2: number of value inputs
1380    ASSERT(acc_.GetNumValueIn(gate) == 2);
1381    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::GreaterEq,
1382                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1383    ReplaceHirWithValue(gate, result);
1384}
1385
1386void SlowPathLowering::LowerGetPropIterator(GateRef gate)
1387{
1388    // 1: number of value inputs
1389    ASSERT(acc_.GetNumValueIn(gate) == 1);
1390    GateRef object = {acc_.GetValueIn(gate, 0)};
1391    GateRef newGate = builder_.CallStub(glue_, gate, CommonStubCSigns::Getpropiterator, {glue_, object});
1392    ReplaceHirWithValue(gate, newGate);
1393}
1394
1395void SlowPathLowering::LowerCloseIterator(GateRef gate)
1396{
1397    const int id = RTSTUB_ID(CloseIterator);
1398    // 1: number of value inputs
1399    ASSERT(acc_.GetNumValueIn(gate) == 1);
1400    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0)});
1401    ReplaceHirWithValue(gate, newGate);
1402}
1403
1404void SlowPathLowering::LowerInc(GateRef gate)
1405{
1406    // 1: number of value inputs
1407    ASSERT(acc_.GetNumValueIn(gate) == 1);
1408    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Inc,
1409        { glue_, acc_.GetValueIn(gate, 0) });
1410    ReplaceHirWithValue(gate, result);
1411}
1412
1413void SlowPathLowering::LowerDec(GateRef gate)
1414{
1415    // 1: number of value inputs
1416    ASSERT(acc_.GetNumValueIn(gate) == 1);
1417    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Dec,
1418        { glue_, acc_.GetValueIn(gate, 0) });
1419    ReplaceHirWithValue(gate, result);
1420}
1421
1422void SlowPathLowering::LowerToNumber(GateRef gate)
1423{
1424    // 1: number of value inputs
1425    ASSERT(acc_.GetNumValueIn(gate) == 1);
1426    Label notNumber(&builder_);
1427    Label checkResult(&builder_);
1428    GateRef value = acc_.GetValueIn(gate, 0);
1429    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), value);
1430    BRANCH_CIR(builder_.TaggedIsNumber(value), &checkResult, &notNumber);
1431    builder_.Bind(&notNumber);
1432    {
1433        result = LowerCallRuntime(gate, RTSTUB_ID(ToNumber), { value }, true);
1434        builder_.Jump(&checkResult);
1435    }
1436    builder_.Bind(&checkResult);
1437    ReplaceHirWithValue(gate, *result);
1438}
1439
1440void SlowPathLowering::LowerNeg(GateRef gate)
1441{
1442    // 1: number of value inputs
1443    ASSERT(acc_.GetNumValueIn(gate) == 1);
1444    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Neg,
1445        { glue_, acc_.GetValueIn(gate, 0) });
1446    ReplaceHirWithValue(gate, result);
1447}
1448
1449void SlowPathLowering::LowerNot(GateRef gate)
1450{
1451    // 1: number of value inputs
1452    ASSERT(acc_.GetNumValueIn(gate) == 1);
1453    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Not,
1454        { glue_, acc_.GetValueIn(gate, 0) });
1455    ReplaceHirWithValue(gate, result);
1456}
1457
1458void SlowPathLowering::LowerShl2(GateRef gate)
1459{
1460    // 2: number of value inputs
1461    ASSERT(acc_.GetNumValueIn(gate) == 2);
1462    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Shl,
1463        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1464    ReplaceHirWithValue(gate, result);
1465}
1466
1467void SlowPathLowering::LowerShr2(GateRef gate)
1468{
1469    // 2: number of value inputs
1470    ASSERT(acc_.GetNumValueIn(gate) == 2);
1471    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Shr,
1472        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1473    ReplaceHirWithValue(gate, result);
1474}
1475
1476void SlowPathLowering::LowerAshr2(GateRef gate)
1477{
1478    // 2: number of value inputs
1479    ASSERT(acc_.GetNumValueIn(gate) == 2);
1480    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Ashr,
1481        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1482    ReplaceHirWithValue(gate, result);
1483}
1484
1485void SlowPathLowering::LowerAnd2(GateRef gate)
1486{
1487    // 2: number of value inputs
1488    ASSERT(acc_.GetNumValueIn(gate) == 2);
1489    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::And,
1490        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1491    ReplaceHirWithValue(gate, result);
1492}
1493
1494void SlowPathLowering::LowerOr2(GateRef gate)
1495{
1496    // 2: number of value inputs
1497    ASSERT(acc_.GetNumValueIn(gate) == 2);
1498    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Or,
1499        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1500    ReplaceHirWithValue(gate, result);
1501}
1502
1503void SlowPathLowering::LowerXor2(GateRef gate)
1504{
1505    // 2: number of value inputs
1506    ASSERT(acc_.GetNumValueIn(gate) == 2);
1507    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Xor,
1508        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1509    ReplaceHirWithValue(gate, result);
1510}
1511
1512void SlowPathLowering::LowerDelObjProp(GateRef gate)
1513{
1514    // 2: number of value inputs
1515    ASSERT(acc_.GetNumValueIn(gate) == 2);
1516    Label successExit(&builder_);
1517    Label exceptionExit(&builder_);
1518    GateRef newGate = builder_.CallStub(glue_, gate, CommonStubCSigns::DeleteObjectProperty,
1519                                        { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1520    BRANCH_CIR(builder_.IsSpecial(newGate, JSTaggedValue::VALUE_EXCEPTION),
1521        &exceptionExit, &successExit);
1522    CREATE_DOUBLE_EXIT(successExit, exceptionExit)
1523    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, newGate);
1524}
1525
1526void SlowPathLowering::LowerExp(GateRef gate)
1527{
1528    const int id = RTSTUB_ID(Exp);
1529    // 2: number of value inputs
1530    ASSERT(acc_.GetNumValueIn(gate) == 2);
1531    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)});
1532    ReplaceHirWithValue(gate, newGate);
1533}
1534
1535void SlowPathLowering::LowerIsIn(GateRef gate)
1536{
1537    const int id = RTSTUB_ID(IsIn);
1538    // 2: number of value inputs
1539    ASSERT(acc_.GetNumValueIn(gate) == 2);
1540    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)});
1541    ReplaceHirWithValue(gate, newGate);
1542}
1543
1544void SlowPathLowering::LowerInstanceof(GateRef gate)
1545{
1546    // 3: number of value inputs
1547    ASSERT(acc_.GetNumValueIn(gate) == 3);
1548    GateRef obj = acc_.GetValueIn(gate, 1);     // 1: the second parameter
1549    GateRef target = acc_.GetValueIn(gate, 2);  // 2: the third parameter
1550    LowerCallStubWithIC(gate, CommonStubCSigns::Instanceof, { obj, target });
1551}
1552
1553void SlowPathLowering::LowerFastStrictNotEqual(GateRef gate)
1554{
1555    // 2: number of value inputs
1556    ASSERT(acc_.GetNumValueIn(gate) == 2);
1557    // 2: number of value inputs
1558    ASSERT(acc_.GetNumValueIn(gate) == 2);
1559    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::StrictNotEqual,
1560                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1561    ReplaceHirWithValue(gate, result);
1562}
1563
1564void SlowPathLowering::LowerFastStrictEqual(GateRef gate)
1565{
1566    // 2: number of value inputs
1567    ASSERT(acc_.GetNumValueIn(gate) == 2);
1568    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::StrictEqual,
1569                                       { glue_, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1) });
1570    ReplaceHirWithValue(gate, result);
1571}
1572
1573void SlowPathLowering::LowerCreateEmptyArray(GateRef gate)
1574{
1575    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::CreateEmptyArray, { glue_ });
1576    GateRef newRes = LowerUpdateArrayHClassAtDefine(gate, result);
1577    ReplaceHirWithValue(gate, newRes, true);
1578}
1579
1580void SlowPathLowering::LowerCreateEmptyObject(GateRef gate)
1581{
1582    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(CreateEmptyObject), {}, true);
1583    ReplaceHirWithValue(gate, result, true);
1584}
1585
1586void SlowPathLowering::LowerCreateArrayWithBuffer(GateRef gate)
1587{
1588    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1589    GateRef index = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
1590    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::CreateArrayWithBuffer, { glue_, index, jsFunc });
1591    // when elementsKind switch on, we should not update arrayHClass here.
1592    GateRef newRes = LowerUpdateArrayHClassAtDefine(gate, result);
1593    ReplaceHirWithValue(gate, newRes, true);
1594}
1595
1596GateRef SlowPathLowering::LowerUpdateArrayHClassAtDefine(GateRef gate, GateRef array)
1597{
1598    ElementsKind kind = acc_.TryGetElementsKind(gate);
1599    if (!Elements::IsGeneric(kind)) {
1600        size_t hclassIndex = static_cast<size_t>(compilationEnv_->GetArrayHClassIndexMap().at(kind).first);
1601        GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
1602            builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false)));
1603        GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * hclassIndex);
1604        GateRef hclass = builder_.Load(VariableType::JS_POINTER(), gConstAddr, constantIndex);
1605        builder_.Store(VariableType::JS_POINTER(), glue_, array, builder_.IntPtr(0), hclass);
1606    }
1607    return array;
1608}
1609
1610void SlowPathLowering::LowerCreateObjectWithBuffer(GateRef gate)
1611{
1612    // 2: number of value inputs
1613    ASSERT(acc_.GetNumValueIn(gate) == 2);
1614    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1615    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
1616    GateRef unsharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::UNSHARED_CONST_POOL);
1617    GateRef index = acc_.GetValueIn(gate, 0);
1618    GateRef module = builder_.GetModuleFromFunction(jsFunc);
1619    GateRef obj = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, unsharedConstPool, module,
1620                                                  builder_.TruncInt64ToInt32(index), ConstPoolType::OBJECT_LITERAL);
1621    GateRef lexEnv = acc_.GetValueIn(gate, 1);
1622    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(CreateObjectHavingMethod), { obj, lexEnv }, true);
1623    ReplaceHirWithValue(gate, result);
1624}
1625
1626void SlowPathLowering::LowerStModuleVar(GateRef gate)
1627{
1628    // 2: number of value inputs
1629    ASSERT(acc_.GetNumValueIn(gate) == 2);
1630    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1631    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
1632    auto result = LowerCallRuntime(gate, RTSTUB_ID(StModuleVarByIndexOnJSFunc),
1633        {index, acc_.GetValueIn(gate, 1), jsFunc}, true);
1634    ReplaceHirWithValue(gate, result, true);
1635}
1636
1637void SlowPathLowering::LowerSetGeneratorState(GateRef gate)
1638{
1639    // 2: number of value inputs
1640    ASSERT(acc_.GetNumValueIn(gate) == 2);
1641    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1642    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
1643    auto result = LowerCallRuntime(gate, RTSTUB_ID(SetGeneratorState),
1644        {acc_.GetValueIn(gate, 1), index, jsFunc}, true);
1645    ReplaceHirWithValue(gate, result, true);
1646}
1647
1648void SlowPathLowering::LowerGetTemplateObject(GateRef gate)
1649{
1650    const int id = RTSTUB_ID(GetTemplateObject);
1651    // 1: number of value inputs
1652    ASSERT(acc_.GetNumValueIn(gate) == 1);
1653    GateRef literal = acc_.GetValueIn(gate, 0);
1654    GateRef newGate = LowerCallRuntime(gate, id, { literal });
1655    ReplaceHirWithValue(gate, newGate);
1656}
1657
1658void SlowPathLowering::LowerSetObjectWithProto(GateRef gate)
1659{
1660    const int id = RTSTUB_ID(SetObjectWithProto);
1661    // 2: number of value inputs
1662    ASSERT(acc_.GetNumValueIn(gate) == 2);
1663    GateRef proto = acc_.GetValueIn(gate, 0);
1664    GateRef obj = acc_.GetValueIn(gate, 1);
1665    GateRef newGate = LowerCallRuntime(gate, id, { proto, obj });
1666    ReplaceHirWithValue(gate, newGate);
1667}
1668
1669void SlowPathLowering::LowerLdBigInt(GateRef gate)
1670{
1671    // 1: number of value inputs
1672    ASSERT(acc_.GetNumValueIn(gate) == 1);
1673    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1674    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
1675    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
1676    GateRef module = builder_.GetModuleFromFunction(jsFunc);
1677    GateRef numberBigInt = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module,
1678                                                           stringId, ConstPoolType::STRING);
1679    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(LdBigInt), {numberBigInt}, true);
1680    ReplaceHirWithValue(gate, result);
1681}
1682
1683void SlowPathLowering::LowerToNumeric(GateRef gate)
1684{
1685    // 1: number of value inputs
1686    ASSERT(acc_.GetNumValueIn(gate) == 1);
1687    Label notNumber(&builder_);
1688    Label checkResult(&builder_);
1689    GateRef value = acc_.GetValueIn(gate, 0);
1690    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), value);
1691    BRANCH_CIR(builder_.TaggedIsNumeric(value), &checkResult, &notNumber);
1692    builder_.Bind(&notNumber);
1693    {
1694        result = LowerCallRuntime(gate, RTSTUB_ID(ToNumeric), { value }, true);
1695        builder_.Jump(&checkResult);
1696    }
1697    builder_.Bind(&checkResult);
1698    ReplaceHirWithValue(gate, *result);
1699}
1700
1701void SlowPathLowering::LowerDynamicImport(GateRef gate)
1702{
1703    const int id = RTSTUB_ID(DynamicImport);
1704    // 1: number of value inputs
1705    ASSERT(acc_.GetNumValueIn(gate) == 1);
1706    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1707    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), jsFunc});
1708    ReplaceHirWithValue(gate, newGate);
1709}
1710
1711void SlowPathLowering::LowerLdLocalModuleVarByIndex(GateRef gate)
1712{
1713    // 2: number of value inputs
1714    ASSERT(acc_.GetNumValueIn(gate) == 1);
1715    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1716    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
1717    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(LdLocalModuleVarByIndexOnJSFunc), {index, jsFunc}, true);
1718    ReplaceHirWithValue(gate, result);
1719}
1720
1721void SlowPathLowering::LowerExternalModule(GateRef gate)
1722{
1723    ASSERT(acc_.GetNumValueIn(gate) == 1);
1724    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1725    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
1726    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(LdExternalModuleVarByIndexOnJSFunc), {index, jsFunc}, true);
1727    ReplaceHirWithValue(gate, result);
1728}
1729
1730void SlowPathLowering::LowerGetModuleNamespace(GateRef gate)
1731{
1732    // 1: number of value inputs
1733    ASSERT(acc_.GetNumValueIn(gate) == 1);
1734    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1735    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
1736    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(GetModuleNamespaceByIndexOnJSFunc), {index, jsFunc}, true);
1737    ReplaceHirWithValue(gate, result);
1738}
1739
1740GateRef SlowPathLowering::GetTaggedArrayFromValueIn(Environment *env, GateRef gate, size_t length)
1741{
1742    NewObjectStubBuilder objBuilder(env);
1743    GateRef taggedArray = objBuilder.NewTaggedArray(glue_, builder_.Int32(length));
1744    for (size_t i = 0; i < length; i++) {
1745        builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, taggedArray,
1746                                       builder_.Int32(i), acc_.GetValueIn(gate, i));
1747    }
1748    return taggedArray;
1749}
1750
1751void SlowPathLowering::LowerSuperCall(GateRef gate)
1752{
1753    Environment env(gate, circuit_, &builder_);
1754    NewObjectStubBuilder objBuilder(&env);
1755    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1756    DEFVALUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1757    DEFVALUE(newTarget, (&builder_), VariableType::JS_ANY(), argAcc_.GetFrameArgsIn(gate, FrameArgIdx::NEW_TARGET));
1758    Label fastPath(&builder_);
1759    Label slowPath(&builder_);
1760    Label callExit(&builder_);
1761    Label replaceGate(&builder_);
1762    size_t length = acc_.GetNumValueIn(gate);
1763    GateRef taggedLength = builder_.ToTaggedInt(builder_.Int64(length));
1764    GateRef taggedArray = GetTaggedArrayFromValueIn(&env, gate, length);
1765    GateRef func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
1766    GateRef superFunc = objBuilder.GetPrototype(glue_, func);
1767
1768    CheckSuperAndNewTarget(objBuilder, superFunc, newTarget, thisObj, fastPath, slowPath);
1769    builder_.Bind(&fastPath);
1770    {
1771        LowerFastSuperCallWithArgArray(taggedArray, {gate, superFunc, *newTarget, *thisObj,
1772            builder_.Int64(length)}, false, result, callExit);  // false: not spread
1773        builder_.Bind(&callExit);
1774        result = objBuilder.ConstructorCheck(glue_, superFunc, *result, *thisObj);
1775        builder_.Jump(&replaceGate);
1776    }
1777    builder_.Bind(&slowPath);
1778    {
1779        result = LowerCallRuntime(gate, RTSTUB_ID(OptSuperCall), { func, *newTarget, taggedArray, taggedLength });
1780        builder_.Jump(&replaceGate);
1781    }
1782    builder_.Bind(&replaceGate);
1783    ReplaceHirWithPendingException(gate, builder_.GetState(), builder_.GetDepend(), *result);
1784}
1785
1786void SlowPathLowering::LowerSuperCallArrow(GateRef gate)
1787{
1788    Environment env(gate, circuit_, &builder_);
1789    NewObjectStubBuilder objBuilder(&env);
1790    const int id = RTSTUB_ID(OptSuperCall);
1791    ASSERT(acc_.GetNumValueIn(gate) > 0);
1792    GateRef newTarget = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::NEW_TARGET);
1793    size_t funcIndex = acc_.GetNumValueIn(gate) - 1;
1794    GateRef taggedLength = builder_.ToTaggedInt(builder_.Int64(funcIndex));
1795    GateRef taggedArray = GetTaggedArrayFromValueIn(&env, gate, funcIndex);
1796    GateRef func = acc_.GetValueIn(gate, funcIndex);
1797    std::vector<GateRef> vec { func, newTarget, taggedArray, taggedLength};
1798    GateRef newGate = LowerCallRuntime(gate, id, vec);
1799    ReplaceHirWithValue(gate, newGate);
1800}
1801
1802void SlowPathLowering::LowerSuperCallSpread(GateRef gate)
1803{
1804    Environment env(gate, circuit_, &builder_);
1805    NewObjectStubBuilder objBuilder(&env);
1806    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1807    DEFVALUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1808    DEFVALUE(newTarget, (&builder_), VariableType::JS_ANY(), argAcc_.GetFrameArgsIn(gate, FrameArgIdx::NEW_TARGET));
1809    Label fastPath(&builder_);
1810    Label slowPath(&builder_);
1811    Label callExit(&builder_);
1812    Label replaceGate(&builder_);
1813
1814    GateRef array = acc_.GetValueIn(gate, 0);
1815    GateRef func = acc_.GetValueIn(gate, 1);
1816    GateRef superFunc = objBuilder.GetPrototype(glue_, func);
1817    CheckSuperAndNewTarget(objBuilder, superFunc, newTarget, thisObj, fastPath, slowPath);
1818    builder_.Bind(&fastPath);
1819    {
1820        GateRef actualArgc = builder_.ZExtInt32ToInt64(
1821            builder_.Load(VariableType::INT32(), array, builder_.IntPtr(JSArray::LENGTH_OFFSET)));
1822        LowerFastSuperCallWithArgArray(array, {gate, superFunc, *newTarget, *thisObj, actualArgc},
1823            true, result, callExit);  // true: is spread
1824        builder_.Bind(&callExit);
1825        result = objBuilder.ConstructorCheck(glue_, superFunc, *result, *thisObj);
1826        builder_.Jump(&replaceGate);
1827    }
1828    builder_.Bind(&slowPath);
1829    {
1830        result = LowerCallRuntime(gate, RTSTUB_ID(OptSuperCallSpread), { func, *newTarget, array });
1831        builder_.Jump(&replaceGate);
1832    }
1833    builder_.Bind(&replaceGate);
1834    ReplaceHirWithPendingException(gate, builder_.GetState(), builder_.GetDepend(), *result);
1835}
1836
1837GateRef SlowPathLowering::IsAotOrFastCall(GateRef func, CircuitBuilder::JudgeMethodType type)
1838{
1839    return builder_.JudgeAotAndFastCall(func, type);
1840}
1841
1842void SlowPathLowering::LowerFastSuperCallWithArgArray(GateRef array, const std::vector<GateRef> &args,
1843                                                      bool isSpread, Variable &result, Label &exit)
1844{
1845    ASSERT(args.size() == 5);  // 5: size of args
1846    GateRef srcElements;
1847    if (isSpread) {
1848        GateRef gate = args[0];  // 0: index of gate
1849        srcElements = builder_.CallStub(glue_, gate, CommonStubCSigns::GetCallSpreadArgs, {glue_, array});
1850    } else {
1851        srcElements = array;
1852    }
1853    GateRef elementsPtr = builder_.GetDataOfTaggedArray(srcElements);
1854    LowerFastSuperCall(args, elementsPtr, result, exit);
1855}
1856
1857void SlowPathLowering::LowerFastSuperCall(const std::vector<GateRef> &args, GateRef elementsPtr,
1858                                          Variable &result, Label &exit)
1859{
1860    Label fastCall(&builder_);
1861    Label notFastCall(&builder_);
1862    Label aotCall(&builder_);
1863    Label notAotCall(&builder_);
1864    ASSERT(args.size() == 5);      // 5: size of args
1865    GateRef gate = args[0];        // 0: index of gate
1866    GateRef superFunc = args[1];   // 1: index of superFunc
1867    GateRef newTartget = args[2];  // 2: index of newTarget
1868    GateRef thisObj = args[3];     // 3: index of thisObj
1869    GateRef actualArgc = args[4];  // 4: index of actualArgc
1870
1871    GateRef method = builder_.GetMethodFromFunction(superFunc);
1872    GateRef expectedNum = builder_.GetExpectedNumOfArgs(method);
1873    BRANCH_CIR(IsAotOrFastCall(superFunc, CircuitBuilder::JudgeMethodType::HAS_AOT_FASTCALL), &fastCall, &notFastCall);
1874    builder_.Bind(&fastCall);
1875    {
1876        Label notBridge(&builder_);
1877        Label bridge(&builder_);
1878        BRANCH_CIR(builder_.Int64Equal(expectedNum, actualArgc), &notBridge, &bridge);
1879        builder_.Bind(&notBridge);
1880        CallNGCRuntimeWithCallTimer(RTSTUB_ID(JSFastCallWithArgV), gate, superFunc, result,
1881            {glue_, superFunc, thisObj, actualArgc, elementsPtr});
1882        builder_.Jump(&exit);
1883        builder_.Bind(&bridge);
1884        CallNGCRuntimeWithCallTimer(RTSTUB_ID(JSFastCallWithArgVAndPushArgv), gate, superFunc, result,
1885            {glue_, superFunc, thisObj, actualArgc, elementsPtr, expectedNum});
1886        builder_.Jump(&exit);
1887    }
1888    builder_.Bind(&notFastCall);
1889    BRANCH_CIR(IsAotOrFastCall(superFunc, CircuitBuilder::JudgeMethodType::HAS_AOT), &aotCall, &notAotCall);
1890    builder_.Bind(&aotCall);
1891    {
1892        Label notBridge(&builder_);
1893        Label bridge(&builder_);
1894        std::vector<GateRef> callArgs {glue_, actualArgc, superFunc, newTartget, thisObj, elementsPtr};
1895        BRANCH_CIR(builder_.Int64Equal(expectedNum, actualArgc), &notBridge, &bridge);
1896        builder_.Bind(&notBridge);
1897        CallNGCRuntimeWithCallTimer(RTSTUB_ID(JSCallWithArgV), gate, superFunc, result, callArgs);
1898        builder_.Jump(&exit);
1899        builder_.Bind(&bridge);
1900        CallNGCRuntimeWithCallTimer(RTSTUB_ID(JSCallWithArgVAndPushArgv), gate, superFunc, result, callArgs);
1901        builder_.Jump(&exit);
1902    }
1903    builder_.Bind(&notAotCall);
1904    CallNGCRuntimeWithCallTimer(RTSTUB_ID(SuperCallWithArgV), gate, superFunc, result,
1905        {glue_, actualArgc, superFunc, newTartget, thisObj, elementsPtr});
1906    builder_.Jump(&exit);
1907}
1908
1909void SlowPathLowering::CallNGCRuntimeWithCallTimer(int index, GateRef gate, GateRef func, Variable &result,
1910                                                   const std::vector<GateRef> &args)
1911{
1912    builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
1913    result = LowerCallNGCRuntime(gate, index, args, true);
1914    builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
1915}
1916
1917void SlowPathLowering::CheckSuperAndNewTarget(NewObjectStubBuilder &objBuilder, GateRef super, Variable &newTarget,
1918                                              Variable &thisObj, Label &fastPath, Label &slowPath)
1919{
1920    Label isHeapObj(&builder_);
1921    Label isJsFunc(&builder_);
1922    Label isCtor(&builder_);
1923    Label targetUndefined(&builder_);
1924    Label normalPath(&builder_);
1925    Label needAllocateThis(&builder_);
1926
1927    BRANCH_CIR(builder_.TaggedIsHeapObject(super), &isHeapObj, &slowPath);
1928    builder_.Bind(&isHeapObj);
1929    BRANCH_CIR(builder_.IsJSFunction(super), &isJsFunc, &slowPath);
1930    builder_.Bind(&isJsFunc);
1931    BRANCH_CIR(builder_.IsConstructor(super), &isCtor, &slowPath);
1932    builder_.Bind(&isCtor);
1933    BRANCH_CIR(builder_.TaggedIsUndefined(*newTarget), &targetUndefined, &normalPath);
1934    builder_.Bind(&targetUndefined);
1935    newTarget = super;
1936    builder_.Jump(&normalPath);
1937    builder_.Bind(&normalPath);
1938    BRANCH_CIR(builder_.IsBase(super), &needAllocateThis, &fastPath);
1939    builder_.Bind(&needAllocateThis);
1940    thisObj = objBuilder.FastSuperAllocateThis(glue_, super, *newTarget);
1941    builder_.Jump(&fastPath);
1942}
1943
1944void SlowPathLowering::LowerSuperCallForwardAllArgs(GateRef gate)
1945{
1946    Environment env(gate, circuit_, &builder_);
1947    NewObjectStubBuilder objBuilder(&env);
1948    DEFVALUE(newTarget, (&builder_), VariableType::JS_ANY(), argAcc_.GetFrameArgsIn(gate, FrameArgIdx::NEW_TARGET));
1949    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1950    DEFVALUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1951    GateRef func = acc_.GetValueIn(gate, 0);
1952    GateRef actualArgc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::ACTUAL_ARGC);
1953    GateRef actualArgv = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::ACTUAL_ARGV);
1954    GateRef super = objBuilder.GetPrototype(glue_, func);
1955    Label fastPath(&builder_);
1956    Label fastPathWithArgv(&builder_);
1957    Label callExit(&builder_);
1958    Label slowPath(&builder_);
1959    Label threadCheck(&builder_);
1960    Label argvIsNull(&builder_);
1961    Label getArgsFromArgAcc(&builder_);
1962
1963    CheckSuperAndNewTarget(objBuilder, super, newTarget, thisObj, fastPath, slowPath);
1964    builder_.Bind(&fastPath);
1965    {
1966        BRANCH_CIR(builder_.Equal(actualArgv, builder_.IntPtr(0)), &argvIsNull, &fastPathWithArgv);
1967        builder_.Bind(&argvIsNull);
1968        {
1969            GateRef method = builder_.GetMethodFromFunction(func);
1970            GateRef expectedFuncArgNum = builder_.ZExtInt32ToInt64(builder_.GetExpectedNumOfArgs(method));
1971            GateRef expected = builder_.Int64Add(expectedFuncArgNum, builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS));
1972            BRANCH_CIR(builder_.Int64Equal(expected, actualArgc), &getArgsFromArgAcc, &slowPath);
1973            builder_.Bind(&getArgsFromArgAcc);
1974            std::vector<GateRef> args { gate, super, actualArgc, *newTarget, *thisObj };
1975            GenerateSuperCallForwardAllArgsWithoutArgv(args, result, threadCheck);
1976        }
1977        builder_.Bind(&fastPathWithArgv);
1978        {
1979            GateRef argc = builder_.Int64Sub(actualArgc, builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS));
1980            GateRef argv = builder_.PtrAdd(actualArgv, builder_.IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8));  // 8: ptr size
1981            LowerFastSuperCall({ gate, super, *newTarget, *thisObj, argc }, argv, result, callExit);
1982            builder_.Bind(&callExit);
1983            result = objBuilder.ConstructorCheck(glue_, super, *result, *thisObj);
1984            builder_.Jump(&threadCheck);
1985        }
1986    }
1987    builder_.Bind(&slowPath);
1988    {
1989        std::vector<GateRef> args { super, *newTarget, builder_.ToTaggedInt(actualArgc) };
1990        result = LowerCallRuntime(gate, RTSTUB_ID(OptSuperCallForwardAllArgs), args, true);
1991        builder_.Jump(&threadCheck);
1992    }
1993    builder_.Bind(&threadCheck);
1994    ReplaceHirWithPendingException(gate, builder_.GetState(), builder_.GetDepend(), *result);
1995}
1996
1997void SlowPathLowering::GenerateSuperCallForwardAllArgsWithoutArgv(const std::vector<GateRef> &args, Variable &result,
1998                                                                  Label &exit)
1999{
2000    ASSERT(args.size() == 5);      // 5: size of args
2001    GateRef gate = args[0];        // 0: gate
2002    GateRef super = args[1];       // 1: super constructor
2003    GateRef actualArgc = args[2];  // 2: num of args
2004    GateRef newTarget = args[3];   // 3: argv
2005    GateRef thisObj = args[4];     // 4: newTarget
2006
2007    Label afterCallSuper(&builder_);
2008    std::vector<GateRef> callArgs { glue_, actualArgc, builder_.IntPtr(0), super, newTarget, thisObj };
2009    std::vector<GateRef> argsFastCall { glue_, super, thisObj };
2010
2011    uint32_t startIdx = static_cast<uint32_t>(CommonArgIdx::NUM_OF_ARGS);
2012    ASSERT(argAcc_.ArgsCount() >= startIdx);
2013    for (uint32_t i = startIdx; i < argAcc_.ArgsCount(); ++i) {
2014        GateRef value = argAcc_.ArgsAt(i);
2015        callArgs.emplace_back(value);
2016        argsFastCall.emplace_back(value);
2017    }
2018
2019    LowerFastCall(gate, glue_, super, actualArgc, callArgs, argsFastCall, &result, &afterCallSuper, true);
2020
2021    builder_.Bind(&afterCallSuper);
2022    result = builder_.CallStub(glue_, gate, CommonStubCSigns::ConstructorCheck, { glue_, super, *result, thisObj });
2023    builder_.Jump(&exit);
2024}
2025
2026void SlowPathLowering::LowerIsTrueOrFalse(GateRef gate, bool flag)
2027{
2028    Label slowpath(&builder_);
2029    Label isTrue(&builder_);
2030    Label isFalse(&builder_);
2031    Label successExit(&builder_);
2032    // 1: number of value inputs
2033    ASSERT(acc_.GetNumValueIn(gate) == 1);
2034    auto value = acc_.GetValueIn(gate, 0);
2035    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), value);
2036    if (flag) {
2037        result = builder_.CallStub(glue_, gate, CommonStubCSigns::ToBooleanTrue, { glue_, value });
2038    } else {
2039        result = builder_.CallStub(glue_, gate, CommonStubCSigns::ToBooleanFalse, { glue_, value });
2040    }
2041    ReplaceHirWithValue(gate, *result, true);
2042}
2043
2044void SlowPathLowering::LowerNewObjRange(GateRef gate)
2045{
2046    Label fastPath(&builder_);
2047    Label slowPath(&builder_);
2048    Label threadCheck(&builder_);
2049    Label successExit(&builder_);
2050    Label exit(&builder_);
2051
2052    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2053
2054    GateRef ctor = acc_.GetValueIn(gate, 0);
2055    GateRef thisObj = builder_.CallStub(glue_, gate, CommonStubCSigns::NewThisObjectChecked, { glue_, ctor });
2056    BRANCH_CIR(builder_.TaggedIsHole(thisObj), &slowPath, &fastPath);
2057    builder_.Bind(&fastPath);
2058    {
2059        GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
2060            EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8));
2061        GateRef actualArgv = builder_.IntPtr(0);
2062        size_t range = acc_.GetNumValueIn(gate);
2063        std::vector<GateRef> args{glue_, actualArgc, actualArgv, ctor, ctor, thisObj};
2064        std::vector<GateRef> argsFastCall{glue_, ctor, thisObj};
2065        for (size_t i = 1; i < range; ++i) {
2066            args.emplace_back(acc_.GetValueIn(gate, i));
2067            argsFastCall.emplace_back(acc_.GetValueIn(gate, i));
2068        }
2069        LowerFastCall(gate, glue_, ctor, actualArgc, args, argsFastCall, &result, &exit, true);
2070        builder_.Bind(&exit);
2071        result = builder_.CallStub(glue_, gate, CommonStubCSigns::ConstructorCheck, { glue_, ctor, *result, thisObj });
2072        builder_.Jump(&threadCheck);
2073    }
2074    builder_.Bind(&slowPath);
2075    {
2076        size_t range = acc_.GetNumValueIn(gate);
2077        std::vector<GateRef> args(range);
2078        for (size_t i = 0; i < range; ++i) {
2079            args[i] = acc_.GetValueIn(gate, i);
2080        }
2081        result = LowerCallRuntime(gate, RTSTUB_ID(OptNewObjRange), args, true);
2082        builder_.Jump(&threadCheck);
2083    }
2084    builder_.Bind(&threadCheck);
2085    ReplaceHirWithPendingException(gate, builder_.GetState(), builder_.GetDepend(), *result);
2086}
2087
2088bool SlowPathLowering::IsDependIfStateMent(GateRef gate, size_t idx)
2089{
2090    return ((acc_.GetOpCode(gate) == OpCode::DEPEND_SELECTOR) || (acc_.GetOpCode(gate) == OpCode::DEPEND_RELAY)) &&
2091           (idx > 0 && (acc_.GetOpCode(acc_.GetIn(acc_.GetIn(gate, 0), idx - 1)) != OpCode::IF_EXCEPTION));
2092}
2093
2094void SlowPathLowering::LowerConditionJump(GateRef gate, bool isEqualJump)
2095{
2096    GateRef value = acc_.GetValueIn(gate, 0);
2097
2098    Label isZero(&builder_);
2099    Label notZero(&builder_);
2100    // GET_ACC().IsFalse()
2101    Label notFalse(&builder_);
2102    BRANCH_CIR(builder_.IsSpecial(value, JSTaggedValue::VALUE_FALSE), &isZero, &notFalse);
2103    builder_.Bind(&notFalse);
2104    {
2105        // (GET_ACC().IsInt() && GET_ACC().GetInt() == 0)
2106        Label isInt(&builder_);
2107        Label notIntZero(&builder_);
2108        BRANCH_CIR(builder_.TaggedIsInt(value), &isInt, &notIntZero);
2109        builder_.Bind(&isInt);
2110        BRANCH_CIR(builder_.Equal(builder_.TaggedGetInt(value), builder_.Int32(0)), &isZero, &notIntZero);
2111        builder_.Bind(&notIntZero);
2112        {
2113            // (GET_ACC().IsDouble() && GET_ACC().GetDouble() == 0.0)
2114            Label isDouble(&builder_);
2115            BRANCH_CIR(builder_.TaggedIsDouble(value), &isDouble, &notZero);
2116            builder_.Bind(&isDouble);
2117            BRANCH_CIR(builder_.Equal(builder_.GetDoubleOfTDouble(value), builder_.Double(0.0)), &isZero, &notZero);
2118            builder_.Bind(&notZero);
2119        }
2120    }
2121    builder_.Bind(&isZero);
2122
2123    Label &ifTrue = isEqualJump ? isZero : notZero;
2124    Label &ifFalse = isEqualJump ? notZero : isZero;
2125    auto uses = acc_.Uses(gate);
2126    for (auto it = uses.begin(); it != uses.end();) {
2127        if (acc_.GetOpCode(*it) == OpCode::IF_TRUE) {
2128            acc_.SetMetaData(*it, circuit_->OrdinaryBlock());
2129            it = acc_.ReplaceIn(it, ifTrue.GetControl());
2130        } else if (acc_.GetOpCode(*it) == OpCode::IF_FALSE) {
2131            acc_.SetMetaData(*it, circuit_->OrdinaryBlock());
2132            it = acc_.ReplaceIn(it, ifFalse.GetControl());
2133        } else if (IsDependIfStateMent(*it, it.GetIndex())) {
2134            it = acc_.ReplaceIn(it, acc_.GetDep(gate));
2135        } else {
2136            LOG_ECMA(FATAL) << "this branch is unreachable";
2137            UNREACHABLE();
2138        }
2139    }
2140    // delete old gate
2141    acc_.DeleteGate(gate);
2142}
2143
2144void SlowPathLowering::LowerGetNextPropName(GateRef gate)
2145{
2146    // 1: number of value inputs
2147    ASSERT(acc_.GetNumValueIn(gate) == 1);
2148    GateRef iter = acc_.GetValueIn(gate, 0);
2149
2150    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2151
2152    Label notFinish(&builder_);
2153    Label notEnumCacheValid(&builder_);
2154    Label fastGetKey(&builder_);
2155    Label slowpath(&builder_);
2156    Label exit(&builder_);
2157
2158    GateRef index = builder_.GetIndexFromForInIterator(iter);
2159    GateRef length = builder_.GetLengthFromForInIterator(iter);
2160    BRANCH_CIR(builder_.Int32GreaterThanOrEqual(index, length), &exit, &notFinish);
2161    builder_.Bind(&notFinish);
2162    GateRef keys = builder_.GetKeysFromForInIterator(iter);
2163    GateRef receiver = builder_.GetObjectFromForInIterator(iter);
2164    GateRef cachedHclass = builder_.GetCachedHclassFromForInIterator(iter);
2165    GateRef kind = builder_.GetEnumCacheKind(glue_, keys);
2166    BRANCH_CIR(builder_.IsEnumCacheValid(receiver, cachedHclass, kind), &fastGetKey, &notEnumCacheValid);
2167    builder_.Bind(&notEnumCacheValid);
2168    BRANCH_CIR(builder_.NeedCheckProperty(receiver), &slowpath, &fastGetKey);
2169    builder_.Bind(&fastGetKey);
2170    {
2171        result = builder_.GetValueFromTaggedArray(keys, index);
2172        builder_.IncreaseInteratorIndex(glue_, iter, index);
2173        builder_.Jump(&exit);
2174    }
2175    builder_.Bind(&slowpath);
2176    {
2177        result = LowerCallRuntime(gate, RTSTUB_ID(GetNextPropNameSlowpath), { iter }, true);
2178        builder_.Jump(&exit);
2179    }
2180
2181    builder_.Bind(&exit);
2182    ReplaceHirWithValue(gate, *result);
2183}
2184
2185void SlowPathLowering::LowerCopyDataProperties(GateRef gate)
2186{
2187    const int id = RTSTUB_ID(CopyDataProperties);
2188    // 2: number of value inputs
2189    ASSERT(acc_.GetNumValueIn(gate) == 2);
2190    GateRef dst = acc_.GetValueIn(gate, 0);
2191    GateRef src = acc_.GetValueIn(gate, 1);
2192    GateRef newGate = LowerCallRuntime(gate, id, { dst, src });
2193    ReplaceHirWithValue(gate, newGate);
2194}
2195
2196void SlowPathLowering::LowerCreateObjectWithExcludedKeys(GateRef gate)
2197{
2198    const int id = RTSTUB_ID(OptCreateObjectWithExcludedKeys);
2199    // 2: number of value inputs
2200    ASSERT(acc_.GetNumValueIn(gate) >= 2);
2201    size_t numIn = acc_.GetNumValueIn(gate);
2202    std::vector<GateRef> args;
2203    for (size_t idx = 0; idx < numIn; idx++) {
2204        GateRef tmpGate = acc_.GetValueIn(gate, idx);
2205        args.emplace_back(tmpGate);
2206    }
2207    GateRef newGate = LowerCallRuntime(gate, id, args);
2208    ReplaceHirWithValue(gate, newGate);
2209}
2210
2211void SlowPathLowering::LowerCreateRegExpWithLiteral(GateRef gate)
2212{
2213    const int id = RTSTUB_ID(CreateRegExpWithLiteral);
2214    // 2: number of value inputs
2215    ASSERT(acc_.GetNumValueIn(gate) == 2);
2216    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2217    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
2218    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2219    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2220    GateRef pattern = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module,
2221                                                      stringId, ConstPoolType::STRING);
2222    GateRef flags = acc_.GetValueIn(gate, 1);
2223    GateRef newGate = LowerCallRuntime(gate, id, { pattern, builder_.ToTaggedInt(flags) }, true);
2224    ReplaceHirWithValue(gate, newGate);
2225}
2226
2227void SlowPathLowering::LowerStOwnByValue(GateRef gate)
2228{
2229    // 3: number of value inputs
2230    ASSERT(acc_.GetNumValueIn(gate) == 3);
2231    GateRef receiver = acc_.GetValueIn(gate, 0);
2232    GateRef propKey = acc_.GetValueIn(gate, 1);
2233    GateRef accValue = acc_.GetValueIn(gate, 2);
2234    // we do not need to merge outValueGate, so using GateRef directly instead of using Variable
2235    GateRef holeConst = builder_.HoleConstant();
2236    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), holeConst);
2237    result = builder_.CallStub(glue_, gate, CommonStubCSigns::StOwnByValue,
2238        { glue_, receiver, propKey, accValue });
2239    ReplaceHirWithValue(gate, *result);
2240}
2241
2242void SlowPathLowering::LowerStOwnByIndex(GateRef gate)
2243{
2244    // 3: number of value inputs
2245    ASSERT(acc_.GetNumValueIn(gate) == 3);
2246    GateRef receiver = acc_.GetValueIn(gate, 0);
2247    GateRef index = acc_.GetValueIn(gate, 1);
2248    GateRef accValue = acc_.GetValueIn(gate, 2);
2249    // we do not need to merge outValueGate, so using GateRef directly instead of using Variable
2250    GateRef holeConst = builder_.HoleConstant();
2251    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), holeConst);
2252    result = builder_.CallStub(glue_, gate, CommonStubCSigns::StOwnByIndex,
2253        { glue_, receiver, builder_.TruncInt64ToInt32(index), accValue });
2254    ReplaceHirWithValue(gate, *result);
2255}
2256
2257void SlowPathLowering::LowerStOwnByName(GateRef gate)
2258{
2259    // 3: number of value inputs
2260    ASSERT(acc_.GetNumValueIn(gate) == 3);
2261    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2262    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
2263    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2264    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2265    GateRef propKey = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module,
2266                                                      stringId, ConstPoolType::STRING);
2267    GateRef receiver = acc_.GetValueIn(gate, 1);
2268    GateRef accValue = acc_.GetValueIn(gate, 2);
2269    // we do not need to merge outValueGate, so using GateRef directly instead of using Variable
2270    GateRef holeConst = builder_.HoleConstant();
2271    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), holeConst);
2272    result = builder_.CallStub(glue_, gate, CommonStubCSigns::StOwnByName,
2273        { glue_, receiver, propKey, accValue });
2274    ReplaceHirWithValue(gate, *result);
2275}
2276
2277void SlowPathLowering::LowerNewLexicalEnv(GateRef gate)
2278{
2279    // 2: number of value inputs
2280    ASSERT(acc_.GetNumValueIn(gate) == 2);
2281    GateRef lexEnv = acc_.GetValueIn(gate, 1);
2282    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::NewLexicalEnv,
2283        { glue_, lexEnv, builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0)) });
2284    ReplaceHirWithValue(gate, result);
2285}
2286
2287void SlowPathLowering::LowerNewLexicalEnvWithName(GateRef gate)
2288{
2289    // 3: number of value inputs
2290    ASSERT(acc_.GetNumValueIn(gate) == 3);
2291    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2292    GateRef lexEnv = acc_.GetValueIn(gate, 2); // 2: Get current lexEnv
2293    auto args = { builder_.ToTaggedInt(acc_.GetValueIn(gate, 0)),
2294                  builder_.ToTaggedInt(acc_.GetValueIn(gate, 1)),
2295                  lexEnv, jsFunc };
2296    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(OptNewLexicalEnvWithName), args, true);
2297    ReplaceHirWithValue(gate, result, true);
2298}
2299
2300void SlowPathLowering::LowerNewSendableEnv(GateRef gate)
2301{
2302    // 2: number of value inputs
2303    ASSERT(acc_.GetNumValueIn(gate) == 1);
2304    auto args = { builder_.ToTaggedInt(acc_.GetValueIn(gate, 0)) };
2305    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(NewSendableEnv), args, true);
2306    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2307    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2308    builder_.SetSendableEnvToModule(glue_, module, result);
2309    ReplaceHirWithValue(gate, result);
2310}
2311
2312void SlowPathLowering::LowerPopLexicalEnv(GateRef gate)
2313{
2314    GateRef currentEnv = acc_.GetValueIn(gate, 0);
2315    GateRef index = builder_.Int32(LexicalEnv::PARENT_ENV_INDEX);
2316    GateRef parentEnv = builder_.GetValueFromTaggedArray(currentEnv, index);
2317    ReplaceHirWithValue(gate, parentEnv, true);
2318}
2319
2320void SlowPathLowering::LowerLdSuperByValue(GateRef gate)
2321{
2322    const int id = RTSTUB_ID(OptLdSuperByValue);
2323    // 2: number of value inputs
2324    ASSERT(acc_.GetNumValueIn(gate) == 2);
2325    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2326    GateRef receiver = acc_.GetValueIn(gate, 0);
2327    GateRef propKey = acc_.GetValueIn(gate, 1);
2328    GateRef newGate = LowerCallRuntime(gate, id, { receiver, propKey, jsFunc });
2329    ReplaceHirWithValue(gate, newGate);
2330}
2331
2332void SlowPathLowering::LowerStSuperByValue(GateRef gate)
2333{
2334    const int id = RTSTUB_ID(OptStSuperByValue);
2335    // 3: number of value inputs
2336    ASSERT(acc_.GetNumValueIn(gate) == 3);
2337    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2338    GateRef receiver = acc_.GetValueIn(gate, 0);
2339    GateRef propKey = acc_.GetValueIn(gate, 1);
2340    GateRef value = acc_.GetValueIn(gate, 2);
2341    GateRef newGate = LowerCallRuntime(gate, id, { receiver, propKey, value, jsFunc});
2342    ReplaceHirWithValue(gate, newGate);
2343}
2344
2345void SlowPathLowering::LowerTryStGlobalByName(GateRef gate)
2346{
2347    // 3: number of value inputs
2348    ASSERT(acc_.GetNumValueIn(gate) == 3);
2349    GateRef stringId = acc_.GetValueIn(gate, 1);  // 1: the second parameter
2350    GateRef value = acc_.GetValueIn(gate, 2);  // 2: the 2nd para is value
2351    LowerCallStubWithIC(gate, CommonStubCSigns::TryStGlobalByName, { stringId, value });
2352}
2353
2354void SlowPathLowering::LowerStConstToGlobalRecord(GateRef gate, bool isConst)
2355{
2356    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2357    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
2358    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2359    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2360    GateRef propKey = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module,
2361                                                      stringId, ConstPoolType::STRING);
2362    acc_.SetDep(gate, propKey);
2363    // 2 : number of value inputs
2364    ASSERT(acc_.GetNumValueIn(gate) == 2);
2365    const int id = RTSTUB_ID(StGlobalRecord);
2366    GateRef value = acc_.GetValueIn(gate, 1);
2367    GateRef isConstGate = isConst ? builder_.TaggedTrue() : builder_.TaggedFalse();
2368    GateRef result = LowerCallRuntime(gate, id, { propKey, value, isConstGate }, true);
2369    ReplaceHirWithValue(gate, result);
2370}
2371
2372void SlowPathLowering::LowerStOwnByValueWithNameSet(GateRef gate)
2373{
2374    // 3: number of value inputs
2375    ASSERT(acc_.GetNumValueIn(gate) == 3);
2376    GateRef receiver = acc_.GetValueIn(gate, 0);
2377    GateRef propKey = acc_.GetValueIn(gate, 1);
2378    GateRef accValue = acc_.GetValueIn(gate, 2);
2379    Label successExit(&builder_);
2380    Label exceptionExit(&builder_);
2381    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::StOwnByValueWithNameSet,
2382        { glue_, receiver, propKey, accValue });
2383    BRANCH_CIR(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
2384        &exceptionExit, &successExit);
2385    CREATE_DOUBLE_EXIT(successExit, exceptionExit)
2386    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, Circuit::NullGate());
2387}
2388
2389void SlowPathLowering::LowerStOwnByNameWithNameSet(GateRef gate)
2390{
2391    // 3: number of value inputs
2392    ASSERT(acc_.GetNumValueIn(gate) == 3);
2393    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2394    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
2395    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2396    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2397    GateRef propKey = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module,
2398                                                      stringId, ConstPoolType::STRING);
2399    GateRef receiver = acc_.GetValueIn(gate, 1);
2400    GateRef accValue = acc_.GetValueIn(gate, 2);
2401    Label successExit(&builder_);
2402    Label exceptionExit(&builder_);
2403    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::StOwnByNameWithNameSet,
2404        { glue_, receiver, propKey, accValue });
2405    BRANCH_CIR(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
2406        &exceptionExit, &successExit);
2407    CREATE_DOUBLE_EXIT(successExit, exceptionExit)
2408    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, Circuit::NullGate());
2409}
2410
2411void SlowPathLowering::LowerLdGlobalVar(GateRef gate)
2412{
2413    // 2: number of value inputs
2414    ASSERT(acc_.GetNumValueIn(gate) == 2);
2415    GateRef stringId = acc_.GetValueIn(gate, 1);  // 1: the second parameter
2416    LowerCallStubWithIC(gate, CommonStubCSigns::LdGlobalVar, { stringId });
2417}
2418
2419void SlowPathLowering::LowerLdObjByName(GateRef gate)
2420{
2421    // 3: number of value inputs
2422    ASSERT(acc_.GetNumValueIn(gate) == 3);
2423    GateRef stringId = acc_.GetValueIn(gate, 1);  // 1: the second parameter
2424    GateRef receiver = acc_.GetValueIn(gate, 2);  // 2: the third parameter
2425    LowerCallStubWithIC(gate, CommonStubCSigns::GetPropertyByName, { receiver, stringId });
2426}
2427
2428void SlowPathLowering::LowerStObjByName(GateRef gate, bool isThis)
2429{
2430    GateRef receiver;
2431    GateRef value;
2432    if (isThis) {
2433        ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: number of value inputs
2434        receiver = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
2435        value = acc_.GetValueIn(gate, 2);      // 2: the third para is value
2436    } else {
2437        ASSERT(acc_.GetNumValueIn(gate) == 4); // 4: number of value inputs
2438        receiver = acc_.GetValueIn(gate, 2);   // 2: the third para is receiver
2439        value = acc_.GetValueIn(gate, 3);      // 3: the 4th para is value
2440    }
2441    GateRef stringId = acc_.GetValueIn(gate, 1);   // 1: the second parameter
2442    LowerCallStubWithIC(gate, CommonStubCSigns::SetPropertyByName, { receiver, stringId, value });
2443}
2444
2445void SlowPathLowering::LowerDefineGetterSetterByValue(GateRef gate)
2446{
2447    const int id = RTSTUB_ID(DefineGetterSetterByValue);
2448    // 5: number of value inputs
2449    ASSERT(acc_.GetNumValueIn(gate) == 5);
2450    GateRef obj = acc_.GetValueIn(gate, 0);
2451    GateRef prop = acc_.GetValueIn(gate, 1);
2452    GateRef getter = acc_.GetValueIn(gate, 2);
2453    GateRef setter = acc_.GetValueIn(gate, 3);
2454    GateRef acc = acc_.GetValueIn(gate, 4);
2455    auto args = { obj, prop, getter, setter, acc,
2456        builder_.UndefineConstant(), builder_.Int32ToTaggedInt(builder_.Int32(1)) };
2457    GateRef result = LowerCallRuntime(gate, id, args);
2458    ReplaceHirWithValue(gate, result);
2459}
2460
2461void SlowPathLowering::LowerLdObjByIndex(GateRef gate)
2462{
2463    // 2: number of value inputs
2464    ASSERT(acc_.GetNumValueIn(gate) == 2);
2465    GateRef holeConst = builder_.HoleConstant();
2466    DEFVALUE(varAcc, (&builder_), VariableType::JS_ANY(), holeConst);
2467    GateRef index = acc_.GetValueIn(gate, 0);
2468    GateRef receiver = acc_.GetValueIn(gate, 1);
2469    varAcc = builder_.CallStub(glue_, gate, CommonStubCSigns::LdObjByIndex,
2470        {glue_, receiver, builder_.TruncInt64ToInt32(index)});
2471    ReplaceHirWithValue(gate, *varAcc);
2472}
2473
2474void SlowPathLowering::LowerStObjByIndex(GateRef gate)
2475{
2476    // 3: number of value inputs
2477    ASSERT(acc_.GetNumValueIn(gate) == 3);
2478    GateRef receiver = acc_.GetValueIn(gate, 0);
2479    GateRef index = acc_.GetValueIn(gate, 1);
2480    GateRef accValue = acc_.GetValueIn(gate, 2);
2481    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
2482    result = builder_.CallStub(glue_, gate, CommonStubCSigns::StObjByIndex,
2483        {glue_, receiver, builder_.TruncInt64ToInt32(index), accValue});
2484    ReplaceHirWithValue(gate, *result);
2485}
2486
2487void SlowPathLowering::LowerLdObjByValue(GateRef gate, bool isThis)
2488{
2489    GateRef receiver;
2490    GateRef propKey;
2491    if (isThis) {
2492        ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: number of value inputs
2493        receiver = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
2494        propKey = acc_.GetValueIn(gate, 1);
2495    } else {
2496        ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: number of value inputs
2497        receiver = acc_.GetValueIn(gate, 1);
2498        propKey = acc_.GetValueIn(gate, 2);    // 2: the third parameter
2499    }
2500    LowerCallStubWithIC(gate, CommonStubCSigns::GetPropertyByValue, { receiver, propKey });
2501}
2502
2503void SlowPathLowering::LowerStObjByValue(GateRef gate, bool isThis)
2504{
2505    GateRef receiver;
2506    GateRef propKey;
2507    GateRef value;
2508    if (isThis) {
2509        ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: number of value inputs
2510        receiver = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
2511        propKey = acc_.GetValueIn(gate, 1);
2512        value = acc_.GetValueIn(gate, 2);      // 2: the third parameter
2513    } else {
2514        // 4: number of value inputs
2515        ASSERT(acc_.GetNumValueIn(gate) == 4);
2516        receiver = acc_.GetValueIn(gate, 1);
2517        propKey = acc_.GetValueIn(gate, 2);   // 2: the third parameter
2518        value = acc_.GetValueIn(gate, 3);     // 3: the 4th parameter
2519    }
2520    LowerCallStubWithIC(gate, CommonStubCSigns::SetPropertyByValue, { receiver, propKey, value });
2521}
2522
2523void SlowPathLowering::LowerLdSuperByName(GateRef gate)
2524{
2525    // 2: number of value inputs
2526    ASSERT(acc_.GetNumValueIn(gate) == 2);
2527    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2528    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
2529    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2530    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2531    GateRef prop = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module, stringId,
2532                                                   ConstPoolType::STRING);
2533    GateRef result =
2534        LowerCallRuntime(gate, RTSTUB_ID(OptLdSuperByValue), {acc_.GetValueIn(gate, 1), prop, jsFunc}, true);
2535    ReplaceHirWithValue(gate, result);
2536}
2537
2538void SlowPathLowering::LowerStSuperByName(GateRef gate)
2539{
2540    // 3: number of value inputs
2541    ASSERT(acc_.GetNumValueIn(gate) == 3);
2542    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2543    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
2544    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2545    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2546    GateRef prop = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module, stringId,
2547                                                   ConstPoolType::STRING);
2548    auto args2 = { acc_.GetValueIn(gate, 1), prop, acc_.GetValueIn(gate, 2), jsFunc };
2549    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(OptStSuperByValue), args2, true);
2550    ReplaceHirWithValue(gate, result);
2551}
2552
2553void SlowPathLowering::LowerCreateGeneratorObj(GateRef gate)
2554{
2555    const int id = RTSTUB_ID(CreateGeneratorObj);
2556    // 1: number of value inputs
2557    ASSERT(acc_.GetNumValueIn(gate) == 1);
2558    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0)});
2559    ReplaceHirWithValue(gate, newGate);
2560}
2561
2562void SlowPathLowering::LowerCreateAsyncGeneratorObj(GateRef gate)
2563{
2564    int id = RTSTUB_ID(CreateAsyncGeneratorObj);
2565    // 1: number of value inputs
2566    ASSERT(acc_.GetNumValueIn(gate) == 1);
2567    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0)});
2568    ReplaceHirWithValue(gate, newGate);
2569}
2570
2571void SlowPathLowering::LowerAsyncGeneratorResolve(GateRef gate)
2572{
2573    SaveFrameToContext(gate);
2574    acc_.SetDep(gate, builder_.GetDepend());
2575    int id = RTSTUB_ID(OptAsyncGeneratorResolve);
2576    GateRef asyncGen = acc_.GetValueIn(gate, 1);
2577    GateRef value = acc_.GetValueIn(gate, 2);
2578    GateRef flag = acc_.GetValueIn(gate, 3);
2579    GateRef newGate = LowerCallRuntime(gate, id, {asyncGen, value, flag});
2580    ReplaceHirWithValue(gate, newGate);
2581}
2582
2583void SlowPathLowering::LowerAsyncGeneratorReject(GateRef gate)
2584{
2585    int id = RTSTUB_ID(AsyncGeneratorReject);
2586    // 2: number of value inputs
2587    ASSERT(acc_.GetNumValueIn(gate) == 2);
2588    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)});
2589    ReplaceHirWithValue(gate, newGate);
2590}
2591
2592void SlowPathLowering::LowerStArraySpread(GateRef gate)
2593{
2594    const int id = RTSTUB_ID(StArraySpread);
2595    // 3: number of value inputs
2596    ASSERT(acc_.GetNumValueIn(gate) == 3);
2597    auto args = { acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1), acc_.GetValueIn(gate, 2) };
2598    GateRef newGate = LowerCallRuntime(gate, id, args);
2599    ReplaceHirWithValue(gate, newGate);
2600}
2601
2602void SlowPathLowering::LowerLdLexVar(GateRef gate)
2603{
2604    // 3: number of value inputs
2605    ASSERT(acc_.GetNumValueIn(gate) == 3);
2606    GateRef level = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2607    GateRef slot = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 1));
2608    DEFVALUE(currentEnv, (&builder_), VariableType::JS_ANY(), acc_.GetValueIn(gate, 2)); // 2: Get current lexEnv
2609    GateRef index = builder_.Int32(LexicalEnv::PARENT_ENV_INDEX);
2610    Label exit(&builder_);
2611    uint64_t constLevel = acc_.TryGetValue(acc_.GetValueIn(gate, 0));
2612    if (constLevel == 0) {
2613        builder_.Jump(&exit);
2614    } else if (constLevel == 1) {
2615        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2616        builder_.Jump(&exit);
2617    } else {
2618        DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
2619        Label loopHead(&builder_);
2620        Label loopEnd(&builder_);
2621        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopHead, &exit);
2622        builder_.LoopBegin(&loopHead);
2623        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2624        i = builder_.Int32Add(*i, builder_.Int32(1));
2625        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopEnd, &exit);
2626        builder_.Bind(&loopEnd);
2627        builder_.LoopEnd(&loopHead);
2628    }
2629    builder_.Bind(&exit);
2630    GateRef valueIndex = builder_.Int32Add(slot, builder_.Int32(LexicalEnv::RESERVED_ENV_LENGTH));
2631    GateRef result = builder_.GetValueFromTaggedArray(*currentEnv, valueIndex);
2632    ReplaceHirWithValue(gate, result, true);
2633}
2634
2635void SlowPathLowering::LowerLdSendableVar(GateRef gate)
2636{
2637    // 2: number of value inputs
2638    ASSERT(acc_.GetNumValueIn(gate) == 2);
2639    GateRef level = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2640    GateRef slot = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 1));
2641    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2642    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2643    DEFVALUE(currentEnv, (&builder_), VariableType::JS_ANY(), builder_.GetSendableEnvFromModule(module));
2644    GateRef index = builder_.Int32(SendableEnv::SENDABLE_PARENT_ENV_INDEX);
2645    Label exit(&builder_);
2646    uint64_t constLevel = acc_.TryGetValue(acc_.GetValueIn(gate, 0));
2647    if (constLevel == 0) {
2648        builder_.Jump(&exit);
2649    } else if (constLevel == 1) {
2650        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2651        builder_.Jump(&exit);
2652    } else {
2653        DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
2654        Label loopHead(&builder_);
2655        Label loopEnd(&builder_);
2656        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopHead, &exit);
2657        builder_.LoopBegin(&loopHead);
2658        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2659        i = builder_.Int32Add(*i, builder_.Int32(1));
2660        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopEnd, &exit);
2661        builder_.Bind(&loopEnd);
2662        builder_.LoopEnd(&loopHead);
2663    }
2664    builder_.Bind(&exit);
2665    GateRef valueIndex = builder_.Int32Add(slot, builder_.Int32(SendableEnv::SENDABLE_RESERVED_ENV_LENGTH));
2666    GateRef result = builder_.GetValueFromTaggedArray(*currentEnv, valueIndex);
2667    ReplaceHirWithValue(gate, result, true);
2668}
2669
2670void SlowPathLowering::LowerStLexVar(GateRef gate)
2671{
2672    // 4: number of value inputs
2673    ASSERT(acc_.GetNumValueIn(gate) == 4);
2674    GateRef level = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2675    GateRef slot = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 1));
2676    GateRef value = acc_.GetValueIn(gate, 3);
2677    DEFVALUE(currentEnv, (&builder_), VariableType::JS_ANY(), acc_.GetValueIn(gate, 2)); // 2: Get current lexEnv
2678    GateRef index = builder_.Int32(LexicalEnv::PARENT_ENV_INDEX);
2679    Label exit(&builder_);
2680    uint64_t constLevel = acc_.TryGetValue(acc_.GetValueIn(gate, 0));
2681    if (constLevel == 0) {
2682        builder_.Jump(&exit);
2683    } else if (constLevel == 1) {
2684        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2685        builder_.Jump(&exit);
2686    } else {
2687        DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
2688        Label loopHead(&builder_);
2689        Label loopEnd(&builder_);
2690        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopHead, &exit);
2691        builder_.LoopBegin(&loopHead);
2692        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2693        i = builder_.Int32Add(*i, builder_.Int32(1));
2694        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopEnd, &exit);
2695        builder_.Bind(&loopEnd);
2696        builder_.LoopEnd(&loopHead);
2697    }
2698    builder_.Bind(&exit);
2699    GateRef valueIndex = builder_.Int32Add(slot, builder_.Int32(LexicalEnv::RESERVED_ENV_LENGTH));
2700    builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *currentEnv, valueIndex, value);
2701    auto result = *currentEnv;
2702    ReplaceHirWithValue(gate, result, true);
2703}
2704
2705void SlowPathLowering::LowerStSendableVar(GateRef gate)
2706{
2707    // 3: number of value inputs
2708    ASSERT(acc_.GetNumValueIn(gate) == 3);
2709    GateRef level = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
2710    GateRef slot = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 1));
2711    GateRef value = acc_.GetValueIn(gate, 2);
2712    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2713    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2714    DEFVALUE(currentEnv, (&builder_), VariableType::JS_ANY(), builder_.GetSendableEnvFromModule(module));
2715    GateRef index = builder_.Int32(SendableEnv::SENDABLE_PARENT_ENV_INDEX);
2716    Label exit(&builder_);
2717    uint64_t constLevel = acc_.TryGetValue(acc_.GetValueIn(gate, 0));
2718    if (constLevel == 0) {
2719        builder_.Jump(&exit);
2720    } else if (constLevel == 1) {
2721        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2722        builder_.Jump(&exit);
2723    } else {
2724        DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
2725        Label loopHead(&builder_);
2726        Label loopEnd(&builder_);
2727        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopHead, &exit);
2728        builder_.LoopBegin(&loopHead);
2729        currentEnv = builder_.GetValueFromTaggedArray(*currentEnv, index);
2730        i = builder_.Int32Add(*i, builder_.Int32(1));
2731        BRANCH_CIR(builder_.Int32LessThan(*i, level), &loopEnd, &exit);
2732        builder_.Bind(&loopEnd);
2733        builder_.LoopEnd(&loopHead);
2734    }
2735    builder_.Bind(&exit);
2736    GateRef valueIndex = builder_.Int32Add(slot, builder_.Int32(SendableEnv::SENDABLE_RESERVED_ENV_LENGTH));
2737    builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *currentEnv, valueIndex, value);
2738    auto result = *currentEnv;
2739    ReplaceHirWithValue(gate, result, true);
2740}
2741
2742void SlowPathLowering::LowerDefineClassWithBuffer(GateRef gate)
2743{
2744    ASSERT(acc_.GetNumValueIn(gate) == 6);  // 6: number of value inputs
2745    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2746    GateRef methodId = acc_.GetValueIn(gate, 0);
2747    GateRef proto = acc_.GetValueIn(gate, 3);
2748    GateRef literalId = acc_.GetValueIn(gate, 1);
2749    GateRef length = acc_.GetValueIn(gate, 2);  // 2: second arg
2750    GateRef lexicalEnv = acc_.GetValueIn(gate, 4); // 4: Get current env
2751    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
2752    GateRef module = builder_.GetModuleFromFunction(jsFunc);
2753    Label isException(&builder_);
2754    Label isNotException(&builder_);
2755
2756    GateRef result;
2757    auto args = { proto, lexicalEnv, sharedConstPool,
2758                  builder_.ToTaggedInt(methodId), builder_.ToTaggedInt(literalId), module,
2759                  builder_.ToTaggedInt(length),
2760#if ECMASCRIPT_ENABLE_IC
2761                  // 5: slot id
2762                  builder_.Int32ToTaggedInt(builder_.ZExtInt16ToInt32(acc_.GetValueIn(gate, 5))), jsFunc
2763#endif
2764    };
2765    result = LowerCallRuntime(gate, RTSTUB_ID(CreateClassWithBuffer), args, true);
2766    BRANCH_CIR(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION), &isException, &isNotException);
2767    CREATE_DOUBLE_EXIT(isNotException, isException)
2768    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, result);
2769}
2770
2771void SlowPathLowering::LowerDefineFunc(GateRef gate)
2772{
2773    Jit::JitLockHolder lock(compilationEnv_, "SlowPathLowering");
2774    Environment env(gate, circuit_, &builder_);
2775    GateRef methodId = acc_.GetValueIn(gate, 1);
2776
2777    FunctionKind kind = FunctionKind::LAST_FUNCTION_KIND;
2778    if (acc_.IsConstantNumber(methodId)) {
2779        // try to speed up the kind checking
2780        JSTaggedValue unsharedCp;
2781        if (compilationEnv_->IsJitCompiler()) {
2782            unsharedCp = compilationEnv_->FindConstpool(compilationEnv_->GetJSPandaFile(), 0);
2783        } else {
2784            auto methodOffset = acc_.TryGetMethodOffset(gate);
2785            unsharedCp = compilationEnv_->FindOrCreateUnsharedConstpool(methodOffset);
2786        }
2787        auto obj = compilationEnv_->GetMethodFromCache(unsharedCp, acc_.GetConstantValue(methodId));
2788        if (obj != JSTaggedValue::Undefined()) {
2789            kind = Method::Cast(obj)->GetFunctionKind();
2790        }
2791    }
2792    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
2793    GateRef length = acc_.GetValueIn(gate, 2);
2794    GateRef lexEnv = acc_.GetValueIn(gate, 3); // 3: Get current env
2795    GateRef slotId = acc_.GetValueIn(gate, 0);
2796    Label success(&builder_);
2797    Label failed(&builder_);
2798    GateRef result = builder_.CallStub(glue_, gate, CommonStubCSigns::Definefunc,
2799        {glue_, jsFunc, builder_.TruncInt64ToInt32(methodId), builder_.TruncInt64ToInt32(length), lexEnv, slotId});
2800    BRANCH_CIR(builder_.TaggedIsException(result), &failed, &success);
2801    CREATE_DOUBLE_EXIT(success, failed)
2802    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, result);
2803}
2804
2805void SlowPathLowering::LowerAsyncFunctionEnter(GateRef gate)
2806{
2807    const int id = RTSTUB_ID(AsyncFunctionEnter);
2808    // 0: number of value inputs
2809    ASSERT(acc_.GetNumValueIn(gate) == 0);
2810    GateRef newGate = LowerCallRuntime(gate, id, {});
2811    ReplaceHirWithValue(gate, newGate);
2812}
2813
2814void SlowPathLowering::LowerTypeof(GateRef gate)
2815{
2816    // 1: number of value inputs
2817    ASSERT(acc_.GetNumValueIn(gate) == 1);
2818    GateRef obj = acc_.GetValueIn(gate, 0);
2819    Label entry(&builder_);
2820    Label exit(&builder_);
2821
2822    GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
2823        builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(builder_.GetCompilationConfig()->Is32Bit())));
2824    GateRef undefinedIndex = builder_.GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX);
2825    GateRef gConstUndefinedStr = builder_.Load(VariableType::JS_POINTER(), gConstAddr, undefinedIndex);
2826    DEFVALUE(result, (&builder_), VariableType::JS_POINTER(), gConstUndefinedStr);
2827    Label objIsTrue(&builder_);
2828    Label objNotTrue(&builder_);
2829    Label defaultLabel(&builder_);
2830    GateRef gConstBooleanStr = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2831        builder_.GetGlobalConstantOffset(ConstantIndex::BOOLEAN_STRING_INDEX));
2832    BRANCH_CIR(builder_.TaggedIsTrue(obj), &objIsTrue, &objNotTrue);
2833    builder_.Bind(&objIsTrue);
2834    {
2835        result = gConstBooleanStr;
2836        builder_.Jump(&exit);
2837    }
2838    builder_.Bind(&objNotTrue);
2839    {
2840        Label objIsFalse(&builder_);
2841        Label objNotFalse(&builder_);
2842        BRANCH_CIR(builder_.TaggedIsFalse(obj), &objIsFalse, &objNotFalse);
2843        builder_.Bind(&objIsFalse);
2844        {
2845            result = gConstBooleanStr;
2846            builder_.Jump(&exit);
2847        }
2848        builder_.Bind(&objNotFalse);
2849        {
2850            Label objIsNull(&builder_);
2851            Label objNotNull(&builder_);
2852            BRANCH_CIR(builder_.TaggedIsNull(obj), &objIsNull, &objNotNull);
2853            builder_.Bind(&objIsNull);
2854            {
2855                result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2856                    builder_.GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
2857                builder_.Jump(&exit);
2858            }
2859            builder_.Bind(&objNotNull);
2860            {
2861                Label objIsUndefined(&builder_);
2862                Label objNotUndefined(&builder_);
2863                BRANCH_CIR(builder_.TaggedIsUndefined(obj), &objIsUndefined, &objNotUndefined);
2864                builder_.Bind(&objIsUndefined);
2865                {
2866                    result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2867                        builder_.GetGlobalConstantOffset(ConstantIndex::UNDEFINED_STRING_INDEX));
2868                    builder_.Jump(&exit);
2869                }
2870                builder_.Bind(&objNotUndefined);
2871                builder_.Jump(&defaultLabel);
2872            }
2873        }
2874    }
2875    builder_.Bind(&defaultLabel);
2876    {
2877        Label objIsHeapObject(&builder_);
2878        Label objNotHeapObject(&builder_);
2879        BRANCH_CIR(builder_.TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
2880        builder_.Bind(&objIsHeapObject);
2881        {
2882            Label objIsString(&builder_);
2883            Label objNotString(&builder_);
2884            BRANCH_CIR(builder_.TaggedObjectIsString(obj), &objIsString, &objNotString);
2885            builder_.Bind(&objIsString);
2886            {
2887                result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2888                    builder_.GetGlobalConstantOffset(ConstantIndex::STRING_STRING_INDEX));
2889                builder_.Jump(&exit);
2890            }
2891            builder_.Bind(&objNotString);
2892            {
2893                Label objIsSymbol(&builder_);
2894                Label objNotSymbol(&builder_);
2895                BRANCH_CIR(builder_.IsJsType(obj, JSType::SYMBOL), &objIsSymbol, &objNotSymbol);
2896                builder_.Bind(&objIsSymbol);
2897                {
2898                    result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2899                        builder_.GetGlobalConstantOffset(ConstantIndex::SYMBOL_STRING_INDEX));
2900                    builder_.Jump(&exit);
2901                }
2902                builder_.Bind(&objNotSymbol);
2903                {
2904                    Label objIsCallable(&builder_);
2905                    Label objNotCallable(&builder_);
2906                    BRANCH_CIR(builder_.IsCallable(obj), &objIsCallable, &objNotCallable);
2907                    builder_.Bind(&objIsCallable);
2908                    {
2909                        result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2910                            builder_.GetGlobalConstantOffset(ConstantIndex::FUNCTION_STRING_INDEX));
2911                        builder_.Jump(&exit);
2912                    }
2913                    builder_.Bind(&objNotCallable);
2914                    {
2915                        Label objIsBigInt(&builder_);
2916                        Label objNotBigInt(&builder_);
2917                        BRANCH_CIR(builder_.IsJsType(obj, JSType::BIGINT), &objIsBigInt, &objNotBigInt);
2918                        builder_.Bind(&objIsBigInt);
2919                        {
2920                            result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2921                                builder_.GetGlobalConstantOffset(ConstantIndex::BIGINT_STRING_INDEX));
2922                            builder_.Jump(&exit);
2923                        }
2924                        builder_.Bind(&objNotBigInt);
2925                        {
2926                            result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2927                                builder_.GetGlobalConstantOffset(ConstantIndex::OBJECT_STRING_INDEX));
2928                            builder_.Jump(&exit);
2929                        }
2930                    }
2931                }
2932            }
2933        }
2934        builder_.Bind(&objNotHeapObject);
2935        {
2936            Label objIsNum(&builder_);
2937            Label objNotNum(&builder_);
2938            BRANCH_CIR(builder_.TaggedIsNumber(obj), &objIsNum, &objNotNum);
2939            builder_.Bind(&objIsNum);
2940            {
2941                result = builder_.Load(VariableType::JS_POINTER(), gConstAddr,
2942                    builder_.GetGlobalConstantOffset(ConstantIndex::NUMBER_STRING_INDEX));
2943                builder_.Jump(&exit);
2944            }
2945            builder_.Bind(&objNotNum);
2946            builder_.Jump(&exit);
2947        }
2948    }
2949    builder_.Bind(&exit);
2950    ReplaceHirWithValue(gate, *result, true);
2951}
2952
2953GateRef SlowPathLowering::GetValueFromTaggedArray(GateRef arrayGate, GateRef indexOffset)
2954{
2955    GateRef offset = builder_.PtrMul(builder_.ZExtInt32ToPtr(indexOffset),
2956                                     builder_.IntPtr(JSTaggedValue::TaggedTypeSize()));
2957    GateRef dataOffset = builder_.PtrAdd(offset, builder_.IntPtr(TaggedArray::DATA_OFFSET));
2958    GateRef value = builder_.Load(VariableType::JS_ANY(), arrayGate, dataOffset);
2959    return value;
2960}
2961
2962void SlowPathLowering::LowerStoreRegister(GateRef gate, GateRef arrayGate)
2963{
2964    ASSERT((acc_.GetOpCode(gate) == OpCode::RESTORE_REGISTER));
2965    auto index = acc_.GetVirtualRegisterIndex(gate);
2966    auto indexOffset = builder_.Int32(index);
2967    GateRef value = GetValueFromTaggedArray(arrayGate, indexOffset);
2968    acc_.ReplaceGate(gate, Circuit::NullGate(), Circuit::NullGate(), value);
2969}
2970
2971void SlowPathLowering::LowerResumeGenerator(GateRef gate)
2972{
2973    GateRef obj = acc_.GetValueIn(gate, 0);
2974    std::vector<GateRef> registerGates {};
2975
2976    AddProfiling(gate, false);
2977    GateRef contextOffset = builder_.IntPtr(JSGeneratorObject::GENERATOR_CONTEXT_OFFSET);
2978    GateRef contextGate = builder_.Load(VariableType::JS_POINTER(), obj, contextOffset);
2979    GateRef arrayOffset = builder_.IntPtr(GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET);
2980    GateRef arrayGate = builder_.Load(VariableType::JS_POINTER(), contextGate, arrayOffset);
2981
2982    auto uses = acc_.Uses(gate);
2983    for (auto it = uses.begin(); it != uses.end(); it++) {
2984        if (acc_.IsValueIn(it) && acc_.GetOpCode(*it) == OpCode::RESTORE_REGISTER) {
2985            registerGates.emplace_back(*it);
2986        }
2987    }
2988    for (auto item : registerGates) {
2989        LowerStoreRegister(item, arrayGate);
2990    }
2991
2992    // 1: number of value inputs
2993    ASSERT(acc_.GetNumValueIn(gate) == 1);
2994    Label isAsyncGeneratorObj(&builder_);
2995    Label notAsyncGeneratorObj(&builder_);
2996    Label exit(&builder_);
2997    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
2998    BRANCH_CIR(builder_.TaggedIsAsyncGeneratorObject(obj), &isAsyncGeneratorObj, &notAsyncGeneratorObj);
2999    builder_.Bind(&isAsyncGeneratorObj);
3000    {
3001        GateRef resumeResultOffset = builder_.IntPtr(JSAsyncGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET);
3002        result = builder_.Load(VariableType::JS_ANY(), obj, resumeResultOffset);
3003        builder_.Jump(&exit);
3004    }
3005    builder_.Bind(&notAsyncGeneratorObj);
3006    {
3007        GateRef resumeResultOffset = builder_.IntPtr(JSGeneratorObject::GENERATOR_RESUME_RESULT_OFFSET);
3008        result = builder_.Load(VariableType::JS_ANY(), obj, resumeResultOffset);
3009        GateRef taskInfoOffset = builder_.IntPtr(JSGeneratorObject::TASK_INFO_OFFSET);
3010        GateRef taskInfo = builder_.Load(VariableType::NATIVE_POINTER(), obj, taskInfoOffset);
3011        GateRef glueTaskOffset =
3012            builder_.IntPtr(JSThread::GlueData::GetTaskInfoOffset(builder_.GetCompilationConfig()->Is32Bit()));
3013        builder_.Store(VariableType::NATIVE_POINTER(), glue_, glue_, glueTaskOffset, taskInfo);
3014        builder_.Store(VariableType::NATIVE_POINTER(), glue_, obj, taskInfoOffset, builder_.IntPtr(0));
3015        builder_.Jump(&exit);
3016    }
3017    builder_.Bind(&exit);
3018    ReplaceHirWithValue(gate, *result, true);
3019}
3020
3021void SlowPathLowering::LowerGetResumeMode(GateRef gate)
3022{
3023    // 1: number of value inputs
3024    ASSERT(acc_.GetNumValueIn(gate) == 1);
3025    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3026    Label isAsyncGeneratorObj(&builder_);
3027    Label notAsyncGeneratorObj(&builder_);
3028    Label exit(&builder_);
3029    GateRef obj = acc_.GetValueIn(gate, 0);
3030    BRANCH_CIR(builder_.TaggedIsAsyncGeneratorObject(obj), &isAsyncGeneratorObj, &notAsyncGeneratorObj);
3031    builder_.Bind(&isAsyncGeneratorObj);
3032    {
3033        GateRef bitFieldOffset = builder_.IntPtr(JSAsyncGeneratorObject::BIT_FIELD_OFFSET);
3034        GateRef bitField = builder_.Load(VariableType::INT32(), obj, bitFieldOffset);
3035        auto bitfieldlsr = builder_.Int32LSR(bitField,
3036                                             builder_.Int32(JSAsyncGeneratorObject::ResumeModeBits::START_BIT));
3037        GateRef modeBits = builder_.Int32And(bitfieldlsr,
3038                                             builder_.Int32((1LU << JSAsyncGeneratorObject::ResumeModeBits::SIZE) - 1));
3039        auto resumeMode = builder_.SExtInt32ToInt64(modeBits);
3040        result = builder_.ToTaggedIntPtr(resumeMode);
3041        builder_.Jump(&exit);
3042    }
3043    builder_.Bind(&notAsyncGeneratorObj);
3044    {
3045        GateRef bitFieldOffset = builder_.IntPtr(JSGeneratorObject::BIT_FIELD_OFFSET);
3046        GateRef bitField = builder_.Load(VariableType::INT32(), obj, bitFieldOffset);
3047        auto bitfieldlsr = builder_.Int32LSR(bitField, builder_.Int32(JSGeneratorObject::ResumeModeBits::START_BIT));
3048        GateRef modeBits = builder_.Int32And(bitfieldlsr,
3049                                             builder_.Int32((1LU << JSGeneratorObject::ResumeModeBits::SIZE) - 1));
3050        auto resumeMode = builder_.SExtInt32ToInt64(modeBits);
3051        result = builder_.ToTaggedIntPtr(resumeMode);
3052        builder_.Jump(&exit);
3053    }
3054    builder_.Bind(&exit);
3055    ReplaceHirWithValue(gate, *result, true);
3056}
3057
3058void SlowPathLowering::LowerDefineMethod(GateRef gate)
3059{
3060    // 5: number of value inputs
3061    ASSERT(acc_.GetNumValueIn(gate) == 5);
3062    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3063    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
3064    GateRef methodId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
3065    GateRef module = builder_.GetModuleFromFunction(jsFunc);
3066    auto method = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module, methodId,
3067                                                  ConstPoolType::METHOD);
3068    GateRef length = acc_.GetValueIn(gate, 1);
3069    GateRef env = acc_.GetValueIn(gate, 2); // 2: Get current env
3070    GateRef homeObject = acc_.GetValueIn(gate, 4);  // 4: homeObject
3071
3072    Label defaultLabel(&builder_);
3073    Label successExit(&builder_);
3074    Label exceptionExit(&builder_);
3075    auto args = {method, homeObject, builder_.ToTaggedInt(length), env, builder_.GetModuleFromFunction(jsFunc),
3076#if ECMASCRIPT_ENABLE_IC
3077        builder_.Int32ToTaggedInt(builder_.ZExtInt16ToInt32(acc_.GetValueIn(gate, 3))), jsFunc  // 3: slot id
3078#endif
3079    };
3080    GateRef result = LowerCallRuntime(gate, RTSTUB_ID(DefineMethod), args, true);
3081    BRANCH_CIR(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION),
3082        &exceptionExit, &successExit);
3083    CREATE_DOUBLE_EXIT(successExit, exceptionExit)
3084    acc_.ReplaceHirWithIfBranch(gate, successControl, failControl, result);
3085}
3086
3087void SlowPathLowering::LowerGetUnmappedArgs(GateRef gate)
3088{
3089    GateRef actualArgc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::ACTUAL_ARGC);
3090    GateRef newGate = builder_.CallStub(glue_, gate, CommonStubCSigns::GetUnmappedArgs,
3091        { glue_, builder_.IntPtr(0), builder_.TruncInt64ToInt32(actualArgc), builder_.Undefined() });
3092    ReplaceHirWithValue(gate, newGate);
3093}
3094
3095void SlowPathLowering::LowerCopyRestArgs(GateRef gate)
3096{
3097    GateRef actualArgc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::ACTUAL_ARGC);
3098    GateRef taggedArgc = builder_.ToTaggedInt(actualArgc);
3099    GateRef restIdx = acc_.GetValueIn(gate, 0);
3100    GateRef taggedRestIdx = builder_.ToTaggedInt(restIdx);
3101
3102    const int id = RTSTUB_ID(OptCopyRestArgs);
3103    GateRef newGate = LowerCallRuntime(gate, id, {taggedArgc, taggedRestIdx});
3104    ReplaceHirWithValue(gate, newGate);
3105}
3106
3107void SlowPathLowering::LowerWideLdPatchVar(GateRef gate)
3108{
3109    const int id = RTSTUB_ID(LdPatchVar);
3110    GateRef index = acc_.GetValueIn(gate, 0);
3111    GateRef newGate = LowerCallRuntime(gate, id, {builder_.ToTaggedInt(index)});
3112    ReplaceHirWithValue(gate, newGate);
3113}
3114
3115void SlowPathLowering::LowerWideStPatchVar(GateRef gate)
3116{
3117    const int id = RTSTUB_ID(StPatchVar);
3118    GateRef index = acc_.GetValueIn(gate, 0);
3119    GateRef newGate = LowerCallRuntime(gate, id, {builder_.ToTaggedInt(index)});
3120    ReplaceHirWithValue(gate, newGate);
3121}
3122
3123void SlowPathLowering::AddProfiling(GateRef gate, bool skipGenerator)
3124{
3125    if (IsTraceBC()) {
3126        EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
3127        if ((ecmaOpcode == EcmaOpcode::SUSPENDGENERATOR_V8 || ecmaOpcode == EcmaOpcode::RESUMEGENERATOR) &&
3128            skipGenerator) {
3129            return;
3130        }
3131        auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
3132        GateRef constOpcode = builder_.ToTaggedInt(builder_.ZExtInt32ToInt64(ecmaOpcodeGate));
3133        GateRef slowPath = builder_.Int32ToTaggedInt(builder_.Int32(0));
3134        GateRef debugGate = builder_.CallRuntime(glue_, RTSTUB_ID(DebugAOTPrint), acc_.GetDep(gate),
3135                                                 { constOpcode, slowPath }, gate);
3136        acc_.SetDep(gate, debugGate);
3137    }
3138
3139    if (IsProfiling()) {
3140        EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
3141        if ((ecmaOpcode == EcmaOpcode::SUSPENDGENERATOR_V8 || ecmaOpcode == EcmaOpcode::RESUMEGENERATOR) &&
3142            skipGenerator) {
3143            return;
3144        }
3145
3146        GateRef func = builder_.Undefined();
3147        if (acc_.HasFrameState(gate)) {
3148            func = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3149        }
3150        GateRef bcIndex = builder_.Int32ToTaggedInt(builder_.Int32(acc_.TryGetBcIndex(gate)));
3151        auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
3152        GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
3153        GateRef mode =
3154            builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::SLOW_PATH)));
3155        GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(gate),
3156            { func, bcIndex, constOpcode, mode }, gate);
3157        acc_.SetDep(gate, profiling);
3158    }
3159}
3160
3161void SlowPathLowering::LowerCallthis0Imm8V8(GateRef gate)
3162{
3163    // 2: number of value inputs
3164    ASSERT(acc_.GetNumValueIn(gate) == 2);
3165
3166    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3167        EcmaOpcode::CALLTHIS0_IMM8_V8));
3168    GateRef actualArgv = builder_.IntPtr(0);
3169    GateRef newTarget = builder_.Undefined();
3170    GateRef thisObj = acc_.GetValueIn(gate, 0);
3171    GateRef func = acc_.GetValueIn(gate, 1);
3172    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj}, {glue_, func, thisObj});
3173}
3174
3175void SlowPathLowering::LowerCallArg1Imm8V8(GateRef gate)
3176{
3177    // 2: number of value inputs
3178    ASSERT(acc_.GetNumValueIn(gate) == 2);
3179    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3180        EcmaOpcode::CALLARG1_IMM8_V8));
3181    GateRef actualArgv = builder_.IntPtr(0);
3182    GateRef newTarget = builder_.Undefined();
3183    GateRef a0Value = acc_.GetValueIn(gate, 0);
3184    GateRef thisObj = builder_.Undefined();
3185    GateRef func = acc_.GetValueIn(gate, 1); // acc
3186    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj, a0Value},
3187        {glue_, func, thisObj, a0Value});
3188}
3189
3190void SlowPathLowering::LowerWideCallrangePrefImm16V8(GateRef gate)
3191{
3192    std::vector<GateRef> vec;
3193    std::vector<GateRef> vec1;
3194    size_t numIns = acc_.GetNumValueIn(gate);
3195    size_t fixedInputsNum = 1; // 1: acc
3196    ASSERT(acc_.GetNumValueIn(gate) >= fixedInputsNum);
3197    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3198        EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8));
3199    GateRef actualArgv = builder_.IntPtr(0);
3200    GateRef callTarget = acc_.GetValueIn(gate, numIns - fixedInputsNum); // acc
3201    GateRef newTarget = builder_.Undefined();
3202    GateRef thisObj = builder_.Undefined();
3203
3204    vec.emplace_back(glue_);
3205    vec.emplace_back(actualArgc);
3206    vec.emplace_back(actualArgv);
3207    vec.emplace_back(callTarget);
3208    vec.emplace_back(newTarget);
3209    vec.emplace_back(thisObj);
3210    // add args
3211    for (size_t i = 0; i < numIns - fixedInputsNum; i++) { // skip acc
3212        vec.emplace_back(acc_.GetValueIn(gate, i));
3213    }
3214
3215    vec.emplace_back(glue_);
3216    vec.emplace_back(callTarget);
3217    vec.emplace_back(thisObj);
3218    // add args
3219    for (size_t i = 0; i < numIns - fixedInputsNum; i++) { // skip acc
3220        vec.emplace_back(acc_.GetValueIn(gate, i));
3221    }
3222    LowerToJSCall(gate, vec, vec1);
3223}
3224
3225void SlowPathLowering::LowerCallThisArg1(GateRef gate)
3226{
3227    // 3: number of value inputs
3228    ASSERT(acc_.GetNumValueIn(gate) == 3);
3229    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3230        EcmaOpcode::CALLTHIS1_IMM8_V8_V8));
3231    GateRef actualArgv = builder_.IntPtr(0);
3232    GateRef newTarget = builder_.Undefined();
3233    GateRef thisObj = acc_.GetValueIn(gate, 0);
3234    GateRef a0 = acc_.GetValueIn(gate, 1); // 1:first parameter
3235    GateRef func = acc_.GetValueIn(gate, 2); // 2:function
3236    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj, a0}, {glue_, func, thisObj, a0});
3237}
3238
3239void SlowPathLowering::LowerCallargs2Imm8V8V8(GateRef gate)
3240{
3241    // 3: number of value inputs
3242    ASSERT(acc_.GetNumValueIn(gate) == 3);
3243    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3244        EcmaOpcode::CALLARGS2_IMM8_V8_V8));
3245    GateRef actualArgv = builder_.IntPtr(0);
3246    GateRef newTarget = builder_.Undefined();
3247    GateRef thisObj = builder_.Undefined();
3248    GateRef a0 = acc_.GetValueIn(gate, 0);
3249    GateRef a1 = acc_.GetValueIn(gate, 1); // 1:first parameter
3250    GateRef func = acc_.GetValueIn(gate, 2); // 2:function
3251
3252    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj, a0, a1},
3253        {glue_, func, thisObj, a0, a1});
3254}
3255
3256void SlowPathLowering::LowerCallargs3Imm8V8V8(GateRef gate)
3257{
3258    // 4: number of value inputs
3259    ASSERT(acc_.GetNumValueIn(gate) == 4);
3260    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3261        EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8));
3262    GateRef actualArgv = builder_.IntPtr(0);
3263    GateRef newTarget = builder_.Undefined();
3264    GateRef thisObj = builder_.Undefined();
3265    GateRef a0 = acc_.GetValueIn(gate, 0);
3266    GateRef a1 = acc_.GetValueIn(gate, 1);
3267    GateRef a2 = acc_.GetValueIn(gate, 2);
3268    GateRef func = acc_.GetValueIn(gate, 3);
3269
3270    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj, a0, a1, a2},
3271        {glue_, func, thisObj, a0, a1, a2});
3272}
3273
3274void SlowPathLowering::LowerCallthis2Imm8V8V8V8(GateRef gate)
3275{
3276    // 4: number of value inputs
3277    ASSERT(acc_.GetNumValueIn(gate) == 4);
3278    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3279        EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8));
3280    GateRef actualArgv = builder_.IntPtr(0);
3281    GateRef newTarget = builder_.Undefined();
3282    GateRef thisObj = acc_.GetValueIn(gate, 0);
3283    GateRef a0Value = acc_.GetValueIn(gate, 1);
3284    GateRef a1Value = acc_.GetValueIn(gate, 2);
3285    GateRef func = acc_.GetValueIn(gate, 3);  //acc
3286
3287    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj, a0Value, a1Value},
3288        {glue_, func, thisObj, a0Value, a1Value});
3289}
3290
3291void SlowPathLowering::LowerCallthis3Imm8V8V8V8V8(GateRef gate)
3292{
3293    // 5: number of value inputs
3294    ASSERT(acc_.GetNumValueIn(gate) == 5);
3295    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3296        EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8));
3297    GateRef actualArgv = builder_.IntPtr(0);
3298    GateRef newTarget = builder_.Undefined();
3299    GateRef thisObj = acc_.GetValueIn(gate, 0);
3300    GateRef a0Value = acc_.GetValueIn(gate, 1);
3301    GateRef a1Value = acc_.GetValueIn(gate, 2);
3302    GateRef a2Value = acc_.GetValueIn(gate, 3);
3303    GateRef func = acc_.GetValueIn(gate, 4);
3304    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj, a0Value, a1Value, a2Value},
3305        {glue_, func, thisObj, a0Value, a1Value, a2Value});
3306}
3307
3308void SlowPathLowering::LowerLdThisByName(GateRef gate)
3309{
3310    ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: number of parameter
3311    GateRef thisObj = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
3312    GateRef prop = acc_.GetValueIn(gate, 1);  // 1: the second parameter
3313    LowerCallStubWithIC(gate, CommonStubCSigns::GetPropertyByName, { thisObj, prop });
3314}
3315
3316bool SlowPathLowering::IsFastCallArgs(size_t index)
3317{
3318    return index != static_cast<size_t>(CommonArgIdx::ACTUAL_ARGC) &&
3319           index != static_cast<size_t>(CommonArgIdx::ACTUAL_ARGV) &&
3320           index != static_cast<size_t>(CommonArgIdx::NEW_TARGET);
3321}
3322
3323void SlowPathLowering::LowerConstruct(GateRef gate)
3324{
3325    Environment env(gate, circuit_, &builder_);
3326    size_t num = acc_.GetNumValueIn(gate);
3327    std::vector<GateRef> args(num);
3328    for (size_t i = 0; i < num; ++i) {
3329        args[i] = acc_.GetValueIn(gate, i);
3330    }
3331    ASSERT(num >= 3); // 3: skip argc argv newtarget
3332    std::vector<GateRef> argsFastCall(num - 3); // 3: skip argc argv newtarget
3333    size_t j = 0;
3334    for (size_t i = 0; i < num; ++i) {
3335        if (IsFastCallArgs(i)) {
3336            argsFastCall[j++] = acc_.GetValueIn(gate, i);
3337        }
3338    }
3339    GateRef ctor = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::FUNC));
3340    GateRef argc = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::ACTUAL_ARGC));
3341    Label exit(&builder_);
3342    DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3343    LowerFastCall(gate, glue_, ctor, argc, args, argsFastCall, &res, &exit, true);
3344    builder_.Bind(&exit);
3345    GateRef thisObj = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::THIS_OBJECT));
3346    GateRef result = builder_.CallStub(
3347        glue_, gate, CommonStubCSigns::ConstructorCheck, { glue_, ctor, *res, thisObj });
3348    GateRef state = builder_.GetState();
3349    ReplaceHirWithPendingException(gate, state, result, result);
3350}
3351
3352void SlowPathLowering::LowerCallInternal(GateRef gate)
3353{
3354    Environment env(gate, circuit_, &builder_);
3355    size_t num = acc_.GetNumValueIn(gate);
3356    std::vector<GateRef> args(num);
3357    for (size_t i = 0; i < num; ++i) {
3358        args[i] = acc_.GetValueIn(gate, i);
3359    }
3360    ASSERT(num >= 3); // 3: skip argc argv newtarget
3361    std::vector<GateRef> argsFastCall(num - 3); // 3:skip argc argv newtarget
3362    size_t j = 0;
3363    for (size_t i = 0; i < num; ++i) {
3364        if (IsFastCallArgs(i)) { // 1: argc index 3: newtarget index 2:ActualArgv
3365            argsFastCall[j++] = acc_.GetValueIn(gate, i);
3366        }
3367    }
3368    GateRef func = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::FUNC));
3369    GateRef argc = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::ACTUAL_ARGC));
3370    Label exit(&builder_);
3371    DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3372    LowerFastCall(gate, glue_, func, argc, args, argsFastCall, &res, &exit, false);
3373    builder_.Bind(&exit);
3374    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
3375}
3376
3377void SlowPathLowering::LowerCallNew(GateRef gate)
3378{
3379    Environment env(gate, circuit_, &builder_);
3380    size_t num = acc_.GetNumValueIn(gate);
3381    bool needPushArgv = acc_.NeedPushArgv(gate);
3382    std::vector<GateRef> args(num);
3383    for (size_t i = 0; i < num; ++i) {
3384        args[i] = acc_.GetValueIn(gate, i);
3385    }
3386    ASSERT(num >= 3); // 3:skip argc argv newtarget
3387    std::vector<GateRef> argsFastCall(num - 3); // 3:skip argc argv newtarget
3388    size_t j = 0;
3389    for (size_t i = 0; i < num; ++i) {
3390        if (IsFastCallArgs(i)) {
3391            argsFastCall[j++] = acc_.GetValueIn(gate, i);
3392        }
3393    }
3394    GateRef ctor = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::FUNC));
3395    Label exit(&builder_);
3396    DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3397    LowerNewFastCall(gate, glue_, ctor, needPushArgv, args, argsFastCall, &res, &exit);
3398    builder_.Bind(&exit);
3399    GateRef thisObj = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::THIS_OBJECT));
3400    GateRef result = builder_.CallStub(
3401        glue_, gate, CommonStubCSigns::ConstructorCheck, { glue_, ctor, *res, thisObj });
3402    GateRef state = builder_.GetState();
3403    ReplaceHirWithPendingException(gate, state, result, result);
3404}
3405
3406void SlowPathLowering::LowerNewFastCall(GateRef gate, GateRef glue, GateRef func,
3407    bool needPushArgv, const std::vector<GateRef> &args,
3408    const std::vector<GateRef> &argsFastCall, Variable *result, Label *exit)
3409{
3410    Label fastCall(&builder_);
3411    Label notFastCall(&builder_);
3412    Label slowCall(&builder_);
3413    Label slowPath(&builder_);
3414    BRANCH_CIR(builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT_FASTCALL),
3415        &fastCall, &notFastCall);
3416    builder_.Bind(&fastCall);
3417    {
3418        if (!needPushArgv) {
3419            builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3420            GateRef code = builder_.GetCodeAddr(func);
3421            auto depend = builder_.GetDepend();
3422            const CallSignature *cs = RuntimeStubCSigns::GetOptimizedFastCallSign();
3423            result->WriteVariable(builder_.Call(cs, glue, code, depend, argsFastCall, gate, "callFastAOT"));
3424            builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3425            builder_.Jump(exit);
3426        } else {
3427            builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3428            const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(OptimizedFastCallAndPushArgv));
3429            GateRef target = builder_.IntPtr(RTSTUB_ID(OptimizedFastCallAndPushArgv));
3430            auto depend = builder_.GetDepend();
3431            result->WriteVariable(builder_.Call(cs, glue, target, depend, args, gate, "callFastBridge"));
3432            builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3433            builder_.Jump(exit);
3434        }
3435    }
3436    builder_.Bind(&notFastCall);
3437    BRANCH_CIR(builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT),
3438        &slowCall, &slowPath);
3439    builder_.Bind(&slowCall);
3440    {
3441        if (!needPushArgv) {
3442            builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3443            GateRef code = builder_.GetCodeAddr(func);
3444            auto depend = builder_.GetDepend();
3445            const CallSignature *cs = RuntimeStubCSigns::GetOptimizedCallSign();
3446            result->WriteVariable(builder_.Call(cs, glue, code, depend, args, gate, "callAOT"));
3447            builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3448            builder_.Jump(exit);
3449        } else {
3450            builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3451            const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(OptimizedCallAndPushArgv));
3452            GateRef target = builder_.IntPtr(RTSTUB_ID(OptimizedCallAndPushArgv));
3453            auto depend = builder_.GetDepend();
3454            result->WriteVariable(builder_.Call(cs, glue, target, depend, args, gate, "callBridge"));
3455            builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3456            builder_.Jump(exit);
3457        }
3458    }
3459    builder_.Bind(&slowPath);
3460    {
3461        builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3462        const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCallNew));
3463        GateRef target = builder_.IntPtr(RTSTUB_ID(JSCallNew));
3464        auto depend = builder_.GetDepend();
3465        result->WriteVariable(builder_.Call(cs, glue, target, depend, args, gate, "slowNew"));
3466        builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3467        builder_.Jump(exit);
3468    }
3469}
3470
3471void SlowPathLowering::LowerFastCall(GateRef gate, GateRef glue, GateRef func, GateRef argc,
3472    const std::vector<GateRef> &args, const std::vector<GateRef> &argsFastCall,
3473    Variable *result, Label *exit, bool isNew)
3474{
3475    Label isHeapObject(&builder_);
3476    Label isJsFcuntion(&builder_);
3477    Label fastCall(&builder_);
3478    Label notFastCall(&builder_);
3479    Label call(&builder_);
3480    Label call1(&builder_);
3481    Label slowCall(&builder_);
3482    Label callBridge(&builder_);
3483    Label callBridge1(&builder_);
3484    Label slowPath(&builder_);
3485    Label notCallConstructor(&builder_);
3486    Label isCallConstructor(&builder_);
3487    BRANCH_CIR(builder_.TaggedIsHeapObject(func), &isHeapObject, &slowPath);
3488    builder_.Bind(&isHeapObject);
3489    {
3490        BRANCH_CIR(builder_.IsJSFunction(func), &isJsFcuntion, &slowPath);
3491        builder_.Bind(&isJsFcuntion);
3492        {
3493            if (!isNew) {
3494                BRANCH_CIR(builder_.IsClassConstructor(func), &slowPath, &notCallConstructor);
3495                builder_.Bind(&notCallConstructor);
3496            }
3497            GateRef method = builder_.GetMethodFromFunction(func);
3498            BRANCH_CIR(builder_.JudgeAotAndFastCall(func,
3499                CircuitBuilder::JudgeMethodType::HAS_AOT_FASTCALL), &fastCall, &notFastCall);
3500            builder_.Bind(&fastCall);
3501            {
3502                GateRef expectedArgc = builder_.Int64Add(builder_.GetExpectedNumOfArgs(method),
3503                    builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS));
3504                BRANCH_CIR(builder_.Equal(expectedArgc, argc), &call, &callBridge);
3505                builder_.Bind(&call);
3506                {
3507                    builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3508                    GateRef code = builder_.GetCodeAddr(func);
3509                    auto depend = builder_.GetDepend();
3510                    const CallSignature *cs = RuntimeStubCSigns::GetOptimizedFastCallSign();
3511                    result->WriteVariable(builder_.Call(cs, glue, code, depend, argsFastCall, gate, "callFastAOT"));
3512                    builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3513                    builder_.Jump(exit);
3514                }
3515                builder_.Bind(&callBridge);
3516                {
3517                    builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3518                    const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(OptimizedFastCallAndPushArgv));
3519                    GateRef target = builder_.IntPtr(RTSTUB_ID(OptimizedFastCallAndPushArgv));
3520                    auto depend = builder_.GetDepend();
3521                    result->WriteVariable(builder_.Call(cs, glue, target, depend, args, gate, "callFastBridge"));
3522                    builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3523                    builder_.Jump(exit);
3524                }
3525            }
3526            builder_.Bind(&notFastCall);
3527            BRANCH_CIR(builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT),
3528                &slowCall, &slowPath);
3529            builder_.Bind(&slowCall);
3530            {
3531                GateRef expectedArgc = builder_.Int64Add(builder_.GetExpectedNumOfArgs(method),
3532                    builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS));
3533                BRANCH_CIR(builder_.Equal(expectedArgc, argc), &call1, &callBridge1);
3534                builder_.Bind(&call1);
3535                {
3536                    builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3537                    GateRef code = builder_.GetCodeAddr(func);
3538                    auto depend = builder_.GetDepend();
3539                    const CallSignature *cs = RuntimeStubCSigns::GetOptimizedCallSign();
3540                    result->WriteVariable(builder_.Call(cs, glue, code, depend, args, gate, "callAOT"));
3541                    builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3542                    builder_.Jump(exit);
3543                }
3544                builder_.Bind(&callBridge1);
3545                {
3546                    builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3547                    const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(OptimizedCallAndPushArgv));
3548                    GateRef target = builder_.IntPtr(RTSTUB_ID(OptimizedCallAndPushArgv));
3549                    auto depend = builder_.GetDepend();
3550                    result->WriteVariable(builder_.Call(cs, glue, target, depend, args, gate, "callBridge"));
3551                    builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3552                    builder_.Jump(exit);
3553                }
3554            }
3555        }
3556    }
3557    builder_.Bind(&slowPath);
3558    {
3559        if (isNew) {
3560            builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3561            const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCallNew));
3562            GateRef target = builder_.IntPtr(RTSTUB_ID(JSCallNew));
3563            auto depend = builder_.GetDepend();
3564            result->WriteVariable(builder_.Call(cs, glue, target, depend, args, gate, "slowNew"));
3565            builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3566            builder_.Jump(exit);
3567        } else {
3568            builder_.StartCallTimer(glue_, gate, {glue_, func, builder_.True()}, true);
3569            const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCall));
3570            GateRef target = builder_.IntPtr(RTSTUB_ID(JSCall));
3571            auto depend = builder_.GetDepend();
3572            result->WriteVariable(builder_.Call(cs, glue, target, depend, args, gate, "jscall"));
3573            builder_.EndCallTimer(glue_, gate, {glue_, func}, true);
3574            builder_.Jump(exit);
3575        }
3576    }
3577}
3578
3579void SlowPathLowering::LowerTypedCall(GateRef gate)
3580{
3581    Environment env(gate, circuit_, &builder_);
3582    GateRef func = acc_.GetValueIn(gate, static_cast<size_t>(CommonArgIdx::FUNC));
3583    GateRef code = builder_.GetCodeAddr(func);
3584    size_t num = acc_.GetNumValueIn(gate);
3585    std::vector<GateRef> args(num);
3586    for (size_t i = 0; i < num; ++i) {
3587        args[i] = acc_.GetValueIn(gate, i);
3588    }
3589    GateRef state = builder_.GetState();
3590    auto depend = builder_.GetDepend();
3591    const CallSignature *cs = RuntimeStubCSigns::GetOptimizedCallSign();
3592    GateRef result = builder_.Call(cs, glue_, code, depend, args, gate, "callAOT");
3593    ReplaceHirWithPendingException(gate, state, result, result);
3594}
3595
3596void SlowPathLowering::LowerTypedFastCall(GateRef gate)
3597{
3598    Environment env(gate, circuit_, &builder_);
3599    GateRef func = acc_.GetValueIn(gate, static_cast<size_t>(FastCallArgIdx::FUNC));
3600    GateRef code = builder_.GetCodeAddr(func);
3601    size_t num = acc_.GetNumValueIn(gate);
3602    std::vector<GateRef> args(num);
3603    for (size_t i = 0; i < num; ++i) {
3604        args[i] = acc_.GetValueIn(gate, i);
3605    }
3606    GateRef state = builder_.GetState();
3607    auto depend = builder_.GetDepend();
3608    const CallSignature *cs = RuntimeStubCSigns::GetOptimizedFastCallSign();
3609    GateRef result = builder_.Call(cs, glue_, code, depend, args, gate, "callFastAOT");
3610    ReplaceHirWithPendingException(gate, state, result, result);
3611}
3612
3613void SlowPathLowering::LowerCheckSafePointAndStackOver(GateRef gate)
3614{
3615    Environment env(gate, circuit_, &builder_);
3616    Label slowPath(&builder_);
3617    Label dispatch(&builder_);
3618    Label checkStackOver(&builder_);
3619    Label stackOverflow(&builder_);
3620    GateRef stackLimit = builder_.Load(VariableType::INT64(), glue_,
3621        builder_.IntPtr(JSThread::GlueData::GetStackLimitOffset(builder_.GetCompilationConfig()->Is32Bit())));
3622    GateRef interruptsFlag = builder_.Load(VariableType::INT8(), glue_,
3623        builder_.IntPtr(JSThread::GlueData::GetInterruptVectorOffset(builder_.GetCompilationConfig()->Is32Bit())));
3624    GateRef spValue = builder_.ReadSp();
3625    builder_.Branch(builder_.Int8Equal(interruptsFlag, builder_.Int8(VmThreadControl::VM_NEED_SUSPENSION)),
3626                    &slowPath, &checkStackOver, BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "checkSafePoint");
3627    builder_.Bind(&slowPath);
3628    {
3629        LowerCallRuntime(glue_, RTSTUB_ID(CheckSafePoint), {}, true);
3630        builder_.Jump(&checkStackOver);
3631    }
3632    builder_.Bind(&checkStackOver);
3633    {
3634        builder_.Branch(builder_.Int64LessThanOrEqual(spValue, stackLimit), &stackOverflow, &dispatch,
3635                        BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "checkStackOverflow");
3636        builder_.Bind(&stackOverflow);
3637        {
3638            GateRef res = LowerCallRuntime(glue_, RTSTUB_ID(ThrowStackOverflowException), {}, true);
3639            builder_.Return(res);
3640        }
3641    }
3642    builder_.Bind(&dispatch);
3643    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3644}
3645
3646void SlowPathLowering::LowerLdPrivateProperty(GateRef gate)
3647{
3648    const int id = RTSTUB_ID(LdPrivateProperty);
3649    // 5: number of value inputs + env + acc
3650    ASSERT(acc_.GetNumValueIn(gate) == 5);
3651    [[maybe_unused]] GateRef slotId = acc_.GetValueIn(gate, 0);
3652    GateRef levelIndex = acc_.GetValueIn(gate, 1);
3653    GateRef slotIndex = acc_.GetValueIn(gate, 2);
3654    GateRef lexicalEnv = acc_.GetValueIn(gate, 3);
3655    GateRef obj = acc_.GetValueIn(gate, 4);  // acc
3656
3657    GateRef newGate = LowerCallRuntime(gate, id, {lexicalEnv,
3658        builder_.ToTaggedInt(levelIndex), builder_.ToTaggedInt(slotIndex), obj});
3659    ReplaceHirWithValue(gate, newGate);
3660}
3661
3662void SlowPathLowering::LowerStPrivateProperty(GateRef gate)
3663{
3664    const int id = RTSTUB_ID(StPrivateProperty);
3665    // 6: number of value inputs + env + acc
3666    ASSERT(acc_.GetNumValueIn(gate) == 6);
3667    [[maybe_unused]] GateRef slotId = acc_.GetValueIn(gate, 0);
3668    GateRef levelIndex = acc_.GetValueIn(gate, 1);
3669    GateRef slotIndex = acc_.GetValueIn(gate, 2);
3670    GateRef obj = acc_.GetValueIn(gate, 3);
3671    GateRef lexicalEnv = acc_.GetValueIn(gate, 4);
3672    GateRef value = acc_.GetValueIn(gate, 5);  // acc
3673
3674    GateRef newGate = LowerCallRuntime(gate, id, {lexicalEnv,
3675        builder_.ToTaggedInt(levelIndex), builder_.ToTaggedInt(slotIndex), obj, value});
3676    ReplaceHirWithValue(gate, newGate);
3677}
3678
3679void SlowPathLowering::LowerTestIn(GateRef gate)
3680{
3681    const int id = RTSTUB_ID(TestIn);
3682    // 5: number of value inputs + acc
3683    ASSERT(acc_.GetNumValueIn(gate) == 5);
3684    [[maybe_unused]] GateRef slotId = acc_.GetValueIn(gate, 0);
3685    GateRef levelIndex = acc_.GetValueIn(gate, 1);
3686    GateRef slotIndex = acc_.GetValueIn(gate, 2);
3687    GateRef lexicalEnv = acc_.GetValueIn(gate, 3);
3688    GateRef obj = acc_.GetValueIn(gate, 4);  // acc
3689
3690    GateRef newGate = LowerCallRuntime(gate, id, {lexicalEnv,
3691        builder_.ToTaggedInt(levelIndex), builder_.ToTaggedInt(slotIndex), obj});
3692    ReplaceHirWithValue(gate, newGate);
3693}
3694
3695void SlowPathLowering::LowerNotifyConcurrentResult(GateRef gate)
3696{
3697    const int id = RTSTUB_ID(NotifyConcurrentResult);
3698
3699    GateRef newGate = LowerCallRuntime(gate, id, {acc_.GetValueIn(gate, 0),
3700                                                  argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC)});
3701    ReplaceHirWithValue(gate, newGate);
3702}
3703
3704void SlowPathLowering::LowerDefineFieldByName(GateRef gate)
3705{
3706    // 4: number of value inputs + acc
3707    ASSERT(acc_.GetNumValueIn(gate) == 4);
3708    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3709    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
3710    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 1));
3711    GateRef obj = acc_.GetValueIn(gate, 2);
3712    GateRef module = builder_.GetModuleFromFunction(jsFunc);
3713    GateRef propKey = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module,
3714                                                      stringId, ConstPoolType::STRING);
3715    GateRef value = acc_.GetValueIn(gate, 3);  // acc
3716
3717    GateRef newGate = builder_.CallStub(glue_, gate, CommonStubCSigns::DefineField,
3718        {glue_, obj, propKey, value});
3719    ReplaceHirWithValue(gate, newGate);
3720}
3721
3722void SlowPathLowering::LowerDefineFieldByValue(GateRef gate)
3723{
3724    // 3: number of value inputs + acc
3725    ASSERT(acc_.GetNumValueIn(gate) == 3);
3726    GateRef obj = acc_.GetValueIn(gate, 1);
3727    GateRef propKey = acc_.GetValueIn(gate, 0);
3728    GateRef value = acc_.GetValueIn(gate, 2);  // acc
3729
3730    GateRef newGate = builder_.CallStub(glue_, gate, CommonStubCSigns::DefineField,
3731        {glue_, obj, propKey, value});
3732    ReplaceHirWithValue(gate, newGate);
3733}
3734
3735void SlowPathLowering::LowerDefineFieldByIndex(GateRef gate)
3736{
3737    // 3: number of value inputs + acc
3738    ASSERT(acc_.GetNumValueIn(gate) == 3);
3739    GateRef obj = acc_.GetValueIn(gate, 1);
3740    GateRef propKey = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
3741    GateRef value = acc_.GetValueIn(gate, 2);  // acc
3742
3743    GateRef newGate = builder_.CallStub(glue_, gate, CommonStubCSigns::DefineField,
3744        {glue_, obj, propKey, value});
3745    ReplaceHirWithValue(gate, newGate);
3746}
3747
3748void SlowPathLowering::LowerToPropertyKey(GateRef gate)
3749{
3750    const int id = RTSTUB_ID(ToPropertyKey);
3751    // 1: number of acc
3752    ASSERT(acc_.GetNumValueIn(gate) == 1);
3753    GateRef value = acc_.GetValueIn(gate, 0);  // acc
3754
3755    GateRef newGate = LowerCallRuntime(gate, id, {value});
3756    ReplaceHirWithValue(gate, newGate);
3757}
3758
3759void SlowPathLowering::LowerCreatePrivateProperty(GateRef gate)
3760{
3761    const int id = RTSTUB_ID(CreatePrivateProperty);
3762    // 3: number of value inputs
3763    ASSERT(acc_.GetNumValueIn(gate) == 3);
3764    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3765    GateRef count = acc_.GetValueIn(gate, 0);
3766    GateRef literalId = acc_.GetValueIn(gate, 1);
3767    GateRef lexicalEnv = acc_.GetValueIn(gate, 2);
3768    GateRef constpool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
3769    GateRef module = builder_.GetModuleFromFunction(jsFunc);
3770
3771    GateRef newGate = LowerCallRuntime(gate, id, {lexicalEnv,
3772        builder_.ToTaggedInt(count), constpool, builder_.ToTaggedInt(literalId), module});
3773    ReplaceHirWithValue(gate, newGate);
3774}
3775
3776void SlowPathLowering::LowerDefinePrivateProperty(GateRef gate)
3777{
3778    const int id = RTSTUB_ID(DefinePrivateProperty);
3779    // 5: number of value inputs + acc
3780    ASSERT(acc_.GetNumValueIn(gate) == 5);
3781    GateRef levelIndex = acc_.GetValueIn(gate, 0);
3782    GateRef slotIndex = acc_.GetValueIn(gate, 1);
3783    GateRef obj = acc_.GetValueIn(gate, 2);
3784    GateRef lexicalEnv = acc_.GetValueIn(gate, 3);
3785    GateRef value = acc_.GetValueIn(gate, 4);  // acc
3786
3787    GateRef newGate = LowerCallRuntime(gate, id, {lexicalEnv,
3788        builder_.ToTaggedInt(levelIndex), builder_.ToTaggedInt(slotIndex), obj, value});
3789    ReplaceHirWithValue(gate, newGate);
3790}
3791
3792void SlowPathLowering::LowerDefineSendableClass(GateRef gate)
3793{
3794    // 4: number of value inputs
3795    ASSERT(acc_.GetNumValueIn(gate) == 4);
3796    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3797    GateRef methodId = acc_.GetValueIn(gate, 0);
3798    GateRef literalId = acc_.GetValueIn(gate, 1);
3799    GateRef length = acc_.GetValueIn(gate, 2);  // 2: second arg
3800    GateRef proto = acc_.GetValueIn(gate, 3);
3801    GateRef constpool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
3802    GateRef module = builder_.GetModuleFromFunction(jsFunc);
3803    auto args = { proto, constpool, builder_.ToTaggedInt(methodId), builder_.ToTaggedInt(literalId),
3804                  builder_.ToTaggedInt(length), module };
3805    GateRef newGate = LowerCallRuntime(gate, RTSTUB_ID(CreateSharedClass), args);
3806    ReplaceHirWithValue(gate, newGate);
3807}
3808
3809void SlowPathLowering::LowerLdSendableClass(GateRef gate)
3810{
3811    GateRef level = acc_.GetValueIn(gate, 0);
3812    GateRef lexicalEnv = acc_.GetValueIn(gate, 1);
3813    GateRef newGate = LowerCallRuntime(gate, RTSTUB_ID(LdSendableClass), { lexicalEnv, builder_.ToTaggedInt(level) });
3814    ReplaceHirWithValue(gate, newGate);
3815}
3816
3817void SlowPathLowering::LowerSendableExternalModule(GateRef gate)
3818{
3819    ASSERT(acc_.GetNumValueIn(gate) == 1);
3820    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3821    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
3822    GateRef result = LowerCallRuntime(gate,
3823        RTSTUB_ID(LdSendableExternalModuleVarByIndex), {index, jsFunc}, true);
3824    ReplaceHirWithValue(gate, result);
3825}
3826
3827void SlowPathLowering::LowerCallInit(GateRef gate)
3828{
3829    // same as callthis0
3830    // 2: number of value inputs
3831    ASSERT(acc_.GetNumValueIn(gate) == 2);
3832
3833    GateRef actualArgc = builder_.Int64(BytecodeCallArgc::ComputeCallArgc(acc_.GetNumValueIn(gate),
3834        EcmaOpcode::CALLTHIS0_IMM8_V8));
3835    GateRef actualArgv = builder_.IntPtr(0);
3836    GateRef newTarget = builder_.Undefined();
3837    GateRef thisObj = acc_.GetValueIn(gate, 0);
3838    GateRef func = acc_.GetValueIn(gate, 1);
3839    LowerToJSCall(gate, {glue_, actualArgc, actualArgv, func, newTarget, thisObj}, {glue_, func, thisObj});
3840}
3841
3842void SlowPathLowering::LowerLdStr(GateRef gate)
3843{
3844    GateRef stringId = builder_.TruncInt64ToInt32(acc_.GetValueIn(gate, 0));
3845    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3846    GateRef sharedConstPool = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::SHARED_CONST_POOL);
3847    GateRef module = builder_.GetModuleFromFunction(jsFunc);
3848    GateRef res = builder_.GetObjectFromConstPool(glue_, gate, sharedConstPool, Circuit::NullGate(), module, stringId,
3849                                                  ConstPoolType::STRING);
3850    ReplaceHirWithValue(gate, res);
3851}
3852
3853void SlowPathLowering::LowerGetSharedConstPool(GateRef gate)
3854{
3855    bool useConstPool = false;
3856    auto uses = acc_.Uses(gate);
3857    for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
3858        if (acc_.GetOpCode(*useIt) != OpCode::FRAME_ARGS) {
3859            useConstPool = true;
3860            break;
3861        }
3862    }
3863    if (!useConstPool) {
3864        acc_.UpdateAllUses(gate, builder_.Undefined());
3865        acc_.DeleteGate(gate);
3866        return;
3867    }
3868    GateRef jsFunc = acc_.GetValueIn(gate, 0);
3869    GateRef methodOffset = builder_.IntPtr(JSFunctionBase::METHOD_OFFSET);
3870    GateRef method = builder_.Load(VariableType::JS_POINTER(), jsFunc, methodOffset, acc_.GetDependRoot());
3871    GateRef sharedConstpool =
3872        builder_.Load(VariableType::JS_ANY(), method, builder_.IntPtr(Method::CONSTANT_POOL_OFFSET), method);
3873    acc_.UpdateAllUses(gate, sharedConstpool);
3874    acc_.DeleteGate(gate);
3875}
3876
3877void SlowPathLowering::LowerGetUnsharedConstPool(GateRef gate)
3878{
3879    bool useConstPool = false;
3880    auto uses = acc_.Uses(gate);
3881    for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
3882        if (acc_.GetOpCode(*useIt) != OpCode::FRAME_ARGS) {
3883            useConstPool = true;
3884            break;
3885        }
3886    }
3887    if (!useConstPool) {
3888        acc_.UpdateAllUses(gate, builder_.Undefined());
3889        acc_.DeleteGate(gate);
3890        return;
3891    }
3892    GateRef sharedConstPool = acc_.GetValueIn(gate, 0);
3893    GateRef constPoolSize = builder_.Load(VariableType::INT32(), sharedConstPool,
3894                                          builder_.IntPtr(TaggedArray::LENGTH_OFFSET), sharedConstPool);
3895    GateRef unshareIdx = builder_.Int32Sub(constPoolSize, builder_.Int32(ConstantPool::UNSHARED_CONSTPOOL_INDEX));
3896    GateRef offset =
3897        builder_.PtrMul(builder_.ZExtInt32ToPtr(unshareIdx), builder_.IntPtr(JSTaggedValue::TaggedTypeSize()));
3898    GateRef dataOffset = builder_.PtrAdd(offset, builder_.IntPtr(TaggedArray::DATA_OFFSET));
3899    GateRef index = builder_.Load(VariableType::JS_ANY(), sharedConstPool, dataOffset, constPoolSize);
3900    GateRef unshareCpOffset = static_cast<int32_t>(JSThread::GlueData::GetUnSharedConstpoolsOffset(false));
3901    GateRef unshareCpAddr =
3902        builder_.Load(VariableType::NATIVE_POINTER(), glue_, builder_.IntPtr(unshareCpOffset), index);
3903    GateRef unshareCpDataOffset =
3904        builder_.PtrAdd(unshareCpAddr, builder_.PtrMul(builder_.IntPtr(JSTaggedValue::TaggedTypeSize()),
3905                                                       builder_.ZExtInt32ToPtr(builder_.TaggedGetInt(index))));
3906    GateRef unsharedConstPool =
3907        builder_.Load(VariableType::JS_ANY(), unshareCpDataOffset, builder_.IntPtr(0), unshareCpAddr);
3908
3909    acc_.UpdateAllUses(gate, unsharedConstPool);
3910
3911    // delete old gate
3912    acc_.DeleteGate(gate);
3913}
3914
3915void SlowPathLowering::LowerLdLazyExternalModuleVar(GateRef gate)
3916{
3917    ASSERT(acc_.GetNumValueIn(gate) == 1);
3918    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3919    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
3920    GateRef result = LowerCallRuntime(gate,
3921        RTSTUB_ID(LdLazyExternalModuleVarByIndex), {index, jsFunc}, true);
3922    ReplaceHirWithValue(gate, result);
3923}
3924
3925void SlowPathLowering::LowerLdLazySendableExternalModuleVar(GateRef gate)
3926{
3927    ASSERT(acc_.GetNumValueIn(gate) == 1);
3928    GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
3929    GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
3930    GateRef result = LowerCallRuntime(gate,
3931        RTSTUB_ID(LdLazySendableExternalModuleVarByIndex), {index, jsFunc}, true);
3932    ReplaceHirWithValue(gate, result);
3933}
3934}  // namespace panda::ecmascript
3935