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