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