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