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