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