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