1/* 2 * Copyright (c) 2022 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/operations_stub_builder.h" 17#include "ecmascript/compiler/interpreter_stub-inl.h" 18#include "ecmascript/compiler/rt_call_signature.h" 19#include "ecmascript/compiler/stub_builder-inl.h" 20 21namespace panda::ecmascript::kungfu { 22GateRef OperationsStubBuilder::Equal(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 23{ 24 auto env = GetEnvironment(); 25 Label entry(env); 26 env->SubCfgEntry(&entry); 27 Label exit(env); 28 Label isHole(env); 29 Label notHole(env); 30 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 31 result = FastEqual(glue, left, right, callback); 32 BRANCH(TaggedIsHole(*result), &isHole, ¬Hole); 33 Bind(&isHole); 34 { 35 // slow path 36 result = CallRuntime(glue, RTSTUB_ID(Eq), { left, right }); 37 Jump(&exit); 38 } 39 Bind(¬Hole); 40 { 41 Label resultIsTrue(env); 42 Label resultNotTrue(env); 43 BRANCH(TaggedIsTrue(*result), &resultIsTrue, &resultNotTrue); 44 Bind(&resultIsTrue); 45 { 46 callback.ProfileBranch(true); 47 Jump(&exit); 48 } 49 Bind(&resultNotTrue); 50 { 51 callback.ProfileBranch(false); 52 Jump(&exit); 53 } 54 } 55 Bind(&exit); 56 auto ret = *result; 57 env->SubCfgExit(); 58 return ret; 59} 60 61GateRef OperationsStubBuilder::NotEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 62{ 63 auto env = GetEnvironment(); 64 Label entry(env); 65 env->SubCfgEntry(&entry); 66 Label exit(env); 67 68 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 69 result = FastEqual(glue, left, right, callback); 70 Label isHole(env); 71 Label notHole(env); 72 BRANCH(TaggedIsHole(*result), &isHole, ¬Hole); 73 Bind(&isHole); 74 { 75 // slow path 76 result = CallRuntime(glue, RTSTUB_ID(NotEq), { left, right }); 77 Jump(&exit); 78 } 79 Bind(¬Hole); 80 { 81 Label resultIsTrue(env); 82 Label resultNotTrue(env); 83 BRANCH(TaggedIsTrue(*result), &resultIsTrue, &resultNotTrue); 84 Bind(&resultIsTrue); 85 { 86 result = TaggedFalse(); 87 callback.ProfileBranch(false); 88 Jump(&exit); 89 } 90 Bind(&resultNotTrue); 91 { 92 callback.ProfileBranch(true); 93 result = TaggedTrue(); 94 Jump(&exit); 95 } 96 } 97 Bind(&exit); 98 auto ret = *result; 99 env->SubCfgExit(); 100 return ret; 101} 102 103GateRef OperationsStubBuilder::StrictEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 104{ 105 auto env = GetEnvironment(); 106 Label entry(env); 107 env->SubCfgEntry(&entry); 108 Label exit(env); 109 Label strictEqual(env); 110 Label notStrictEqual(env); 111 DEFVARIABLE(result, VariableType::JS_ANY(), TaggedTrue()); 112 BRANCH(FastStrictEqual(glue, left, right, callback), &strictEqual, ¬StrictEqual); 113 Bind(&strictEqual); 114 { 115 callback.ProfileBranch(true); 116 Jump(&exit); 117 } 118 Bind(¬StrictEqual); 119 { 120 result = TaggedFalse(); 121 callback.ProfileBranch(false); 122 Jump(&exit); 123 } 124 Bind(&exit); 125 auto ret = *result; 126 env->SubCfgExit(); 127 return ret; 128} 129 130GateRef OperationsStubBuilder::StrictNotEqual(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 131{ 132 auto env = GetEnvironment(); 133 Label entry(env); 134 env->SubCfgEntry(&entry); 135 Label exit(env); 136 Label strictEqual(env); 137 Label notStrictEqual(env); 138 DEFVARIABLE(result, VariableType::JS_ANY(), TaggedTrue()); 139 BRANCH(FastStrictEqual(glue, left, right, callback), &strictEqual, ¬StrictEqual); 140 Bind(&strictEqual); 141 { 142 result = TaggedFalse(); 143 callback.ProfileBranch(false); 144 Jump(&exit); 145 } 146 Bind(¬StrictEqual); 147 { 148 callback.ProfileBranch(true); 149 Jump(&exit); 150 } 151 Bind(&exit); 152 auto ret = *result; 153 env->SubCfgExit(); 154 return ret; 155} 156 157GateRef OperationsStubBuilder::Less(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 158{ 159 auto env = GetEnvironment(); 160 Label entry(env); 161 env->SubCfgEntry(&entry); 162 Label exit(env); 163 Label leftIsInt(env); 164 Label leftOrRightNotInt(env); 165 Label leftLessRight(env); 166 Label leftNotLessRight(env); 167 Label slowPath(env); 168 169 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 170 BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); 171 Bind(&leftIsInt); 172 { 173 Label rightIsInt(env); 174 BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); 175 Bind(&rightIsInt); 176 { 177 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 178 GateRef intLeft = TaggedGetInt(left); 179 GateRef intRight = TaggedGetInt(right); 180 BRANCH(Int32LessThan(intLeft, intRight), &leftLessRight, &leftNotLessRight); 181 } 182 } 183 Bind(&leftOrRightNotInt); 184 { 185 Label leftIsNumber(env); 186 BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath); 187 Bind(&leftIsNumber); 188 { 189 Label rightIsNumber(env); 190 BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath); 191 Bind(&rightIsNumber); 192 { 193 // fast path 194 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); 195 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); 196 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType())); 197 Label leftIsInt1(env); 198 Label leftNotInt1(env); 199 Label exit1(env); 200 Label exit2(env); 201 Label rightIsInt1(env); 202 Label rightNotInt1(env); 203 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); 204 Bind(&leftIsInt1); 205 { 206 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); 207 Jump(&exit1); 208 } 209 Bind(&leftNotInt1); 210 { 211 curType = TaggedInt(PGOSampleType::DoubleType()); 212 doubleLeft = GetDoubleOfTDouble(left); 213 Jump(&exit1); 214 } 215 Bind(&exit1); 216 { 217 BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); 218 } 219 Bind(&rightIsInt1); 220 { 221 GateRef type = TaggedInt(PGOSampleType::IntType()); 222 COMBINE_TYPE_CALL_BACK(curType, type); 223 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); 224 Jump(&exit2); 225 } 226 Bind(&rightNotInt1); 227 { 228 GateRef type = TaggedInt(PGOSampleType::DoubleType()); 229 COMBINE_TYPE_CALL_BACK(curType, type); 230 doubleRight = GetDoubleOfTDouble(right); 231 Jump(&exit2); 232 } 233 Bind(&exit2); 234 { 235 BRANCH(DoubleLessThan(*doubleLeft, *doubleRight), &leftLessRight, &leftNotLessRight); 236 } 237 } 238 } 239 } 240 Bind(&leftLessRight); 241 { 242 callback.ProfileBranch(true); 243 result = TaggedTrue(); 244 Jump(&exit); 245 } 246 Bind(&leftNotLessRight); 247 { 248 callback.ProfileBranch(false); 249 result = TaggedFalse(); 250 Jump(&exit); 251 } 252 Bind(&slowPath); 253 { 254 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 255 result = CallRuntime(glue, RTSTUB_ID(Less), { left, right }); 256 Jump(&exit); 257 } 258 Bind(&exit); 259 auto ret = *result; 260 env->SubCfgExit(); 261 return ret; 262} 263 264GateRef OperationsStubBuilder::LessEq(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 265{ 266 auto env = GetEnvironment(); 267 Label entry(env); 268 env->SubCfgEntry(&entry); 269 Label exit(env); 270 Label leftIsInt(env); 271 Label leftOrRightNotInt(env); 272 Label leftLessEqRight(env); 273 Label leftNotLessEqRight(env); 274 Label slowPath(env); 275 276 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 277 BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); 278 Bind(&leftIsInt); 279 { 280 Label rightIsInt(env); 281 BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); 282 Bind(&rightIsInt); 283 { 284 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 285 GateRef intLeft = TaggedGetInt(left); 286 GateRef intRight = TaggedGetInt(right); 287 BRANCH(Int32LessThanOrEqual(intLeft, intRight), &leftLessEqRight, &leftNotLessEqRight); 288 } 289 } 290 Bind(&leftOrRightNotInt); 291 { 292 Label leftIsNumber(env); 293 BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath); 294 Bind(&leftIsNumber); 295 { 296 Label rightIsNumber(env); 297 BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath); 298 Bind(&rightIsNumber); 299 { 300 // fast path 301 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); 302 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); 303 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType())); 304 Label leftIsInt1(env); 305 Label leftNotInt1(env); 306 Label exit1(env); 307 Label exit2(env); 308 Label rightIsInt1(env); 309 Label rightNotInt1(env); 310 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); 311 Bind(&leftIsInt1); 312 { 313 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); 314 Jump(&exit1); 315 } 316 Bind(&leftNotInt1); 317 { 318 curType = TaggedInt(PGOSampleType::DoubleType()); 319 doubleLeft = GetDoubleOfTDouble(left); 320 Jump(&exit1); 321 } 322 Bind(&exit1); 323 { 324 BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); 325 } 326 Bind(&rightIsInt1); 327 { 328 GateRef type = TaggedInt(PGOSampleType::IntType()); 329 COMBINE_TYPE_CALL_BACK(curType, type); 330 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); 331 Jump(&exit2); 332 } 333 Bind(&rightNotInt1); 334 { 335 GateRef type = TaggedInt(PGOSampleType::DoubleType()); 336 COMBINE_TYPE_CALL_BACK(curType, type); 337 doubleRight = GetDoubleOfTDouble(right); 338 Jump(&exit2); 339 } 340 Bind(&exit2); 341 { 342 BRANCH(DoubleLessThanOrEqual(*doubleLeft, *doubleRight), &leftLessEqRight, &leftNotLessEqRight); 343 } 344 } 345 } 346 } 347 Bind(&leftLessEqRight); 348 { 349 callback.ProfileBranch(true); 350 result = TaggedTrue(); 351 Jump(&exit); 352 } 353 Bind(&leftNotLessEqRight); 354 { 355 callback.ProfileBranch(false); 356 result = TaggedFalse(); 357 Jump(&exit); 358 } 359 Bind(&slowPath); 360 { 361 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 362 result = CallRuntime(glue, RTSTUB_ID(LessEq), { left, right }); 363 Jump(&exit); 364 } 365 Bind(&exit); 366 auto ret = *result; 367 env->SubCfgExit(); 368 return ret; 369} 370 371GateRef OperationsStubBuilder::Greater(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 372{ 373 auto env = GetEnvironment(); 374 Label entry(env); 375 env->SubCfgEntry(&entry); 376 Label exit(env); 377 Label leftIsInt(env); 378 Label leftOrRightNotInt(env); 379 Label leftGreaterRight(env); 380 Label leftNotGreaterRight(env); 381 Label slowPath(env); 382 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 383 BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); 384 Bind(&leftIsInt); 385 { 386 Label rightIsInt(env); 387 BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); 388 Bind(&rightIsInt); 389 { 390 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 391 GateRef intLeft = TaggedGetInt(left); 392 GateRef intRight = TaggedGetInt(right); 393 BRANCH(Int32GreaterThan(intLeft, intRight), &leftGreaterRight, &leftNotGreaterRight); 394 } 395 } 396 Bind(&leftOrRightNotInt); 397 { 398 Label leftIsNumber(env); 399 BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath); 400 Bind(&leftIsNumber); 401 { 402 Label rightIsNumber(env); 403 BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath); 404 Bind(&rightIsNumber); 405 { 406 // fast path 407 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); 408 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); 409 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType())); 410 Label leftIsInt1(env); 411 Label leftNotInt1(env); 412 Label exit1(env); 413 Label exit2(env); 414 Label rightIsInt1(env); 415 Label rightNotInt1(env); 416 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); 417 Bind(&leftIsInt1); 418 { 419 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); 420 Jump(&exit1); 421 } 422 Bind(&leftNotInt1); 423 { 424 curType = TaggedInt(PGOSampleType::DoubleType()); 425 doubleLeft = GetDoubleOfTDouble(left); 426 Jump(&exit1); 427 } 428 Bind(&exit1); 429 { 430 BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); 431 } 432 Bind(&rightIsInt1); 433 { 434 GateRef type = TaggedInt(PGOSampleType::IntType()); 435 COMBINE_TYPE_CALL_BACK(curType, type); 436 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); 437 Jump(&exit2); 438 } 439 Bind(&rightNotInt1); 440 { 441 GateRef type = TaggedInt(PGOSampleType::DoubleType()); 442 COMBINE_TYPE_CALL_BACK(curType, type); 443 doubleRight = GetDoubleOfTDouble(right); 444 Jump(&exit2); 445 } 446 Bind(&exit2); 447 { 448 BRANCH(DoubleGreaterThan(*doubleLeft, *doubleRight), &leftGreaterRight, &leftNotGreaterRight); 449 } 450 } 451 } 452 } 453 Bind(&leftGreaterRight); 454 { 455 callback.ProfileBranch(true); 456 result = TaggedTrue(); 457 Jump(&exit); 458 } 459 Bind(&leftNotGreaterRight); 460 { 461 callback.ProfileBranch(false); 462 result = TaggedFalse(); 463 Jump(&exit); 464 } 465 Bind(&slowPath); 466 { 467 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 468 result = CallRuntime(glue, RTSTUB_ID(Greater), { left, right }); 469 Jump(&exit); 470 } 471 Bind(&exit); 472 auto ret = *result; 473 env->SubCfgExit(); 474 return ret; 475} 476 477GateRef OperationsStubBuilder::GreaterEq(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 478{ 479 auto env = GetEnvironment(); 480 Label entry(env); 481 env->SubCfgEntry(&entry); 482 Label exit(env); 483 Label leftIsInt(env); 484 Label leftOrRightNotInt(env); 485 Label leftGreaterEqRight(env); 486 Label leftNotGreaterEQRight(env); 487 Label slowPath(env); 488 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 489 BRANCH(TaggedIsInt(left), &leftIsInt, &leftOrRightNotInt); 490 Bind(&leftIsInt); 491 { 492 Label rightIsInt(env); 493 BRANCH(TaggedIsInt(right), &rightIsInt, &leftOrRightNotInt); 494 Bind(&rightIsInt); 495 { 496 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 497 GateRef intLeft = TaggedGetInt(left); 498 GateRef intRight = TaggedGetInt(right); 499 BRANCH(Int32GreaterThanOrEqual(intLeft, intRight), &leftGreaterEqRight, &leftNotGreaterEQRight); 500 } 501 } 502 Bind(&leftOrRightNotInt); 503 { 504 Label leftIsNumber(env); 505 BRANCH(TaggedIsNumber(left), &leftIsNumber, &slowPath); 506 Bind(&leftIsNumber); 507 { 508 Label rightIsNumber(env); 509 BRANCH(TaggedIsNumber(right), &rightIsNumber, &slowPath); 510 Bind(&rightIsNumber); 511 { 512 // fast path 513 DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0)); 514 DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0)); 515 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::IntType())); 516 Label leftIsInt1(env); 517 Label leftNotInt1(env); 518 Label exit1(env); 519 Label exit2(env); 520 Label rightIsInt1(env); 521 Label rightNotInt1(env); 522 BRANCH(TaggedIsInt(left), &leftIsInt1, &leftNotInt1); 523 Bind(&leftIsInt1); 524 { 525 doubleLeft = ChangeInt32ToFloat64(TaggedGetInt(left)); 526 Jump(&exit1); 527 } 528 Bind(&leftNotInt1); 529 { 530 curType = TaggedInt(PGOSampleType::DoubleType()); 531 doubleLeft = GetDoubleOfTDouble(left); 532 Jump(&exit1); 533 } 534 Bind(&exit1); 535 { 536 BRANCH(TaggedIsInt(right), &rightIsInt1, &rightNotInt1); 537 } 538 Bind(&rightIsInt1); 539 { 540 GateRef type = TaggedInt(PGOSampleType::IntType()); 541 COMBINE_TYPE_CALL_BACK(curType, type); 542 doubleRight = ChangeInt32ToFloat64(TaggedGetInt(right)); 543 Jump(&exit2); 544 } 545 Bind(&rightNotInt1); 546 { 547 GateRef type = TaggedInt(PGOSampleType::DoubleType()); 548 COMBINE_TYPE_CALL_BACK(curType, type); 549 doubleRight = GetDoubleOfTDouble(right); 550 Jump(&exit2); 551 } 552 Bind(&exit2); 553 { 554 BRANCH(DoubleGreaterThanOrEqual(*doubleLeft, *doubleRight), 555 &leftGreaterEqRight, &leftNotGreaterEQRight); 556 } 557 } 558 } 559 } 560 Bind(&leftGreaterEqRight); 561 { 562 callback.ProfileBranch(true); 563 result = TaggedTrue(); 564 Jump(&exit); 565 } 566 Bind(&leftNotGreaterEQRight); 567 { 568 callback.ProfileBranch(false); 569 result = TaggedFalse(); 570 Jump(&exit); 571 } 572 Bind(&slowPath); 573 { 574 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 575 result = CallRuntime(glue, RTSTUB_ID(GreaterEq), { left, right }); 576 Jump(&exit); 577 } 578 Bind(&exit); 579 auto ret = *result; 580 env->SubCfgExit(); 581 return ret; 582} 583 584GateRef OperationsStubBuilder::Add(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 585{ 586 auto env = GetEnvironment(); 587 Label entry(env); 588 env->SubCfgEntry(&entry); 589 Label exit(env); 590 Label slowPath(env); 591 DEFVARIABLE(result, VariableType::JS_ANY(), FastAdd(glue, left, right, callback)); 592 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 593 Bind(&slowPath); 594 { 595 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 596 result = CallRuntime(glue, RTSTUB_ID(Add2), { left, right }); 597 Jump(&exit); 598 } 599 Bind(&exit); 600 auto ret = *result; 601 env->SubCfgExit(); 602 return ret; 603} 604 605GateRef OperationsStubBuilder::Sub(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 606{ 607 auto env = GetEnvironment(); 608 Label entry(env); 609 env->SubCfgEntry(&entry); 610 Label exit(env); 611 Label slowPath(env); 612 DEFVARIABLE(result, VariableType::JS_ANY(), FastSub(glue, left, right, callback)); 613 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 614 Bind(&slowPath); 615 { 616 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 617 result = CallRuntime(glue, RTSTUB_ID(Sub2), { left, right }); 618 Jump(&exit); 619 } 620 Bind(&exit); 621 auto ret = *result; 622 env->SubCfgExit(); 623 return ret; 624} 625 626GateRef OperationsStubBuilder::Mul(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 627{ 628 auto env = GetEnvironment(); 629 Label entry(env); 630 env->SubCfgEntry(&entry); 631 Label exit(env); 632 Label slowPath(env); 633 DEFVARIABLE(result, VariableType::JS_ANY(), FastMul(glue, left, right, callback)); 634 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 635 Bind(&slowPath); 636 { 637 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 638 result = CallRuntime(glue, RTSTUB_ID(Mul2), { left, right }); 639 Jump(&exit); 640 } 641 Bind(&exit); 642 auto ret = *result; 643 env->SubCfgExit(); 644 return ret; 645} 646 647GateRef OperationsStubBuilder::Div(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 648{ 649 auto env = GetEnvironment(); 650 Label entry(env); 651 env->SubCfgEntry(&entry); 652 Label exit(env); 653 Label slowPath(env); 654 DEFVARIABLE(result, VariableType::JS_ANY(), FastDiv(left, right, callback)); 655 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 656 Bind(&slowPath); 657 { 658 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 659 result = CallRuntime(glue, RTSTUB_ID(Div2), { left, right }); 660 Jump(&exit); 661 } 662 Bind(&exit); 663 auto ret = *result; 664 env->SubCfgExit(); 665 return ret; 666} 667 668GateRef OperationsStubBuilder::Mod(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 669{ 670 auto env = GetEnvironment(); 671 Label entry(env); 672 env->SubCfgEntry(&entry); 673 Label exit(env); 674 Label slowPath(env); 675 DEFVARIABLE(result, VariableType::JS_ANY(), FastMod(glue, left, right, callback)); 676 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 677 Bind(&slowPath); 678 { 679 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 680 result = CallRuntime(glue, RTSTUB_ID(Mod2), { left, right }); 681 Jump(&exit); 682 } 683 Bind(&exit); 684 auto ret = *result; 685 env->SubCfgExit(); 686 return ret; 687} 688 689GateRef OperationsStubBuilder::Shl(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 690{ 691 auto env = GetEnvironment(); 692 Label entry(env); 693 env->SubCfgEntry(&entry); 694 Label exit(env); 695 696 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 697 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); 698 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); 699 700 Label calculate(env); 701 Label leftIsNumber(env); 702 Label leftNotNumberOrRightNotNumber(env); 703 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); 704 Bind(&leftIsNumber); 705 { 706 Label rightIsNumber(env); 707 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); 708 Bind(&rightIsNumber); 709 { 710 Label leftIsInt(env); 711 Label leftIsDouble(env); 712 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble); 713 Bind(&leftIsInt); 714 { 715 Label rightIsInt(env); 716 Label rightIsDouble(env); 717 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 718 Bind(&rightIsInt); 719 { 720 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 721 opNumber0 = GetInt32OfTInt(left); 722 opNumber1 = GetInt32OfTInt(right); 723 Jump(&calculate); 724 } 725 Bind(&rightIsDouble); 726 { 727 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 728 GateRef rightDouble = GetDoubleOfTDouble(right); 729 opNumber0 = GetInt32OfTInt(left); 730 opNumber1 = DoubleToInt(glue, rightDouble); 731 Jump(&calculate); 732 } 733 } 734 Bind(&leftIsDouble); 735 { 736 Label rightIsInt(env); 737 Label rightIsDouble(env); 738 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 739 Bind(&rightIsInt); 740 { 741 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 742 GateRef leftDouble = GetDoubleOfTDouble(left); 743 opNumber0 = DoubleToInt(glue, leftDouble); 744 opNumber1 = GetInt32OfTInt(right); 745 Jump(&calculate); 746 } 747 Bind(&rightIsDouble); 748 { 749 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 750 GateRef rightDouble = GetDoubleOfTDouble(right); 751 GateRef leftDouble = GetDoubleOfTDouble(left); 752 opNumber0 = DoubleToInt(glue, leftDouble); 753 opNumber1 = DoubleToInt(glue, rightDouble); 754 Jump(&calculate); 755 } 756 } 757 } 758 } 759 // slow path 760 Bind(&leftNotNumberOrRightNotNumber); 761 { 762 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 763 result = CallRuntime(glue, RTSTUB_ID(Shl2), { left, right }); 764 Jump(&exit); 765 } 766 Bind(&calculate); 767 { 768 GateRef shift = Int32And(*opNumber1, Int32(0x1f)); 769 GateRef val = Int32LSL(*opNumber0, shift); 770 result = IntToTaggedPtr(val); 771 Jump(&exit); 772 } 773 Bind(&exit); 774 auto ret = *result; 775 env->SubCfgExit(); 776 return ret; 777} 778 779GateRef OperationsStubBuilder::Shr(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 780{ 781 auto env = GetEnvironment(); 782 Label entry(env); 783 env->SubCfgEntry(&entry); 784 Label exit(env); 785 786 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 787 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); 788 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); 789 DEFVARIABLE(curType, VariableType::INT64(), TaggedInt(PGOSampleType::None())); 790 791 Label doShr(env); 792 Label overflow(env); 793 Label notOverflow(env); 794 Label leftIsNumber(env); 795 Label leftNotNumberOrRightNotNumber(env); 796 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); 797 Bind(&leftIsNumber); 798 { 799 Label rightIsNumber(env); 800 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); 801 Bind(&rightIsNumber); 802 { 803 Label leftIsInt(env); 804 Label leftIsDouble(env); 805 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble); 806 Bind(&leftIsInt); 807 { 808 Label rightIsInt(env); 809 Label rightIsDouble(env); 810 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 811 Bind(&rightIsInt); 812 { 813 curType = TaggedInt(PGOSampleType::IntType()); 814 opNumber0 = GetInt32OfTInt(left); 815 opNumber1 = GetInt32OfTInt(right); 816 Jump(&doShr); 817 } 818 Bind(&rightIsDouble); 819 { 820 curType = TaggedInt(PGOSampleType::NumberType()); 821 GateRef rightDouble = GetDoubleOfTDouble(right); 822 opNumber0 = GetInt32OfTInt(left); 823 opNumber1 = DoubleToInt(glue, rightDouble); 824 Jump(&doShr); 825 } 826 } 827 Bind(&leftIsDouble); 828 { 829 Label rightIsInt(env); 830 Label rightIsDouble(env); 831 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 832 Bind(&rightIsInt); 833 { 834 curType = TaggedInt(PGOSampleType::NumberType()); 835 GateRef leftDouble = GetDoubleOfTDouble(left); 836 opNumber0 = DoubleToInt(glue, leftDouble); 837 opNumber1 = GetInt32OfTInt(right); 838 Jump(&doShr); 839 } 840 Bind(&rightIsDouble); 841 { 842 curType = TaggedInt(PGOSampleType::DoubleType()); 843 GateRef rightDouble = GetDoubleOfTDouble(right); 844 GateRef leftDouble = GetDoubleOfTDouble(left); 845 opNumber0 = DoubleToInt(glue, leftDouble); 846 opNumber1 = DoubleToInt(glue, rightDouble); 847 Jump(&doShr); 848 } 849 } 850 } 851 } 852 // slow path 853 Bind(&leftNotNumberOrRightNotNumber); 854 { 855 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 856 result = CallRuntime(glue, RTSTUB_ID(Shr2), { left, right }); 857 Jump(&exit); 858 } 859 Bind(&doShr); 860 { 861 GateRef shift = Int32And(*opNumber1, Int32(0x1f)); 862 GateRef val = Int32LSR(*opNumber0, shift); 863 auto condition = Int32UnsignedGreaterThan(val, Int32(INT32_MAX)); 864 BRANCH(condition, &overflow, ¬Overflow); 865 Bind(&overflow); 866 { 867 callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType())); 868 result = DoubleToTaggedDoublePtr(ChangeUInt32ToFloat64(val)); 869 Jump(&exit); 870 } 871 Bind(¬Overflow); 872 { 873 callback.ProfileOpType(*curType); 874 result = IntToTaggedPtr(val); 875 Jump(&exit); 876 } 877 } 878 Bind(&exit); 879 auto ret = *result; 880 env->SubCfgExit(); 881 return ret; 882} 883 884GateRef OperationsStubBuilder::Ashr(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 885{ 886 auto env = GetEnvironment(); 887 Label entry(env); 888 env->SubCfgEntry(&entry); 889 Label exit(env); 890 891 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 892 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); 893 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); 894 895 Label calculate(env); 896 Label leftIsNumber(env); 897 Label leftNotNumberOrRightNotNumber(env); 898 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); 899 Bind(&leftIsNumber); 900 { 901 Label rightIsNumber(env); 902 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); 903 Bind(&rightIsNumber); 904 { 905 Label leftIsInt(env); 906 Label leftIsDouble(env); 907 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble); 908 Bind(&leftIsInt); 909 { 910 Label rightIsInt(env); 911 Label rightIsDouble(env); 912 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 913 Bind(&rightIsInt); 914 { 915 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 916 opNumber0 = GetInt32OfTInt(left); 917 opNumber1 = GetInt32OfTInt(right); 918 Jump(&calculate); 919 } 920 Bind(&rightIsDouble); 921 { 922 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 923 GateRef rightDouble = GetDoubleOfTDouble(right); 924 opNumber0 = GetInt32OfTInt(left); 925 opNumber1 = DoubleToInt(glue, rightDouble); 926 Jump(&calculate); 927 } 928 } 929 Bind(&leftIsDouble); 930 { 931 Label rightIsInt(env); 932 Label rightIsDouble(env); 933 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 934 Bind(&rightIsInt); 935 { 936 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 937 GateRef leftDouble = GetDoubleOfTDouble(left); 938 opNumber0 = DoubleToInt(glue, leftDouble); 939 opNumber1 = GetInt32OfTInt(right); 940 Jump(&calculate); 941 } 942 Bind(&rightIsDouble); 943 { 944 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 945 GateRef rightDouble = GetDoubleOfTDouble(right); 946 GateRef leftDouble = GetDoubleOfTDouble(left); 947 opNumber0 = DoubleToInt(glue, leftDouble); 948 opNumber1 = DoubleToInt(glue, rightDouble); 949 Jump(&calculate); 950 } 951 } 952 } 953 } 954 // slow path 955 Bind(&leftNotNumberOrRightNotNumber); 956 { 957 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 958 result = CallRuntime(glue, RTSTUB_ID(Ashr2), { left, right }); 959 Jump(&exit); 960 } 961 Bind(&calculate); 962 { 963 GateRef shift = Int32And(*opNumber1, Int32(0x1f)); 964 GateRef val = Int32ASR(*opNumber0, shift); 965 result = IntToTaggedPtr(val); 966 Jump(&exit); 967 } 968 Bind(&exit); 969 auto ret = *result; 970 env->SubCfgExit(); 971 return ret; 972} 973 974GateRef OperationsStubBuilder::And(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 975{ 976 auto env = GetEnvironment(); 977 Label entry(env); 978 env->SubCfgEntry(&entry); 979 Label exit(env); 980 981 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 982 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); 983 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); 984 985 Label calculate(env); 986 Label leftIsNumber(env); 987 Label leftNotNumberOrRightNotNumber(env); 988 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); 989 Bind(&leftIsNumber); 990 { 991 Label rightIsNumber(env); 992 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); 993 Bind(&rightIsNumber); 994 { 995 Label leftIsInt(env); 996 Label leftIsDouble(env); 997 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble); 998 Bind(&leftIsInt); 999 { 1000 Label rightIsInt(env); 1001 Label rightIsDouble(env); 1002 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 1003 Bind(&rightIsInt); 1004 { 1005 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 1006 opNumber0 = GetInt32OfTInt(left); 1007 opNumber1 = GetInt32OfTInt(right); 1008 Jump(&calculate); 1009 } 1010 Bind(&rightIsDouble); 1011 { 1012 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 1013 opNumber0 = GetInt32OfTInt(left); 1014 GateRef rightDouble = GetDoubleOfTDouble(right); 1015 opNumber1 = DoubleToInt(glue, rightDouble); 1016 Jump(&calculate); 1017 } 1018 } 1019 Bind(&leftIsDouble); 1020 { 1021 Label rightIsInt(env); 1022 Label rightIsDouble(env); 1023 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 1024 Bind(&rightIsInt); 1025 { 1026 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 1027 GateRef leftDouble = GetDoubleOfTDouble(left); 1028 opNumber0 = DoubleToInt(glue, leftDouble); 1029 opNumber1 = GetInt32OfTInt(right); 1030 Jump(&calculate); 1031 } 1032 Bind(&rightIsDouble); 1033 { 1034 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 1035 GateRef rightDouble = GetDoubleOfTDouble(right); 1036 GateRef leftDouble = GetDoubleOfTDouble(left); 1037 opNumber0 = DoubleToInt(glue, leftDouble); 1038 opNumber1 = DoubleToInt(glue, rightDouble); 1039 Jump(&calculate); 1040 } 1041 } 1042 } 1043 } 1044 // slow path 1045 Bind(&leftNotNumberOrRightNotNumber); 1046 { 1047 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 1048 result = CallRuntime(glue, RTSTUB_ID(And2), { left, right }); 1049 Jump(&exit); 1050 } 1051 Bind(&calculate); 1052 { 1053 GateRef val = Int32And(*opNumber0, *opNumber1); 1054 result = IntToTaggedPtr(val); 1055 Jump(&exit); 1056 } 1057 Bind(&exit); 1058 auto ret = *result; 1059 env->SubCfgExit(); 1060 return ret; 1061} 1062 1063GateRef OperationsStubBuilder::Or(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 1064{ 1065 auto env = GetEnvironment(); 1066 Label entry(env); 1067 env->SubCfgEntry(&entry); 1068 Label exit(env); 1069 1070 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 1071 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); 1072 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); 1073 1074 Label calculate(env); 1075 Label leftIsNumber(env); 1076 Label leftNotNumberOrRightNotNumber(env); 1077 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); 1078 Bind(&leftIsNumber); 1079 { 1080 Label rightIsNumber(env); 1081 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); 1082 Bind(&rightIsNumber); 1083 { 1084 Label leftIsInt(env); 1085 Label leftIsDouble(env); 1086 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble); 1087 Bind(&leftIsInt); 1088 { 1089 Label rightIsInt(env); 1090 Label rightIsDouble(env); 1091 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 1092 Bind(&rightIsInt); 1093 { 1094 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 1095 opNumber0 = GetInt32OfTInt(left); 1096 opNumber1 = GetInt32OfTInt(right); 1097 Jump(&calculate); 1098 } 1099 Bind(&rightIsDouble); 1100 { 1101 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 1102 GateRef rightDouble = GetDoubleOfTDouble(right); 1103 opNumber0 = GetInt32OfTInt(left); 1104 opNumber1 = DoubleToInt(glue, rightDouble); 1105 Jump(&calculate); 1106 } 1107 } 1108 Bind(&leftIsDouble); 1109 { 1110 Label rightIsInt(env); 1111 Label rightIsDouble(env); 1112 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 1113 Bind(&rightIsInt); 1114 { 1115 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 1116 GateRef leftDouble = GetDoubleOfTDouble(left); 1117 opNumber0 = DoubleToInt(glue, leftDouble); 1118 opNumber1 = GetInt32OfTInt(right); 1119 Jump(&calculate); 1120 } 1121 Bind(&rightIsDouble); 1122 { 1123 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 1124 GateRef rightDouble = GetDoubleOfTDouble(right); 1125 GateRef leftDouble = GetDoubleOfTDouble(left); 1126 opNumber0 = DoubleToInt(glue, leftDouble); 1127 opNumber1 = DoubleToInt(glue, rightDouble); 1128 Jump(&calculate); 1129 } 1130 } 1131 } 1132 } 1133 // slow path 1134 Bind(&leftNotNumberOrRightNotNumber); 1135 { 1136 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 1137 result = CallRuntime(glue, RTSTUB_ID(Or2), { left, right }); 1138 Jump(&exit); 1139 } 1140 Bind(&calculate); 1141 { 1142 GateRef val = Int32Or(*opNumber0, *opNumber1); 1143 result = IntToTaggedPtr(val); 1144 Jump(&exit); 1145 } 1146 Bind(&exit); 1147 auto ret = *result; 1148 env->SubCfgExit(); 1149 return ret; 1150} 1151 1152GateRef OperationsStubBuilder::Xor(GateRef glue, GateRef left, GateRef right, ProfileOperation callback) 1153{ 1154 auto env = GetEnvironment(); 1155 Label entry(env); 1156 env->SubCfgEntry(&entry); 1157 Label exit(env); 1158 1159 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 1160 DEFVARIABLE(opNumber0, VariableType::INT32(), Int32(0)); 1161 DEFVARIABLE(opNumber1, VariableType::INT32(), Int32(0)); 1162 1163 Label calculate(env); 1164 Label leftIsNumber(env); 1165 Label leftNotNumberOrRightNotNumber(env); 1166 BRANCH(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber); 1167 Bind(&leftIsNumber); 1168 { 1169 Label rightIsNumber(env); 1170 BRANCH(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber); 1171 Bind(&rightIsNumber); 1172 { 1173 Label leftIsInt(env); 1174 Label leftIsDouble(env); 1175 BRANCH(TaggedIsInt(left), &leftIsInt, &leftIsDouble); 1176 Bind(&leftIsInt); 1177 { 1178 Label rightIsInt(env); 1179 Label rightIsDouble(env); 1180 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 1181 Bind(&rightIsInt); 1182 { 1183 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 1184 opNumber0 = GetInt32OfTInt(left); 1185 opNumber1 = GetInt32OfTInt(right); 1186 Jump(&calculate); 1187 } 1188 Bind(&rightIsDouble); 1189 { 1190 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 1191 GateRef rightDouble = GetDoubleOfTDouble(right); 1192 opNumber0 = GetInt32OfTInt(left); 1193 opNumber1 = DoubleToInt(glue, rightDouble); 1194 Jump(&calculate); 1195 } 1196 } 1197 Bind(&leftIsDouble); 1198 { 1199 Label rightIsInt(env); 1200 Label rightIsDouble(env); 1201 BRANCH(TaggedIsInt(right), &rightIsInt, &rightIsDouble); 1202 Bind(&rightIsInt); 1203 { 1204 callback.ProfileOpType(TaggedInt(PGOSampleType::NumberType())); 1205 GateRef leftDouble = GetDoubleOfTDouble(left); 1206 opNumber0 = DoubleToInt(glue, leftDouble); 1207 opNumber1 = GetInt32OfTInt(right); 1208 Jump(&calculate); 1209 } 1210 Bind(&rightIsDouble); 1211 { 1212 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 1213 GateRef rightDouble = GetDoubleOfTDouble(right); 1214 GateRef leftDouble = GetDoubleOfTDouble(left); 1215 opNumber0 = DoubleToInt(glue, leftDouble); 1216 opNumber1 = DoubleToInt(glue, rightDouble); 1217 Jump(&calculate); 1218 } 1219 } 1220 } 1221 } 1222 // slow path 1223 Bind(&leftNotNumberOrRightNotNumber); 1224 { 1225 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 1226 result = CallRuntime(glue, RTSTUB_ID(Xor2), { left, right }); 1227 Jump(&exit); 1228 } 1229 Bind(&calculate); 1230 { 1231 GateRef val = Int32Xor(*opNumber0, *opNumber1); 1232 result = IntToTaggedPtr(val); 1233 Jump(&exit); 1234 } 1235 Bind(&exit); 1236 auto ret = *result; 1237 env->SubCfgExit(); 1238 return ret; 1239} 1240 1241GateRef OperationsStubBuilder::Inc(GateRef glue, GateRef value, ProfileOperation callback) 1242{ 1243 auto env = GetEnvironment(); 1244 Label entry(env); 1245 env->SubCfgEntry(&entry); 1246 Label exit(env); 1247 1248 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 1249 Label valueIsInt(env); 1250 Label valueNotInt(env); 1251 Label slowPath(env); 1252 BRANCH(TaggedIsInt(value), &valueIsInt, &valueNotInt); 1253 Bind(&valueIsInt); 1254 { 1255 GateRef valueInt = GetInt32OfTInt(value); 1256 Label valueNoOverflow(env); 1257 BRANCH(Int32Equal(valueInt, Int32(INT32_MAX)), &valueNotInt, &valueNoOverflow); 1258 Bind(&valueNoOverflow); 1259 { 1260 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 1261 result = IntToTaggedPtr(Int32Add(valueInt, Int32(1))); 1262 Jump(&exit); 1263 } 1264 } 1265 Bind(&valueNotInt); 1266 { 1267 Label valueIsDouble(env); 1268 BRANCH(TaggedIsDouble(value), &valueIsDouble, &slowPath); 1269 Bind(&valueIsDouble); 1270 { 1271 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 1272 GateRef valueDouble = GetDoubleOfTDouble(value); 1273 result = DoubleToTaggedDoublePtr(DoubleAdd(valueDouble, Double(1.0))); 1274 Jump(&exit); 1275 } 1276 } 1277 Bind(&slowPath); 1278 { 1279 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 1280 result = CallRuntime(glue, RTSTUB_ID(Inc), { value }); 1281 Jump(&exit); 1282 } 1283 Bind(&exit); 1284 auto ret = *result; 1285 env->SubCfgExit(); 1286 return ret; 1287} 1288 1289GateRef OperationsStubBuilder::Dec(GateRef glue, GateRef value, ProfileOperation callback) 1290{ 1291 auto env = GetEnvironment(); 1292 Label entry(env); 1293 env->SubCfgEntry(&entry); 1294 Label exit(env); 1295 1296 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 1297 Label valueIsInt(env); 1298 Label valueNotInt(env); 1299 Label slowPath(env); 1300 BRANCH(TaggedIsInt(value), &valueIsInt, &valueNotInt); 1301 Bind(&valueIsInt); 1302 { 1303 GateRef valueInt = GetInt32OfTInt(value); 1304 Label valueNoOverflow(env); 1305 BRANCH(Int32Equal(valueInt, Int32(INT32_MIN)), &valueNotInt, &valueNoOverflow); 1306 Bind(&valueNoOverflow); 1307 { 1308 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 1309 result = IntToTaggedPtr(Int32Sub(valueInt, Int32(1))); 1310 Jump(&exit); 1311 } 1312 } 1313 Bind(&valueNotInt); 1314 { 1315 Label valueIsDouble(env); 1316 BRANCH(TaggedIsDouble(value), &valueIsDouble, &slowPath); 1317 Bind(&valueIsDouble); 1318 { 1319 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 1320 GateRef valueDouble = GetDoubleOfTDouble(value); 1321 result = DoubleToTaggedDoublePtr(DoubleSub(valueDouble, Double(1.0))); 1322 Jump(&exit); 1323 } 1324 } 1325 Bind(&slowPath); 1326 { 1327 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 1328 result = CallRuntime(glue, RTSTUB_ID(Dec), { value }); 1329 Jump(&exit); 1330 } 1331 1332 Bind(&exit); 1333 auto ret = *result; 1334 env->SubCfgExit(); 1335 return ret; 1336} 1337 1338GateRef OperationsStubBuilder::Neg(GateRef glue, GateRef value, ProfileOperation callback) 1339{ 1340 auto env = GetEnvironment(); 1341 Label entry(env); 1342 env->SubCfgEntry(&entry); 1343 Label exit(env); 1344 1345 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 1346 Label valueIsInt(env); 1347 Label valueNotInt(env); 1348 BRANCH(TaggedIsInt(value), &valueIsInt, &valueNotInt); 1349 Bind(&valueIsInt); 1350 { 1351 GateRef valueInt = GetInt32OfTInt(value); 1352 Label valueIsZero(env); 1353 Label valueNotZero(env); 1354 BRANCH(Int32Equal(valueInt, Int32(0)), &valueIsZero, &valueNotZero); 1355 Bind(&valueIsZero); 1356 { 1357 callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType())); 1358 result = DoubleToTaggedDoublePtr(Double(-0.0)); 1359 Jump(&exit); 1360 } 1361 Bind(&valueNotZero); 1362 { 1363 Label valueIsInt32Min(env); 1364 Label valueNotInt32Min(env); 1365 BRANCH(Int32Equal(valueInt, Int32(INT32_MIN)), &valueIsInt32Min, &valueNotInt32Min); 1366 Bind(&valueIsInt32Min); 1367 { 1368 callback.ProfileOpType(TaggedInt(PGOSampleType::IntOverFlowType())); 1369 result = DoubleToTaggedDoublePtr(Double(-static_cast<double>(INT32_MIN))); 1370 Jump(&exit); 1371 } 1372 Bind(&valueNotInt32Min); 1373 { 1374 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 1375 result = IntToTaggedPtr(Int32Sub(Int32(0), valueInt)); 1376 Jump(&exit); 1377 } 1378 } 1379 } 1380 Bind(&valueNotInt); 1381 { 1382 Label valueIsDouble(env); 1383 Label valueNotDouble(env); 1384 BRANCH(TaggedIsDouble(value), &valueIsDouble, &valueNotDouble); 1385 Bind(&valueIsDouble); 1386 { 1387 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 1388 GateRef valueDouble = GetDoubleOfTDouble(value); 1389 result = DoubleToTaggedDoublePtr(DoubleMul(Double(-1), valueDouble)); 1390 Jump(&exit); 1391 } 1392 Bind(&valueNotDouble); 1393 { 1394 // slow path 1395 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 1396 result = CallRuntime(glue, RTSTUB_ID(Neg), { value }); 1397 Jump(&exit); 1398 } 1399 } 1400 Bind(&exit); 1401 auto ret = *result; 1402 env->SubCfgExit(); 1403 return ret; 1404} 1405 1406GateRef OperationsStubBuilder::Not(GateRef glue, GateRef value, ProfileOperation callback) 1407{ 1408 auto env = GetEnvironment(); 1409 Label entry(env); 1410 env->SubCfgEntry(&entry); 1411 Label exit(env); 1412 1413 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 1414 Label numberIsInt(env); 1415 Label numberNotInt(env); 1416 BRANCH(TaggedIsInt(value), &numberIsInt, &numberNotInt); 1417 Bind(&numberIsInt); 1418 { 1419 callback.ProfileOpType(TaggedInt(PGOSampleType::IntType())); 1420 GateRef valueInt = GetInt32OfTInt(value); 1421 result = IntToTaggedPtr(Int32Not(valueInt)); 1422 Jump(&exit); 1423 } 1424 Bind(&numberNotInt); 1425 { 1426 Label numberIsDouble(env); 1427 Label numberNotDouble(env); 1428 BRANCH(TaggedIsDouble(value), &numberIsDouble, &numberNotDouble); 1429 Bind(&numberIsDouble); 1430 { 1431 callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); 1432 GateRef valueDouble = GetDoubleOfTDouble(value); 1433 result = IntToTaggedPtr(Int32Not(DoubleToInt(glue, valueDouble))); 1434 Jump(&exit); 1435 } 1436 Bind(&numberNotDouble); 1437 { 1438 // slow path 1439 callback.ProfileOpType(TaggedInt(PGOSampleType::AnyType())); 1440 result = CallRuntime(glue, RTSTUB_ID(Not), { value }); 1441 Jump(&exit); 1442 } 1443 } 1444 Bind(&exit); 1445 auto ret = *result; 1446 env->SubCfgExit(); 1447 return ret; 1448} 1449} // namespace panda::ecmascript::kungfu 1450