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