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#include "ecmascript/compiler/access_object_stub_builder.h" 16#include "ecmascript/compiler/ic_stub_builder.h" 17#include "ecmascript/compiler/interpreter_stub-inl.h" 18#include "ecmascript/compiler/profiler_stub_builder.h" 19#include "ecmascript/compiler/rt_call_signature.h" 20#include "ecmascript/compiler/stub_builder-inl.h" 21#include "ecmascript/ic/profile_type_info.h" 22 23namespace panda::ecmascript::kungfu { 24GateRef AccessObjectStubBuilder::LoadObjByName(GateRef glue, GateRef receiver, GateRef prop, const StringIdInfo &info, 25 GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) 26{ 27 auto env = GetEnvironment(); 28 Label entry(env); 29 env->SubCfgEntry(&entry); 30 Label exit(env); 31 Label tryFastPath(env); 32 Label slowPath(env); 33 Label tryPreDump(env); 34 35 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 36 GateRef value = 0; 37 ICStubBuilder builder(this); 38 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId); 39 builder.LoadICByName(&result, &tryFastPath, &tryPreDump, &exit, callback); 40 Bind(&tryFastPath); 41 { 42 GateRef propKey = ResolvePropKey(glue, prop, info); 43 result = GetPropertyByName(glue, receiver, propKey, callback, True()); 44 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 45 } 46 Bind(&tryPreDump); 47 { 48 callback.TryPreDump(); 49 Jump(&slowPath); 50 } 51 Bind(&slowPath); 52 { 53 GateRef propKey = ResolvePropKey(glue, prop, info); 54 result = 55 CallRuntime(glue, RTSTUB_ID(LoadICByName), {profileTypeInfo, receiver, propKey, IntToTaggedInt(slotId)}); 56 Jump(&exit); 57 } 58 Bind(&exit); 59 auto ret = *result; 60 env->SubCfgExit(); 61 return ret; 62} 63 64GateRef AccessObjectStubBuilder::LoadPrivatePropertyByName( 65 GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) 66{ 67 auto env = GetEnvironment(); 68 Label entry(env); 69 env->SubCfgEntry(&entry); 70 Label exit(env); 71 Label tryFastPath(env); 72 Label slowPath(env); 73 Label tryPreDump(env); 74 75 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 76 GateRef value = 0; 77 ICStubBuilder builder(this); 78 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId); 79 builder.LoadICByName(&result, &tryFastPath, &tryPreDump, &exit, callback); 80 Bind(&tryFastPath); 81 { 82 result = GetPropertyByName(glue, receiver, key, callback, True()); 83 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 84 } 85 Bind(&tryPreDump); 86 { 87 callback.TryPreDump(); 88 Jump(&slowPath); 89 } 90 Bind(&slowPath); 91 { 92 result = CallRuntime(glue, RTSTUB_ID(LoadICByName), {profileTypeInfo, receiver, key, IntToTaggedInt(slotId)}); 93 Jump(&exit); 94 } 95 Bind(&exit); 96 auto ret = *result; 97 env->SubCfgExit(); 98 return ret; 99} 100 101// Used for deprecated bytecodes which will not support ic 102GateRef AccessObjectStubBuilder::DeprecatedLoadObjByName(GateRef glue, GateRef receiver, GateRef propKey) 103{ 104 auto env = GetEnvironment(); 105 Label entry(env); 106 env->SubCfgEntry(&entry); 107 Label exit(env); 108 Label fastPath(env); 109 Label slowPath(env); 110 111 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 112 BRANCH(TaggedIsHeapObject(receiver), &fastPath, &slowPath); 113 Bind(&fastPath); 114 { 115 result = GetPropertyByName(glue, receiver, propKey, ProfileOperation(), True()); 116 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 117 } 118 Bind(&slowPath); 119 { 120 result = CallRuntime(glue, RTSTUB_ID(LoadICByName), 121 { Undefined(), receiver, propKey, IntToTaggedInt(Int32(0xFF)) }); // 0xFF: invalid slot id 122 Jump(&exit); 123 } 124 Bind(&exit); 125 auto ret = *result; 126 env->SubCfgExit(); 127 return ret; 128} 129 130GateRef AccessObjectStubBuilder::StoreObjByName(GateRef glue, GateRef receiver, GateRef prop, const StringIdInfo &info, 131 GateRef value, GateRef profileTypeInfo, GateRef slotId, 132 ProfileOperation callback) 133{ 134 auto env = GetEnvironment(); 135 Label entry(env); 136 env->SubCfgEntry(&entry); 137 Label exit(env); 138 Label tryFastPath(env); 139 Label slowPath(env); 140 Label tryPreDump(env); 141 142 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 143 ICStubBuilder builder(this); 144 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, callback); 145 builder.StoreICByName(&result, &tryFastPath, &tryPreDump, &exit); 146 Bind(&tryFastPath); 147 { 148 GateRef propKey = ResolvePropKey(glue, prop, info); 149 result = SetPropertyByName(glue, receiver, propKey, value, false, True(), callback); 150 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 151 } 152 Bind(&tryPreDump); 153 { 154 callback.TryPreDump(); 155 Jump(&slowPath); 156 } 157 Bind(&slowPath); 158 { 159 GateRef propKey = ResolvePropKey(glue, prop, info); 160 result = CallRuntime( 161 glue, RTSTUB_ID(StoreICByName), {profileTypeInfo, receiver, propKey, value, IntToTaggedInt(slotId)}); 162 Jump(&exit); 163 } 164 165 Bind(&exit); 166 auto ret = *result; 167 env->SubCfgExit(); 168 return ret; 169} 170 171GateRef AccessObjectStubBuilder::StorePrivatePropertyByName(GateRef glue, 172 GateRef receiver, 173 GateRef key, 174 GateRef value, 175 GateRef profileTypeInfo, 176 GateRef slotId, 177 ProfileOperation callback) 178{ 179 auto env = GetEnvironment(); 180 Label entry(env); 181 env->SubCfgEntry(&entry); 182 Label exit(env); 183 Label tryFastPath(env); 184 Label slowPath(env); 185 Label tryPreDump(env); 186 187 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 188 ICStubBuilder builder(this); 189 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, callback); 190 builder.StoreICByName(&result, &tryFastPath, &tryPreDump, &exit); 191 Bind(&tryFastPath); 192 { 193 result = SetPropertyByName(glue, receiver, key, value, false, True(), callback); 194 Branch(TaggedIsHole(*result), &slowPath, &exit); 195 } 196 Bind(&tryPreDump); 197 { 198 callback.TryPreDump(); 199 Jump(&slowPath); 200 } 201 Bind(&slowPath); 202 { 203 result = CallRuntime( 204 glue, RTSTUB_ID(StoreICByName), {profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId)}); 205 Jump(&exit); 206 } 207 208 Bind(&exit); 209 auto ret = *result; 210 env->SubCfgExit(); 211 return ret; 212} 213 214GateRef AccessObjectStubBuilder::ResolvePropKey(GateRef glue, GateRef prop, const StringIdInfo &info) 215{ 216 if (jsFunc_ != Circuit::NullGate()) { 217 GateRef constpool = GetConstPoolFromFunction(jsFunc_); 218 return GetStringFromConstPool(glue, constpool, ChangeIntPtrToInt32(prop)); 219 } 220 if (!info.IsValid()) { 221 return prop; 222 } 223 ASSERT(info.IsValid()); 224 InterpreterToolsStubBuilder builder(GetCallSignature(), GetEnvironment()); 225 GateRef stringId = builder.GetStringId(info); 226 return GetStringFromConstPool(glue, info.GetConstantPool(), stringId); 227} 228 229GateRef AccessObjectStubBuilder::LoadObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef profileTypeInfo, 230 GateRef slotId, ProfileOperation callback) 231{ 232 auto env = GetEnvironment(); 233 Label entry(env); 234 env->SubCfgEntry(&entry); 235 Label exit(env); 236 Label tryFastPath(env); 237 Label slowPath(env); 238 Label tryPreDump(env); 239 240 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 241 GateRef value = 0; 242 ICStubBuilder builder(this); 243 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key); 244 builder.LoadICByValue(&result, &tryFastPath, &tryPreDump, &exit, callback); 245 Bind(&tryFastPath); 246 { 247 result = GetPropertyByValue(glue, receiver, key, callback); 248 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 249 } 250 Bind(&tryPreDump); 251 { 252 callback.TryPreDump(); 253 Jump(&slowPath); 254 } 255 Bind(&slowPath); 256 { 257 result = CallRuntime(glue, RTSTUB_ID(LoadICByValue), {profileTypeInfo, receiver, key, IntToTaggedInt(slotId)}); 258 Jump(&exit); 259 } 260 Bind(&exit); 261 auto ret = *result; 262 env->SubCfgExit(); 263 return ret; 264} 265 266// Used for deprecated bytecodes which will not support ic 267GateRef AccessObjectStubBuilder::DeprecatedLoadObjByValue(GateRef glue, GateRef receiver, GateRef key) 268{ 269 auto env = GetEnvironment(); 270 Label entry(env); 271 env->SubCfgEntry(&entry); 272 Label exit(env); 273 Label fastPath(env); 274 Label slowPath(env); 275 276 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 277 BRANCH(TaggedIsHeapObject(receiver), &fastPath, &slowPath); 278 Bind(&fastPath); 279 { 280 result = GetPropertyByValue(glue, receiver, key, ProfileOperation()); 281 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 282 } 283 Bind(&slowPath); 284 { 285 result = CallRuntime(glue, RTSTUB_ID(LoadICByValue), 286 { Undefined(), receiver, key, IntToTaggedInt(Int32(0xFF)) }); // 0xFF: invalied slot id 287 Jump(&exit); 288 } 289 Bind(&exit); 290 auto ret = *result; 291 env->SubCfgExit(); 292 return ret; 293} 294 295GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, 296 GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) 297{ 298 auto env = GetEnvironment(); 299 Label entry(env); 300 env->SubCfgEntry(&entry); 301 Label exit(env); 302 Label tryFastPath(env); 303 Label slowPath(env); 304 Label tryPreDump(env); 305 306 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 307 ICStubBuilder builder(this); 308 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, key, callback); 309 builder.StoreICByValue(&result, &tryFastPath, &tryPreDump, &exit); 310 Bind(&tryFastPath); 311 { 312 result = SetPropertyByValue(glue, receiver, key, value, false, callback); 313 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 314 } 315 Bind(&tryPreDump); 316 { 317 callback.TryPreDump(); 318 Jump(&slowPath); 319 } 320 Bind(&slowPath); 321 { 322 result = CallRuntime( 323 glue, RTSTUB_ID(StoreICByValue), {profileTypeInfo, receiver, key, value, IntToTaggedInt(slotId)}); 324 Jump(&exit); 325 } 326 Bind(&exit); 327 auto ret = *result; 328 env->SubCfgExit(); 329 return ret; 330} 331 332GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, 333 GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) 334{ 335 auto env = GetEnvironment(); 336 Label entry(env); 337 env->SubCfgEntry(&entry); 338 Label exit(env); 339 Label tryFastPath(env); 340 Label slowPath(env); 341 Label tryPreDump(env); 342 343 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 344 ICStubBuilder builder(this); 345 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, IntToTaggedPtr(index), callback); 346 builder.StoreICByValue(&result, &tryFastPath, &tryPreDump, &exit); 347 Bind(&tryFastPath); 348 { 349 Label isHeapObject(env); 350 BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); 351 Bind(&isHeapObject); 352 Label notClassConstructor(env); 353 BRANCH(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); 354 Bind(¬ClassConstructor); 355 Label notClassPrototype(env); 356 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); 357 Bind(¬ClassPrototype); 358 result = SetPropertyByIndex(glue, receiver, index, value, true); 359 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 360 } 361 Bind(&tryPreDump); 362 { 363 callback.TryPreDump(); 364 Jump(&slowPath); 365 } 366 Bind(&slowPath); 367 { 368 result = CallRuntime(glue, 369 RTSTUB_ID(StoreOwnICByValue), 370 {profileTypeInfo, receiver, IntToTaggedInt(index), value, IntToTaggedInt(slotId)}); 371 Jump(&exit); 372 } 373 Bind(&exit); 374 auto ret = *result; 375 env->SubCfgExit(); 376 return ret; 377} 378 379GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info, 380 GateRef profileTypeInfo, GateRef slotId, 381 ProfileOperation callback) 382{ 383 auto env = GetEnvironment(); 384 Label entry(env); 385 env->SubCfgEntry(&entry); 386 Label exit(env); 387 Label tryFastPath(env); 388 Label slowPath(env); 389 390 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 391 GateRef receiver = 0; 392 GateRef value = 0; 393 ICStubBuilder builder(this); 394 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId); 395 builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit); 396 Bind(&tryFastPath); 397 { 398 GateRef propKey = ResolvePropKey(glue, prop, info); 399 GateRef record = LdGlobalRecord(glue, propKey); 400 Label foundInRecord(env); 401 Label notFoundInRecord(env); 402 BRANCH(TaggedIsUndefined(record), ¬FoundInRecord, &foundInRecord); 403 Bind(&foundInRecord); 404 { 405 result = Load(VariableType::JS_ANY(), record, IntPtr(PropertyBox::VALUE_OFFSET)); 406 Jump(&exit); 407 } 408 Bind(¬FoundInRecord); 409 { 410 GateRef globalObject = GetGlobalObject(glue); 411 result = GetGlobalOwnProperty(glue, globalObject, propKey, callback); 412 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 413 } 414 } 415 Bind(&slowPath); 416 { 417 GateRef propKey = ResolvePropKey(glue, prop, info); 418 result = CallRuntime(glue, RTSTUB_ID(TryLdGlobalICByName), 419 { profileTypeInfo, propKey, IntToTaggedInt(slotId) }); 420 Jump(&exit); 421 } 422 423 Bind(&exit); 424 auto ret = *result; 425 env->SubCfgExit(); 426 return ret; 427} 428 429GateRef AccessObjectStubBuilder::TryStoreGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info, 430 GateRef value, GateRef profileTypeInfo, GateRef slotId, 431 ProfileOperation callback) 432{ 433 auto env = GetEnvironment(); 434 Label entry(env); 435 env->SubCfgEntry(&entry); 436 Label exit(env); 437 Label tryFastPath(env); 438 Label slowPath(env); 439 440 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 441 GateRef receiver = 0; 442 ICStubBuilder builder(this); 443 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId); 444 builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit); 445 Bind(&tryFastPath); 446 { 447 GateRef propKey = ResolvePropKey(glue, prop, info); 448 GateRef record = LdGlobalRecord(glue, propKey); 449 Label foundInRecord(env); 450 Label notFoundInRecord(env); 451 BRANCH(TaggedIsUndefined(record), ¬FoundInRecord, &foundInRecord); 452 Bind(&foundInRecord); 453 { 454 result = CallRuntime(glue, RTSTUB_ID(TryUpdateGlobalRecord), { propKey, value }); 455 Jump(&exit); 456 } 457 Bind(¬FoundInRecord); 458 { 459 GateRef globalObject = GetGlobalObject(glue); 460 result = GetGlobalOwnProperty(glue, globalObject, propKey, callback); 461 Label isFoundInGlobal(env); 462 Label notFoundInGlobal(env); 463 BRANCH(TaggedIsHole(*result), ¬FoundInGlobal, &isFoundInGlobal); 464 Bind(&isFoundInGlobal); 465 { 466 result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value }); 467 Jump(&exit); 468 } 469 Bind(¬FoundInGlobal); 470 { 471 result = CallRuntime(glue, RTSTUB_ID(ThrowReferenceError), { propKey }); 472 Jump(&exit); 473 } 474 } 475 } 476 Bind(&slowPath); 477 { 478 GateRef propKey = ResolvePropKey(glue, prop, info); 479 GateRef globalObject = GetGlobalObject(glue); 480 result = CallRuntime(glue, RTSTUB_ID(StoreMiss), 481 { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId), 482 IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalTryStoreIC))) }); 483 Jump(&exit); 484 } 485 486 Bind(&exit); 487 auto ret = *result; 488 env->SubCfgExit(); 489 return ret; 490} 491 492GateRef AccessObjectStubBuilder::LoadGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info, 493 GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback) 494{ 495 auto env = GetEnvironment(); 496 Label entry(env); 497 env->SubCfgEntry(&entry); 498 Label exit(env); 499 Label tryFastPath(env); 500 Label slowPath(env); 501 502 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 503 GateRef receiver = 0; 504 GateRef value = 0; 505 ICStubBuilder builder(this); 506 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId); 507 builder.TryLoadGlobalICByName(&result, &tryFastPath, &slowPath, &exit); 508 Bind(&tryFastPath); 509 { 510 GateRef globalObject = GetGlobalObject(glue); 511 GateRef propKey = ResolvePropKey(glue, prop, info); 512 result = GetGlobalOwnProperty(glue, globalObject, propKey, callback); 513 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 514 } 515 Bind(&slowPath); 516 { 517 GateRef globalObject = GetGlobalObject(glue); 518 GateRef propKey = ResolvePropKey(glue, prop, info); 519 result = CallRuntime(glue, RTSTUB_ID(LdGlobalICVar), 520 { globalObject, propKey, profileTypeInfo, IntToTaggedInt(slotId) }); 521 Jump(&exit); 522 } 523 524 Bind(&exit); 525 auto ret = *result; 526 env->SubCfgExit(); 527 return ret; 528} 529 530GateRef AccessObjectStubBuilder::StoreGlobalVar(GateRef glue, GateRef prop, const StringIdInfo &info, 531 GateRef value, GateRef profileTypeInfo, GateRef slotId) 532{ 533 auto env = GetEnvironment(); 534 Label entry(env); 535 env->SubCfgEntry(&entry); 536 Label exit(env); 537 Label tryFastPath(env); 538 Label slowPath(env); 539 540 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 541 GateRef receiver = 0; 542 ICStubBuilder builder(this); 543 builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId); 544 builder.TryStoreGlobalICByName(&result, &tryFastPath, &slowPath, &exit); 545 Bind(&tryFastPath); 546 { 547 GateRef propKey = ResolvePropKey(glue, prop, info); 548 // IR later 549 result = CallRuntime(glue, RTSTUB_ID(StGlobalVar), { propKey, value }); 550 Jump(&exit); 551 } 552 Bind(&slowPath); 553 { 554 GateRef propKey = ResolvePropKey(glue, prop, info); 555 GateRef globalObject = GetGlobalObject(glue); 556 result = CallRuntime(glue, RTSTUB_ID(StoreMiss), 557 { profileTypeInfo, globalObject, propKey, value, IntToTaggedInt(slotId), 558 IntToTaggedInt(Int32(static_cast<int>(ICKind::NamedGlobalStoreIC))) }); 559 Jump(&exit); 560 } 561 562 Bind(&exit); 563 auto ret = *result; 564 env->SubCfgExit(); 565 return ret; 566} 567 568GateRef AccessObjectStubBuilder::StOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value) 569{ 570 auto env = GetEnvironment(); 571 Label entry(env); 572 env->SubCfgEntry(&entry); 573 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 574 Label isHeapObject(env); 575 Label slowPath(env); 576 Label exit(env); 577 BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); 578 Bind(&isHeapObject); 579 Label notClassConstructor(env); 580 BRANCH(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); 581 Bind(¬ClassConstructor); 582 Label notClassPrototype(env); 583 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); 584 Bind(¬ClassPrototype); 585 { 586 result = SetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), value, true); 587 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 588 } 589 Bind(&slowPath); 590 { 591 result = CallRuntime(glue, RTSTUB_ID(StOwnByIndex), {receiver, IntToTaggedInt(index), value }); 592 Jump(&exit); 593 } 594 Bind(&exit); 595 auto ret = *result; 596 env->SubCfgExit(); 597 return ret; 598} 599 600GateRef AccessObjectStubBuilder::StOwnByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value) 601{ 602 auto env = GetEnvironment(); 603 Label entry(env); 604 env->SubCfgEntry(&entry); 605 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 606 Label isHeapObject(env); 607 Label slowPath(env); 608 Label exit(env); 609 BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); 610 Bind(&isHeapObject); 611 Label notClassConstructor(env); 612 BRANCH(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); 613 Bind(¬ClassConstructor); 614 Label notClassPrototype(env); 615 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); 616 Bind(¬ClassPrototype); 617 { 618 result = SetPropertyByValue(glue, receiver, key, value, true); 619 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 620 } 621 Bind(&slowPath); 622 { 623 result = CallRuntime(glue, RTSTUB_ID(StOwnByValue), { receiver, key, value }); 624 Jump(&exit); 625 } 626 Bind(&exit); 627 auto ret = *result; 628 env->SubCfgExit(); 629 return ret; 630} 631 632GateRef AccessObjectStubBuilder::StOwnByName(GateRef glue, GateRef receiver, GateRef key, GateRef value) 633{ 634 auto env = GetEnvironment(); 635 Label entry(env); 636 env->SubCfgEntry(&entry); 637 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 638 Label isJSObject(env); 639 Label slowPath(env); 640 Label exit(env); 641 BRANCH(IsJSObject(receiver), &isJSObject, &slowPath); 642 Bind(&isJSObject); 643 Label notClassConstructor(env); 644 BRANCH(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); 645 Bind(¬ClassConstructor); 646 Label notClassPrototype(env); 647 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); 648 Bind(¬ClassPrototype); 649 { 650 result = SetPropertyByName(glue, receiver, key, value, true, True()); 651 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 652 } 653 Bind(&slowPath); 654 { 655 result = CallRuntime(glue, RTSTUB_ID(StOwnByName), { receiver, key, value }); 656 Jump(&exit); 657 } 658 Bind(&exit); 659 auto ret = *result; 660 env->SubCfgExit(); 661 return ret; 662} 663 664GateRef AccessObjectStubBuilder::StOwnByValueWithNameSet(GateRef glue, GateRef receiver, GateRef key, GateRef value) 665{ 666 auto env = GetEnvironment(); 667 Label entry(env); 668 env->SubCfgEntry(&entry); 669 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 670 Label isHeapObject(env); 671 Label slowPath(env); 672 Label notClassConstructor(env); 673 Label notClassPrototype(env); 674 Label notHole(env); 675 Label exit(env); 676 BRANCH(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath); 677 Bind(&isHeapObject); 678 { 679 BRANCH(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor); 680 Bind(¬ClassConstructor); 681 { 682 BRANCH(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype); 683 Bind(¬ClassPrototype); 684 { 685 result = SetPropertyByValue(glue, receiver, key, value, true, ProfileOperation(), true); 686 BRANCH(TaggedIsHole(*result), &slowPath, ¬Hole); 687 Bind(¬Hole); 688 { 689 Label notexception(env); 690 BRANCH(TaggedIsException(*result), &exit, ¬exception); 691 Bind(¬exception); 692 CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), { value, key }); 693 Jump(&exit); 694 } 695 } 696 } 697 } 698 Bind(&slowPath); 699 { 700 result = CallRuntime(glue, RTSTUB_ID(StOwnByValueWithNameSet), { receiver, key, value }); 701 Jump(&exit); 702 } 703 Bind(&exit); 704 auto ret = *result; 705 env->SubCfgExit(); 706 return ret; 707} 708 709GateRef AccessObjectStubBuilder::StOwnByNameWithNameSet(GateRef glue, GateRef receiver, GateRef key, GateRef value) 710{ 711 auto env = GetEnvironment(); 712 Label entry(env); 713 env->SubCfgEntry(&entry); 714 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 715 Label isJSObject(env); 716 Label notJSObject(env); 717 Label notClassConstructor(env); 718 Label notClassPrototype(env); 719 Label notHole(env); 720 Label exit(env); 721 BRANCH(IsJSObject(receiver), &isJSObject, ¬JSObject); 722 Bind(&isJSObject); 723 { 724 BRANCH(IsClassConstructor(receiver), ¬JSObject, ¬ClassConstructor); 725 Bind(¬ClassConstructor); 726 { 727 BRANCH(IsClassPrototype(receiver), ¬JSObject, ¬ClassPrototype); 728 Bind(¬ClassPrototype); 729 { 730 result = SetPropertyByName(glue, receiver, key, value, true, True(), ProfileOperation(), false, true); 731 BRANCH(TaggedIsHole(*result), ¬JSObject, ¬Hole); 732 Bind(¬Hole); 733 { 734 Label notException(env); 735 BRANCH(TaggedIsException(*result), &exit, ¬Exception); 736 Bind(¬Exception); 737 CallRuntime(glue, RTSTUB_ID(SetFunctionNameNoPrefix), {value, key}); 738 Jump(&exit); 739 } 740 } 741 } 742 } 743 Bind(¬JSObject); 744 { 745 result = CallRuntime(glue, RTSTUB_ID(StOwnByNameWithNameSet), { receiver, key, value }); 746 Jump(&exit); 747 } 748 Bind(&exit); 749 auto ret = *result; 750 env->SubCfgExit(); 751 return ret; 752} 753 754GateRef AccessObjectStubBuilder::StObjByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value) 755{ 756 auto env = GetEnvironment(); 757 Label entry(env); 758 env->SubCfgEntry(&entry); 759 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 760 Label exit(env); 761 Label fastPath(env); 762 Label slowPath(env); 763 BRANCH(TaggedIsHeapObject(receiver), &fastPath, &slowPath); 764 Bind(&fastPath); 765 { 766 result = SetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), value, false); 767 BRANCH(TaggedIsHole(*result), &slowPath, &exit); 768 } 769 Bind(&slowPath); 770 { 771 result = CallRuntime(glue, RTSTUB_ID(StObjByIndex), {receiver, IntToTaggedInt(index), value}); 772 Jump(&exit); 773 } 774 Bind(&exit); 775 auto ret = *result; 776 env->SubCfgExit(); 777 return ret; 778} 779 780GateRef AccessObjectStubBuilder::LdObjByIndex(GateRef glue, GateRef receiver, GateRef index) 781{ 782 auto env = GetEnvironment(); 783 Label entry(env); 784 env->SubCfgEntry(&entry); 785 DEFVARIABLE(varAcc, VariableType::JS_ANY(), Hole()); 786 Label fastPath(env); 787 Label slowPath(env); 788 Label exit(env); 789 BRANCH(TaggedIsHeapObject(receiver), &fastPath, &slowPath); 790 Bind(&fastPath); 791 { 792 varAcc = GetPropertyByIndex(glue, receiver, TruncInt64ToInt32(index), ProfileOperation()); 793 BRANCH(TaggedIsHole(*varAcc), &slowPath, &exit); 794 } 795 Bind(&slowPath); 796 { 797 GateRef undefined = Undefined(); 798 auto args = { receiver, IntToTaggedInt(index), TaggedFalse(), undefined }; 799 varAcc = CallRuntime(glue, RTSTUB_ID(LdObjByIndex), args); 800 Jump(&exit); 801 } 802 Bind(&exit); 803 auto ret = *varAcc; 804 env->SubCfgExit(); 805 return ret; 806} 807} // namespace panda::ecmascript::kungfu 808