1/* 2 * Copyright (c) 2023 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#include "ecmascript/compiler/mcr_lowering.h" 16#include "ecmascript/compiler/argument_accessor.h" 17#include "ecmascript/compiler/bytecodes.h" 18#include "ecmascript/compiler/share_gate_meta_data.h" 19#include "ecmascript/compiler/share_opcodes.h" 20#include "ecmascript/compiler/pgo_type/pgo_type_manager.h" 21#include "ecmascript/global_env.h" 22#include "ecmascript/js_function.h" 23#include "ecmascript/js_hclass.h" 24#include "ecmascript/js_thread.h" 25#include "ecmascript/jspandafile/program_object.h" 26#include "ecmascript/message_string.h" 27 28namespace panda::ecmascript::kungfu { 29 30GateRef MCRLowering::VisitGate(GateRef gate) 31{ 32 auto op = acc_.GetOpCode(gate); 33 switch (op) { 34 case OpCode::STATE_SPLIT: 35 DeleteStateSplit(gate); 36 break; 37 case OpCode::ARRAY_GUARDIAN_CHECK: 38 LowerArrayGuardianCheck(gate); 39 break; 40 case OpCode::HCLASS_STABLE_ARRAY_CHECK: 41 LowerHClassStableArrayCheck(gate); 42 break; 43 case OpCode::HEAP_OBJECT_CHECK: 44 LowerHeapObjectCheck(gate); 45 break; 46 case OpCode::LOAD_CONST_OFFSET: 47 LowerLoadConstOffset(gate); 48 break; 49 case OpCode::LOAD_HCLASS_FROM_CONSTPOOL: 50 LowerLoadHClassFromConstpool(gate); 51 break; 52 case OpCode::STORE_CONST_OFFSET: 53 LowerStoreConstOffset(gate); 54 break; 55 case OpCode::CONVERT_HOLE_AS_UNDEFINED: 56 LowerConvertHoleAsUndefined(gate); 57 break; 58 case OpCode::GET_GLOBAL_ENV: 59 LowerGetGlobalEnv(gate); 60 break; 61 case OpCode::GET_GLOBAL_ENV_OBJ: 62 LowerGetGlobalEnvObj(gate); 63 break; 64 case OpCode::GET_GLOBAL_ENV_OBJ_HCLASS: 65 LowerGetGlobalEnvObjHClass(gate); 66 break; 67 case OpCode::GET_GLOBAL_CONSTANT_VALUE: 68 LowerGetGlobalConstantValue(gate); 69 break; 70 case OpCode::INT32_CHECK_RIGHT_IS_ZERO: 71 LowerInt32CheckRightIsZero(gate); 72 break; 73 case OpCode::REMAINDER_IS_NEGATIVE_ZERO: 74 LowerRemainderIsNegativeZero(gate); 75 break; 76 case OpCode::FLOAT64_CHECK_RIGHT_IS_ZERO: 77 LowerFloat64CheckRightIsZero(gate); 78 break; 79 case OpCode::VALUE_CHECK_NEG_OVERFLOW: 80 LowerValueCheckNegOverflow(gate); 81 break; 82 case OpCode::OVERFLOW_CHECK: 83 LowerOverflowCheck(gate); 84 break; 85 case OpCode::INT32_UNSIGNED_UPPER_BOUND_CHECK: 86 LowerInt32UnsignedUpperBoundCheck(gate); 87 break; 88 case OpCode::INT32_DIV_WITH_CHECK: 89 LowerInt32DivWithCheck(gate); 90 break; 91 case OpCode::LEX_VAR_IS_HOLE_CHECK: 92 LowerLexVarIsHoleCheck(gate); 93 break; 94 case OpCode::IS_UNDEFINED_OR_HOLE_CHECK: 95 LowerIsUndefinedOrHoleCheck(gate); 96 break; 97 case OpCode::IS_NOT_UNDEFINED_OR_HOLE_CHECK: 98 LowerIsNotUndefinedOrHoleCheck(gate); 99 break; 100 case OpCode::IS_DATA_VIEW_CHECK: 101 LowerIsDataViewCheck(gate); 102 break; 103 case OpCode::STORE_MEMORY: 104 LowerStoreMemory(gate); 105 break; 106 case OpCode::CHECK_AND_CONVERT: 107 LowerCheckAndConvert(gate); 108 break; 109 case OpCode::TAGGED_IS_HEAP_OBJECT: 110 LowerTaggedIsHeapObject(gate); 111 break; 112 case OpCode::IS_MARKER_CELL_VALID: 113 LowerIsMarkerCellValid(gate); 114 break; 115 case OpCode::IS_SPECIFIC_OBJECT_TYPE: 116 LowerIsSpecificObjectType(gate); 117 break; 118 case OpCode::MIGRATE_FROM_HEAPVALUE_TO_RAWVALUE: 119 LowerMigrateFromHeapValueToRawValue(gate); 120 break; 121 case OpCode::MIGRATE_FROM_RAWVALUE_TO_HEAPVALUES: 122 LowerMigrateFromRawValueToHeapValues(gate); 123 break; 124 case OpCode::MIGRATE_FROM_HOLEINT_TO_HOLENUMBER: 125 LowerMigrateFromHoleIntToHoleNumber(gate); 126 break; 127 case OpCode::MIGRATE_FROM_HOLENUMBER_TO_HOLEINT: 128 LowerMigrateFromHoleNumberToHoleInt(gate); 129 break; 130 case OpCode::HEAP_OBJECT_IS_ECMA_OBJECT: 131 LowerHeapObjectIsEcmaObject(gate); 132 break; 133 case OpCode::IS_CALLABLE_CHECK: 134 LowerIsCallableCheck(gate); 135 break; 136 default: 137 break; 138 } 139 return Circuit::NullGate(); 140} 141 142void MCRLowering::LowerConvertHoleAsUndefined(GateRef gate) 143{ 144 Environment env(gate, circuit_, &builder_); 145 146 Label returnUndefined(&builder_); 147 Label exit(&builder_); 148 GateRef receiver = acc_.GetValueIn(gate, 0); 149 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), receiver); 150 151 builder_.Branch(builder_.TaggedIsHole(*result), &returnUndefined, &exit, 1, BranchWeight::DEOPT_WEIGHT, 152 "holeCheck"); 153 builder_.Bind(&returnUndefined); 154 { 155 result = builder_.UndefineConstant(); 156 builder_.Jump(&exit); 157 } 158 builder_.Bind(&exit); 159 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); 160} 161 162void MCRLowering::LowerLoadConstOffset(GateRef gate) 163{ 164 Environment env(gate, circuit_, &builder_); 165 GateRef receiver = acc_.GetValueIn(gate, 0); 166 GateRef offset = builder_.IntPtr(acc_.GetOffset(gate)); 167 VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate)); 168 GateRef result = builder_.Load(type, receiver, offset, acc_.GetMemoryAttribute(gate)); 169 acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result); 170} 171 172void MCRLowering::LowerLoadHClassFromConstpool(GateRef gate) 173{ 174 Environment env(gate, circuit_, &builder_); 175 GateRef constpool = acc_.GetValueIn(gate, 0); 176 uint32_t index = acc_.GetIndex(gate); 177 if (!env_->IsJitCompiler()) { 178 GateRef constPoolSize = builder_.GetLengthOfTaggedArray(constpool); 179 GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(ConstantPool::AOT_HCLASS_INFO_INDEX)); 180 GateRef valVec = builder_.GetValueFromTaggedArray(constpool, valVecIndex); 181 GateRef hclass = builder_.GetValueFromTaggedArray(valVec, builder_.Int32(index)); 182 acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), hclass); 183 } else { 184 JSTaggedValue hclass = env_->GetPTManager()->QueryHClassByIndexForJIT(index); 185 acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), builder_.TaggedValueConstant(hclass)); 186 } 187} 188 189void MCRLowering::LowerStoreConstOffset(GateRef gate) 190{ 191 Environment env(gate, circuit_, &builder_); 192 193 GateRef receiver = acc_.GetValueIn(gate, 0); 194 GateRef value = acc_.GetValueIn(gate, 1); 195 GateRef offset = builder_.IntPtr(acc_.GetOffset(gate)); 196 VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate)); 197 builder_.Store(type, glue_, receiver, offset, value, acc_.GetMemoryAttribute(gate)); 198 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 199} 200 201void MCRLowering::LowerHeapObjectCheck(GateRef gate) 202{ 203 Environment env(gate, circuit_, &builder_); 204 GateRef frameState = acc_.GetFrameState(gate); 205 GateRef receiver = acc_.GetValueIn(gate, 0); 206 207 GateRef heapObjectCheck = builder_.TaggedIsHeapObject(receiver); 208 builder_.DeoptCheck(heapObjectCheck, frameState, DeoptType::NOTHEAPOBJECT1); 209 210 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 211} 212 213void MCRLowering::LowerTaggedIsHeapObject(GateRef gate) 214{ 215 Environment env(gate, circuit_, &builder_); 216 GateRef receiver = acc_.GetValueIn(gate, 0); 217 GateRef result = builder_.TaggedIsHeapObject(receiver); 218 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 219} 220 221void MCRLowering::LowerIsMarkerCellValid(GateRef gate) 222{ 223 Environment env(gate, circuit_, &builder_); 224 GateRef cell = acc_.GetValueIn(gate, 0); 225 GateRef result = builder_.IsMarkerCellValid(cell); 226 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 227} 228 229void MCRLowering::LowerIsSpecificObjectType(GateRef gate) 230{ 231 Environment env(gate, circuit_, &builder_); 232 JSType expectType = static_cast<JSType>(acc_.GetJSType(gate)); 233 GateRef obj = acc_.GetValueIn(gate, 0); 234 GateRef result; 235 switch (expectType) { 236 case JSType::JS_MAP: { 237 result = builder_.TaggedObjectIsJSMap(obj); 238 break; 239 } 240 case JSType::JS_SET: { 241 result = builder_.TaggedObjectIsJSSet(obj); 242 break; 243 } 244 case JSType::JS_DATE: { 245 result = builder_.TaggedObjectIsJSDate(obj); 246 break; 247 } 248 case JSType::JS_ARRAY: { 249 result = builder_.TaggedObjectIsJSArray(obj); 250 break; 251 } 252 case JSType::STRING_FIRST: { 253 result = builder_.TaggedObjectIsString(obj); 254 break; 255 } 256 case JSType::JS_TYPED_ARRAY_FIRST: { 257 result = builder_.TaggedObjectIsTypedArray(obj); 258 break; 259 } 260 default: { 261 LOG_COMPILER(FATAL) << "this branch is unreachable"; 262 UNREACHABLE(); 263 } 264 } 265 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 266} 267 268void MCRLowering::DeleteStateSplit(GateRef gate) 269{ 270 auto depend = acc_.GetDep(gate); 271 auto frameState = acc_.GetFrameState(gate); 272 acc_.DeleteGateIfNoUse(frameState); 273 acc_.ReplaceGate(gate, Circuit::NullGate(), depend, Circuit::NullGate()); 274} 275 276void MCRLowering::LowerArrayGuardianCheck(GateRef gate) 277{ 278 Environment env(gate, circuit_, &builder_); 279 280 GateRef frameState = acc_.GetFrameState(gate); 281 GateRef guardiansOffset = builder_.IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(false)); 282 GateRef check = builder_.Load(VariableType::BOOL(), glue_, guardiansOffset); 283 builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY1); 284 285 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 286} 287 288void MCRLowering::LowerHClassStableArrayCheck(GateRef gate) 289{ 290 Environment env(gate, circuit_, &builder_); 291 GateRef frameState = acc_.GetFrameState(gate); 292 GateRef hclass = acc_.GetValueIn(gate, 0); 293 294 GateRef check = builder_.IsStableElements(hclass); 295 builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY2); 296 297 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 298} 299 300StateDepend MCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate) 301{ 302 Environment env(stateDepend.State(), stateDepend.Depend(), {}, circuit_, &builder_); 303 GateRef value = acc_.GetValueIn(gate); 304 ValueType dstType = acc_.GetDstType(gate); 305 GateRef result = Circuit::NullGate(); 306 Label exit(&builder_); 307 switch (acc_.GetSrcType(gate)) { 308 case ValueType::BOOL: 309 ASSERT(dstType == ValueType::TAGGED_BOOLEAN); 310 result = ConvertBoolToTaggedBoolean(value); 311 break; 312 case ValueType::INT32: 313 if (dstType == ValueType::TAGGED_INT) { 314 result = ConvertInt32ToTaggedInt(value); 315 } else if (dstType == ValueType::FLOAT64) { 316 result = ConvertInt32ToFloat64(value); 317 } else { 318 ASSERT(dstType == ValueType::BOOL); 319 result = builder_.NotEqual(value, builder_.Int32(0)); 320 } 321 break; 322 case ValueType::UINT32: 323 if (dstType == ValueType::TAGGED_NUMBER) { 324 result = ConvertUInt32ToTaggedNumber(value, &exit); 325 } else if (dstType == ValueType::FLOAT64) { 326 result = ConvertUInt32ToFloat64(value); 327 } else { 328 ASSERT(dstType == ValueType::BOOL); 329 result = builder_.NotEqual(value, builder_.Int32(0)); 330 } 331 break; 332 case ValueType::FLOAT64: 333 if (dstType == ValueType::TAGGED_DOUBLE) { 334 result = ConvertFloat64ToTaggedDouble(value); 335 } else if (dstType == ValueType::INT32) { 336 result = ConvertFloat64ToInt32(value, &exit); 337 } else { 338 ASSERT(dstType == ValueType::BOOL); 339 result = ConvertFloat64ToBool(value); 340 } 341 break; 342 case ValueType::TAGGED_BOOLEAN: 343 ASSERT((dstType == ValueType::BOOL)); 344 result = ConvertTaggedBooleanToBool(value); 345 break; 346 case ValueType::TAGGED_INT: 347 ASSERT((dstType == ValueType::INT32)); 348 result = ConvertTaggedIntToInt32(value); 349 break; 350 case ValueType::TAGGED_DOUBLE: 351 ASSERT((dstType == ValueType::FLOAT64)); 352 result = ConvertTaggedDoubleToFloat64(value); 353 break; 354 case ValueType::CHAR: { 355 GateRef glue = acc_.GetGlueFromArgList(); 356 if (dstType == ValueType::ECMA_STRING) { 357 result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateStringBySingleCharCode, { glue, value }); 358 } else if (dstType == ValueType::INT32) { 359 result = builder_.CallStub(glue, gate, CommonStubCSigns::ConvertCharToInt32, { glue, value }); 360 } else { 361 ASSERT((dstType == ValueType::FLOAT64)); 362 result = builder_.CallStub(glue, gate, CommonStubCSigns::ConvertCharToDouble, { glue, value }); 363 } 364 break; 365 } 366 case ValueType::HOLE_INT: 367 if (dstType == ValueType::TAGGED_INT) { 368 result = ConvertSpecialHoleIntToTagged(value, &exit); 369 } 370 break; 371 case ValueType::HOLE_DOUBLE: 372 if (dstType == ValueType::TAGGED_DOUBLE) { 373 result = ConvertSpecialHoleDoubleToTagged(value, &exit); 374 } 375 break; 376 default: 377 LOG_COMPILER(FATAL) << "this branch is unreachable"; 378 break; 379 } 380 acc_.ReplaceGate(gate, Circuit::NullGate(), Circuit::NullGate(), result); 381 return builder_.GetStateDepend(); 382} 383 384GateRef MCRLowering::ConvertSpecialHoleIntToTagged(GateRef gate, Label* exit) 385{ 386 Label returnUndefined(&builder_); 387 Label returnTaggedInt(&builder_); 388 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); 389 390 builder_.Branch(builder_.IsSpecialHole(gate), &returnUndefined, &returnTaggedInt, 1, BranchWeight::DEOPT_WEIGHT, 391 "specialHoleCheck"); 392 builder_.Bind(&returnUndefined); 393 { 394 result = builder_.UndefineConstant(); 395 builder_.Jump(exit); 396 } 397 builder_.Bind(&returnTaggedInt); 398 { 399 GateRef rawInt = builder_.TruncInt64ToInt32(gate); 400 result = ConvertInt32ToTaggedInt(rawInt); 401 builder_.Jump(exit); 402 } 403 builder_.Bind(exit); 404 return *result; 405} 406 407GateRef MCRLowering::ConvertSpecialHoleDoubleToTagged(GateRef gate, Label* exit) 408{ 409 Label returnUndefined(&builder_); 410 Label returnTaggedDouble(&builder_); 411 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); 412 413 builder_.Branch(builder_.IsSpecialHole(gate), &returnUndefined, &returnTaggedDouble, 1, BranchWeight::DEOPT_WEIGHT, 414 "specialHoleCheck"); 415 builder_.Bind(&returnUndefined); 416 { 417 result = builder_.UndefineConstant(); 418 builder_.Jump(exit); 419 } 420 builder_.Bind(&returnTaggedDouble); 421 { 422 GateRef rawDouble = builder_.CastInt64ToFloat64(gate); 423 result = ConvertFloat64ToTaggedDouble(rawDouble); 424 builder_.Jump(exit); 425 } 426 builder_.Bind(exit); 427 return *result; 428} 429 430GateRef MCRLowering::ConvertTaggedNumberToBool(GateRef gate, Label *exit) 431{ 432 DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(false)); 433 Label isInt(&builder_); 434 Label isDouble(&builder_); 435 Label toInt32(&builder_); 436 BRANCH_CIR(builder_.TaggedIsInt(gate), &isInt, &isDouble); 437 builder_.Bind(&isInt); 438 { 439 GateRef intVal = builder_.GetInt64OfTInt(gate); 440 result = builder_.NotEqual(intVal, builder_.Int64(0)); 441 } 442 builder_.Jump(exit); 443 builder_.Bind(&isDouble); 444 { 445 GateRef doubleVal = builder_.GetDoubleOfTDouble(gate); 446 result = ConvertFloat64ToBool(doubleVal); 447 } 448 builder_.Jump(exit); 449 builder_.Bind(exit); 450 return *result; 451} 452 453GateRef MCRLowering::ConvertTaggedNumberToInt32(GateRef gate, Label *exit) 454{ 455 DEFVALUE(result, (&builder_), VariableType::INT32(), builder_.Int32(0)); 456 Label isInt(&builder_); 457 Label isDouble(&builder_); 458 Label toInt32(&builder_); 459 BRANCH_CIR(builder_.TaggedIsInt(gate), &isInt, &isDouble); 460 builder_.Bind(&isInt); 461 result = ConvertTaggedIntToInt32(gate); 462 builder_.Jump(exit); 463 builder_.Bind(&isDouble); 464 result = ConvertFloat64ToInt32(ConvertTaggedDoubleToFloat64(gate), &toInt32); 465 builder_.Jump(exit); 466 builder_.Bind(exit); 467 return *result; 468} 469 470GateRef MCRLowering::ConvertTaggedNumberToFloat64(GateRef gate, Label *exit) 471{ 472 DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.Double(0)); 473 Label isInt(&builder_); 474 Label isDouble(&builder_); 475 BRANCH_CIR(builder_.TaggedIsInt(gate), &isInt, &isDouble); 476 builder_.Bind(&isInt); 477 result = ConvertInt32ToFloat64(ConvertTaggedIntToInt32(gate)); 478 builder_.Jump(exit); 479 builder_.Bind(&isDouble); 480 result = ConvertTaggedDoubleToFloat64(gate); 481 builder_.Jump(exit); 482 builder_.Bind(exit); 483 return *result; 484} 485 486void MCRLowering::LowerCheckAndConvert(GateRef gate) 487{ 488 Environment env(gate, circuit_, &builder_); 489 GateRef frameState = acc_.GetFrameState(gate); 490 ValueType srcType = acc_.GetSrcType(gate); 491 Label exit(&builder_); 492 switch (srcType) { 493 case ValueType::UINT32: 494 LowerCheckUInt32AndConvert(gate, frameState); 495 break; 496 case ValueType::TAGGED_INT: 497 LowerCheckTaggedIntAndConvert(gate, frameState); 498 break; 499 case ValueType::TAGGED_DOUBLE: 500 LowerCheckTaggedDoubleAndConvert(gate, frameState, &exit); 501 break; 502 case ValueType::TAGGED_BOOLEAN: 503 LowerCheckTaggedBoolAndConvert(gate, frameState); 504 break; 505 case ValueType::TAGGED_NUMBER: 506 LowerCheckTaggedNumberAndConvert(gate, frameState, &exit); 507 break; 508 case ValueType::BOOL: 509 LowerCheckSupportAndConvert(gate, frameState); 510 break; 511 case ValueType::TAGGED_NULL: 512 LowerCheckNullAndConvert(gate, frameState); 513 break; 514 case ValueType::UNDEFINED: 515 LowerUndefinedAndConvert(gate, frameState); 516 break; 517 case ValueType::HOLE_INT: 518 LowerCheckSpecialHoleAndConvert(gate, frameState); 519 break; 520 case ValueType::HOLE_DOUBLE: 521 LowerCheckSpecialHoleAndConvert(gate, frameState); 522 break; 523 case ValueType::FLOAT64: 524 LowerCheckFloat64AndConvert(gate, frameState, &exit); 525 break; 526 default: 527 UNREACHABLE(); 528 } 529} 530 531void MCRLowering::LowerCheckFloat64AndConvert(GateRef gate, GateRef frameState, Label *exit) 532{ 533 GateRef value = acc_.GetValueIn(gate, 0); 534 535 GateRef result = ConvertFloat64ToInt32(value, exit); 536 GateRef check = builder_.DoubleEqual(builder_.ChangeInt32ToFloat64(result), value); 537 builder_.DeoptCheck(check, frameState, DeoptType::INT32OVERFLOW1); 538 539 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 540} 541 542void MCRLowering::LowerCheckSpecialHoleAndConvert(GateRef gate, GateRef frameState) 543{ 544 GateRef value = acc_.GetValueIn(gate, 0); 545 GateRef typeCheck = builder_.IsNotSpecialHole(value); 546 builder_.DeoptCheck(typeCheck, frameState, DeoptType::CANNOTSTORESPECAILHOLE); 547 GateRef result = Circuit::NullGate(); 548 ValueType dst = acc_.GetDstType(gate); 549 if (dst == ValueType::INT32) { 550 result = builder_.TruncInt64ToInt32(value); 551 } else if (dst == ValueType::FLOAT64) { 552 result = builder_.CastInt64ToFloat64(value); 553 } else if (dst == ValueType::TAGGED_INT) { 554 GateRef rawInt = builder_.TruncInt64ToInt32(gate); 555 result = ConvertInt32ToTaggedInt(rawInt); 556 } else if (dst == ValueType::TAGGED_DOUBLE) { 557 GateRef rawDouble = builder_.CastInt64ToFloat64(value); 558 result = ConvertFloat64ToTaggedDouble(rawDouble); 559 } else { 560 UNREACHABLE(); 561 } 562 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 563} 564 565void MCRLowering::LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState) 566{ 567 GateRef value = acc_.GetValueIn(gate, 0); 568 GateRef upperBound = builder_.Int32(INT32_MAX); 569 GateRef check = builder_.Int32UnsignedLessThanOrEqual(value, upperBound); 570 builder_.DeoptCheck(check, frameState, DeoptType::INT32OVERFLOW1); 571 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), value); 572} 573 574void MCRLowering::LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState) 575{ 576 GateRef value = acc_.GetValueIn(gate, 0); 577 GateRef typeCheck = builder_.TaggedIsInt(value); 578 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT1); 579 GateRef result = Circuit::NullGate(); 580 ValueType dst = acc_.GetDstType(gate); 581 ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64); 582 if (dst == ValueType::INT32) { 583 result = ConvertTaggedIntToInt32(value); 584 } else { 585 result = ConvertTaggedIntToFloat64(value); 586 } 587 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 588} 589 590void MCRLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit) 591{ 592 GateRef value = acc_.GetValueIn(gate, 0); 593 GateRef typeCheck = builder_.TaggedIsDouble(value); 594 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE1); 595 GateRef result = Circuit::NullGate(); 596 ValueType dst = acc_.GetDstType(gate); 597 ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64); 598 if (dst == ValueType::INT32) { 599 result = ConvertTaggedDoubleToInt32(value, exit); 600 } else { 601 result = ConvertTaggedDoubleToFloat64(value); 602 } 603 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 604} 605 606void MCRLowering::LowerCheckTaggedNumberAndConvert(GateRef gate, GateRef frameState, Label *exit) 607{ 608 GateRef value = acc_.GetValueIn(gate, 0); 609 GateRef typeCheck = builder_.TaggedIsNumber(value); 610 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER1); 611 GateRef result = Circuit::NullGate(); 612 ValueType dst = acc_.GetDstType(gate); 613 if (dst == ValueType::INT32) { 614 result = ConvertTaggedNumberToInt32(value, exit); 615 } else if (dst == ValueType::FLOAT64) { 616 result = ConvertTaggedNumberToFloat64(value, exit); 617 } else { 618 ASSERT(dst == ValueType::BOOL); 619 result = ConvertTaggedNumberToBool(value, exit); 620 } 621 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 622} 623 624void MCRLowering::LowerCheckSupportAndConvert(GateRef gate, GateRef frameState) 625{ 626 ValueType dstType = acc_.GetDstType(gate); 627 ASSERT(dstType == ValueType::INT32 || dstType == ValueType::FLOAT64); 628 bool support = acc_.IsConvertSupport(gate); 629 GateRef value = acc_.GetValueIn(gate, 0); 630 631 GateRef result = Circuit::NullGate(); 632 if (dstType == ValueType::INT32) { 633 builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTINT2); 634 result = builder_.BooleanToInt32(value); 635 } else { 636 builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTDOUBLE2); 637 result = builder_.BooleanToFloat64(value); 638 } 639 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 640} 641 642void MCRLowering::LowerCheckTaggedBoolAndConvert(GateRef gate, GateRef frameState) 643{ 644 GateRef value = acc_.GetValueIn(gate, 0); 645 GateRef typeCheck = builder_.TaggedIsBoolean(value); 646 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTBOOL1); 647 GateRef result = Circuit::NullGate(); 648 GateRef boolValue = ConvertTaggedBooleanToBool(value); 649 if (acc_.GetDstType(gate) == ValueType::BOOL) { 650 result = boolValue; 651 } else if (acc_.GetDstType(gate) == ValueType::INT32) { 652 result = builder_.ZExtInt1ToInt32(boolValue); 653 } else if (acc_.GetDstType(gate) == ValueType::FLOAT64) { 654 result = builder_.BooleanToFloat64(boolValue); 655 } else { 656 UNREACHABLE(); 657 } 658 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 659} 660 661void MCRLowering::LowerCheckNullAndConvert(GateRef gate, GateRef frameState) 662{ 663 GateRef value = acc_.GetValueIn(gate, 0); 664 GateRef typeCheck = builder_.TaggedIsNull(value); 665 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNULL1); 666 GateRef result = Circuit::NullGate(); 667 if (acc_.GetDstType(gate) == ValueType::INT32) { 668 result = builder_.Int32(0); 669 } else if (acc_.GetDstType(gate) == ValueType::FLOAT64) { 670 result = builder_.Double(0); 671 } else if (acc_.GetDstType(gate) == ValueType::BOOL) { 672 result = builder_.False(); 673 } else { 674 UNREACHABLE(); 675 } 676 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 677} 678 679void MCRLowering::LowerUndefinedAndConvert(GateRef gate, GateRef frameState) 680{ 681 GateRef value = acc_.GetValueIn(gate, 0); 682 GateRef typeCheck = builder_.TaggedIsUndefined(value); 683 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNULL2); 684 GateRef result = Circuit::NullGate(); 685 if (acc_.GetDstType(gate) == ValueType::FLOAT64) { 686 result = builder_.NanValue(); 687 } else if (acc_.GetDstType(gate) == ValueType::BOOL) { 688 result = builder_.False(); 689 } else if (acc_.GetDstType(gate) == ValueType::INT32) { 690 result = builder_.Int32(0); 691 } else { 692 UNREACHABLE(); 693 } 694 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 695} 696 697GateRef MCRLowering::ConvertTaggedBooleanToBool(GateRef value) 698{ 699 return builder_.TaggedIsTrue(value); 700} 701 702GateRef MCRLowering::ConvertBoolToTaggedBoolean(GateRef gate) 703{ 704 return builder_.BooleanToTaggedBooleanPtr(gate); 705} 706 707GateRef MCRLowering::ConvertInt32ToFloat64(GateRef gate) 708{ 709 return builder_.ChangeInt32ToFloat64(gate); 710} 711 712GateRef MCRLowering::ConvertUInt32ToFloat64(GateRef gate) 713{ 714 return builder_.ChangeUInt32ToFloat64(gate); 715} 716 717GateRef MCRLowering::ConvertInt32ToTaggedInt(GateRef gate) 718{ 719 return builder_.Int32ToTaggedPtr(gate); 720} 721 722GateRef MCRLowering::ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit) 723{ 724 Label isOverFlow(&builder_); 725 Label notOverFlow(&builder_); 726 GateRef upperBound = builder_.Int32(INT32_MAX); 727 DEFVALUE(taggedVal, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); 728 BRANCH_CIR(builder_.Int32UnsignedLessThanOrEqual(gate, upperBound), ¬OverFlow, &isOverFlow); 729 builder_.Bind(¬OverFlow); 730 taggedVal = builder_.Int32ToTaggedPtr(gate); 731 builder_.Jump(exit); 732 builder_.Bind(&isOverFlow); 733 taggedVal = builder_.DoubleToTaggedDoublePtr(builder_.ChangeUInt32ToFloat64(gate)); 734 builder_.Jump(exit); 735 builder_.Bind(exit); 736 return *taggedVal; 737} 738 739GateRef MCRLowering::ConvertFloat64ToInt32(GateRef gate, Label *exit) 740{ 741 return builder_.DoubleToInt(gate, exit); 742} 743 744GateRef MCRLowering::ConvertFloat64ToBool(GateRef gate) 745{ 746 return LogicAndBuilder(builder_.GetCurrentEnvironment()) 747 .And(builder_.DoubleNotEqual(gate, builder_.Double(0.0))) 748 .And(builder_.BoolNot(builder_.DoubleIsNAN(gate))) 749 .Done(); 750} 751 752GateRef MCRLowering::ConvertFloat64ToTaggedDouble(GateRef gate) 753{ 754 return builder_.DoubleToTaggedDoublePtr(gate); 755} 756 757GateRef MCRLowering::ConvertTaggedIntToInt32(GateRef gate) 758{ 759 return builder_.GetInt32OfTInt(gate); 760} 761 762GateRef MCRLowering::ConvertTaggedIntToFloat64(GateRef gate) 763{ 764 return builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(gate)); 765} 766 767GateRef MCRLowering::ConvertTaggedDoubleToInt32(GateRef gate, Label *exit) 768{ 769 return builder_.DoubleToInt(builder_.GetDoubleOfTDouble(gate), exit); 770} 771 772GateRef MCRLowering::ConvertTaggedDoubleToFloat64(GateRef gate) 773{ 774 return builder_.GetDoubleOfTDouble(gate); 775} 776 777void MCRLowering::LowerGetGlobalEnv(GateRef gate) 778{ 779 Environment env(gate, circuit_, &builder_); 780 GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(false)); 781 GateRef glueGlobalEnv = builder_.Load(VariableType::JS_POINTER(), glue_, glueGlobalEnvOffset); 782 acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), glueGlobalEnv); 783} 784 785void MCRLowering::LowerGetGlobalEnvObj(GateRef gate) 786{ 787 Environment env(gate, circuit_, &builder_); 788 GateRef globalEnv = acc_.GetValueIn(gate, 0); 789 size_t index = acc_.GetIndex(gate); 790 GateRef offset = builder_.IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index); 791 GateRef object = builder_.Load(VariableType::JS_ANY(), globalEnv, offset); 792 acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), object); 793} 794 795void MCRLowering::LowerGetGlobalEnvObjHClass(GateRef gate) 796{ 797 Environment env(gate, circuit_, &builder_); 798 GateRef globalEnv = acc_.GetValueIn(gate, 0); 799 size_t index = acc_.GetIndex(gate); 800 GateRef offset = builder_.IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index); 801 GateRef object = builder_.Load(VariableType::JS_ANY(), globalEnv, offset); 802 auto hclass = builder_.Load(VariableType::JS_POINTER(), object, 803 builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 804 acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), hclass); 805} 806 807void MCRLowering::LowerGetGlobalConstantValue(GateRef gate) 808{ 809 Environment env(gate, circuit_, &builder_); 810 size_t index = acc_.GetIndex(gate); 811 GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_, 812 builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false))); 813 GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * index); 814 GateRef result = builder_.Load(VariableType::JS_POINTER(), gConstAddr, constantIndex); 815 acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result); 816} 817 818void MCRLowering::HeapAllocateInSOld(GateRef gate) 819{ 820 GateRef size = acc_.GetValueIn(gate, 0); 821 GateRef ret = builder_.CallRuntime(glue_, RTSTUB_ID(AllocateInSOld), Gate::InvalidGateRef, 822 {builder_.ToTaggedInt(size)}, gate); 823 824 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret); 825} 826 827void MCRLowering::LowerInt32CheckRightIsZero(GateRef gate) 828{ 829 Environment env(gate, circuit_, &builder_); 830 GateRef frameState = acc_.GetFrameState(gate); 831 GateRef right = acc_.GetValueIn(gate, 0); 832 GateRef rightNotZero = builder_.Int32NotEqual(right, builder_.Int32(0)); 833 builder_.DeoptCheck(rightNotZero, frameState, DeoptType::MODZERO1); 834 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 835} 836 837void MCRLowering::LowerRemainderIsNegativeZero(GateRef gate) 838{ 839 Environment env(gate, circuit_, &builder_); 840 GateRef frameState = acc_.GetFrameState(gate); 841 GateRef left = acc_.GetValueIn(gate, 0); 842 GateRef right = acc_.GetValueIn(gate, 1); 843 GateRef remainderIsNegative = LogicAndBuilder(&env) 844 .And(builder_.Int32LessThan(left, builder_.Int32(0))) 845 .And(builder_.Int32Equal(builder_.Int32(0), 846 builder_.BinaryArithmetic(circuit_->Smod(), MachineType::I32, left, right, GateType::NJSValue()))) 847 .Done(); 848 GateRef remainderIsNotNegative = builder_.BoolNot(remainderIsNegative); 849 builder_.DeoptCheck(remainderIsNotNegative, frameState, DeoptType::REMAINDERISNEGATIVEZERO); 850 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 851} 852 853void MCRLowering::LowerFloat64CheckRightIsZero(GateRef gate) 854{ 855 Environment env(gate, circuit_, &builder_); 856 GateRef frameState = acc_.GetFrameState(gate); 857 GateRef right = acc_.GetValueIn(gate, 0); 858 GateRef rightNotZero = builder_.DoubleNotEqual(right, builder_.Double(0.0)); 859 builder_.DeoptCheck(rightNotZero, frameState, DeoptType::DIVZERO1); 860 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 861} 862 863void MCRLowering::LowerLexVarIsHoleCheck(GateRef gate) 864{ 865 Environment env(gate, circuit_, &builder_); 866 GateRef frameState = acc_.GetFrameState(gate); 867 GateRef value = acc_.GetValueIn(gate, 0); 868 GateRef valueIsNotHole = builder_.TaggedIsNotHole(value); 869 builder_.DeoptCheck(valueIsNotHole, frameState, DeoptType::LEXVARISHOLE1); 870 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 871} 872 873void MCRLowering::LowerIsUndefinedOrHoleCheck(GateRef gate) 874{ 875 Environment env(gate, circuit_, &builder_); 876 GateRef frameState = acc_.GetFrameState(gate); 877 GateRef value = acc_.GetValueIn(gate, 0); 878 GateRef isNotUndefinedorHole = builder_.BoolNot(builder_.TaggedIsUndefinedOrHole(value)); 879 builder_.DeoptCheck(isNotUndefinedorHole, frameState, DeoptType::ISUNDEFINEDORHOLE); 880 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 881} 882 883void MCRLowering::LowerIsNotUndefinedOrHoleCheck(GateRef gate) 884{ 885 Environment env(gate, circuit_, &builder_); 886 GateRef frameState = acc_.GetFrameState(gate); 887 GateRef value = acc_.GetValueIn(gate, 0); 888 GateRef isUndefinedorHole = builder_.TaggedIsUndefinedOrHole(value); 889 builder_.DeoptCheck(isUndefinedorHole, frameState, DeoptType::ISNOTUNDEFINEDORHOLE); 890 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 891} 892 893void MCRLowering::LowerIsDataViewCheck(GateRef gate) 894{ 895 Environment env(gate, circuit_, &builder_); 896 GateRef frameState = acc_.GetFrameState(gate); 897 GateRef obj = acc_.GetValueIn(gate, 0); 898 GateRef isDataView = builder_.CheckJSType(obj, JSType::JS_DATA_VIEW); 899 builder_.DeoptCheck(isDataView, frameState, DeoptType::ISNOTDATAVIEW); 900 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 901} 902 903void MCRLowering::LowerValueCheckNegOverflow(GateRef gate) 904{ 905 Environment env(gate, circuit_, &builder_); 906 GateRef frameState = acc_.GetFrameState(gate); 907 GateRef value = acc_.GetValueIn(gate, 0); 908 GateRef valueNotZero = builder_.NotEqual(value, builder_.Int32(0)); 909 builder_.DeoptCheck(valueNotZero, frameState, DeoptType::NOTNEGOV1); 910 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 911} 912 913void MCRLowering::LowerOverflowCheck(GateRef gate) 914{ 915 Environment env(gate, circuit_, &builder_); 916 GateRef frameState = acc_.GetFrameState(gate); 917 GateRef result = acc_.GetValueIn(gate, 0); 918 GateRef condition = builder_.BoolNot(builder_.ExtractValue(MachineType::I1, result, builder_.Int32(1))); 919 builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT3); 920 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 921} 922 923void MCRLowering::LowerInt32UnsignedUpperBoundCheck(GateRef gate) 924{ 925 Environment env(gate, circuit_, &builder_); 926 GateRef frameState = acc_.GetFrameState(gate); 927 GateRef value = acc_.GetValueIn(gate, 0); 928 GateRef upperBound = acc_.GetValueIn(gate, 1); 929 GateRef condition = builder_.Int32UnsignedLessThanOrEqual(value, upperBound); 930 builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT4); 931 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 932} 933 934void MCRLowering::LowerInt32DivWithCheck(GateRef gate) 935{ 936 Environment env(gate, circuit_, &builder_); 937 GateRef frameState = acc_.GetFrameState(gate); 938 GateRef left = acc_.GetValueIn(gate, 0); 939 GateRef right = acc_.GetValueIn(gate, 1); 940 GateRef result = Circuit::NullGate(); 941 GateRef condition = LogicOrBuilder(&env) 942 .Or(builder_.Int32GreaterThan(right, builder_.Int32(0))) 943 .Or(builder_.BitAnd(builder_.Int32LessThan(right, builder_.Int32(0)), 944 builder_.Int32NotEqual(left, builder_.Int32(0)))) 945 .Done(); 946 builder_.DeoptCheck(condition, frameState, DeoptType::DIVZERO2); 947 result = builder_.BinaryArithmetic(circuit_->Sdiv(), MachineType::I32, left, right, GateType::NJSValue()); 948 GateRef truncated = builder_.BinaryArithmetic(circuit_->Mul(), 949 MachineType::I32, result, right, GateType::NJSValue()); 950 GateRef overCheck = builder_.Int32Equal(truncated, left); 951 builder_.DeoptCheck(overCheck, frameState, DeoptType::NOTINT5); 952 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result); 953} 954 955void MCRLowering::LowerStoreMemory(GateRef gate) 956{ 957 Environment env(gate, circuit_, &builder_); 958 GateRef receiver = acc_.GetValueIn(gate, 0); 959 GateRef index = acc_.GetValueIn(gate, 1); 960 GateRef value = acc_.GetValueIn(gate, 2); 961 builder_.Store(VariableType::VOID(), glue_, receiver, index, value); 962 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 963} 964 965void MCRLowering::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef glue, 966 GateRef value, GateRef start, GateRef end) 967{ 968 Label begin(&builder_); 969 Label storeValue(&builder_); 970 Label endLoop(&builder_); 971 972 DEFVALUE(startOffset, (&builder_), VariableType::INT32(), start); 973 builder_.Jump(&begin); 974 builder_.LoopBegin(&begin); 975 { 976 BRANCH_CIR(builder_.Int32UnsignedLessThan(*startOffset, end), &storeValue, exit); 977 builder_.Bind(&storeValue); 978 { 979 builder_.Store(VariableType::INT64(), glue, object, builder_.ZExtInt32ToPtr(*startOffset), value); 980 startOffset = builder_.Int32Add(*startOffset, builder_.Int32(JSTaggedValue::TaggedTypeSize())); 981 builder_.Jump(&endLoop); 982 } 983 builder_.Bind(&endLoop); 984 builder_.LoopEnd(&begin); 985 } 986} 987 988void MCRLowering::LowerMigrateFromRawValueToHeapValues(GateRef gate) 989{ 990 Environment env(gate, circuit_, &builder_); 991 DEFVALUE(newElements, (&builder_), VariableType::JS_ANY(), builder_.Undefined()); 992 Label exit(&builder_); 993 GateRef object = acc_.GetValueIn(gate, 0); 994 GateRef needCOW = acc_.GetValueIn(gate, 1); 995 GateRef isIntKind = acc_.GetValueIn(gate, 2); 996 GateRef elements = builder_.GetElementsArray(object); 997 GateRef length = builder_.GetLengthOfTaggedArray(elements); 998 Label createCOW(&builder_); 999 Label createNormal(&builder_); 1000 Label finishElementsInit(&builder_); 1001 BRANCH_CIR(needCOW, &createCOW, &createNormal); 1002 builder_.Bind(&createCOW); 1003 { 1004 newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewCOWTaggedArray), acc_.GetDep(gate), 1005 { builder_.Int32ToTaggedPtr(length) }, gate); 1006 builder_.Jump(&finishElementsInit); 1007 } 1008 builder_.Bind(&createNormal); 1009 { 1010 newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), acc_.GetDep(gate), 1011 { builder_.Int32ToTaggedPtr(length) }, gate); 1012 builder_.Jump(&finishElementsInit); 1013 } 1014 builder_.Bind(&finishElementsInit); 1015 1016 DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0)); 1017 Label loopHead(&builder_); 1018 Label loopEnd(&builder_); 1019 Label afterLoop(&builder_); 1020 Label storeValue(&builder_); 1021 builder_.Jump(&loopHead); 1022 builder_.LoopBegin(&loopHead); 1023 { 1024 Label storeHole(&builder_); 1025 Label storeNormalValue(&builder_); 1026 Label finishStore(&builder_); 1027 BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop); 1028 builder_.Bind(&storeValue); 1029 { 1030 Label rawValueIsInt(&builder_); 1031 Label rawValueIsNumber(&builder_); 1032 GateRef value = builder_.GetValueFromJSArrayWithElementsKind(VariableType::INT64(), elements, *index); 1033 BRANCH_CIR(builder_.IsSpecialHole(value), &storeHole, &storeNormalValue); 1034 builder_.Bind(&storeHole); 1035 { 1036 builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *newElements, *index, builder_.Hole()); 1037 builder_.Jump(&finishStore); 1038 } 1039 builder_.Bind(&storeNormalValue); 1040 { 1041 BRANCH_CIR(isIntKind, &rawValueIsInt, &rawValueIsNumber); 1042 builder_.Bind(&rawValueIsInt); 1043 { 1044 GateRef convertedInt = builder_.ToTaggedIntPtr(value); 1045 builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *newElements, *index, convertedInt); 1046 builder_.Jump(&finishStore); 1047 } 1048 builder_.Bind(&rawValueIsNumber); 1049 { 1050 GateRef tmpDouble = builder_.CastInt64ToFloat64(value); 1051 GateRef convertedDouble = builder_.DoubleToTaggedDoublePtr(tmpDouble); 1052 builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *newElements, 1053 *index, convertedDouble); 1054 builder_.Jump(&finishStore); 1055 } 1056 } 1057 builder_.Bind(&finishStore); 1058 { 1059 index = builder_.Int32Add(*index, builder_.Int32(1)); 1060 builder_.Jump(&loopEnd); 1061 } 1062 } 1063 } 1064 builder_.Bind(&loopEnd); 1065 builder_.LoopEnd(&loopHead); 1066 builder_.Bind(&afterLoop); 1067 { 1068 builder_.Jump(&exit); 1069 } 1070 builder_.Bind(&exit); 1071 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *newElements); 1072} 1073 1074void MCRLowering::LowerMigrateFromHeapValueToRawValue(GateRef gate) 1075{ 1076 Environment env(gate, circuit_, &builder_); 1077 DEFVALUE(newElements, (&builder_), VariableType::JS_ANY(), builder_.Undefined()); 1078 Label exit(&builder_); 1079 GateRef object = acc_.GetValueIn(gate, 0); 1080 GateRef needCOW = acc_.GetValueIn(gate, 1); 1081 GateRef isIntKind = acc_.GetValueIn(gate, 2); 1082 1083 GateRef elements = builder_.GetElementsArray(object); 1084 GateRef length = builder_.GetLengthOfTaggedArray(elements); 1085 Label createCOW(&builder_); 1086 Label createNormal(&builder_); 1087 Label finishElementsInit(&builder_); 1088 BRANCH_CIR(needCOW, &createCOW, &createNormal); 1089 builder_.Bind(&createCOW); 1090 { 1091 newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewCOWMutantTaggedArray), acc_.GetDep(gate), 1092 { builder_.Int32ToTaggedPtr(length) }, gate); 1093 builder_.Jump(&finishElementsInit); 1094 } 1095 builder_.Bind(&createNormal); 1096 { 1097 newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewMutantTaggedArray), acc_.GetDep(gate), 1098 { builder_.Int32ToTaggedPtr(length) }, gate); 1099 builder_.Jump(&finishElementsInit); 1100 } 1101 builder_.Bind(&finishElementsInit); 1102 1103 DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0)); 1104 Label loopHead(&builder_); 1105 Label loopEnd(&builder_); 1106 Label afterLoop(&builder_); 1107 Label storeValue(&builder_); 1108 builder_.Jump(&loopHead); 1109 builder_.LoopBegin(&loopHead); 1110 { 1111 Label storeSpecialHole(&builder_); 1112 Label storeNormalValue(&builder_); 1113 Label finishStore(&builder_); 1114 BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop); 1115 builder_.Bind(&storeValue); 1116 { 1117 Label convertToInt(&builder_); 1118 Label convertToDouble(&builder_); 1119 GateRef value = builder_.GetValueFromTaggedArray(elements, *index); 1120 BRANCH_CIR(builder_.TaggedIsHole(value), &storeSpecialHole, &storeNormalValue); 1121 builder_.Bind(&storeSpecialHole); 1122 { 1123 builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements, 1124 *index, builder_.SpecialHoleConstant()); 1125 builder_.Jump(&finishStore); 1126 } 1127 builder_.Bind(&storeNormalValue); 1128 { 1129 Label valueIsInt(&builder_); 1130 Label valueIsDouble(&builder_); 1131 BRANCH_CIR(isIntKind, &convertToInt, &convertToDouble); 1132 builder_.Bind(&convertToInt); 1133 { 1134 GateRef convertedInt = builder_.GetInt64OfTInt(value); 1135 builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements, *index, convertedInt); 1136 builder_.Jump(&finishStore); 1137 } 1138 builder_.Bind(&convertToDouble); 1139 { 1140 BRANCH_CIR(builder_.TaggedIsInt(value), &valueIsInt, &valueIsDouble); 1141 builder_.Bind(&valueIsInt); 1142 { 1143 GateRef convertedDoubleFromTInt = builder_.CastDoubleToInt64(builder_.GetDoubleOfTInt(value)); 1144 builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements, *index, 1145 convertedDoubleFromTInt); 1146 builder_.Jump(&finishStore); 1147 } 1148 builder_.Bind(&valueIsDouble); 1149 { 1150 GateRef doubleValue = builder_.GetDoubleOfTDouble(value); 1151 GateRef convertedDoubleFromTDouble = builder_.CastDoubleToInt64(doubleValue); 1152 builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements, *index, 1153 convertedDoubleFromTDouble); 1154 builder_.Jump(&finishStore); 1155 } 1156 } 1157 } 1158 builder_.Bind(&finishStore); 1159 { 1160 index = builder_.Int32Add(*index, builder_.Int32(1)); 1161 builder_.Jump(&loopEnd); 1162 } 1163 } 1164 } 1165 builder_.Bind(&loopEnd); 1166 builder_.LoopEnd(&loopHead); 1167 builder_.Bind(&afterLoop); 1168 { 1169 builder_.Jump(&exit); 1170 } 1171 1172 builder_.Bind(&exit); 1173 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *newElements); 1174} 1175 1176void MCRLowering::LowerMigrateFromHoleIntToHoleNumber(GateRef gate) 1177{ 1178 Environment env(gate, circuit_, &builder_); 1179 GateRef object = acc_.GetValueIn(gate, 0); 1180 Label exit(&builder_); 1181 GateRef elements = builder_.GetElementsArray(object); 1182 GateRef length = builder_.GetLengthOfTaggedArray(elements); 1183 DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0)); 1184 Label loopHead(&builder_); 1185 Label loopEnd(&builder_); 1186 Label afterLoop(&builder_); 1187 Label storeValue(&builder_); 1188 builder_.Jump(&loopHead); 1189 builder_.LoopBegin(&loopHead); 1190 { 1191 Label storeNormalValue(&builder_); 1192 Label finishStore(&builder_); 1193 BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop); 1194 builder_.Bind(&storeValue); 1195 { 1196 GateRef value = builder_.GetValueFromTaggedArray(VariableType::INT64(), elements, *index); 1197 BRANCH_CIR(builder_.IsSpecialHole(value), &finishStore, &storeNormalValue); 1198 builder_.Bind(&storeNormalValue); 1199 { 1200 GateRef intVal = builder_.TruncInt64ToInt32(value); 1201 GateRef convertedValue = builder_.CastDoubleToInt64(builder_.ChangeInt32ToFloat64(intVal)); 1202 builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, elements, *index, 1203 convertedValue); 1204 builder_.Jump(&finishStore); 1205 } 1206 builder_.Bind(&finishStore); 1207 { 1208 index = builder_.Int32Add(*index, builder_.Int32(1)); 1209 builder_.Jump(&loopEnd); 1210 } 1211 } 1212 } 1213 builder_.Bind(&loopEnd); 1214 builder_.LoopEnd(&loopHead); 1215 builder_.Bind(&afterLoop); 1216 { 1217 builder_.Jump(&exit); 1218 } 1219 1220 builder_.Bind(&exit); 1221 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 1222} 1223 1224void MCRLowering::LowerMigrateFromHoleNumberToHoleInt(GateRef gate) 1225{ 1226 Environment env(gate, circuit_, &builder_); 1227 GateRef object = acc_.GetValueIn(gate, 0); 1228 Label exit(&builder_); 1229 GateRef elements = builder_.GetElementsArray(object); 1230 GateRef length = builder_.GetLengthOfTaggedArray(elements); 1231 DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0)); 1232 Label loopHead(&builder_); 1233 Label loopEnd(&builder_); 1234 Label afterLoop(&builder_); 1235 Label storeValue(&builder_); 1236 builder_.Jump(&loopHead); 1237 builder_.LoopBegin(&loopHead); 1238 { 1239 Label storeNormalValue(&builder_); 1240 Label finishStore(&builder_); 1241 BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop); 1242 builder_.Bind(&storeValue); 1243 { 1244 GateRef value = builder_.GetValueFromTaggedArray(VariableType::INT64(), elements, *index); 1245 BRANCH_CIR(builder_.IsSpecialHole(value), &finishStore, &storeNormalValue); 1246 builder_.Bind(&storeNormalValue); 1247 { 1248 GateRef doubleVal = builder_.CastInt64ToFloat64(value); 1249 GateRef convertedValue = builder_.SExtInt32ToInt64(builder_.ChangeFloat64ToInt32(doubleVal)); 1250 builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, elements, *index, 1251 convertedValue); 1252 builder_.Jump(&finishStore); 1253 } 1254 builder_.Bind(&finishStore); 1255 { 1256 index = builder_.Int32Add(*index, builder_.Int32(1)); 1257 builder_.Jump(&loopEnd); 1258 } 1259 } 1260 } 1261 builder_.Bind(&loopEnd); 1262 builder_.LoopEnd(&loopHead); 1263 builder_.Bind(&afterLoop); 1264 { 1265 builder_.Jump(&exit); 1266 } 1267 1268 builder_.Bind(&exit); 1269 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 1270} 1271 1272void MCRLowering::LowerHeapObjectIsEcmaObject(GateRef gate) 1273{ 1274 Environment env(gate, circuit_, &builder_); 1275 GateRef frameState = acc_.GetFrameState(gate); 1276 GateRef value = acc_.GetValueIn(gate, 0); 1277 1278 GateRef isEcmaObject = builder_.TaggedObjectIsEcmaObject(value); 1279 builder_.DeoptCheck(isEcmaObject, frameState, DeoptType::NOT_ECMA_OBJECT); 1280 1281 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 1282} 1283 1284void MCRLowering::LowerIsCallableCheck(GateRef gate) 1285{ 1286 Environment env(gate, circuit_, &builder_); 1287 GateRef func = acc_.GetValueIn(gate, 0); 1288 GateRef frameState = acc_.GetFrameState(gate); 1289 GateRef isCallable = LogicAndBuilder(&env).And(builder_.TaggedIsHeapObject(func)) 1290 .And(builder_.IsCallable(func)).Done(); 1291 builder_.DeoptCheck(isCallable, frameState, DeoptType::NOTCALLABLE); 1292 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate()); 1293} 1294} // namespace panda::ecmascript 1295