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