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