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