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