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 16#include "ecmascript/compiler/builtins/builtins_object_stub_builder.h" 17 18#include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h" 19#include "ecmascript/compiler/circuit_builder_helper.h" 20#include "ecmascript/compiler/new_object_stub_builder.h" 21#include "ecmascript/compiler/stub_builder-inl.h" 22#include "ecmascript/js_arguments.h" 23#include "ecmascript/js_primitive_ref.h" 24#include "ecmascript/message_string.h" 25#include "ecmascript/tagged_dictionary.h" 26 27namespace panda::ecmascript::kungfu { 28GateRef BuiltinsObjectStubBuilder::CreateListFromArrayLike(GateRef glue, GateRef arrayObj) 29{ 30 auto env = GetEnvironment(); 31 Label entry(env); 32 env->SubCfgEntry(&entry); 33 DEFVARIABLE(res, VariableType::JS_ANY(), Hole()); 34 DEFVARIABLE(index, VariableType::INT32(), Int32(0)); 35 Label exit(env); 36 37 // 3. If Type(obj) is Object, throw a TypeError exception. 38 Label targetIsHeapObject(env); 39 Label targetIsEcmaObject(env); 40 Label targetNotEcmaObject(env); 41 BRANCH(TaggedIsHeapObject(arrayObj), &targetIsHeapObject, &targetNotEcmaObject); 42 Bind(&targetIsHeapObject); 43 BRANCH(TaggedObjectIsEcmaObject(arrayObj), &targetIsEcmaObject, &targetNotEcmaObject); 44 Bind(&targetNotEcmaObject); 45 { 46 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject)); 47 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); 48 Jump(&exit); 49 } 50 Bind(&targetIsEcmaObject); 51 { 52 Label targetIsTypeArray(env); 53 Label targetNotTypeArray(env); 54 BRANCH(IsTypedArray(arrayObj), &targetIsTypeArray, &targetNotTypeArray); 55 Bind(&targetIsTypeArray); 56 { 57 GateRef int32Len = GetLengthOfJSTypedArray(arrayObj); 58 NewObjectStubBuilder newBuilder(this); 59 GateRef array = newBuilder.NewTaggedArray(glue, int32Len); 60 BuiltinsTypedArrayStubBuilder arrayStubBuilder(this); 61 arrayStubBuilder.FastCopyElementToArray(glue, arrayObj, array); 62 // c. ReturnIfAbrupt(next). 63 Label isPendingException2(env); 64 Label noPendingException2(env); 65 BRANCH(HasPendingException(glue), &isPendingException2, &noPendingException2); 66 Bind(&isPendingException2); 67 { 68 Jump(&exit); 69 } 70 Bind(&noPendingException2); 71 { 72 res = array; 73 Jump(&exit); 74 } 75 } 76 Bind(&targetNotTypeArray); 77 // 4. Let len be ToLength(Get(obj, "length")). 78 GateRef lengthString = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, 79 ConstantIndex::LENGTH_STRING_INDEX); 80 GateRef value = FastGetPropertyByName(glue, arrayObj, lengthString, ProfileOperation()); 81 GateRef number = ToLength(glue, value); 82 // 5. ReturnIfAbrupt(len). 83 Label isPendingException1(env); 84 Label noPendingException1(env); 85 BRANCH(HasPendingException(glue), &isPendingException1, &noPendingException1); 86 Bind(&isPendingException1); 87 { 88 Jump(&exit); 89 } 90 Bind(&noPendingException1); 91 { 92 Label indexInRange(env); 93 Label indexOutRange(env); 94 95 GateRef doubleLen = GetDoubleOfTNumber(number); 96 BRANCH(DoubleGreaterThan(doubleLen, Double(JSObject::MAX_ELEMENT_INDEX)), &indexOutRange, &indexInRange); 97 Bind(&indexOutRange); 98 { 99 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax)); 100 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); 101 Jump(&exit); 102 } 103 Bind(&indexInRange); 104 { 105 // 8. Repeat while index < len 106 GateRef int32Length = DoubleToInt(glue, doubleLen); 107 NewObjectStubBuilder newBuilder(this); 108 GateRef array = newBuilder.NewTaggedArray(glue, int32Length); 109 Label loopHead(env); 110 Label loopEnd(env); 111 Label afterLoop(env); 112 Label isPendingException3(env); 113 Label noPendingException3(env); 114 Label storeValue(env); 115 Jump(&loopHead); 116 LoopBegin(&loopHead); 117 { 118 BRANCH(Int32UnsignedLessThan(*index, int32Length), &storeValue, &afterLoop); 119 Bind(&storeValue); 120 { 121 GateRef next = FastGetPropertyByIndex(glue, arrayObj, *index, ProfileOperation()); 122 // c. ReturnIfAbrupt(next). 123 BRANCH(HasPendingException(glue), &isPendingException3, &noPendingException3); 124 Bind(&isPendingException3); 125 { 126 Jump(&exit); 127 } 128 Bind(&noPendingException3); 129 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, next); 130 index = Int32Add(*index, Int32(1)); 131 Jump(&loopEnd); 132 } 133 } 134 Bind(&loopEnd); 135 LoopEnd(&loopHead, env, glue); 136 Bind(&afterLoop); 137 { 138 res = array; 139 Jump(&exit); 140 } 141 } 142 } 143 } 144 Bind(&exit); 145 GateRef ret = *res; 146 env->SubCfgExit(); 147 return ret; 148} 149GateRef BuiltinsObjectStubBuilder::CreateArrayFromList(GateRef glue, GateRef elements) 150{ 151 auto env = GetEnvironment(); 152 DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined()); 153 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 154 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); 155 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX); 156 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR); 157 GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 158 NewObjectStubBuilder newBuilder(this); 159 newBuilder.SetParameters(glue, 0); 160 GateRef len = GetLengthOfTaggedArray(elements); 161 result = newBuilder.NewJSObject(glue, intialHClass); 162 SetPropertyInlinedProps(glue, *result, intialHClass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX)); 163 SetArrayLength(glue, *result, len); 164 SetExtensibleToBitfield(glue, *result, true); 165 SetElementsArray(VariableType::JS_POINTER(), glue_, *result, elements); 166 auto res = *result; 167 return res; 168} 169 170void BuiltinsObjectStubBuilder::ToString(Variable *result, Label *exit, Label *slowPath) 171{ 172 auto env = GetEnvironment(); 173 Label ecmaObj(env); 174 // undefined 175 Label undefined(env); 176 Label checknull(env); 177 BRANCH(TaggedIsUndefined(thisValue_), &undefined, &checknull); 178 Bind(&undefined); 179 { 180 *result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::UNDEFINED_TO_STRING_INDEX); 181 Jump(exit); 182 } 183 // null 184 Bind(&checknull); 185 Label null(env); 186 Label checkObject(env); 187 BRANCH(TaggedIsUndefined(thisValue_), &null, &checkObject); 188 Bind(&null); 189 { 190 *result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::NULL_TO_STRING_INDEX); 191 Jump(exit); 192 } 193 194 Bind(&checkObject); 195 BRANCH(IsEcmaObject(thisValue_), &ecmaObj, slowPath); 196 Bind(&ecmaObj); 197 { 198 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); 199 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset); 200 GateRef toStringTagSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, 201 GlobalEnv::TOSTRINGTAG_SYMBOL_INDEX); 202 GateRef tag = FastGetPropertyByName(glue_, thisValue_, toStringTagSymbol, ProfileOperation()); 203 204 Label defaultToString(env); 205 BRANCH(TaggedIsString(tag), slowPath, &defaultToString); 206 Bind(&defaultToString); 207 { 208 // default object 209 Label objectTag(env); 210 BRANCH(IsJSObjectType(thisValue_, JSType::JS_OBJECT), &objectTag, slowPath); 211 Bind(&objectTag); 212 { 213 // [object object] 214 *result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, 215 ConstantIndex::OBJECT_TO_STRING_INDEX); 216 Jump(exit); 217 } 218 } 219 } 220} 221 222 223void BuiltinsObjectStubBuilder::Create(Variable *result, Label *exit, Label *slowPath) 224{ 225 auto env = GetEnvironment(); 226 Label newObject(env); 227 228 GateRef proto = GetCallArg0(numArgs_); 229 GateRef protoCheck = LogicAndBuilder(env).And(BoolNot(IsEcmaObject(proto))) 230 .And(BoolNot(TaggedIsNull(proto))).Done(); 231 BRANCH(LogicOrBuilder(env).Or(protoCheck).Or(TaggedIsSharedObj(proto)).Done(), slowPath, &newObject); 232 Bind(&newObject); 233 { 234 Label noProperties(env); 235 GateRef propertiesObject = GetCallArg1(numArgs_); 236 BRANCH(TaggedIsUndefined(propertiesObject), &noProperties, slowPath); 237 Bind(&noProperties); 238 { 239 // OrdinaryNewJSObjectCreate 240 *result = OrdinaryNewJSObjectCreate(glue_, proto); 241 Jump(exit); 242 } 243 } 244} 245 246void BuiltinsObjectStubBuilder::AssignEnumElementProperty(Variable *result, Label *funcExit, 247 GateRef toAssign, GateRef source) 248{ 249 auto env = GetEnvironment(); 250 Label entryLabel(env); 251 env->SubCfgEntry(&entryLabel); 252 Label exit(env); 253 254 GateRef elements = GetElementsArray(source); 255 Label dictionaryMode(env); 256 Label notDictionaryMode(env); 257 BRANCH(IsDictionaryMode(elements), &dictionaryMode, ¬DictionaryMode); 258 Bind(¬DictionaryMode); 259 { 260 GateRef len = GetLengthOfTaggedArray(elements); 261 DEFVARIABLE(idx, VariableType::INT32(), Int32(0)); 262 Label loopHead(env); 263 Label loopEnd(env); 264 Label next(env); 265 Label loopExit(env); 266 267 Jump(&loopHead); 268 LoopBegin(&loopHead); 269 { 270 BRANCH(Int32LessThan(*idx, len), &next, &loopExit); 271 Bind(&next); 272 GateRef value = GetTaggedValueWithElementsKind(source, *idx); 273 Label notHole(env); 274 BRANCH(TaggedIsHole(value), &loopEnd, ¬Hole); 275 Bind(¬Hole); 276 { 277 // key, value 278 FastSetPropertyByIndex(glue_, toAssign, *idx, value); 279 Label exception(env); 280 BRANCH(HasPendingException(glue_), &exception, &loopEnd); 281 Bind(&exception); 282 { 283 *result = Exception(); 284 Jump(funcExit); 285 } 286 } 287 } 288 Bind(&loopEnd); 289 idx = Int32Add(*idx, Int32(1)); 290 LoopEnd(&loopHead, env, glue_); 291 Bind(&loopExit); 292 Jump(&exit); 293 } 294 Bind(&dictionaryMode); 295 { 296 // NumberDictionary::VisitAllEnumProperty 297 GateRef sizeIndex = Int32(TaggedHashTable<NumberDictionary>::SIZE_INDEX); 298 GateRef size = GetInt32OfTInt(GetValueFromTaggedArray(elements, sizeIndex)); 299 DEFVARIABLE(idx, VariableType::INT32(), Int32(0)); 300 Label loopHead(env); 301 Label loopEnd(env); 302 Label next(env); 303 Label loopExit(env); 304 305 Jump(&loopHead); 306 LoopBegin(&loopHead); 307 { 308 BRANCH(Int32LessThan(*idx, size), &next, &loopExit); 309 Bind(&next); 310 GateRef key = GetKeyFromDictionary<NumberDictionary>(elements, *idx); 311 Label checkEnumerable(env); 312 BRANCH(LogicOrBuilder(env).Or(TaggedIsUndefined(key)).Or(TaggedIsHole(key)).Done(), 313 &loopEnd, &checkEnumerable); 314 Bind(&checkEnumerable); 315 { 316 GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, *idx); 317 Label enumerable(env); 318 BRANCH(IsEnumerable(attr), &enumerable, &loopEnd); 319 Bind(&enumerable); 320 { 321 GateRef value = GetValueFromDictionary<NumberDictionary>(elements, *idx); 322 Label notHole(env); 323 BRANCH(TaggedIsHole(value), &loopEnd, ¬Hole); 324 Bind(¬Hole); 325 { 326 // value 327 FastSetPropertyByIndex(glue_, toAssign, *idx, value); 328 Label exception(env); 329 BRANCH(HasPendingException(glue_), &exception, &loopEnd); 330 Bind(&exception); 331 { 332 *result = Exception(); 333 Jump(funcExit); 334 } 335 } 336 } 337 } 338 } 339 Bind(&loopEnd); 340 idx = Int32Add(*idx, Int32(1)); 341 LoopEnd(&loopHead, env, glue_); 342 Bind(&loopExit); 343 Jump(&exit); 344 } 345 Bind(&exit); 346 env->SubCfgExit(); 347} 348 349void BuiltinsObjectStubBuilder::LayoutInfoAssignAllEnumProperty(Variable *result, Label *funcExit, 350 GateRef toAssign, GateRef source) 351{ 352 auto env = GetEnvironment(); 353 Label entryLabel(env); 354 env->SubCfgEntry(&entryLabel); 355 Label exit(env); 356 357 // LayoutInfo::VisitAllEnumProperty 358 GateRef cls = LoadHClass(source); 359 GateRef num = GetNumberOfPropsFromHClass(cls); 360 GateRef layout = GetLayoutFromHClass(cls); 361 DEFVARIABLE(idx, VariableType::INT32(), Int32(0)); 362 Label loopHead(env); 363 Label loopEnd(env); 364 Label next(env); 365 Label loopExit(env); 366 367 Jump(&loopHead); 368 LoopBegin(&loopHead); 369 { 370 BRANCH(Int32LessThan(*idx, num), &next, &loopExit); 371 Bind(&next); 372 373 GateRef key = GetKeyFromLayoutInfo(layout, *idx); 374 GateRef attr = GetPropAttrFromLayoutInfo(layout, *idx); 375 Label stringKey(env); 376 BRANCH(TaggedIsString(key), &stringKey, &loopEnd); 377 Bind(&stringKey); 378 { 379 Label enumerable(env); 380 BRANCH(IsEnumerable(attr), &enumerable, &loopEnd); 381 Bind(&enumerable); 382 { 383 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); 384 value = JSObjectGetProperty(source, cls, attr); 385 // exception 386 Label exception0(env); 387 Label noexception0(env); 388 BRANCH(HasPendingException(glue_), &exception0, &noexception0); 389 Bind(&exception0); 390 { 391 *result = Exception(); 392 Jump(funcExit); 393 } 394 Bind(&noexception0); 395 Label propertyBox(env); 396 Label checkAccessor(env); 397 Label setValue(env); 398 BRANCH(TaggedIsPropertyBox(*value), &propertyBox, &checkAccessor); 399 Bind(&propertyBox); 400 { 401 value = GetValueFromPropertyBox(*value); 402 Jump(&setValue); 403 } 404 Bind(&checkAccessor); 405 Label isAccessor(env); 406 BRANCH(IsAccessor(attr), &isAccessor, &setValue); 407 Bind(&isAccessor); 408 { 409 value = CallGetterHelper(glue_, source, source, *value, ProfileOperation()); 410 Label exception(env); 411 BRANCH(HasPendingException(glue_), &exception, &setValue); 412 Bind(&exception); 413 { 414 *result = Exception(); 415 Jump(funcExit); 416 } 417 } 418 Bind(&setValue); 419 { 420 FastSetPropertyByName(glue_, toAssign, key, *value); 421 Label exception(env); 422 BRANCH(HasPendingException(glue_), &exception, &loopEnd); 423 Bind(&exception); 424 { 425 *result = Exception(); 426 Jump(funcExit); 427 } 428 } 429 } 430 } 431 } 432 Bind(&loopEnd); 433 idx = Int32Add(*idx, Int32(1)); 434 LoopEnd(&loopHead, env, glue_); 435 Bind(&loopExit); 436 Jump(&exit); 437 438 Bind(&exit); 439 env->SubCfgExit(); 440} 441 442void BuiltinsObjectStubBuilder::NameDictionaryAssignAllEnumProperty(Variable *result, Label *funcExit, 443 GateRef toAssign, GateRef source, GateRef properties) 444{ 445 // NameDictionary::VisitAllEnumProperty 446 auto env = GetEnvironment(); 447 Label entryLabel(env); 448 env->SubCfgEntry(&entryLabel); 449 Label exit(env); 450 451 GateRef sizeIndex = Int32(TaggedHashTable<NameDictionary>::SIZE_INDEX); 452 GateRef size = GetInt32OfTInt(GetValueFromTaggedArray(properties, sizeIndex)); 453 DEFVARIABLE(idx, VariableType::INT32(), Int32(0)); 454 Label loopHead(env); 455 Label loopEnd(env); 456 Label next(env); 457 Label loopExit(env); 458 459 Jump(&loopHead); 460 LoopBegin(&loopHead); 461 { 462 BRANCH(Int32LessThan(*idx, size), &next, &loopExit); 463 Bind(&next); 464 GateRef key = GetKeyFromDictionary<NameDictionary>(properties, *idx); 465 Label stringKey(env); 466 BRANCH(TaggedIsString(key), &stringKey, &loopEnd); 467 Bind(&stringKey); 468 { 469 GateRef attr = GetAttributesFromDictionary<NameDictionary>(properties, *idx); 470 Label enumerable(env); 471 BRANCH(IsEnumerable(attr), &enumerable, &loopEnd); 472 Bind(&enumerable); 473 { 474 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); 475 value = GetValueFromDictionary<NameDictionary>(properties, *idx); 476 Label notHole(env); 477 BRANCH(TaggedIsHole(*value), &loopEnd, ¬Hole); 478 Bind(¬Hole); 479 { 480 Label isAccessor(env); 481 Label notAccessor(env); 482 BRANCH(IsAccessor(attr), &isAccessor, ¬Accessor); 483 Bind(&isAccessor); 484 { 485 value = CallGetterHelper(glue_, source, source, *value, ProfileOperation()); 486 // exception 487 Label exception(env); 488 BRANCH(HasPendingException(glue_), &exception, ¬Accessor); 489 Bind(&exception); 490 { 491 *result = Exception(); 492 Jump(funcExit); 493 } 494 } 495 Bind(¬Accessor); 496 { 497 FastSetPropertyByName(glue_, toAssign, key, *value); 498 Label exception(env); 499 BRANCH(HasPendingException(glue_), &exception, &loopEnd); 500 Bind(&exception); 501 { 502 *result = Exception(); 503 Jump(funcExit); 504 } 505 } 506 } 507 } 508 } 509 } 510 Bind(&loopEnd); 511 idx = Int32Add(*idx, Int32(1)); 512 LoopEnd(&loopHead, env, glue_); 513 Bind(&loopExit); 514 Jump(&exit); 515 516 Bind(&exit); 517 env->SubCfgExit(); 518} 519 520void BuiltinsObjectStubBuilder::AssignAllEnumProperty(Variable *res, Label *funcExit, 521 GateRef toAssign, GateRef source) 522{ 523 auto env = GetEnvironment(); 524 Label entryLabel(env); 525 env->SubCfgEntry(&entryLabel); 526 Label exit(env); 527 528 GateRef properties = GetPropertiesArray(source); 529 Label dictionaryMode(env); 530 Label notDictionaryMode(env); 531 BRANCH(IsDictionaryMode(properties), &dictionaryMode, ¬DictionaryMode); 532 Bind(¬DictionaryMode); 533 { 534 LayoutInfoAssignAllEnumProperty(res, funcExit, toAssign, source); 535 Jump(&exit); 536 } 537 Bind(&dictionaryMode); 538 { 539 NameDictionaryAssignAllEnumProperty(res, funcExit, toAssign, source, properties); 540 Jump(&exit); 541 } 542 Bind(&exit); 543 env->SubCfgExit(); 544} 545 546void BuiltinsObjectStubBuilder::SlowAssign(Variable *result, Label *funcExit, GateRef toAssign, GateRef source) 547{ 548 auto env = GetEnvironment(); 549 Label entryLabel(env); 550 env->SubCfgEntry(&entryLabel); 551 Label exit(env); 552 CallRuntime(glue_, RTSTUB_ID(ObjectSlowAssign), { toAssign, source }); 553 554 Label exception(env); 555 BRANCH(HasPendingException(glue_), &exception, &exit); 556 Bind(&exception); 557 { 558 *result = Exception(); 559 Jump(funcExit); 560 } 561 Bind(&exit); 562 env->SubCfgExit(); 563} 564 565void BuiltinsObjectStubBuilder::FastAssign(Variable *res, Label *funcExit, GateRef toAssign, GateRef source) 566{ 567 // visit elements 568 AssignEnumElementProperty(res, funcExit, toAssign, source); 569 AssignAllEnumProperty(res, funcExit, toAssign, source); 570} 571 572void BuiltinsObjectStubBuilder::Assign(Variable *res, Label *nextIt, Label *funcExit, 573 GateRef toAssign, GateRef source) 574{ 575 auto env = GetEnvironment(); 576 Label checkJsObj(env); 577 BRANCH(TaggedIsUndefinedOrNull(source), nextIt, &checkJsObj); 578 Bind(&checkJsObj); 579 { 580 Label fastAssign(env); 581 Label slowAssign(env); 582 BRANCH(IsJSObjectType(source, JSType::JS_OBJECT), &fastAssign, &slowAssign); 583 Bind(&fastAssign); 584 { 585 FastAssign(res, funcExit, toAssign, source); 586 Jump(nextIt); 587 } 588 Bind(&slowAssign); 589 { 590 SlowAssign(res, funcExit, toAssign, source); 591 Jump(nextIt); 592 } 593 } 594} 595 596void BuiltinsObjectStubBuilder::Assign(Variable *result, Label *exit, Label *slowPath) 597{ 598 auto env = GetEnvironment(); 599 Label thisCollectionObj(env); 600 601 GateRef target = GetCallArg0(numArgs_); 602 *result = target; 603 Label jsObject(env); 604 BRANCH(IsJSObjectType(target, JSType::JS_OBJECT), &jsObject, slowPath); 605 Bind(&jsObject); 606 { 607 Label twoArg(env); 608 Label notTwoArg(env); 609 BRANCH(Int64Equal(numArgs_, IntPtr(2)), &twoArg, ¬TwoArg); // 2 : two args 610 Bind(&twoArg); 611 { 612 GateRef source = GetCallArg1(numArgs_); 613 Label next(env); 614 Assign(result, &next, exit, target, source); 615 Bind(&next); 616 Jump(exit); 617 } 618 Bind(¬TwoArg); 619 Label threeArg(env); 620 Label notThreeArg(env); 621 BRANCH(Int64Equal(numArgs_, IntPtr(3)), &threeArg, ¬ThreeArg); // 3 : three args 622 Bind(&threeArg); 623 { 624 Label nextArg(env); 625 GateRef source = GetCallArg1(numArgs_); 626 Label next(env); 627 Assign(result, &next, exit, target, source); 628 Bind(&next); 629 Label next1(env); 630 GateRef source1 = GetCallArg2(numArgs_); 631 Assign(result, &next1, exit, target, source1); 632 Bind(&next1); 633 Jump(exit); 634 } 635 Bind(¬ThreeArg); 636 { 637 Jump(slowPath); 638 } 639 } 640} 641 642void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, Label *slowPath) 643{ 644 GateRef prop = GetCallArg0(numArgs_); 645 HasOwnProperty(result, exit, slowPath, thisValue_, prop); 646} 647 648void BuiltinsObjectStubBuilder::HasOwnProperty(Variable *result, Label *exit, Label *slowPath, GateRef thisValue, 649 GateRef prop, GateRef hir) 650{ 651 auto env = GetEnvironment(); 652 Label keyIsString(env); 653 Label valid(env); 654 Label isHeapObject(env); 655 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); 656 Bind(&isHeapObject); 657 BRANCH(TaggedIsRegularObject(thisValue), &valid, slowPath); 658 Bind(&valid); 659 { 660 Label isIndex(env); 661 Label notIndex(env); 662 BRANCH(TaggedIsString(prop), &keyIsString, slowPath); // 2 : two args 663 Bind(&keyIsString); 664 { 665 GateRef res = StringToElementIndex(glue_, prop); 666 // -1: not find element index 667 BRANCH(Int64NotEqual(res, Int64(-1)), &isIndex, ¬Index); 668 Bind(&isIndex); 669 { 670 GateRef index = TruncInt64ToInt32(res); 671 Label findByIndex(env); 672 GateRef elements = GetElementsArray(thisValue); 673 GateRef len = GetLengthOfTaggedArray(elements); 674 BRANCH(Int32Equal(len, Int32(0)), exit, &findByIndex); 675 Bind(&findByIndex); 676 { 677 Label isDictionaryElement(env); 678 Label notDictionaryElement(env); 679 BRANCH(IsDictionaryMode(elements), &isDictionaryElement, ¬DictionaryElement); 680 Bind(¬DictionaryElement); 681 { 682 Label lessThanLength(env); 683 Label notLessThanLength(env); 684 BRANCH(Int32UnsignedLessThanOrEqual(len, index), exit, &lessThanLength); 685 Bind(&lessThanLength); 686 { 687 Label notHole(env); 688 GateRef value = GetTaggedValueWithElementsKind(thisValue, index); 689 BRANCH(TaggedIsNotHole(value), ¬Hole, exit); 690 Bind(¬Hole); 691 { 692 *result = TaggedTrue(); 693 Jump(exit); 694 } 695 } 696 } 697 Bind(&isDictionaryElement); 698 { 699 GateRef entryA = FindElementFromNumberDictionary(glue_, elements, index); 700 Label notNegtiveOne(env); 701 BRANCH(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, exit); 702 Bind(¬NegtiveOne); 703 { 704 *result = TaggedTrue(); 705 Jump(exit); 706 } 707 } 708 } 709 } 710 Bind(¬Index); 711 { 712 Label findInStringTabel(env); 713 Label notInternString(env); 714 DEFVARIABLE(stringTable, VariableType::JS_ANY(), prop); 715 BRANCH(IsInternalString(prop), &findInStringTabel, ¬InternString); 716 Bind(¬InternString); 717 { 718 GateRef internString = CallRuntime(glue_, RTSTUB_ID(TryGetInternString), { prop }); 719 stringTable = internString; 720 BRANCH(TaggedIsHole(internString), exit, &findInStringTabel) 721 } 722 Bind(&findInStringTabel); 723 { 724 Label isDicMode(env); 725 Label notDicMode(env); 726 GateRef hclass = LoadHClass(thisValue); 727 BRANCH(IsDictionaryModeByHClass(hclass), &isDicMode, ¬DicMode); 728 Bind(¬DicMode); 729 { 730 GateRef layOutInfo = GetLayoutFromHClass(hclass); 731 GateRef propsNum = GetNumberOfPropsFromHClass(hclass); 732 // int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber) 733 GateRef entryA = FindElementWithCache(glue_, layOutInfo, hclass, *stringTable, propsNum, hir); 734 Label hasEntry(env); 735 // if branch condition : entry != -1 736 BRANCH(Int32NotEqual(entryA, Int32(-1)), &hasEntry, exit); 737 Bind(&hasEntry); 738 { 739 *result = TaggedTrue(); 740 Jump(exit); 741 } 742 } 743 Bind(&isDicMode); 744 { 745 GateRef array = GetPropertiesArray(thisValue); 746 // int entry = dict->FindEntry(key) 747 GateRef entryB = FindEntryFromNameDictionary(glue_, array, *stringTable, hir); 748 Label notNegtiveOne(env); 749 // if branch condition : entry != -1 750 BRANCH(Int32NotEqual(entryB, Int32(-1)), ¬NegtiveOne, exit); 751 Bind(¬NegtiveOne); 752 { 753 *result = TaggedTrue(); 754 Jump(exit); 755 } 756 } 757 } 758 } 759 } 760 } 761} 762 763GateRef BuiltinsObjectStubBuilder::GetNumKeysFromLayoutInfo(GateRef object, GateRef end, GateRef layoutInfo) 764{ 765 auto env = GetEnvironment(); 766 Label entry(env); 767 env->SubCfgEntry(&entry); 768 Label exit(env); 769 DEFVARIABLE(result, VariableType::INT32(), Int32(0)); 770 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 771 772 Label loopHead(env); 773 Label loopEnd(env); 774 Label iLessEnd(env); 775 Label isString(env); 776 Label initializedProp(env); 777 Label isEnumerable(env); 778 Jump(&loopHead); 779 LoopBegin(&loopHead); 780 { 781 BRANCH(Int32UnsignedLessThan(*i, end), &iLessEnd, &exit); 782 Bind(&iLessEnd); 783 { 784 GateRef key = GetKey(layoutInfo, *i); 785 BRANCH(TaggedIsString(key), &isString, &loopEnd); 786 Bind(&isString); 787 BRANCH(IsUninitializedProperty(object, *i, layoutInfo), &loopEnd, &initializedProp); 788 Bind(&initializedProp); 789 BRANCH(IsEnumerable(GetAttr(layoutInfo, *i)), &isEnumerable, &loopEnd); 790 Bind(&isEnumerable); 791 result = Int32Add(*result, Int32(1)); 792 Jump(&loopEnd); 793 } 794 Bind(&loopEnd); 795 i = Int32Add(*i, Int32(1)); 796 LoopEnd(&loopHead, env, glue_); 797 } 798 Bind(&exit); 799 auto ret = *result; 800 env->SubCfgExit(); 801 return ret; 802} 803 804GateRef BuiltinsObjectStubBuilder::IsUninitializedProperty(GateRef object, GateRef index, GateRef layoutInfo) 805{ 806 auto env = GetEnvironment(); 807 Label entry(env); 808 env->SubCfgEntry(&entry); 809 Label exit(env); 810 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined()); 811 DEFVARIABLE(result, VariableType::BOOL(), False()); 812 813 Label inlinedProp(env); 814 GateRef attr = GetAttr(layoutInfo, index); 815 GateRef rep = GetRepInPropAttr(attr); 816 GateRef hclass = LoadHClass(object); 817 BRANCH(IsInlinedProperty(attr), &inlinedProp, &exit); 818 Bind(&inlinedProp); 819 { 820 value = GetPropertyInlinedProps(object, hclass, index); 821 result = TaggedIsHole(*value); 822 Label nonDoubleToTagged(env); 823 Label doubleToTagged(env); 824 BRANCH(IsDoubleRepInPropAttr(rep), &doubleToTagged, &nonDoubleToTagged); 825 Bind(&doubleToTagged); 826 { 827 value = TaggedPtrToTaggedDoublePtr(*value); 828 result = TaggedIsHole(*value); 829 Jump(&exit); 830 } 831 Bind(&nonDoubleToTagged); 832 { 833 Label intToTagged(env); 834 BRANCH(IsIntRepInPropAttr(rep), &intToTagged, &exit); 835 Bind(&intToTagged); 836 { 837 value = TaggedPtrToTaggedIntPtr(*value); 838 result = TaggedIsHole(*value); 839 Jump(&exit); 840 } 841 } 842 } 843 844 Bind(&exit); 845 auto ret = *result; 846 env->SubCfgExit(); 847 return ret; 848} 849 850GateRef BuiltinsObjectStubBuilder::GetNumKeysFromDictionary(GateRef array) 851{ 852 auto env = GetEnvironment(); 853 Label entry(env); 854 env->SubCfgEntry(&entry); 855 Label exit(env); 856 857 GateRef sizeIndex = Int32(TaggedHashTable<NameDictionary>::SIZE_INDEX); 858 GateRef size = GetInt32OfTInt(GetValueFromTaggedArray(array, sizeIndex)); 859 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 860 DEFVARIABLE(result, VariableType::INT32(), Int32(0)); 861 862 Label loopHead(env); 863 Label loopEnd(env); 864 Label afterLoop(env); 865 Label iLessSize(env); 866 Label isString(env); 867 Label initializedProp(env); 868 Label isEnumerable(env); 869 870 Jump(&loopHead); 871 LoopBegin(&loopHead); 872 { 873 BRANCH(Int32UnsignedLessThan(*i, size), &iLessSize, &afterLoop); 874 Bind(&iLessSize); 875 { 876 GateRef key = GetKeyFromDictionary<NameDictionary>(array, *i); 877 BRANCH(TaggedIsString(key), &isString, &loopEnd); 878 Bind(&isString); 879 GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, *i); 880 BRANCH(IsEnumerable(attr), &isEnumerable, &loopEnd); 881 Bind(&isEnumerable); 882 result = Int32Add(*result, Int32(1)); 883 Jump(&loopEnd); 884 } 885 Bind(&loopEnd); 886 i = Int32Add(*i, Int32(1)); 887 LoopEnd(&loopHead, env, glue_); 888 } 889 Bind(&afterLoop); 890 Jump(&exit); 891 892 Bind(&exit); 893 auto ret = *result; 894 env->SubCfgExit(); 895 return ret; 896} 897 898void BuiltinsObjectStubBuilder::LayoutInfoGetAllEnumKeys(GateRef end, GateRef offset, 899 GateRef array, GateRef object, GateRef layoutInfo) 900{ 901 auto env = GetEnvironment(); 902 Label entry(env); 903 env->SubCfgEntry(&entry); 904 Label exit(env); 905 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 906 DEFVARIABLE(enumKeys, VariableType::INT32(), Int32(0)); 907 Label loopHead(env); 908 Label loopEnd(env); 909 Label afterLoop(env); 910 Label iLessEnd(env); 911 Label isEnumerable(env); 912 Label initializedProp(env); 913 Jump(&loopHead); 914 LoopBegin(&loopHead); 915 { 916 BRANCH(Int32UnsignedLessThan(*i, end), &iLessEnd, &afterLoop); 917 Bind(&iLessEnd); 918 { 919 GateRef key = GetKey(layoutInfo, *i); 920 GateRef iVal = *i; 921 BRANCH(LogicAndBuilder(env).And(TaggedIsString(key)).And(IsEnumerable(GetAttr(layoutInfo, iVal))).Done(), 922 &isEnumerable, &loopEnd); 923 Bind(&isEnumerable); 924 BRANCH(IsUninitializedProperty(object, *i, layoutInfo), &loopEnd, &initializedProp); 925 Bind(&initializedProp); 926 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, array, Int32Add(*enumKeys, offset), key); 927 enumKeys = Int32Add(*enumKeys, Int32(1)); 928 Jump(&loopEnd); 929 } 930 Bind(&loopEnd); 931 i = Int32Add(*i, Int32(1)); 932 LoopEnd(&loopHead, env, glue_); 933 } 934 Bind(&afterLoop); 935 Jump(&exit); 936 Bind(&exit); 937 env->SubCfgExit(); 938} 939 940GateRef BuiltinsObjectStubBuilder::CopyFromEnumCache(GateRef glue, GateRef elements) 941{ 942 auto env = GetEnvironment(); 943 Label subEntry(env); 944 env->SubCfgEntry(&subEntry); 945 Label exit(env); 946 DEFVARIABLE(result, VariableType::JS_ANY(), Hole()); 947 DEFVARIABLE(index, VariableType::INT32(), Int32(0)); 948 DEFVARIABLE(newLen, VariableType::INT32(), Int32(0)); 949 NewObjectStubBuilder newBuilder(this); 950 951 Label lenIsZero(env); 952 Label lenNotZero(env); 953 Label afterLenCon(env); 954 GateRef oldLen = GetLengthOfTaggedArray(elements); 955 BRANCH(Int32Equal(oldLen, Int32(0)), &lenIsZero, &lenNotZero); 956 { 957 Bind(&lenIsZero); 958 { 959 newLen = Int32(0); 960 Jump(&afterLenCon); 961 } 962 Bind(&lenNotZero); 963 newLen = Int32Sub(oldLen, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE)); 964 Jump(&afterLenCon); 965 } 966 Bind(&afterLenCon); 967 GateRef array = newBuilder.NewTaggedArray(glue, *newLen); 968 Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::LENGTH_OFFSET), *newLen); 969 GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements); 970 Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen); 971 Label loopHead(env); 972 Label loopEnd(env); 973 Label afterLoop(env); 974 Label storeValue(env); 975 Jump(&loopHead); 976 LoopBegin(&loopHead); 977 { 978 BRANCH(Int32UnsignedLessThan(*index, *newLen), &storeValue, &afterLoop); 979 Bind(&storeValue); 980 { 981 GateRef value = GetValueFromTaggedArray(elements, Int32Add(*index, 982 Int32(EnumCache::ENUM_CACHE_HEADER_SIZE))); 983 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value); 984 index = Int32Add(*index, Int32(1)); 985 Jump(&loopEnd); 986 } 987 } 988 Bind(&loopEnd); 989 LoopEnd(&loopHead, env, glue); 990 Bind(&afterLoop); 991 { 992 result = array; 993 Jump(&exit); 994 } 995 Bind(&exit); 996 auto ret = *result; 997 env->SubCfgExit(); 998 return ret; 999} 1000 1001GateRef BuiltinsObjectStubBuilder::GetAllEnumKeys(GateRef glue, GateRef obj) 1002{ 1003 auto env = GetEnvironment(); 1004 Label subEntry(env); 1005 env->SubCfgEntry(&subEntry); 1006 Label exit(env); 1007 Label isDictionary(env); 1008 Label notDictionary(env); 1009 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1010 GateRef array = GetPropertiesArray(obj); 1011 BRANCH(IsDictionaryMode(array), &isDictionary, ¬Dictionary); 1012 Bind(&isDictionary); 1013 { 1014 Label propsNotZero(env); 1015 Label propsIsZero(env); 1016 GateRef numOfKeys = GetNumKeysFromDictionary(array); 1017 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &propsNotZero, &propsIsZero); 1018 Bind(&propsNotZero); 1019 result = CallRuntime(glue, RTSTUB_ID(NameDictionaryGetAllEnumKeys), { obj, IntToTaggedInt(numOfKeys) }); 1020 Jump(&exit); 1021 Bind(&propsIsZero); 1022 GateRef emptyArray = GetEmptyArray(glue); 1023 result = emptyArray; 1024 Jump(&exit); 1025 } 1026 Bind(¬Dictionary); 1027 { 1028 Label hasProps(env); 1029 Label notHasProps(env); 1030 GateRef hclass = LoadHClass(obj); 1031 // JSObject::GetNumberOfEnumKeys() 1032 GateRef num = GetNumberOfPropsFromHClass(hclass); 1033 BRANCH(Int32GreaterThan(num, Int32(0)), &hasProps, ¬HasProps); 1034 Bind(&hasProps); 1035 { 1036 Label isOnlyOwnKeys(env); 1037 Label notOnlyOwnKeys(env); 1038 GateRef layout = GetLayoutFromHClass(hclass); 1039 GateRef numOfKeys = GetNumKeysFromLayoutInfo(obj, num, layout); 1040 // JSObject::GetAllEnumKeys 1041 GateRef enumCache = GetEnumCacheFromHClass(hclass); 1042 GateRef kind = GetEnumCacheKind(glue, enumCache); 1043 BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::ONLY_OWN_KEYS))), 1044 &isOnlyOwnKeys, ¬OnlyOwnKeys); 1045 Bind(&isOnlyOwnKeys); 1046 { 1047 result = CopyFromEnumCache(glue, enumCache); 1048 Jump(&exit); 1049 } 1050 Bind(¬OnlyOwnKeys); 1051 { 1052 Label numNotZero(env); 1053 Label inSharedHeap(env); 1054 Label notInSharedHeap(env); 1055 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &numNotZero, ¬HasProps); 1056 Bind(&numNotZero); 1057 NewObjectStubBuilder newBuilder(this); 1058 GateRef keyArray = newBuilder.NewTaggedArray(glue, 1059 Int32Add(numOfKeys, Int32(static_cast<int32_t>(EnumCache::ENUM_CACHE_HEADER_SIZE)))); 1060 LayoutInfoGetAllEnumKeys(num, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE), keyArray, obj, layout); 1061 SetValueToTaggedArray(VariableType::JS_ANY(), glue, keyArray, 1062 Int32(EnumCache::ENUM_CACHE_KIND_OFFSET), 1063 IntToTaggedInt(Int32(static_cast<int32_t>(EnumCacheKind::ONLY_OWN_KEYS)))); 1064 GateRef hclassRegion = ObjectAddressToRange(hclass); 1065 BRANCH(InSharedHeap(hclassRegion), &inSharedHeap, ¬InSharedHeap); 1066 Bind(&inSharedHeap); 1067 { 1068 result = CopyFromEnumCache(glue, keyArray); 1069 Jump(&exit); 1070 } 1071 Bind(¬InSharedHeap); 1072 { 1073 SetEnumCacheToHClass(VariableType::JS_ANY(), glue, hclass, keyArray); 1074 result = CopyFromEnumCache(glue, keyArray); 1075 Jump(&exit); 1076 } 1077 } 1078 } 1079 Bind(¬HasProps); 1080 { 1081 GateRef emptyArray = GetEmptyArray(glue); 1082 result = emptyArray; 1083 Jump(&exit); 1084 } 1085 } 1086 Bind(&exit); 1087 auto ret = *result; 1088 env->SubCfgExit(); 1089 return ret; 1090} 1091 1092GateRef BuiltinsObjectStubBuilder::GetEnumElementKeys(GateRef glue, GateRef obj) 1093{ 1094 auto env = GetEnvironment(); 1095 Label subEntry(env); 1096 env->SubCfgEntry(&subEntry); 1097 Label exit(env); 1098 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1099 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 1100 DEFVARIABLE(j, VariableType::INT32(), Int32(0)); 1101 DEFVARIABLE(elementIndex, VariableType::INT32(), Int32(0)); 1102 1103 Label propsNotZero(env); 1104 Label propsIsZero(env); 1105 GateRef numOfElements = GetNumberOfElements(obj); 1106 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &propsNotZero, &propsIsZero); 1107 Bind(&propsNotZero); 1108 { 1109 Label isJSPrimitiveRef(env); 1110 Label isPrimitiveString(env); 1111 Label notPrimitiveString(env); 1112 Label isDictMode(env); 1113 Label notDictMode(env); 1114 1115 NewObjectStubBuilder newBuilder(this); 1116 GateRef elementArray = newBuilder.NewTaggedArray(glue, numOfElements); 1117 BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, ¬PrimitiveString); 1118 Bind(&isJSPrimitiveRef); 1119 GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET)); 1120 BRANCH(TaggedIsString(value), &isPrimitiveString, ¬PrimitiveString); 1121 Bind(&isPrimitiveString); 1122 { 1123 Label loopHead(env); 1124 Label loopEnd(env); 1125 Label iLessLength(env); 1126 GateRef strLen = GetLengthFromString(value); 1127 Jump(&loopHead); 1128 LoopBegin(&loopHead); 1129 { 1130 BRANCH(Int32UnsignedLessThan(*i, strLen), &iLessLength, ¬PrimitiveString); 1131 Bind(&iLessLength); 1132 { 1133 GateRef str = IntToEcmaString(glue, *i); 1134 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elementArray, 1135 *elementIndex, str); 1136 elementIndex = Int32Add(*elementIndex, Int32(1)); 1137 Jump(&loopEnd); 1138 } 1139 Bind(&loopEnd); 1140 i = Int32Add(*i, Int32(1)); 1141 LoopEnd(&loopHead, env, glue); 1142 } 1143 } 1144 Bind(¬PrimitiveString); 1145 GateRef elements = GetElementsArray(obj); 1146 BRANCH(IsDictionaryMode(elements), &isDictMode, ¬DictMode); 1147 Bind(¬DictMode); 1148 { 1149 Label loopHead(env); 1150 Label loopEnd(env); 1151 Label iLessLength(env); 1152 Label notHole(env); 1153 Label afterLoop(env); 1154 GateRef elementsLen = GetLengthOfTaggedArray(elements); 1155 Jump(&loopHead); 1156 LoopBegin(&loopHead); 1157 { 1158 BRANCH(Int32UnsignedLessThan(*j, elementsLen), &iLessLength, &afterLoop); 1159 Bind(&iLessLength); 1160 { 1161 GateRef element = GetTaggedValueWithElementsKind(obj, *j); 1162 BRANCH(TaggedIsHole(element), &loopEnd, ¬Hole); 1163 Bind(¬Hole); 1164 GateRef str = IntToEcmaString(glue, *j); 1165 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elementArray, 1166 *elementIndex, str); 1167 elementIndex = Int32Add(*elementIndex, Int32(1)); 1168 Jump(&loopEnd); 1169 } 1170 Bind(&loopEnd); 1171 j = Int32Add(*j, Int32(1)); 1172 LoopEnd(&loopHead, env, glue); 1173 Bind(&afterLoop); 1174 { 1175 result = elementArray; 1176 Label needTrim(env); 1177 BRANCH(Int32LessThan(*elementIndex, numOfElements), &needTrim, &exit); 1178 Bind(&needTrim); 1179 { 1180 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), 1181 {glue, elementArray, ZExtInt32ToInt64(*elementIndex)}); 1182 Jump(&exit); 1183 } 1184 } 1185 } 1186 } 1187 Bind(&isDictMode); 1188 { 1189 CallRuntime(glue, RTSTUB_ID(NumberDictionaryGetAllEnumKeys), 1190 { elements, elementArray, IntToTaggedInt(*elementIndex) }); 1191 result = elementArray; 1192 Jump(&exit); 1193 } 1194 } 1195 Bind(&propsIsZero); 1196 { 1197 GateRef emptyArray = GetEmptyArray(glue); 1198 result = emptyArray; 1199 Jump(&exit); 1200 } 1201 Bind(&exit); 1202 auto ret = *result; 1203 env->SubCfgExit(); 1204 return ret; 1205} 1206 1207GateRef BuiltinsObjectStubBuilder::IsNotSlowObjectKey(GateRef obj) 1208{ 1209 auto env = GetEnvironment(); 1210 return LogicAndBuilder(env) 1211 .And(IsJSObject(obj)) 1212 .And(BoolNot(LogicOrBuilder(env).Or(IsTypedArray(obj)).Or(IsModuleNamespace(obj)) 1213 .Or(IsJSGlobalObject(obj)).Done())) 1214 .Done(); 1215} 1216 1217void BuiltinsObjectStubBuilder::Keys(Variable *result, Label *exit, Label *slowPath) 1218{ 1219 auto env = GetEnvironment(); 1220 GateRef msg = GetCallArg0(numArgs_); 1221 // 1. Let obj be ToObject(O). 1222 GateRef obj = ToObject(glue_, msg); 1223 Label isPendingException(env); 1224 Label noPendingException(env); 1225 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException); 1226 Bind(&isPendingException); 1227 Jump(exit); 1228 Bind(&noPendingException); 1229 Label isFast(env); 1230 // EnumerableOwnNames(obj) 1231 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath); 1232 Bind(&isFast); 1233 { 1234 Label hasKeyAndEle(env); 1235 Label nonKeyAndEle(env); 1236 GateRef elementArray = GetEnumElementKeys(glue_, obj); 1237 GateRef keyArray = GetAllEnumKeys(glue_, obj); 1238 GateRef lengthOfKeys = GetLengthOfTaggedArray(keyArray); 1239 GateRef lengthOfElements = GetLengthOfTaggedArray(elementArray); 1240 GateRef KeyAndEle = BitAnd(Int32NotEqual(lengthOfElements, Int32(0)), Int32NotEqual(lengthOfKeys, Int32(0))); 1241 BRANCH(KeyAndEle, &hasKeyAndEle, &nonKeyAndEle); 1242 Bind(&hasKeyAndEle); 1243 { 1244 GateRef allKeys = AppendSkipHole(glue_, elementArray, keyArray, Int32Add(lengthOfKeys, lengthOfElements)); 1245 *result = CreateArrayFromList(glue_, allKeys); 1246 Jump(exit); 1247 } 1248 Bind(&nonKeyAndEle); 1249 { 1250 Label hasKey(env); 1251 Label nonKey(env); 1252 BRANCH(Int32NotEqual(lengthOfKeys, Int32(0)), &hasKey, &nonKey); 1253 Bind(&hasKey); 1254 { 1255 *result = CreateArrayFromList(glue_, keyArray); 1256 Jump(exit); 1257 } 1258 Bind(&nonKey); 1259 { 1260 Label hasEle(env); 1261 Label nonEle(env); 1262 BRANCH(Int32NotEqual(lengthOfElements, Int32(0)), &hasEle, &nonEle); 1263 Bind(&hasEle); 1264 { 1265 *result = CreateArrayFromList(glue_, elementArray); 1266 Jump(exit); 1267 } 1268 Bind(&nonEle); 1269 { 1270 GateRef emptyArray = GetEmptyArray(glue_); 1271 *result = CreateArrayFromList(glue_, emptyArray); 1272 Jump(exit); 1273 } 1274 } 1275 } 1276 } 1277} 1278 1279void BuiltinsObjectStubBuilder::GetPrototypeOf(Variable *result, Label *exit, Label *slowPath) 1280{ 1281 auto env = GetEnvironment(); 1282 Label isPendingException(env); 1283 Label noPendingException(env); 1284 GateRef msg = GetCallArg0(numArgs_); 1285 GateRef obj = ToObject(glue_, msg); 1286 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException); 1287 Bind(&isPendingException); 1288 { 1289 Jump(exit); 1290 } 1291 Bind(&noPendingException); 1292 { 1293 Label isEcmaObject(env); 1294 Label notJsProxy(env); 1295 BRANCH(IsEcmaObject(obj), &isEcmaObject, slowPath); 1296 Bind(&isEcmaObject); 1297 { 1298 BRANCH(IsJsProxy(obj), slowPath, ¬JsProxy); 1299 Bind(¬JsProxy); 1300 { 1301 GateRef hClass = LoadHClass(obj); 1302 GateRef prototype = GetPrototypeFromHClass(hClass); 1303 *result = prototype; 1304 Jump(exit); 1305 } 1306 } 1307 } 1308} 1309 1310void BuiltinsObjectStubBuilder::SetPrototypeOf(Variable *result, Label *exit, Label *slowPath) 1311{ 1312 auto env = GetEnvironment(); 1313 GateRef obj = GetCallArg0(numArgs_); 1314 DEFVARIABLE(proto, VariableType::JS_ANY(), Undefined()); 1315 Label checkJsObj(env); 1316 Label setProto(env); 1317 BRANCH(TaggedIsUndefinedOrNull(obj), slowPath, &checkJsObj); 1318 Bind(&checkJsObj); 1319 { 1320 Label checkProto(env); 1321 proto = GetCallArg1(numArgs_); 1322 GateRef protoVal = *proto; 1323 BRANCH(LogicOrBuilder(env).Or(TaggedIsNull(protoVal)).Or(IsEcmaObject(protoVal)).Done(), 1324 &checkProto, slowPath); 1325 Bind(&checkProto); 1326 { 1327 Label isEcmaObject(env); 1328 Label notEcmaObject(env); 1329 BRANCH(IsEcmaObject(obj), &isEcmaObject, ¬EcmaObject); 1330 Bind(&isEcmaObject); 1331 Jump(&setProto); 1332 Bind(¬EcmaObject); 1333 { 1334 *result = obj; 1335 Jump(exit); 1336 } 1337 } 1338 } 1339 Bind(&setProto); 1340 { 1341 Label objNotSpecial(env); 1342 GateRef protoVal = *proto; 1343 GateRef isSpecialobj = LogicOrBuilder(env).Or(IsJsProxy(obj)).Or(TaggedIsSharedObj(obj)) 1344 .Or(TaggedIsSharedObj(protoVal)).Or(ObjIsSpecialContainer(obj)).Or(IsModuleNamespace(obj)).Done(); 1345 BRANCH(isSpecialobj, slowPath, &objNotSpecial); 1346 Bind(&objNotSpecial); 1347 Label isFunction(env); 1348 Label notFunction(env); 1349 GateRef isFunc = LogicAndBuilder(env) 1350 .And(TaggedIsHeapObject(obj)).And(TaggedIsHeapObject(protoVal)) 1351 .And(IsJSFunction(obj)).And(IsJSFunction(protoVal)) 1352 .Done(); 1353 BRANCH(isFunc, &isFunction, ¬Function); 1354 Bind(&isFunction); 1355 { 1356 Label isDerivedCtor(env); 1357 auto protoOrHclass = Load(VariableType::JS_ANY(), obj, 1358 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 1359 GateRef isDerivedCtorCheck = LogicAndBuilder(env).And(TaggedIsHeapObject(protoOrHclass)) 1360 .And(IsJSHClass(protoOrHclass)).And(IsDerived(obj)).Done(); 1361 BRANCH(isDerivedCtorCheck, &isDerivedCtor, ¬Function); 1362 Bind(&isDerivedCtor); 1363 auto cachedJSHClass = GetPrototypeFromHClass(protoOrHclass); 1364 SetProtoOrHClassToFunction(glue_, obj, cachedJSHClass); 1365 Jump(¬Function); 1366 } 1367 Bind(¬Function); 1368 { 1369 Label statusIsTrue(env); 1370 Label statusIsFalse(env); 1371 BRANCH(ObjectSetPrototype(glue_, obj, *proto), &statusIsTrue, &statusIsFalse); 1372 Bind(&statusIsTrue); 1373 *result = obj; 1374 Jump(exit); 1375 Bind(&statusIsFalse); 1376 { 1377 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPrototypeOfFailed)); 1378 CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) }); 1379 *result = Exception(); 1380 Jump(exit); 1381 } 1382 } 1383 } 1384} 1385 1386GateRef BuiltinsObjectStubBuilder::ObjectSetPrototype(GateRef glue, GateRef obj, GateRef proto) 1387{ 1388 auto env = GetEnvironment(); 1389 Label subEntry(env); 1390 env->SubCfgEntry(&subEntry); 1391 Label exit(env); 1392 1393 DEFVARIABLE(result, VariableType::BOOL(), False()); 1394 Label isEqual(env); 1395 Label notEqual(env); 1396 Label isExtensible(env); 1397 Label notExtensible(env); 1398 GateRef current = GetPrototype(glue, obj); 1399 BRANCH(IntPtrEqual(proto, current), &isEqual, ¬Equal); 1400 Bind(&isEqual); 1401 { 1402 result = True(); 1403 Jump(&exit); 1404 } 1405 Bind(¬Equal); 1406 { 1407 BRANCH(IsExtensible(obj), &isExtensible, ¬Extensible); 1408 Bind(&isExtensible); 1409 { 1410 DEFVARIABLE(done, VariableType::BOOL(), False()); 1411 DEFVARIABLE(tempProto, VariableType::JS_ANY(), proto); 1412 Label loopHead(env); 1413 Label loopEnd(env); 1414 Label next(env); 1415 Label loopExit(env); 1416 Jump(&loopHead); 1417 LoopBegin(&loopHead); 1418 { 1419 BRANCH(BoolNot(*done), &next, &loopExit); 1420 Bind(&next); 1421 { 1422 Label isNull(env); 1423 Label notNull(env); 1424 Label isEqual2(env); 1425 Label notEqual2(env); 1426 Label protoNotProxy(env); 1427 GateRef tempProtoVal = *tempProto; 1428 GateRef protoIsNull = LogicOrBuilder(env).Or(TaggedIsNull(tempProtoVal)) 1429 .Or(BoolNot(IsEcmaObject(tempProtoVal))).Done(); 1430 BRANCH(protoIsNull, &isNull, ¬Null); 1431 Bind(&isNull); 1432 { 1433 done = True(); 1434 Jump(&loopEnd); 1435 } 1436 Bind(¬Null); 1437 { 1438 BRANCH(IntPtrEqual(*tempProto, obj), &isEqual2, ¬Equal2); 1439 Bind(&isEqual2); 1440 { 1441 result = False(); 1442 Jump(&exit); 1443 } 1444 Bind(¬Equal2); 1445 { 1446 BRANCH(IsJsProxy(*tempProto), &loopExit, &protoNotProxy); 1447 Bind(&protoNotProxy); 1448 { 1449 tempProto = GetPrototype(glue, *tempProto); 1450 Jump(&loopEnd); 1451 } 1452 } 1453 } 1454 } 1455 Bind(&loopEnd); 1456 LoopEnd(&loopHead, env, glue_); 1457 } 1458 Bind(&loopExit); 1459 CallRuntime(glue, RTSTUB_ID(SetPrototypeTransition), { obj, proto}); 1460 result = True(); 1461 Jump(&exit); 1462 } 1463 Bind(¬Extensible); 1464 { 1465 result = False(); 1466 Jump(&exit); 1467 } 1468 } 1469 Bind(&exit); 1470 auto ret = *result; 1471 env->SubCfgExit(); 1472 return ret; 1473} 1474 1475void BuiltinsObjectStubBuilder::GetOwnPropertyNames(Variable *result, Label *exit, Label *slowPath) 1476{ 1477 auto env = GetEnvironment(); 1478 Label isPendingException(env); 1479 Label noPendingException(env); 1480 GateRef msg = GetCallArg0(numArgs_); 1481 GateRef obj = ToObject(glue_, msg); 1482 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException); 1483 Bind(&isPendingException); 1484 { 1485 Jump(exit); 1486 } 1487 Bind(&noPendingException); 1488 { 1489 Label isFast(env); 1490 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath); 1491 Bind(&isFast); 1492 { 1493 Label notDictMode(env); 1494 GateRef isDictMode = LogicOrBuilder(env).Or(IsDictionaryMode(GetElementsArray(obj))) 1495 .Or(IsDictionaryMode(GetPropertiesArray(obj))).Done(); 1496 BRANCH(isDictMode, slowPath, ¬DictMode); 1497 Bind(¬DictMode); 1498 { 1499 Label getAllElementKeys(env); 1500 Label checkNumOfKeys(env); 1501 GateRef hclass = LoadHClass(obj); 1502 GateRef numOfElements = GetNumberOfElements(obj); 1503 GateRef numOfKeys = GetNumberOfPropsFromHClass(hclass); 1504 GateRef keyLen = Int32Add(numOfElements, numOfKeys); 1505 NewObjectStubBuilder newBuilder(this); 1506 GateRef keyArray = newBuilder.NewTaggedArray(glue_, keyLen); 1507 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &getAllElementKeys, &checkNumOfKeys); 1508 Bind(&getAllElementKeys); 1509 { 1510 GetAllElementKeys(glue_, obj, Int32(0), keyArray); 1511 Jump(&checkNumOfKeys); 1512 } 1513 Bind(&checkNumOfKeys); 1514 { 1515 Label getAllPropertyKeys(env); 1516 Label checkElementType(env); 1517 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &getAllPropertyKeys, &checkElementType); 1518 Bind(&getAllPropertyKeys); 1519 { 1520 GetAllPropertyKeys(glue_, obj, numOfElements, keyArray); 1521 Jump(&checkElementType); 1522 } 1523 Bind(&checkElementType); 1524 { 1525 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 1526 DEFVARIABLE(pos, VariableType::INT32(), Int32(0)); 1527 Label loopHead(env); 1528 Label loopEnd(env); 1529 Label next(env); 1530 Label loopExit(env); 1531 Label needTrim(env); 1532 Label setResult(env); 1533 Jump(&loopHead); 1534 LoopBegin(&loopHead); 1535 { 1536 BRANCH(Int32UnsignedLessThan(*i, keyLen), &next, &loopExit); 1537 Bind(&next); 1538 { 1539 Label isString(env); 1540 Label setValue(env); 1541 Label adjustPos(env); 1542 GateRef element = GetValueFromTaggedArray(keyArray, *i); 1543 BRANCH(TaggedIsString(element), &isString, &loopEnd); 1544 Bind(&isString); 1545 { 1546 // compare pos and i to skip holes 1547 BRANCH(Int32Equal(*pos, *i), &adjustPos, &setValue); 1548 Bind(&setValue); 1549 { 1550 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, keyArray, *pos, element); 1551 Jump(&adjustPos); 1552 } 1553 Bind(&adjustPos); 1554 { 1555 pos = Int32Add(*pos, Int32(1)); 1556 Jump(&loopEnd); 1557 } 1558 } 1559 } 1560 Bind(&loopEnd); 1561 i = Int32Add(*i, Int32(1)); 1562 LoopEnd(&loopHead, env, glue_); 1563 } 1564 Bind(&loopExit); 1565 BRANCH(Int32UnsignedLessThan(*pos, keyLen), &needTrim, &setResult); 1566 Bind(&needTrim); 1567 { 1568 CallNGCRuntime(glue_, RTSTUB_ID(ArrayTrim), {glue_, keyArray, ZExtInt32ToInt64(*pos)}); 1569 Jump(&setResult); 1570 } 1571 Bind(&setResult); 1572 { 1573 *result = CreateArrayFromList(glue_, keyArray); 1574 Jump(exit); 1575 } 1576 } 1577 } 1578 } 1579 } 1580 } 1581} 1582 1583void BuiltinsObjectStubBuilder::GetOwnPropertySymbols(Variable *result, Label *exit, Label *slowPath) 1584{ 1585 auto env = GetEnvironment(); 1586 Label isPendingException(env); 1587 Label noPendingException(env); 1588 GateRef msg = GetCallArg0(numArgs_); 1589 GateRef obj = ToObject(glue_, msg); 1590 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException); 1591 Bind(&isPendingException); 1592 { 1593 Jump(exit); 1594 } 1595 Bind(&noPendingException); 1596 { 1597 Label isFast(env); 1598 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath); 1599 Bind(&isFast); 1600 { 1601 Label notDictMode(env); 1602 GateRef isDictMode = LogicOrBuilder(env).Or(IsDictionaryMode(GetElementsArray(obj))) 1603 .Or(IsDictionaryMode(GetPropertiesArray(obj))).Done(); 1604 BRANCH(isDictMode, slowPath, ¬DictMode); 1605 Bind(¬DictMode); 1606 { 1607 Label getAllElementKeys(env); 1608 Label checkNumOfKeys(env); 1609 GateRef hclass = LoadHClass(obj); 1610 GateRef numOfElements = GetNumberOfElements(obj); 1611 GateRef numOfKeys = GetNumberOfPropsFromHClass(hclass); 1612 GateRef keyLen = Int32Add(numOfElements, numOfKeys); 1613 NewObjectStubBuilder newBuilder(this); 1614 GateRef keyArray = newBuilder.NewTaggedArray(glue_, keyLen); 1615 BRANCH(Int32GreaterThan(numOfElements, Int32(0)), &getAllElementKeys, &checkNumOfKeys); 1616 Bind(&getAllElementKeys); 1617 { 1618 GetAllElementKeys(glue_, obj, Int32(0), keyArray); 1619 Jump(&checkNumOfKeys); 1620 } 1621 Bind(&checkNumOfKeys); 1622 { 1623 Label getAllPropertyKeys(env); 1624 Label checkElementType(env); 1625 BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &getAllPropertyKeys, &checkElementType); 1626 Bind(&getAllPropertyKeys); 1627 { 1628 GetAllPropertyKeys(glue_, obj, numOfElements, keyArray); 1629 Jump(&checkElementType); 1630 } 1631 Bind(&checkElementType); 1632 { 1633 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 1634 DEFVARIABLE(pos, VariableType::INT32(), Int32(0)); 1635 Label loopHead(env); 1636 Label loopEnd(env); 1637 Label next(env); 1638 Label loopExit(env); 1639 Label needTrim(env); 1640 Label setResult(env); 1641 Jump(&loopHead); 1642 LoopBegin(&loopHead); 1643 { 1644 BRANCH(Int32UnsignedLessThan(*i, keyLen), &next, &loopExit); 1645 Bind(&next); 1646 { 1647 Label isSymbol(env); 1648 Label setValue(env); 1649 Label adjustPos(env); 1650 GateRef element = GetValueFromTaggedArray(keyArray, *i); 1651 BRANCH(TaggedIsSymbol(element), &isSymbol, &loopEnd); 1652 Bind(&isSymbol); 1653 { 1654 // compare pos and i to skip holes 1655 BRANCH(Int32Equal(*pos, *i), &adjustPos, &setValue); 1656 Bind(&setValue); 1657 { 1658 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, keyArray, *pos, element); 1659 Jump(&adjustPos); 1660 } 1661 Bind(&adjustPos); 1662 { 1663 pos = Int32Add(*pos, Int32(1)); 1664 Jump(&loopEnd); 1665 } 1666 } 1667 } 1668 Bind(&loopEnd); 1669 i = Int32Add(*i, Int32(1)); 1670 LoopEnd(&loopHead, env, glue_); 1671 } 1672 Bind(&loopExit); 1673 BRANCH(Int32UnsignedLessThan(*pos, keyLen), &needTrim, &setResult); 1674 Bind(&needTrim); 1675 { 1676 CallNGCRuntime(glue_, RTSTUB_ID(ArrayTrim), {glue_, keyArray, ZExtInt32ToInt64(*pos)}); 1677 Jump(&setResult); 1678 } 1679 Bind(&setResult); 1680 { 1681 *result = CreateArrayFromList(glue_, keyArray); 1682 Jump(exit); 1683 } 1684 } 1685 } 1686 } 1687 } 1688 } 1689} 1690 1691GateRef BuiltinsObjectStubBuilder::GetAllElementKeys(GateRef glue, GateRef obj, GateRef offset, GateRef array) 1692{ 1693 auto env = GetEnvironment(); 1694 Label subEntry(env); 1695 env->SubCfgEntry(&subEntry); 1696 1697 DEFVARIABLE(i, VariableType::INT32(), offset); 1698 DEFVARIABLE(j, VariableType::INT32(), Int32(0)); 1699 DEFVARIABLE(pos, VariableType::INT32(), Int32(0)); 1700 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1701 Label isJSPrimitiveRef(env); 1702 Label isPrimitiveString(env); 1703 Label notPrimitiveString(env); 1704 BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, ¬PrimitiveString); 1705 Bind(&isJSPrimitiveRef); 1706 { 1707 GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET)); 1708 BRANCH(TaggedIsString(value), &isPrimitiveString, ¬PrimitiveString); 1709 Bind(&isPrimitiveString); 1710 { 1711 Label loopHead(env); 1712 Label loopEnd(env); 1713 Label next(env); 1714 GateRef elementIndex = Int32Add(GetLengthFromString(value), offset); 1715 Jump(&loopHead); 1716 LoopBegin(&loopHead); 1717 { 1718 BRANCH(Int32UnsignedLessThan(*i, elementIndex), &next, ¬PrimitiveString); 1719 Bind(&next); 1720 { 1721 GateRef str = IntToEcmaString(glue, *i); 1722 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *pos, str); 1723 pos = Int32Add(*pos, Int32(1)); 1724 Jump(&loopEnd); 1725 } 1726 Bind(&loopEnd); 1727 i = Int32Add(*i, Int32(1)); 1728 LoopEnd(&loopHead, env, glue); 1729 } 1730 } 1731 } 1732 Bind(¬PrimitiveString); 1733 { 1734 Label isDictMode(env); 1735 Label notDictMode(env); 1736 Label exit(env); 1737 GateRef elements = GetElementsArray(obj); 1738 BRANCH(IsDictionaryMode(elements), &isDictMode, ¬DictMode); 1739 Bind(&isDictMode); 1740 { 1741 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); 1742 Jump(&exit); 1743 } 1744 Bind(¬DictMode); 1745 { 1746 Label loopHead(env); 1747 Label loopEnd(env); 1748 Label next(env); 1749 Label loopExit(env); 1750 GateRef elementsLen = GetLengthOfTaggedArray(elements); 1751 Jump(&loopHead); 1752 LoopBegin(&loopHead); 1753 { 1754 Label notHole(env); 1755 BRANCH(Int32UnsignedLessThan(*j, elementsLen), &next, &loopExit); 1756 Bind(&next); 1757 { 1758 GateRef element = GetTaggedValueWithElementsKind(obj, *j); 1759 BRANCH(TaggedIsHole(element), &loopEnd, ¬Hole); 1760 Bind(¬Hole); 1761 { 1762 GateRef str = IntToEcmaString(glue, *j); 1763 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *pos, str); 1764 pos = Int32Add(*pos, Int32(1)); 1765 Jump(&loopEnd); 1766 } 1767 } 1768 Bind(&loopEnd); 1769 j = Int32Add(*j, Int32(1)); 1770 LoopEnd(&loopHead, env, glue); 1771 Bind(&loopExit); 1772 result = array; 1773 Jump(&exit); 1774 } 1775 } 1776 Bind(&exit); 1777 auto ret = *result; 1778 env->SubCfgExit(); 1779 return ret; 1780 } 1781} 1782 1783GateRef BuiltinsObjectStubBuilder::GetAllPropertyKeys(GateRef glue, GateRef obj, GateRef offset, GateRef array) 1784{ 1785 auto env = GetEnvironment(); 1786 Label subEntry(env); 1787 env->SubCfgEntry(&subEntry); 1788 1789 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 1790 DEFVARIABLE(pos, VariableType::INT32(), Int32(0)); 1791 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); 1792 Label isDictionary(env); 1793 Label notDictionary(env); 1794 Label exit(env); 1795 GateRef properties = GetPropertiesArray(obj); 1796 BRANCH(IsDictionaryMode(properties), &isDictionary, ¬Dictionary); 1797 Bind(&isDictionary); 1798 { 1799 FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) }); 1800 Jump(&exit); 1801 } 1802 Bind(¬Dictionary); 1803 { 1804 Label loopHead(env); 1805 Label loopEnd(env); 1806 Label next(env); 1807 Label loopExit(env); 1808 GateRef hclass = LoadHClass(obj); 1809 GateRef layout = GetLayoutFromHClass(hclass); 1810 GateRef number = GetNumberOfPropsFromHClass(hclass); 1811 Jump(&loopHead); 1812 LoopBegin(&loopHead); 1813 { 1814 BRANCH(Int32UnsignedLessThan(*i, number), &next, &loopExit); 1815 Bind(&next); 1816 { 1817 Label checkString(env); 1818 Label checkSymbol(env); 1819 Label setValue(env); 1820 GateRef key = GetKey(layout, *i); 1821 BRANCH(TaggedIsString(key), &checkString, &checkSymbol); 1822 Bind(&checkString); 1823 { 1824 BRANCH(IsUninitializedProperty(obj, *i, layout), &checkSymbol, &setValue); 1825 } 1826 Bind(&checkSymbol); 1827 { 1828 BRANCH(TaggedIsSymbol(key), &setValue, &loopEnd); 1829 } 1830 Bind(&setValue); 1831 { 1832 SetValueToTaggedArray(VariableType::JS_ANY(), glue_, array, Int32Add(*pos, offset), key); 1833 pos = Int32Add(*pos, Int32(1)); 1834 Jump(&loopEnd); 1835 } 1836 } 1837 Bind(&loopEnd); 1838 i = Int32Add(*i, Int32(1)); 1839 LoopEnd(&loopHead, env, glue_); 1840 } 1841 Bind(&loopExit); 1842 Jump(&exit); 1843 } 1844 Bind(&exit); 1845 auto ret = *result; 1846 env->SubCfgExit(); 1847 return ret; 1848} 1849 1850void BuiltinsObjectStubBuilder::Entries(Variable* result, Label* exit, Label* slowPath) 1851{ 1852 auto env = GetEnvironment(); 1853 Label isPendingException(env); 1854 Label noPendingException(env); 1855 GateRef msg = GetCallArg0(numArgs_); 1856 GateRef obj = ToObject(glue_, msg); 1857 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException); 1858 Bind(&isPendingException); 1859 { 1860 Jump(exit); 1861 } 1862 Bind(&noPendingException); 1863 { 1864 Label isFast(env); 1865 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath); 1866 Bind(&isFast); 1867 { 1868 Label notDictMode(env); 1869 GateRef isDictMode = LogicOrBuilder(env).Or(IsDictionaryMode(GetElementsArray(obj))) 1870 .Or(IsDictionaryMode(GetPropertiesArray(obj))).Done(); 1871 BRANCH(isDictMode, slowPath, ¬DictMode); 1872 Bind(¬DictMode); 1873 { 1874 Label hasKeyAndEle(env); 1875 Label nonKeyAndEle(env); 1876 GateRef elementArray = GetEnumElementEntries(glue_, obj, slowPath); 1877 GateRef propertyArray = GetEnumPropertyEntries(glue_, obj, slowPath); 1878 GateRef elementLen = GetLengthOfTaggedArray(elementArray); 1879 GateRef propertyLen = GetLengthOfTaggedArray(propertyArray); 1880 GateRef keyAndEle = BitAnd(Int32NotEqual(elementLen, Int32(0)), Int32NotEqual(propertyLen, Int32(0))); 1881 BRANCH(keyAndEle, &hasKeyAndEle, &nonKeyAndEle); 1882 Bind(&hasKeyAndEle); 1883 { 1884 GateRef allEntries = AppendSkipHole(glue_, elementArray, propertyArray, 1885 Int32Add(elementLen, propertyLen)); 1886 *result = CreateArrayFromList(glue_, allEntries); 1887 Jump(exit); 1888 } 1889 Bind(&nonKeyAndEle); 1890 { 1891 Label hasKey(env); 1892 Label nonKey(env); 1893 BRANCH(Int32NotEqual(propertyLen, Int32(0)), &hasKey, &nonKey); 1894 Bind(&hasKey); 1895 { 1896 *result = CreateArrayFromList(glue_, propertyArray); 1897 Jump(exit); 1898 } 1899 Bind(&nonKey); 1900 { 1901 Label hasEle(env); 1902 Label nonEle(env); 1903 BRANCH(Int32NotEqual(elementLen, Int32(0)), &hasEle, &nonEle); 1904 Bind(&hasEle); 1905 { 1906 *result = CreateArrayFromList(glue_, elementArray); 1907 Jump(exit); 1908 } 1909 Bind(&nonEle); 1910 { 1911 GateRef emptyArray = GetEmptyArray(glue_); 1912 *result = CreateArrayFromList(glue_, emptyArray); 1913 Jump(exit); 1914 } 1915 } 1916 } 1917 } 1918 } 1919 } 1920} 1921 1922GateRef BuiltinsObjectStubBuilder::GetEnumElementEntries(GateRef glue, GateRef obj, Label* slowPath) 1923{ 1924 auto env = GetEnvironment(); 1925 Label subEntry(env); 1926 env->SubCfgEntry(&subEntry); 1927 1928 DEFVARIABLE(idx, VariableType::INT32(), Int32(0)); 1929 DEFVARIABLE(pos, VariableType::INT32(), Int32(0)); 1930 GateRef elementKeys = GetEnumElementKeys(glue, obj); 1931 GateRef elements = GetElementsArray(obj); 1932 GateRef len = GetLengthOfTaggedArray(elements); 1933 GateRef realLen = GetLengthOfTaggedArray(elementKeys); 1934 NewObjectStubBuilder newBuilder(this); 1935 GateRef numElementArray = newBuilder.NewTaggedArray(glue, realLen); 1936 1937 Label isJSPrimitiveRef(env); 1938 Label notPrimitiveString(env); 1939 Label notDictMode(env); 1940 BRANCH(IsJSPrimitiveRef(obj), &isJSPrimitiveRef, ¬PrimitiveString); 1941 Bind(&isJSPrimitiveRef); 1942 GateRef els = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET)); 1943 BRANCH(TaggedIsString(els), slowPath, ¬PrimitiveString); 1944 Bind(¬PrimitiveString); 1945 BRANCH(IsDictionaryMode(elements), slowPath, ¬DictMode); 1946 Bind(¬DictMode); 1947 { 1948 Label loopHead(env); 1949 Label loopEnd(env); 1950 Label LoopNext(env); 1951 Label loopExit(env); 1952 1953 Jump(&loopHead); 1954 LoopBegin(&loopHead); 1955 { 1956 BRANCH(Int32LessThan(*idx, len), &LoopNext, &loopExit); 1957 Bind(&LoopNext); 1958 GateRef value = GetTaggedValueWithElementsKind(obj, *idx); 1959 Label notHole(env); 1960 BRANCH(TaggedIsHole(value), &loopEnd, ¬Hole); 1961 Bind(¬Hole); 1962 { 1963 NewObjectStubBuilder newBuilderProp(this); 1964 GateRef arrayProp = newBuilderProp.NewTaggedArray(glue, Int32(2)); 1965 GateRef str = IntToEcmaString(glue, *idx); 1966 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(0), str); 1967 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(1), value); 1968 GateRef propArray = CreateArrayFromList(glue, arrayProp); 1969 SetValueToTaggedArray(VariableType::JS_ANY(), glue, numElementArray, *pos, propArray); 1970 pos = Int32Add(*pos, Int32(1)); 1971 Jump(&loopEnd); 1972 } 1973 } 1974 1975 Bind(&loopEnd); 1976 idx = Int32Add(*idx, Int32(1)); 1977 LoopEnd(&loopHead, env, glue); 1978 Bind(&loopExit); 1979 auto ret = numElementArray; 1980 env->SubCfgExit(); 1981 return ret; 1982 } 1983} 1984 1985GateRef BuiltinsObjectStubBuilder::GetEnumPropertyEntries(GateRef glue, GateRef obj, Label* slowPath) 1986{ 1987 auto env = GetEnvironment(); 1988 Label subEntry(env); 1989 env->SubCfgEntry(&subEntry); 1990 Label exit(env); 1991 Label notDictionary(env); 1992 GateRef array = GetPropertiesArray(obj); 1993 BRANCH(IsDictionaryMode(array), slowPath, ¬Dictionary); 1994 Bind(¬Dictionary); 1995 1996 DEFVARIABLE(idx, VariableType::INT32(), Int32(0)); 1997 DEFVARIABLE(length, VariableType::INT32(), Int32(0)); 1998 GateRef cls = LoadHClass(obj); 1999 GateRef len = GetNumberOfPropsFromHClass(cls); 2000 GateRef layout = GetLayoutFromHClass(cls); 2001 2002 NewObjectStubBuilder newBuilder(this); 2003 GateRef allEnumArray = newBuilder.NewTaggedArray(glue, len); 2004 2005 Label loopHead(env); 2006 Label loopEnd(env); 2007 Label LoopNext(env); 2008 Label loopExit(env); 2009 Label propertyIsEnumerable(env); 2010 Label propertyIsString(env); 2011 2012 Jump(&loopHead); 2013 LoopBegin(&loopHead); 2014 { 2015 BRANCH(Int32LessThan(*idx, len), &LoopNext, &loopExit); 2016 Bind(&LoopNext); 2017 NewObjectStubBuilder newBuilderProp(this); 2018 GateRef arrayProp = newBuilderProp.NewTaggedArray(glue, Int32(2)); 2019 GateRef key = GetKeyFromLayoutInfo(layout, *idx); 2020 GateRef attr = GetPropAttrFromLayoutInfo(layout, *idx); 2021 GateRef value = JSObjectGetProperty(obj, cls, attr); 2022 BRANCH(IsEnumerable(attr), &propertyIsEnumerable, &loopEnd); 2023 Bind(&propertyIsEnumerable); 2024 { 2025 BRANCH(TaggedIsString(key), &propertyIsString, &loopEnd); 2026 Bind(&propertyIsString); 2027 { 2028 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(0), key); 2029 SetValueToTaggedArray(VariableType::JS_ANY(), glue, arrayProp, Int32(1), value); 2030 GateRef propArray = CreateArrayFromList(glue, arrayProp); 2031 SetValueToTaggedArray(VariableType::JS_ANY(), glue, allEnumArray, *length, propArray); 2032 length = Int32Add(*length, Int32(1)); 2033 Jump(&loopEnd); 2034 } 2035 } 2036 } 2037 Bind(&loopEnd); 2038 idx = Int32Add(*idx, Int32(1)); 2039 LoopEnd(&loopHead, env, glue); 2040 Bind(&loopExit); 2041 Label needTrim(env); 2042 BRANCH(Int32LessThan(*length, len), &needTrim, &exit); 2043 Bind(&needTrim); 2044 { 2045 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, allEnumArray, ZExtInt32ToInt64(*length)}); 2046 Jump(&exit); 2047 } 2048 Bind(&exit); 2049 auto ret = allEnumArray; 2050 env->SubCfgExit(); 2051 return ret; 2052} 2053 2054void BuiltinsObjectStubBuilder::IsFrozen(Variable *result, Label *exit, Label *slowPath) 2055{ 2056 auto env = GetEnvironment(); 2057 GateRef obj = GetCallArg0(numArgs_); 2058 Label isEcmaObj(env); 2059 Label notEcmaObj(env); 2060 BRANCH(BoolNot(IsEcmaObject(obj)), ¬EcmaObj, &isEcmaObj); 2061 Bind(¬EcmaObj); 2062 { 2063 result->WriteVariable(TaggedTrue()); 2064 Jump(exit); 2065 } 2066 Bind(&isEcmaObj); 2067 { 2068 // 1: IntegrityLevel::FROZEN 2069 GateRef status = TestIntegrityLevel(glue_, obj, Int32(1), slowPath); 2070 Label statusIsTrue(env); 2071 Label statusIsFalse(env); 2072 BRANCH(status, &statusIsTrue, &statusIsFalse); 2073 Bind(&statusIsTrue); 2074 { 2075 result->WriteVariable(TaggedTrue()); 2076 Jump(exit); 2077 } 2078 Bind(&statusIsFalse); 2079 { 2080 result->WriteVariable(TaggedFalse()); 2081 Jump(exit); 2082 } 2083 } 2084} 2085 2086void BuiltinsObjectStubBuilder::IsSealed(Variable *result, Label *exit, Label *slowPath) 2087{ 2088 auto env = GetEnvironment(); 2089 GateRef obj = GetCallArg0(numArgs_); 2090 Label isEcmaObj(env); 2091 Label notEcmaObj(env); 2092 BRANCH(BoolNot(IsEcmaObject(obj)), ¬EcmaObj, &isEcmaObj); 2093 Bind(¬EcmaObj); 2094 { 2095 result->WriteVariable(TaggedTrue()); 2096 Jump(exit); 2097 } 2098 Bind(&isEcmaObj); 2099 { 2100 // 0: IntegrityLevel::SEALED 2101 GateRef status = TestIntegrityLevel(glue_, obj, Int32(0), slowPath); 2102 Label statusIsTrue(env); 2103 Label statusIsFalse(env); 2104 BRANCH(status, &statusIsTrue, &statusIsFalse); 2105 Bind(&statusIsTrue); 2106 { 2107 result->WriteVariable(TaggedTrue()); 2108 Jump(exit); 2109 } 2110 Bind(&statusIsFalse); 2111 { 2112 result->WriteVariable(TaggedFalse()); 2113 Jump(exit); 2114 } 2115 } 2116} 2117 2118GateRef BuiltinsObjectStubBuilder::TestIntegrityLevel(GateRef glue, 2119 GateRef obj, GateRef level, Label *slowPath) 2120{ 2121 auto env = GetEnvironment(); 2122 Label entryPass(env); 2123 env->SubCfgEntry(&entryPass); 2124 DEFVARIABLE(result, VariableType::BOOL(), False()); 2125 Label isExtensible(env); 2126 Label isNotExtensible(env); 2127 Label exit(env); 2128 2129 Label isNotJsProxy(env); 2130 Label isNotTypedArray(env); 2131 Label isNotModuleNamespace(env); 2132 Label isNotSpecialContainer(env); 2133 Label notDicMode(env); 2134 Label notHasElementKey(env); 2135 BRANCH(IsJsProxy(obj), slowPath, &isNotJsProxy); 2136 Bind(&isNotJsProxy); 2137 BRANCH(IsTypedArray(obj), slowPath, &isNotTypedArray); 2138 Bind(&isNotTypedArray); 2139 BRANCH(IsModuleNamespace(obj), slowPath, &isNotModuleNamespace); 2140 Bind(&isNotModuleNamespace); 2141 BRANCH(IsSpecialContainer(GetObjectType(LoadHClass(obj))), slowPath, &isNotSpecialContainer); 2142 Bind(&isNotSpecialContainer); 2143 GateRef cls = LoadHClass(obj); 2144 BRANCH(IsDictionaryModeByHClass(cls), slowPath, ¬DicMode); 2145 Bind(¬DicMode); 2146 GateRef layout = GetLayoutFromHClass(cls); 2147 GateRef lengthOfKeys = GetNumberOfPropsFromHClass(cls); 2148 GateRef elementArray = GetEnumElementKeys(glue_, obj); 2149 GateRef lengthOfElements = GetLengthOfTaggedArray(elementArray); 2150 BRANCH(Int32Equal(lengthOfElements, Int32(0)), ¬HasElementKey, slowPath); 2151 Bind(¬HasElementKey); 2152 2153 GateRef status = IsExtensible(obj); 2154 BRANCH(status, &isExtensible, &isNotExtensible); 2155 Bind(&isExtensible); 2156 { 2157 result = False(); 2158 Jump(&exit); 2159 } 2160 Bind(&isNotExtensible); 2161 { 2162 Label lengthIsZero(env); 2163 Label lengthNotZero(env); 2164 BRANCH(Int32Equal(lengthOfKeys, Int32(0)), &lengthIsZero, &lengthNotZero); 2165 Bind(&lengthIsZero); 2166 { 2167 result = True(); 2168 Jump(&exit); 2169 } 2170 Bind(&lengthNotZero); 2171 { 2172 DEFVARIABLE(index, VariableType::INT32(), Int32(0)); 2173 Label loopHead(env); 2174 Label loopEnd(env); 2175 Label afterLoop(env); 2176 Label inRange(env); 2177 Jump(&loopHead); 2178 LoopBegin(&loopHead); 2179 { 2180 BRANCH(Int32LessThan(*index, lengthOfKeys), &inRange, &afterLoop); 2181 Bind(&inRange); 2182 { 2183 GateRef attr = GetPropAttrFromLayoutInfo(layout, *index); 2184 Label configable(env); 2185 Label notConfigable(env); 2186 Label notFrozen(env); 2187 BRANCH(IsConfigable(attr), &configable, ¬Configable); 2188 Bind(&configable); 2189 { 2190 result = False(); 2191 Jump(&exit); 2192 } 2193 Bind(¬Configable); 2194 { 2195 // 1: IntegrityLevel::FROZEN 2196 GateRef isFrozen = LogicAndBuilder(env).And(Int32Equal(level, Int32(1))) 2197 .And(BoolNot(IsAccessor(attr))).And(IsWritable(attr)).Done(); 2198 BRANCH(isFrozen, ¬Frozen, &loopEnd); 2199 Bind(¬Frozen); 2200 { 2201 result = False(); 2202 Jump(&exit); 2203 } 2204 } 2205 } 2206 } 2207 Bind(&loopEnd); 2208 index = Int32Add(*index, Int32(1)); 2209 LoopEnd(&loopHead, env, glue); 2210 Bind(&afterLoop); 2211 { 2212 result = True(); 2213 Jump(&exit); 2214 } 2215 } 2216 } 2217 Bind(&exit); 2218 auto ret = *result; 2219 env->SubCfgExit(); 2220 return ret; 2221} 2222 2223void BuiltinsObjectStubBuilder::GetOwnPropertyDescriptors(Variable *result, Label *exit, Label *slowPath) 2224{ 2225 auto env = GetEnvironment(); 2226 GateRef msg = GetCallArg0(numArgs_); 2227 GateRef obj = ToObject(glue_, msg); 2228 Label isPendingException(env); 2229 Label noPendingException(env); 2230 BRANCH(HasPendingException(glue_), &isPendingException, &noPendingException); 2231 Bind(&isPendingException); 2232 { 2233 Jump(exit); 2234 } 2235 Bind(&noPendingException); 2236 { 2237 Label isFast(env); 2238 BRANCH(IsNotSlowObjectKey(obj), &isFast, slowPath); 2239 Bind(&isFast); 2240 { 2241 Label notDictMode(env); 2242 GateRef properties = GetPropertiesArray(obj); 2243 BRANCH(IsDictionaryMode(properties), slowPath, ¬DictMode); 2244 Bind(¬DictMode); 2245 { 2246 Label onlyProperties(env); 2247 GateRef numOfElements = GetNumberOfElements(obj); 2248 BRANCH(Int32Equal(numOfElements, Int32(0)), &onlyProperties, slowPath); 2249 Bind(&onlyProperties); 2250 { 2251 DEFVARIABLE(i, VariableType::INT32(), Int32(0)); 2252 GateRef hclass = LoadHClass(obj); 2253 GateRef layout = GetLayoutFromHClass(hclass); 2254 GateRef number = GetNumberOfPropsFromHClass(hclass); 2255 GateRef keyValue = CallRuntime(glue_, RTSTUB_ID(ToPropertyKeyValue), {}); 2256 GateRef keyWritable = CallRuntime(glue_, RTSTUB_ID(ToPropertyKeyWritable), {}); 2257 GateRef keyEnumerable = CallRuntime(glue_, RTSTUB_ID(ToPropertyKeyEnumerable), {}); 2258 GateRef keyConfigurable = CallRuntime(glue_, RTSTUB_ID(ToPropertyKeyConfigurable), {}); 2259 NewObjectStubBuilder newBuilder(this); 2260 newBuilder.SetParameters(glue_, 0); 2261 GateRef descriptors = newBuilder.CreateEmptyObject(glue_); 2262 Label loopHead(env); 2263 Label loopEnd(env); 2264 Label next(env); 2265 Label loopExit(env); 2266 Jump(&loopHead); 2267 LoopBegin(&loopHead); 2268 { 2269 BRANCH(Int32UnsignedLessThan(*i, number), &next, &loopExit); 2270 Bind(&next); 2271 { 2272 Label CheckIsWritable(env); 2273 Label CheckIsEnumerable(env); 2274 Label CheckIsIsConfigable(env); 2275 Label setDescriptor(env); 2276 GateRef key = GetKey(layout, *i); 2277 GateRef attr = GetAttr(layout, *i); 2278 GateRef descriptor = newBuilder.CreateEmptyObject(glue_); 2279 GateRef value = JSObjectGetProperty(obj, hclass, attr); 2280 FastSetPropertyByName(glue_, descriptor, keyValue, value); 2281 Jump(&CheckIsWritable); 2282 2283 Bind(&CheckIsWritable); 2284 { 2285 Label isWritable(env); 2286 Label notWritable(env); 2287 BRANCH(IsWritable(attr), &isWritable, ¬Writable); 2288 Bind(&isWritable); 2289 { 2290 FastSetPropertyByName(glue_, descriptor, keyWritable, TaggedTrue()); 2291 Jump(&CheckIsEnumerable); 2292 } 2293 Bind(¬Writable); 2294 { 2295 FastSetPropertyByName(glue_, descriptor, keyWritable, TaggedFalse()); 2296 Jump(&CheckIsEnumerable); 2297 } 2298 } 2299 Bind(&CheckIsEnumerable); 2300 { 2301 Label isEnumerable(env); 2302 Label notEnumerable(env); 2303 BRANCH(IsEnumerable(attr), &isEnumerable, ¬Enumerable); 2304 Bind(&isEnumerable); 2305 { 2306 FastSetPropertyByName(glue_, descriptor, keyEnumerable, TaggedTrue()); 2307 Jump(&CheckIsIsConfigable); 2308 } 2309 Bind(¬Enumerable); 2310 { 2311 FastSetPropertyByName(glue_, descriptor, keyEnumerable, TaggedFalse()); 2312 Jump(&CheckIsIsConfigable); 2313 } 2314 } 2315 Bind(&CheckIsIsConfigable); 2316 { 2317 Label isConfigable(env); 2318 Label notConfigable(env); 2319 BRANCH(IsConfigable(attr), &isConfigable, ¬Configable); 2320 Bind(&isConfigable); 2321 { 2322 FastSetPropertyByName(glue_, descriptor, keyConfigurable, TaggedTrue()); 2323 Jump(&setDescriptor); 2324 } 2325 Bind(¬Configable); 2326 { 2327 FastSetPropertyByName(glue_, descriptor, keyConfigurable, TaggedFalse()); 2328 Jump(&setDescriptor); 2329 } 2330 } 2331 Bind(&setDescriptor); 2332 { 2333 FastSetPropertyByName(glue_, descriptors, key, descriptor); 2334 Jump(&loopEnd); 2335 } 2336 } 2337 } 2338 Bind(&loopEnd); 2339 i = Int32Add(*i, Int32(1)); 2340 LoopEnd(&loopHead, env, glue_); 2341 Bind(&loopExit); 2342 *result = descriptors; 2343 Jump(exit); 2344 } 2345 } 2346 } 2347 } 2348} 2349 2350} // namespace panda::ecmascript::kungfu 2351