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