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