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, &notDictionaryMode);
258    Bind(&notDictionaryMode);
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, &notHole);
275            Bind(&notHole);
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, &notHole);
324                    Bind(&notHole);
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, &notHole);
478                Bind(&notHole);
479                {
480                    Label isAccessor(env);
481                    Label notAccessor(env);
482                    BRANCH(IsAccessor(attr), &isAccessor, &notAccessor);
483                    Bind(&isAccessor);
484                    {
485                        value = CallGetterHelper(glue_, source, source, *value, ProfileOperation());
486                        // exception
487                        Label exception(env);
488                        BRANCH(HasPendingException(glue_), &exception, &notAccessor);
489                        Bind(&exception);
490                        {
491                            *result = Exception();
492                            Jump(funcExit);
493                        }
494                    }
495                    Bind(&notAccessor);
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, &notDictionaryMode);
532    Bind(&notDictionaryMode);
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, &notTwoArg); // 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(&notTwoArg);
619        Label threeArg(env);
620        Label notThreeArg(env);
621        BRANCH(Int64Equal(numArgs_, IntPtr(3)), &threeArg, &notThreeArg); // 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(&notThreeArg);
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, &notIndex);
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, &notDictionaryElement);
680                    Bind(&notDictionaryElement);
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), &notHole, exit);
690                            Bind(&notHole);
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)), &notNegtiveOne, exit);
702                        Bind(&notNegtiveOne);
703                        {
704                            *result = TaggedTrue();
705                            Jump(exit);
706                        }
707                    }
708                }
709            }
710            Bind(&notIndex);
711            {
712                Label findInStringTabel(env);
713                Label notInternString(env);
714                DEFVARIABLE(stringTable, VariableType::JS_ANY(), prop);
715                BRANCH(IsInternalString(prop), &findInStringTabel, &notInternString);
716                Bind(&notInternString);
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, &notDicMode);
728                    Bind(&notDicMode);
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)), &notNegtiveOne, exit);
751                        Bind(&notNegtiveOne);
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, &notDictionary);
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(&notDictionary);
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, &notHasProps);
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, &notOnlyOwnKeys);
1045            Bind(&isOnlyOwnKeys);
1046            {
1047                result = CopyFromEnumCache(glue, enumCache);
1048                Jump(&exit);
1049            }
1050            Bind(&notOnlyOwnKeys);
1051            {
1052                Label numNotZero(env);
1053                Label inSharedHeap(env);
1054                Label notInSharedHeap(env);
1055                BRANCH(Int32GreaterThan(numOfKeys, Int32(0)), &numNotZero, &notHasProps);
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, &notInSharedHeap);
1066                Bind(&inSharedHeap);
1067                {
1068                    result = CopyFromEnumCache(glue, keyArray);
1069                    Jump(&exit);
1070                }
1071                Bind(&notInSharedHeap);
1072                {
1073                    SetEnumCacheToHClass(VariableType::JS_ANY(), glue, hclass, keyArray);
1074                    result = CopyFromEnumCache(glue, keyArray);
1075                    Jump(&exit);
1076                }
1077            }
1078        }
1079        Bind(&notHasProps);
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, &notPrimitiveString);
1118        Bind(&isJSPrimitiveRef);
1119        GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1120        BRANCH(TaggedIsString(value), &isPrimitiveString, &notPrimitiveString);
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, &notPrimitiveString);
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(&notPrimitiveString);
1145        GateRef elements = GetElementsArray(obj);
1146        BRANCH(IsDictionaryMode(elements), &isDictMode, &notDictMode);
1147        Bind(&notDictMode);
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, &notHole);
1163                    Bind(&notHole);
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, &notJsProxy);
1299            Bind(&notJsProxy);
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, &notEcmaObject);
1330            Bind(&isEcmaObject);
1331            Jump(&setProto);
1332            Bind(&notEcmaObject);
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, &notFunction);
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, &notFunction);
1362            Bind(&isDerivedCtor);
1363            auto cachedJSHClass = GetPrototypeFromHClass(protoOrHclass);
1364            SetProtoOrHClassToFunction(glue_, obj, cachedJSHClass);
1365            Jump(&notFunction);
1366        }
1367        Bind(&notFunction);
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, &notEqual);
1400    Bind(&isEqual);
1401    {
1402        result = True();
1403        Jump(&exit);
1404    }
1405    Bind(&notEqual);
1406    {
1407        BRANCH(IsExtensible(obj), &isExtensible, &notExtensible);
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, &notNull);
1431                    Bind(&isNull);
1432                    {
1433                        done = True();
1434                        Jump(&loopEnd);
1435                    }
1436                    Bind(&notNull);
1437                    {
1438                        BRANCH(IntPtrEqual(*tempProto, obj), &isEqual2, &notEqual2);
1439                        Bind(&isEqual2);
1440                        {
1441                            result = False();
1442                            Jump(&exit);
1443                        }
1444                        Bind(&notEqual2);
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(&notExtensible);
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, &notDictMode);
1497            Bind(&notDictMode);
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, &notDictMode);
1605            Bind(&notDictMode);
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, &notPrimitiveString);
1705    Bind(&isJSPrimitiveRef);
1706    {
1707        GateRef value = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1708        BRANCH(TaggedIsString(value), &isPrimitiveString, &notPrimitiveString);
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, &notPrimitiveString);
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(&notPrimitiveString);
1733    {
1734        Label isDictMode(env);
1735        Label notDictMode(env);
1736        Label exit(env);
1737        GateRef elements = GetElementsArray(obj);
1738        BRANCH(IsDictionaryMode(elements), &isDictMode, &notDictMode);
1739        Bind(&isDictMode);
1740        {
1741            FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1742            Jump(&exit);
1743        }
1744        Bind(&notDictMode);
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, &notHole);
1760                    Bind(&notHole);
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, &notDictionary);
1797    Bind(&isDictionary);
1798    {
1799        FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1800        Jump(&exit);
1801    }
1802    Bind(&notDictionary);
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, &notDictMode);
1872            Bind(&notDictMode);
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, &notPrimitiveString);
1941    Bind(&isJSPrimitiveRef);
1942    GateRef els = Load(VariableType::JS_ANY(), obj, IntPtr(JSPrimitiveRef::VALUE_OFFSET));
1943    BRANCH(TaggedIsString(els), slowPath, &notPrimitiveString);
1944    Bind(&notPrimitiveString);
1945    BRANCH(IsDictionaryMode(elements), slowPath, &notDictMode);
1946    Bind(&notDictMode);
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, &notHole);
1961            Bind(&notHole);
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, &notDictionary);
1994    Bind(&notDictionary);
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)), &notEcmaObj, &isEcmaObj);
2061    Bind(&notEcmaObj);
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)), &notEcmaObj, &isEcmaObj);
2093    Bind(&notEcmaObj);
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, &notDicMode);
2145    Bind(&notDicMode);
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)), &notHasElementKey, slowPath);
2151    Bind(&notHasElementKey);
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, &notConfigable);
2188                    Bind(&configable);
2189                    {
2190                        result = False();
2191                        Jump(&exit);
2192                    }
2193                    Bind(&notConfigable);
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, &notFrozen, &loopEnd);
2199                        Bind(&notFrozen);
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, &notDictMode);
2244            Bind(&notDictMode);
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, &notWritable);
2288                                Bind(&isWritable);
2289                                {
2290                                    FastSetPropertyByName(glue_, descriptor, keyWritable, TaggedTrue());
2291                                    Jump(&CheckIsEnumerable);
2292                                }
2293                                Bind(&notWritable);
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, &notEnumerable);
2304                                Bind(&isEnumerable);
2305                                {
2306                                    FastSetPropertyByName(glue_, descriptor, keyEnumerable, TaggedTrue());
2307                                    Jump(&CheckIsIsConfigable);
2308                                }
2309                                Bind(&notEnumerable);
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, &notConfigable);
2320                                Bind(&isConfigable);
2321                                {
2322                                    FastSetPropertyByName(glue_, descriptor, keyConfigurable, TaggedTrue());
2323                                    Jump(&setDescriptor);
2324                                }
2325                                Bind(&notConfigable);
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