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