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_array_stub_builder.h"
17
18#include "ecmascript/builtins/builtins_string.h"
19#include "ecmascript/compiler/builtins/builtins_stubs.h"
20#include "ecmascript/compiler/call_stub_builder.h"
21#include "ecmascript/compiler/new_object_stub_builder.h"
22#include "ecmascript/compiler/profiler_operation.h"
23#include "ecmascript/compiler/rt_call_signature.h"
24#include "ecmascript/runtime_call_id.h"
25#include "ecmascript/js_iterator.h"
26#include "ecmascript/compiler/access_object_stub_builder.h"
27#include "ecmascript/base/array_helper.h"
28
29namespace panda::ecmascript::kungfu {
30
31void BuiltinsArrayStubBuilder::ElementsKindHclassCompare(GateRef glue, GateRef arrayCls,
32    Label *matchCls, Label *slowPath)
33{
34    auto env = GetEnvironment();
35    Label isGeneric(env);
36    GateRef elementsKind = GetElementsKindFromHClass(arrayCls);
37    GateRef notGeneric = NotEqual(elementsKind, Int32(static_cast<uint32_t>(ElementsKind::GENERIC)));
38    BRANCH(notGeneric, matchCls, &isGeneric);
39    Bind(&isGeneric);
40    {
41        GateRef intialHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
42                                                      ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX);
43        BRANCH(Equal(intialHClass, arrayCls), matchCls, slowPath);
44    }
45}
46
47void BuiltinsArrayStubBuilder::With(GateRef glue, GateRef thisValue, GateRef numArgs,
48    Variable *result, Label *exit, Label *slowPath)
49{
50    auto env = GetEnvironment();
51    DEFVARIABLE(relativeIndex, VariableType::INT64(), Int64(0));
52    DEFVARIABLE(actualIndex, VariableType::INT64(), Int64(0));
53    Label isHeapObject(env);
54    Label isJsArray(env);
55    Label isStableArray(env);
56    Label defaultConstr(env);
57    Label notCOWArray(env);
58    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
59    Bind(&isHeapObject);
60    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
61    Bind(&isJsArray);
62    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
63    Bind(&defaultConstr);
64    BRANCH(IsStableJSArray(glue, thisValue), &isStableArray, slowPath);
65    Bind(&isStableArray);
66    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
67    Bind(&notCOWArray);
68
69    GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
70    GateRef index = GetCallArg0(numArgs);
71    Label taggedIsInt(env);
72    BRANCH(TaggedIsInt(index), &taggedIsInt, slowPath);
73    Bind(&taggedIsInt);
74    {
75        relativeIndex = GetInt64OfTInt(index);
76        DEFVARIABLE(value, VariableType::JS_ANY(), Hole());
77        Label twoArg(env);
78        Label ifOneArg(env);
79        Label getIndex(env);
80        // 2 : means there are two args
81        BRANCH(Int64Equal(numArgs, IntPtr(2)), &twoArg, &ifOneArg);
82        Bind(&twoArg);
83        {
84            value = GetCallArg1(numArgs);
85            Jump(&getIndex);
86        }
87        Bind(&ifOneArg);
88        {
89            // 1 : means there are only one arg
90            BRANCH(Int64Equal(numArgs, IntPtr(1)), &getIndex, slowPath);
91        }
92        Bind(&getIndex);
93        {
94            Label indexGreaterOrEqualZero(env);
95            Label indexLessZero(env);
96            Label next(env);
97            Label notOutOfRange(env);
98            BRANCH(Int64GreaterThanOrEqual(*relativeIndex, Int64(0)), &indexGreaterOrEqualZero, &indexLessZero);
99            Bind(&indexGreaterOrEqualZero);
100            {
101                actualIndex = *relativeIndex;
102                Jump(&next);
103            }
104            Bind(&indexLessZero);
105            {
106                actualIndex = Int64Add(thisLen, *relativeIndex);
107                Jump(&next);
108            }
109            Bind(&next);
110            {
111                BRANCH(BitOr(Int64GreaterThanOrEqual(*actualIndex, thisLen), Int64LessThan(*actualIndex, Int64(0))),
112                    slowPath, &notOutOfRange);
113                Bind(&notOutOfRange);
114                {
115                    GateRef newArray = NewArray(glue, Int32(0));
116                    GrowElementsCapacity(glue, newArray, TruncInt64ToInt32(thisLen));
117                    DEFVARIABLE(k, VariableType::INT64(), Int64(0));
118                    Label loopHead(env);
119                    Label loopEnd(env);
120                    Label loopExit(env);
121                    Label loopNext(env);
122                    Label replaceIndex(env);
123                    Label notReplaceIndex(env);
124                    Jump(&loopHead);
125                    LoopBegin(&loopHead);
126                    {
127                        BRANCH(Int64LessThan(*k, thisLen), &loopNext, &loopExit);
128                        Bind(&loopNext);
129                        BRANCH(Int64Equal(*k, *actualIndex), &replaceIndex, &notReplaceIndex);
130                        Bind(&replaceIndex);
131                        {
132                            SetValueWithElementsKind(glue, newArray, *value, *k, Boolean(true),
133                                Int32(static_cast<uint32_t>(ElementsKind::NONE)));
134                            Jump(&loopEnd);
135                        }
136                        Bind(&notReplaceIndex);
137                        {
138                            GateRef ele = GetTaggedValueWithElementsKind(thisValue, *k);
139                            Label eleIsHole(env);
140                            Label eleNotHole(env);
141                            BRANCH(TaggedIsHole(ele), &eleIsHole, &eleNotHole);
142                            Bind(&eleIsHole);
143                            {
144                                SetValueWithElementsKind(glue, newArray, Undefined(), *k, Boolean(true),
145                                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
146                                Jump(&loopEnd);
147                            }
148                            Bind(&eleNotHole);
149                            {
150                                SetValueWithElementsKind(glue, newArray, ele, *k, Boolean(true),
151                                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
152                                Jump(&loopEnd);
153                            }
154                        }
155                    }
156                    Bind(&loopEnd);
157                    k = Int64Add(*k, Int64(1));
158                    LoopEnd(&loopHead);
159                    Bind(&loopExit);
160                    SetArrayLength(glue, newArray, thisLen);
161                    result->WriteVariable(newArray);
162                    Jump(exit);
163                }
164            }
165        }
166    }
167}
168
169void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef numArgs,
170    Variable *result, Label *exit, Label *slowPath)
171{
172    auto env = GetEnvironment();
173    Label isHeapObject(env);
174    Label isJsArray(env);
175    Label isStableJsArray(env);
176    Label notOverRange(env);
177    Label numNotEqualZero(env);
178    Label numLessThanOrEqualThree(env);
179    Label afterCopy(env);
180    Label grow(env);
181    Label setValue(env);
182    Label matchCls(env);
183    Label numEqual2(env);
184    Label numEqual3(env);
185    Label threeArgs(env);
186    Label final(env);
187    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
188    Bind(&isHeapObject);
189    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
190    Bind(&isJsArray);
191    BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath);
192    Bind(&isStableJsArray);
193    GateRef arrayCls = LoadHClass(thisValue);
194    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
195    Bind(&matchCls);
196    BRANCH(Int64GreaterThan(numArgs, IntPtr(0)), &numNotEqualZero, slowPath);
197    Bind(&numNotEqualZero);
198    GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
199    GateRef argLen = ZExtInt32ToInt64(ChangeIntPtrToInt32(numArgs));
200    GateRef newLen = Int64Add(thisLen, argLen);
201    BRANCH(Int64GreaterThan(newLen, Int64(base::MAX_SAFE_INTEGER)), slowPath, &notOverRange);
202    Bind(&notOverRange);
203    // 3 : max param num
204    BRANCH(Int64LessThanOrEqual(numArgs, IntPtr(3)), &numLessThanOrEqualThree, slowPath);
205    Bind(&numLessThanOrEqualThree);
206    GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(GetElementsArray(thisValue)));
207    BRANCH(Int64GreaterThan(newLen, capacity), &grow, &setValue);
208    Bind(&grow);
209    {
210        GrowElementsCapacity(glue, thisValue, TruncInt64ToInt32(newLen));
211        Jump(&setValue);
212    }
213    Bind(&setValue);
214    {
215        Label elementsKindEnabled(env);
216        GateRef elements = GetElementsArray(thisValue);
217        GateRef arrayStart = GetDataPtrInTaggedArray(elements);
218        GateRef moveTo = PtrAdd(arrayStart, PtrMul(numArgs, IntPtr(JSTaggedValue::TaggedTypeSize())));
219        GateRef isElementsKindEnabled = IsEnableElementsKind(glue);
220        Label isIntOrNumber(env);
221        Label isTagged(env);
222        BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged);
223        Bind(&elementsKindEnabled);
224        {
225            GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue));
226            GateRef isInt = LogicAndBuilder(env)
227                            .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::INT))))
228                            .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_INT))))
229                            .Done();
230            GateRef isNumber = LogicAndBuilder(env)
231                               .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::NUMBER))))
232                               .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER))))
233                               .Done();
234            GateRef isIntOrNumberKind = LogicOrBuilder(env).Or(isInt).Or(isNumber).Done();
235            BRANCH_NO_WEIGHT(isIntOrNumberKind, &isIntOrNumber, &isTagged);
236            Bind(&isIntOrNumber);
237            {
238                ArrayCopy<MustOverlap>(glue, arrayStart, moveTo, TruncInt64ToInt32(thisLen),
239                                       MemoryAttribute::NoBarrier());
240                Jump(&afterCopy);
241            }
242            Bind(&isTagged);
243            {
244                ArrayCopy<MustOverlap>(glue, arrayStart, moveTo, TruncInt64ToInt32(thisLen));
245                Jump(&afterCopy);
246            }
247            Bind(&afterCopy);
248            {
249                GateRef value0 = GetCallArg0(numArgs);
250                // 0 : the first Element position
251                SetValueWithElementsKind(glue, thisValue, value0, Int64(0), Boolean(false),
252                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
253                // 2 : the second param
254                BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(2)), &numEqual2, &numEqual3);
255                Bind(&numEqual2);
256                {
257                    GateRef value1 = GetCallArg1(numArgs);
258                    // 1 : the second Element position
259                    SetValueWithElementsKind(glue, thisValue, value1, Int64(1), Boolean(false),
260                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
261                    Jump(&numEqual3);
262                }
263                Bind(&numEqual3);
264                {
265                    // 3 : the third param
266                    BRANCH(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &final);
267                    Bind(&threeArgs);
268                    GateRef value2 = GetCallArg2(numArgs);
269                    // 2 : the third Element position
270                    SetValueWithElementsKind(glue, thisValue, value2, Int64(2), Boolean(false),
271                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
272                    Jump(&final);
273                }
274                Bind(&final);
275                {
276                    SetArrayLength(glue, thisValue, newLen);
277                    result->WriteVariable(IntToTaggedPtr(newLen));
278                    Jump(exit);
279                }
280            }
281        }
282    }
283}
284
285void BuiltinsArrayStubBuilder::Shift(GateRef glue, GateRef thisValue,
286    [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
287{
288    auto env = GetEnvironment();
289    Label isHeapObject(env);
290    Label stableJSArray(env);
291    Label isDefaultConstructor(env);
292    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
293    Bind(&isHeapObject);
294    BRANCH(HasConstructor(thisValue), slowPath, &isDefaultConstructor);
295    Bind(&isDefaultConstructor);
296    BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
297    Bind(&stableJSArray);
298    {
299        Label isLengthWritable(env);
300        BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath);
301        Bind(&isLengthWritable);
302        {
303            GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
304            Label lengthNotZero(env);
305            BRANCH(Int64Equal(thisLen, Int64(0)), exit, &lengthNotZero);
306            Bind(&lengthNotZero);
307            {
308                Label isJsCOWArray(env);
309                Label getElements(env);
310                BRANCH(IsJsCOWArray(thisValue), &isJsCOWArray, &getElements);
311                Bind(&isJsCOWArray);
312                {
313                    CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), { thisValue });
314                    Jump(&getElements);
315                }
316                Bind(&getElements);
317                {
318                    GateRef elements = GetElementsArray(thisValue);
319                    GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(elements));
320                    GateRef index = Int64Sub(thisLen, Int64(1));
321                    DEFVARIABLE(element, VariableType::JS_ANY(), Hole());
322                    element = GetTaggedValueWithElementsKind(thisValue, Int64(0));
323                    Label hasException0(env);
324                    Label taggedHole(env);
325                    Label copyArray(env);
326                    BRANCH(TaggedIsHole(*element), &taggedHole, &copyArray);
327                    Bind(&taggedHole);
328                    {
329                        element = FastGetPropertyByIndex(glue, thisValue, Int32(0), ProfileOperation());
330                        BRANCH(HasPendingException(glue), &hasException0, &copyArray);
331                        Bind(&hasException0);
332                        {
333                            result->WriteVariable(Exception());
334                            Jump(exit);
335                        }
336                    }
337                    Bind(&copyArray);
338                    {
339                        DEFVARIABLE(fromKey, VariableType::INT64(), Int64(1));
340                        DEFVARIABLE(toKey, VariableType::INT64(), Int64Sub(*fromKey, Int64(1)));
341                        Label loopHead(env);
342                        Label loopNext(env);
343                        Label loopEnd(env);
344                        Label loopExit(env);
345                        Jump(&loopHead);
346                        LoopBegin(&loopHead);
347                        {
348                            BRANCH(Int64LessThan(*fromKey, thisLen), &loopNext, &loopExit);
349                            Bind(&loopNext);
350                            {
351                                GateRef ele = GetTaggedValueWithElementsKind(thisValue, *fromKey);
352                                SetValueWithElementsKind(glue, thisValue, ele, *toKey, Boolean(false),
353                                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
354                                Jump(&loopEnd);
355                            }
356                        }
357                        Bind(&loopEnd);
358                        fromKey = Int64Add(*fromKey, Int64(1));
359                        toKey = Int64Add(*toKey, Int64(1));
360                        LoopEnd(&loopHead);
361                        Bind(&loopExit);
362                        {
363                            Label noTrim(env);
364                            Label needTrim(env);
365                            Label setNewLen(env);
366                            GateRef unused = Int64Sub(capacity, index);
367                            BRANCH(Int64GreaterThan(unused, Int64(TaggedArray::MAX_END_UNUSED)), &needTrim, &noTrim);
368                            Bind(&needTrim);
369                            {
370                                CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, elements, index});
371                                Jump(&setNewLen);
372                            }
373                            Bind(&noTrim);
374                            {
375                                SetValueWithElementsKind(glue, thisValue, Hole(), index, Boolean(false),
376                                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
377                                Jump(&setNewLen);
378                            }
379                            Bind(&setNewLen);
380                            {
381                                GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
382                                Store(VariableType::INT32(), glue, thisValue, lengthOffset, index);
383
384                                Label isNotHole(env);
385                                BRANCH(TaggedIsHole(*element), exit, &isNotHole);
386                                Bind(&isNotHole);
387                                {
388                                    result->WriteVariable(*element);
389                                    Jump(exit);
390                                }
391                            }
392                        }
393                    }
394                }
395            }
396        }
397    }
398}
399
400void BuiltinsArrayStubBuilder::Concat(GateRef glue, GateRef thisValue, GateRef numArgs,
401    Variable *result, Label *exit, Label *slowPath)
402{
403    auto env = GetEnvironment();
404    Label isHeapObject(env);
405    Label isJsArray(env);
406    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
407    Bind(&isHeapObject);
408    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
409    Bind(&isJsArray);
410    {
411        Label isExtensible(env);
412        BRANCH(HasConstructor(thisValue), slowPath, &isExtensible);
413        Bind(&isExtensible);
414        {
415            Label numArgsOne(env);
416            BRANCH(Int64Equal(numArgs, IntPtr(1)), &numArgsOne, slowPath);
417            Bind(&numArgsOne);
418            {
419                GateRef arg0 = GetCallArg0(numArgs);
420                Label allStableJsArray(env);
421                GateRef isAllStableJsArray = LogicAndBuilder(env).And(IsStableJSArray(glue, thisValue))
422                    .And(IsStableJSArray(glue, arg0)).Done();
423                BRANCH(isAllStableJsArray, &allStableJsArray, slowPath);
424                Bind(&allStableJsArray);
425                {
426                    GateRef maxArrayIndex = Int64(TaggedArray::MAX_ARRAY_INDEX);
427                    GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
428                    GateRef argLen = ZExtInt32ToInt64(GetArrayLength(arg0));
429                    GateRef sumArrayLen = Int64Add(argLen, thisLen);
430                    Label isEmptyArray(env);
431                    Label notEmptyArray(env);
432                    BRANCH(Int64Equal(sumArrayLen, Int64(0)), &isEmptyArray, &notEmptyArray);
433                    Bind(&isEmptyArray);
434                    {
435                        NewObjectStubBuilder newBuilder(this);
436                        result->WriteVariable(newBuilder.CreateEmptyArray(glue));
437                        Jump(exit);
438                    }
439                    Bind(&notEmptyArray);
440                    Label notOverFlow(env);
441                    BRANCH(Int64GreaterThan(sumArrayLen, maxArrayIndex), slowPath, &notOverFlow);
442                    Bind(&notOverFlow);
443                    {
444                        Label spreadable(env);
445                        GateRef isAllConcatSpreadable = LogicAndBuilder(env).And(IsConcatSpreadable(glue, thisValue))
446                            .And(IsConcatSpreadable(glue, arg0)).Done();
447                        BRANCH(isAllConcatSpreadable, &spreadable, slowPath);
448                        Bind(&spreadable);
449                        {
450                            Label setProperties(env);
451                            GateRef glueGlobalEnvOffset =
452                                IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
453                            GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
454                            auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
455                                GlobalEnv::ARRAY_FUNCTION_INDEX);
456                            GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc,
457                                IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
458                            NewObjectStubBuilder newBuilder(this);
459                            newBuilder.SetParameters(glue, 0);
460                            GateRef newArray = newBuilder.NewJSArrayWithSize(intialHClass, sumArrayLen);
461                            BRANCH(TaggedIsException(newArray), exit, &setProperties);
462                            Bind(&setProperties);
463                            {
464                                GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
465                                Store(VariableType::INT32(), glue, newArray, lengthOffset,
466                                    TruncInt64ToInt32(sumArrayLen));
467                                GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
468                                    ConstantIndex::ARRAY_LENGTH_ACCESSOR);
469                                SetPropertyInlinedProps(glue, newArray, intialHClass, accessor,
470                                    Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
471                                SetExtensibleToBitfield(glue, newArray, true);
472                                DEFVARIABLE(i, VariableType::INT64(), Int64(0));
473                                DEFVARIABLE(j, VariableType::INT64(), Int64(0));
474                                DEFVARIABLE(k, VariableType::INT64(), Int64(0));
475                                Label loopHead(env);
476                                Label loopEnd(env);
477                                Label next(env);
478                                Label loopExit(env);
479                                Jump(&loopHead);
480                                LoopBegin(&loopHead);
481                                {
482                                    BRANCH(Int64LessThan(*i, thisLen), &next, &loopExit);
483                                    Bind(&next);
484                                    GateRef ele = GetTaggedValueWithElementsKind(thisValue, *i);
485                                    #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
486                                    SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
487                                        Int32(static_cast<uint32_t>(ElementsKind::GENERIC)));
488                                    #else
489                                    SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
490                                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
491                                    #endif
492                                    Jump(&loopEnd);
493                                }
494                                Bind(&loopEnd);
495                                i = Int64Add(*i, Int64(1));
496                                j = Int64Add(*j, Int64(1));
497                                LoopEnd(&loopHead, env, glue);
498                                Bind(&loopExit);
499                                Label loopHead1(env);
500                                Label loopEnd1(env);
501                                Label next1(env);
502                                Label loopExit1(env);
503                                Jump(&loopHead1);
504                                LoopBegin(&loopHead1);
505                                {
506                                    BRANCH(Int64LessThan(*k, argLen), &next1, &loopExit1);
507                                    Bind(&next1);
508                                    GateRef ele = GetTaggedValueWithElementsKind(arg0, *k);
509                                    #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
510                                    SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
511                                                             Int32(static_cast<uint32_t>(ElementsKind::GENERIC)));
512                                    #else
513                                    SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
514                                                             Int32(static_cast<uint32_t>(ElementsKind::NONE)));
515                                    #endif
516                                    Jump(&loopEnd1);
517                                }
518                                Bind(&loopEnd1);
519                                k = Int64Add(*k, Int64(1));
520                                j = Int64Add(*j, Int64(1));
521                                LoopEnd(&loopHead1);
522                                Bind(&loopExit1);
523                                result->WriteVariable(newArray);
524                                Jump(exit);
525                            }
526                        }
527                    }
528                }
529            }
530        }
531    }
532}
533
534void BuiltinsArrayStubBuilder::Filter(GateRef glue, GateRef thisValue, GateRef numArgs,
535    Variable *result, Label *exit, Label *slowPath)
536{
537    auto env = GetEnvironment();
538    Label isHeapObject(env);
539    Label isJsArray(env);
540    Label defaultConstr(env);
541    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
542    Bind(&isHeapObject);
543    GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue))
544        .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done();
545    BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath);
546    Bind(&isJsArray);
547    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
548    Bind(&defaultConstr);
549
550    GateRef callbackFnHandle = GetCallArg0(numArgs);
551    Label argOHeapObject(env);
552    Label callable(env);
553    Label notOverFlow(env);
554    BRANCH(TaggedIsHeapObject(callbackFnHandle), &argOHeapObject, slowPath);
555    Bind(&argOHeapObject);
556    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
557    Bind(&callable);
558    GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue));
559    Label isEmptyArray(env);
560    Label notEmptyArray(env);
561    BRANCH(Int64Equal(len, Int64(0)), &isEmptyArray, &notEmptyArray);
562    Bind(&isEmptyArray);
563    {
564        NewObjectStubBuilder newBuilder(this);
565        result->WriteVariable(newBuilder.CreateEmptyArray(glue));
566        Jump(exit);
567    }
568    Bind(&notEmptyArray);
569    BRANCH(Int64GreaterThan(len, Int64(JSObject::MAX_GAP)), slowPath, &notOverFlow);
570    Bind(&notOverFlow);
571
572    GateRef argHandle = GetCallArg1(numArgs);
573    GateRef newArray = NewArray(glue, len);
574    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
575    GateRef newArrayEles = GetElementsArray(newArray);
576    Label stableJSArray(env);
577    Label notStableJSArray(env);
578    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
579    DEFVARIABLE(toIndex, VariableType::INT64(), Int64(0));
580    BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
581    Bind(&stableJSArray);
582    {
583        DEFVARIABLE(thisArrLenVar, VariableType::INT64(), len);
584        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
585        Label loopHead(env);
586        Label loopEnd(env);
587        Label next(env);
588        Label loopExit(env);
589        Jump(&loopHead);
590        LoopBegin(&loopHead);
591        {
592            BRANCH(Int64LessThan(*i, *thisArrLenVar), &next, &loopExit);
593            Bind(&next);
594            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
595            Label kValueIsHole(env);
596            Label kValueNotHole(env);
597            Label arrayValueIsHole(env);
598            Label arrayValueNotHole(env);
599            Label hasProperty(env);
600            BRANCH(TaggedIsHole(*kValue), &arrayValueIsHole, &arrayValueNotHole);
601            Bind(&arrayValueIsHole);
602            {
603                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
604                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &arrayValueNotHole);
605                Bind(&hasProperty);
606                Label hasException0(env);
607                Label notHasException0(env);
608                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
609                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
610                Bind(&hasException0);
611                {
612                    result->WriteVariable(Exception());
613                    Jump(exit);
614                }
615                Bind(&notHasException0);
616                {
617                    Jump(&arrayValueNotHole);
618                }
619            }
620            Bind(&arrayValueNotHole);
621            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &kValueNotHole);
622            Bind(&kValueNotHole);
623            {
624                GateRef key = Int64ToTaggedInt(*i);
625                Label checkArray(env);
626                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
627                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
628                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
629                    Circuit::NullGate(), callArgs);
630                GateRef retValue = callBuilder.JSCallDispatch();
631                Label find(env);
632                Label hasException1(env);
633                Label notHasException1(env);
634                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
635                Bind(&hasException1);
636                {
637                    result->WriteVariable(Exception());
638                    Jump(exit);
639                }
640                Bind(&notHasException1);
641                BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &checkArray);
642                Bind(&find);
643                {
644                    SetValueWithElementsKind(glue, newArray, *kValue, *toIndex, Boolean(true),
645                                             Int32(static_cast<uint32_t>(ElementsKind::NONE)));
646                    toIndex = Int64Add(*toIndex, Int64(1));
647                    Jump(&checkArray);
648                }
649                Bind(&checkArray);
650                {
651                    Label lenChange(env);
652                    GateRef tmpArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
653                    BRANCH(Int64LessThan(tmpArrLen, *thisArrLenVar), &lenChange, &kValueIsHole);
654                    Bind(&lenChange);
655                    {
656                        thisArrLenVar = tmpArrLen;
657                        Jump(&kValueIsHole);
658                    }
659                }
660            }
661            Bind(&kValueIsHole);
662            i = Int64Add(*i, Int64(1));
663            BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, &notStableJSArray);
664        }
665        Bind(&loopEnd);
666        LoopEnd(&loopHead, env, glue);
667        Bind(&loopExit);
668        Jump(&notStableJSArray);
669    }
670    Bind(&notStableJSArray);
671    {
672        Label finish(env);
673        Label callRT(env);
674        BRANCH(Int32LessThan(*i, len), &callRT, &finish);
675        Bind(&callRT);
676        {
677            CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, newArrayEles, *toIndex});
678            Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(*toIndex));
679            GateRef ret = CallRuntime(glue, RTSTUB_ID(JSArrayFilterUnStable), { argHandle, thisValue,
680                IntToTaggedInt(*i), IntToTaggedInt(len), IntToTaggedInt(*toIndex), newArray, callbackFnHandle });
681            result->WriteVariable(ret);
682            Jump(exit);
683        }
684        Bind(&finish);
685        {
686            result->WriteVariable(newArray);
687            Label needTrim(env);
688            BRANCH(Int64LessThan(*toIndex, len), &needTrim, exit);
689            Bind(&needTrim);
690            CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, newArrayEles, *toIndex});
691            Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(*toIndex));
692            Jump(exit);
693        }
694    }
695}
696
697void BuiltinsArrayStubBuilder::Map(GateRef glue, GateRef thisValue, GateRef numArgs,
698    Variable *result, Label *exit, Label *slowPath)
699{
700    auto env = GetEnvironment();
701    Label isHeapObject(env);
702    Label isJsArray(env);
703    Label defaultConstr(env);
704    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
705    Bind(&isHeapObject);
706    GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue))
707        .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done();
708    BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath);
709    Bind(&isJsArray);
710    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
711    Bind(&defaultConstr);
712
713    GateRef callbackFnHandle = GetCallArg0(numArgs);
714    Label argOHeapObject(env);
715    Label callable(env);
716    Label notOverFlow(env);
717    BRANCH(TaggedIsHeapObject(callbackFnHandle), &argOHeapObject, slowPath);
718    Bind(&argOHeapObject);
719    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
720    Bind(&callable);
721    GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue));
722    Label isEmptyArray(env);
723    Label notEmptyArray(env);
724    BRANCH(Int64Equal(len, Int64(0)), &isEmptyArray, &notEmptyArray);
725    Bind(&isEmptyArray);
726    {
727        NewObjectStubBuilder newBuilder(this);
728        result->WriteVariable(newBuilder.CreateEmptyArray(glue));
729        Jump(exit);
730    }
731    Bind(&notEmptyArray);
732    BRANCH(Int64GreaterThan(len, Int64(JSObject::MAX_GAP)), slowPath, &notOverFlow);
733    Bind(&notOverFlow);
734
735    GateRef argHandle = GetCallArg1(numArgs);
736    GateRef newArray = NewArray(glue, len);
737    Label stableJSArray(env);
738    Label notStableJSArray(env);
739    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
740    BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
741    Bind(&stableJSArray);
742    {
743        DEFVARIABLE(thisArrLenVar, VariableType::INT64(), len);
744        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
745        Label loopHead(env);
746        Label loopEnd(env);
747        Label next(env);
748        Label loopExit(env);
749        Jump(&loopHead);
750        LoopBegin(&loopHead);
751        {
752            BRANCH(Int64LessThan(*i, *thisArrLenVar), &next, &loopExit);
753            Bind(&next);
754            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
755            Label kValueIsHole(env);
756            Label kValueNotHole(env);
757            Label arrayValueIsHole(env);
758            Label arrayValueNotHole(env);
759            Label hasProperty(env);
760            BRANCH(TaggedIsHole(*kValue), &arrayValueIsHole, &arrayValueNotHole);
761            Bind(&arrayValueIsHole);
762            {
763                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
764                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &arrayValueNotHole);
765                Bind(&hasProperty);
766                Label hasException0(env);
767                Label notHasException0(env);
768                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
769                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
770                Bind(&hasException0);
771                {
772                    result->WriteVariable(Exception());
773                    Jump(exit);
774                }
775                Bind(&notHasException0);
776                {
777                    Jump(&arrayValueNotHole);
778                }
779            }
780            Bind(&arrayValueNotHole);
781            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &kValueNotHole);
782            Bind(&kValueNotHole);
783            {
784                GateRef key = Int64ToTaggedInt(*i);
785                Label checkArray(env);
786                JSCallArgs callArgs = (JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
787                callArgs.callThisArg3WithReturnArgs = {argHandle, *kValue, key, thisValue};
788                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
789                    Circuit::NullGate(), callArgs);
790                GateRef retValue = callBuilder.JSCallDispatch();
791                Label hasException1(env);
792                Label notHasException1(env);
793                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
794                Bind(&hasException1);
795                {
796                    result->WriteVariable(Exception());
797                    Jump(exit);
798                }
799                Bind(&notHasException1);
800                SetValueWithElementsKind(glue, newArray, retValue, *i, Boolean(true),
801                                         Int32(static_cast<uint32_t>(ElementsKind::NONE)));
802                Label lenChange(env);
803                GateRef tmpArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
804                BRANCH(Int64LessThan(tmpArrLen, *thisArrLenVar), &lenChange, &kValueIsHole);
805                Bind(&lenChange);
806                {
807                    thisArrLenVar = tmpArrLen;
808                    Jump(&kValueIsHole);
809                }
810            }
811            Bind(&kValueIsHole);
812            i = Int64Add(*i, Int64(1));
813            BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, &notStableJSArray);
814        }
815        Bind(&loopEnd);
816        LoopEnd(&loopHead);
817        Bind(&loopExit);
818        Jump(&notStableJSArray);
819    }
820    Bind(&notStableJSArray);
821    {
822        GateRef ret = CallRuntime(glue, RTSTUB_ID(JSArrayMapUnStable), { argHandle, thisValue,
823            IntToTaggedInt(*i), IntToTaggedInt(len), newArray, callbackFnHandle });
824        result->WriteVariable(ret);
825        Jump(exit);
826    }
827}
828
829// Note: unused arguments are reserved for further development
830void BuiltinsArrayStubBuilder::ForEach([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs,
831    [[maybe_unused]] Variable *result, Label *exit, Label *slowPath)
832{
833    auto env = GetEnvironment();
834    Label thisExists(env);
835    Label matchCls(env);
836    Label isHeapObject(env);
837    Label isGeneric(env);
838    Label isJsArray(env);
839    Label defaultConstr(env);
840    Label isStability(env);
841    Label notCOWArray(env);
842    Label equalCls(env);
843    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
844    Bind(&thisExists);
845    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
846    Bind(&isHeapObject);
847    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
848    Bind(&isJsArray);
849    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
850    Bind(&defaultConstr);
851    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
852    Bind(&isStability);
853    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
854    Bind(&notCOWArray);
855    GateRef arrayCls = LoadHClass(thisValue);
856    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
857    Bind(&matchCls);
858    Label arg0HeapObject(env);
859    Label callable(env);
860    Label thisIsStable(env);
861    Label thisNotStable(env);
862    GateRef callbackFnHandle = GetCallArg0(numArgs);
863    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
864    Bind(&arg0HeapObject);
865    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
866    Bind(&callable);
867    GateRef argHandle = GetCallArg1(numArgs);
868
869    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
870    DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0));
871    thisLen = GetArrayLength(thisValue);
872    Jump(&thisIsStable);
873
874    Bind(&thisIsStable);
875    {
876        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
877        Label loopHead(env);
878        Label loopEnd(env);
879        Label next(env);
880        Label loopExit(env);
881        Jump(&loopHead);
882        LoopBegin(&loopHead);
883        {
884            Label nextStep(env);
885            Label kValueIsHole(env);
886            Label callDispatch(env);
887            Label hasProperty(env);
888            Label hasException0(env);
889            Label hasException1(env);
890            GateRef newLen = GetArrayLength(thisValue);
891            BRANCH(BitAnd(IsStableJSArray(glue, thisValue), Int32Equal(*thisLen, newLen)),
892                &nextStep, &thisNotStable);
893            Bind(&nextStep);
894            BRANCH(Int64GreaterThanOrEqual(*i, ZExtInt32ToInt64(*thisLen)), &loopExit, &next);
895            Bind(&next);
896            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
897            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
898            Bind(&kValueIsHole);
899            {
900                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
901                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
902                Bind(&hasProperty);
903                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
904                BRANCH(HasPendingException(glue), &hasException0, &callDispatch);
905                Bind(&hasException0);
906                {
907                    result->WriteVariable(Exception());
908                    Jump(exit);
909                }
910            }
911            Bind(&callDispatch);
912            {
913                GateRef key = Int64ToTaggedInt(*i);
914                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
915                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
916                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
917                    Circuit::NullGate(), callArgs);
918                callBuilder.JSCallDispatch();
919                BRANCH(HasPendingException(glue), &hasException1, &loopEnd);
920                Bind(&hasException1);
921                {
922                    result->WriteVariable(Exception());
923                    Jump(exit);
924                }
925            }
926        }
927        Bind(&loopEnd);
928        i = Int64Add(*i, Int64(1));
929        LoopEnd(&loopHead);
930        Bind(&loopExit);
931        Jump(exit);
932    }
933
934    Bind(&thisNotStable);
935    {
936        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
937        Label loopHead(env);
938        Label loopEnd(env);
939        Label next(env);
940        Label loopExit(env);
941        Jump(&loopHead);
942        LoopBegin(&loopHead);
943        {
944            Label hasProperty(env);
945            Label hasException0(env);
946            Label notHasException0(env);
947            Label hasException1(env);
948            BRANCH(Int64GreaterThanOrEqual(*i, ZExtInt32ToInt64(*thisLen)), &loopExit, &next);
949            Bind(&next);
950            GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
951            BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
952            Bind(&hasProperty);
953            kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
954            BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
955            Bind(&hasException0);
956            {
957                result->WriteVariable(Exception());
958                Jump(exit);
959            }
960            Bind(&notHasException0);
961            {
962                GateRef key = Int64ToTaggedInt(*i);
963                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
964                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
965                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
966                    Circuit::NullGate(), callArgs);
967                callBuilder.JSCallDispatch();
968                BRANCH(HasPendingException(glue), &hasException1, &loopEnd);
969                Bind(&hasException1);
970                {
971                    result->WriteVariable(Exception());
972                    Jump(exit);
973                }
974            }
975        }
976        Bind(&loopEnd);
977        i = Int64Add(*i, Int64(1));
978        LoopEnd(&loopHead);
979        Bind(&loopExit);
980        Jump(exit);
981    }
982}
983
984// Note: unused arguments are reserved for further development
985void BuiltinsArrayStubBuilder::IndexOf([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs,
986    Variable *result, Label *exit, Label *slowPath)
987{
988    auto env = GetEnvironment();
989    Label thisIsEmpty(env);
990    // Fast path if: (1) this is an empty array; (2) fromIndex is missing
991    JsArrayRequirements req;
992    BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, slowPath);
993    Bind(&thisIsEmpty);
994    {
995        Label atMostOneArg(env);
996        BRANCH(Int32LessThanOrEqual(TruncPtrToInt32(numArgs), Int32(1)), &atMostOneArg, slowPath);
997        // Returns -1 on fast path
998        Bind(&atMostOneArg);
999        result->WriteVariable(IntToTaggedPtr(Int32(-1)));
1000        Jump(exit);
1001    }
1002}
1003
1004// Note: unused arguments are reserved for further development
1005void BuiltinsArrayStubBuilder::LastIndexOf([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs,
1006    Variable *result, Label *exit, Label *slowPath)
1007{
1008    auto env = GetEnvironment();
1009    Label thisIsEmpty(env);
1010    // Fast path if: (1) this is an empty array; (2) fromIndex is missing
1011    JsArrayRequirements req;
1012    BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, slowPath);
1013    Bind(&thisIsEmpty);
1014    {
1015        Label atMostOneArg(env);
1016        BRANCH(Int32LessThanOrEqual(TruncPtrToInt32(numArgs), Int32(1)), &atMostOneArg, slowPath);
1017        // Returns -1 on fast path
1018        Bind(&atMostOneArg);
1019        result->WriteVariable(IntToTaggedPtr(Int32(-1)));
1020        Jump(exit);
1021    }
1022}
1023
1024void BuiltinsArrayStubBuilder::Pop(GateRef glue, GateRef thisValue,
1025    [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
1026{
1027    auto env = GetEnvironment();
1028    Label isHeapObject(env);
1029    Label stableJSArray(env);
1030    Label isDeufaltConstructor(env);
1031    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1032    Bind(&isHeapObject);
1033    BRANCH(HasConstructor(thisValue), slowPath, &isDeufaltConstructor);
1034    Bind(&isDeufaltConstructor);
1035    BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
1036    Bind(&stableJSArray);
1037
1038    Label isLengthWritable(env);
1039    BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath);
1040    Bind(&isLengthWritable);
1041    GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1042
1043    Label notZeroLen(env);
1044    BRANCH(Int64Equal(thisLen, Int64(0)), exit, &notZeroLen);
1045    Bind(&notZeroLen);
1046    Label isJsCOWArray(env);
1047    Label getElements(env);
1048    BRANCH(IsJsCOWArray(thisValue), &isJsCOWArray, &getElements);
1049    Bind(&isJsCOWArray);
1050    {
1051        CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), { thisValue });
1052        Jump(&getElements);
1053    }
1054    Bind(&getElements);
1055    GateRef elements = GetElementsArray(thisValue);
1056    GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(elements));
1057    GateRef index = Int64Sub(thisLen, Int64(1));
1058
1059    Label inRange(env);
1060    Label trimCheck(env);
1061    Label noTrimCheck(env);
1062    Label setNewLen(env);
1063    Label isHole(env);
1064    DEFVARIABLE(element, VariableType::JS_ANY(), Hole());
1065    BRANCH(Int64LessThan(index, capacity), &inRange, &trimCheck);
1066    Bind(&inRange);
1067    {
1068        element = GetTaggedValueWithElementsKind(thisValue, index);
1069        Jump(&isHole);
1070    }
1071    Bind(&isHole);
1072    BRANCH(TaggedIsHole(*element), &noTrimCheck, &trimCheck);
1073    Bind(&noTrimCheck);
1074    {
1075        Label hasException0(env);
1076        Label notHasException0(env);
1077        element = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(index), ProfileOperation());
1078        BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
1079        Bind(&hasException0);
1080        {
1081            result->WriteVariable(Exception());
1082            Jump(exit);
1083        }
1084        Bind(&notHasException0);
1085        {
1086            Jump(&setNewLen);
1087        }
1088    }
1089    Bind(&trimCheck);
1090    // ShouldTrim check
1091    // (oldLength - newLength > MAX_END_UNUSED)
1092    Label noTrim(env);
1093    Label needTrim(env);
1094    GateRef unused = Int64Sub(capacity, index);
1095    BRANCH(Int64GreaterThan(unused, Int64(TaggedArray::MAX_END_UNUSED)), &needTrim, &noTrim);
1096    Bind(&needTrim);
1097    {
1098        CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, elements, index});
1099        Jump(&setNewLen);
1100    }
1101    Bind(&noTrim);
1102    {
1103        SetValueWithElementsKind(glue, thisValue, Hole(), index, Boolean(false),
1104                                 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1105        Jump(&setNewLen);
1106    }
1107    Bind(&setNewLen);
1108    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1109    Store(VariableType::INT32(), glue, thisValue, lengthOffset, TruncInt64ToInt32(index));
1110
1111    Label isNotHole(env);
1112    BRANCH(TaggedIsHole(*element), exit, &isNotHole);
1113    Bind(&isNotHole);
1114    {
1115        result->WriteVariable(*element);
1116        Jump(exit);
1117    }
1118}
1119
1120void BuiltinsArrayStubBuilder::Slice(GateRef glue, GateRef thisValue, GateRef numArgs,
1121    Variable *result, Label *exit, Label *slowPath)
1122{
1123    auto env = GetEnvironment();
1124    Label isHeapObject(env);
1125    Label isJsArray(env);
1126    Label noConstructor(env);
1127    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1128    Bind(&isHeapObject);
1129    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1130    Bind(&isJsArray);
1131    BRANCH(HasConstructor(thisValue), slowPath, &noConstructor);
1132    Bind(&noConstructor);
1133
1134    Label thisIsEmpty(env);
1135    Label thisNotEmpty(env);
1136    // Fast path if:
1137    // (1) this is an empty array with constructor not reset (see ArraySpeciesCreate for details);
1138    // (2) no arguments exist
1139    JsArrayRequirements req;
1140    req.defaultConstructor = true;
1141    BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, &thisNotEmpty);
1142    Bind(&thisIsEmpty);
1143    {
1144        Label noArgs(env);
1145        GateRef numArgsAsInt32 = TruncPtrToInt32(numArgs);
1146        BRANCH(Int32Equal(numArgsAsInt32, Int32(0)), &noArgs, slowPath);
1147        // Creates a new empty array on fast path
1148        Bind(&noArgs);
1149        NewObjectStubBuilder newBuilder(this);
1150        result->WriteVariable(newBuilder.CreateEmptyArray(glue));
1151        Jump(exit);
1152    }
1153    Bind(&thisNotEmpty);
1154    {
1155        Label stableJSArray(env);
1156        Label arrayLenNotZero(env);
1157
1158        GateRef isThisStableJSArray = IsStableJSArray(glue, thisValue);
1159        BRANCH(isThisStableJSArray, &stableJSArray, slowPath);
1160        Bind(&stableJSArray);
1161
1162        GateRef msg0 = GetCallArg0(numArgs);
1163        GateRef msg1 = GetCallArg1(numArgs);
1164        GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1165        Label msg0Int(env);
1166        BRANCH(TaggedIsInt(msg0), &msg0Int, slowPath);
1167        Bind(&msg0Int);
1168        DEFVARIABLE(start, VariableType::INT64(), Int64(0));
1169        DEFVARIABLE(end, VariableType::INT64(), thisArrLen);
1170
1171        GateRef argStart = SExtInt32ToInt64(TaggedGetInt(msg0));
1172        Label arg0LessZero(env);
1173        Label arg0NotLessZero(env);
1174        Label startDone(env);
1175        BRANCH(Int64LessThan(argStart, Int64(0)), &arg0LessZero, &arg0NotLessZero);
1176        Bind(&arg0LessZero);
1177        {
1178            Label tempGreaterZero(env);
1179            Label tempNotGreaterZero(env);
1180            GateRef tempStart = Int64Add(argStart, thisArrLen);
1181            BRANCH(Int64GreaterThan(tempStart, Int64(0)), &tempGreaterZero, &tempNotGreaterZero);
1182            Bind(&tempGreaterZero);
1183            {
1184                start = tempStart;
1185                Jump(&startDone);
1186            }
1187            Bind(&tempNotGreaterZero);
1188            {
1189                Jump(&startDone);
1190            }
1191        }
1192        Bind(&arg0NotLessZero);
1193        {
1194            Label argLessLen(env);
1195            Label argNotLessLen(env);
1196            BRANCH(Int64LessThan(argStart, thisArrLen), &argLessLen, &argNotLessLen);
1197            Bind(&argLessLen);
1198            {
1199                start = argStart;
1200                Jump(&startDone);
1201            }
1202            Bind(&argNotLessLen);
1203            {
1204                start = thisArrLen;
1205                Jump(&startDone);
1206            }
1207        }
1208        Bind(&startDone);
1209        {
1210            Label endDone(env);
1211            Label msg1Def(env);
1212            BRANCH(TaggedIsUndefined(msg1), &endDone, &msg1Def);
1213            Bind(&msg1Def);
1214            {
1215                Label msg1Int(env);
1216                BRANCH(TaggedIsInt(msg1), &msg1Int, slowPath);
1217                Bind(&msg1Int);
1218                {
1219                    GateRef argEnd = SExtInt32ToInt64(TaggedGetInt(msg1));
1220                    Label arg1LessZero(env);
1221                    Label arg1NotLessZero(env);
1222                    BRANCH(Int64LessThan(argEnd, Int64(0)), &arg1LessZero, &arg1NotLessZero);
1223                    Bind(&arg1LessZero);
1224                    {
1225                        Label tempGreaterZero(env);
1226                        Label tempNotGreaterZero(env);
1227                        GateRef tempEnd = Int64Add(argEnd, thisArrLen);
1228                        BRANCH(Int64GreaterThan(tempEnd, Int64(0)), &tempGreaterZero, &tempNotGreaterZero);
1229                        Bind(&tempGreaterZero);
1230                        {
1231                            end = tempEnd;
1232                            Jump(&endDone);
1233                        }
1234                        Bind(&tempNotGreaterZero);
1235                        {
1236                            end = Int64(0);
1237                            Jump(&endDone);
1238                        }
1239                    }
1240                    Bind(&arg1NotLessZero);
1241                    {
1242                        Label argLessLen(env);
1243                        Label argNotLessLen(env);
1244                        BRANCH(Int64LessThan(argEnd, thisArrLen), &argLessLen, &argNotLessLen);
1245                        Bind(&argLessLen);
1246                        {
1247                            end = argEnd;
1248                            Jump(&endDone);
1249                        }
1250                        Bind(&argNotLessLen);
1251                        {
1252                            end = thisArrLen;
1253                            Jump(&endDone);
1254                        }
1255                    }
1256                }
1257            }
1258            Bind(&endDone);
1259            {
1260                DEFVARIABLE(count, VariableType::INT64(), Int64(0));
1261                GateRef tempCnt = Int64Sub(*end, *start);
1262                Label tempCntGreaterOrEqualZero(env);
1263                Label tempCntDone(env);
1264                BRANCH(Int64LessThan(tempCnt, Int64(0)), &tempCntDone, &tempCntGreaterOrEqualZero);
1265                Bind(&tempCntGreaterOrEqualZero);
1266                {
1267                    count = tempCnt;
1268                    Jump(&tempCntDone);
1269                }
1270                Bind(&tempCntDone);
1271                {
1272                    Label notOverFlow(env);
1273                    BRANCH(Int64GreaterThan(*count, Int64(JSObject::MAX_GAP)), slowPath, &notOverFlow);
1274                    Bind(&notOverFlow);
1275                    {
1276                        GateRef newArray = NewArray(glue, *count);
1277                        GateRef thisEles = GetElementsArray(thisValue);
1278                        GateRef thisElesLen = ZExtInt32ToInt64(GetLengthOfTaggedArray(thisEles));
1279
1280                        Label inThisEles(env);
1281                        Label outThisEles(env);
1282                        BRANCH(Int64GreaterThan(thisElesLen, Int64Add(*start, *count)), &inThisEles, &outThisEles);
1283                        Bind(&inThisEles);
1284                        {
1285                            DEFVARIABLE(idx, VariableType::INT64(), Int64(0));
1286                            Label loopHead(env);
1287                            Label loopEnd(env);
1288                            Label next(env);
1289                            Label loopExit(env);
1290                            Jump(&loopHead);
1291                            LoopBegin(&loopHead);
1292                            {
1293                                BRANCH(Int64LessThan(*idx, *count), &next, &loopExit);
1294                                Bind(&next);
1295
1296                                GateRef ele = GetTaggedValueWithElementsKind(thisValue, Int64Add(*idx, *start));
1297                                SetValueWithElementsKind(glue, newArray, ele, *idx, Boolean(true),
1298                                                         Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1299                                Jump(&loopEnd);
1300                            }
1301                            Bind(&loopEnd);
1302                            idx = Int64Add(*idx, Int64(1));
1303                            LoopEnd(&loopHead, env, glue);
1304                            Bind(&loopExit);
1305                            result->WriteVariable(newArray);
1306                            Jump(exit);
1307                        }
1308                        Bind(&outThisEles);
1309                        {
1310                            DEFVARIABLE(idx, VariableType::INT64(), Int64(0));
1311                            Label loopHead(env);
1312                            Label loopEnd(env);
1313                            Label next(env);
1314                            Label loopExit(env);
1315                            Jump(&loopHead);
1316                            LoopBegin(&loopHead);
1317                            {
1318                                BRANCH(Int64LessThan(*idx, *count), &next, &loopExit);
1319                                Bind(&next);
1320                                GateRef index = Int64Add(*idx, *start);
1321                                DEFVARIABLE(ele, VariableType::JS_ANY(), Hole());
1322
1323                                Label indexOutRange(env);
1324                                Label indexInRange(env);
1325                                Label setEle(env);
1326                                BRANCH(Int64GreaterThan(thisElesLen, index), &indexInRange, &indexOutRange);
1327                                Bind(&indexInRange);
1328                                {
1329                                    ele = GetTaggedValueWithElementsKind(thisValue, index);
1330                                    Jump(&setEle);
1331                                }
1332                                Bind(&indexOutRange);
1333                                {
1334                                    ele = Hole();
1335                                    Jump(&setEle);
1336                                }
1337                                Bind(&setEle);
1338                                SetValueWithElementsKind(glue, newArray, *ele, *idx, Boolean(true),
1339                                                         Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1340                                Jump(&loopEnd);
1341                            }
1342                            Bind(&loopEnd);
1343                            idx = Int64Add(*idx, Int64(1));
1344                            LoopEnd(&loopHead, env, glue);
1345                            Bind(&loopExit);
1346                            result->WriteVariable(newArray);
1347                            Jump(exit);
1348                        }
1349                    }
1350                }
1351            }
1352        }
1353    }
1354}
1355
1356void BuiltinsArrayStubBuilder::Sort(GateRef glue, GateRef thisValue,
1357    GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
1358{
1359    GateRef callbackFnHandle = GetCallArg0(numArgs);
1360    SortAfterArgs(glue, thisValue, callbackFnHandle, result, exit, slowPath);
1361}
1362
1363void BuiltinsArrayStubBuilder::SortAfterArgs(GateRef glue, GateRef thisValue,
1364    GateRef callbackFnHandle, Variable *result, Label *exit, Label *slowPath, GateRef hir)
1365{
1366    auto env = GetEnvironment();
1367    Label isHeapObject(env);
1368    Label isJsArray(env);
1369    Label defaultConstr(env);
1370    Label isStability(env);
1371    Label notCOWArray(env);
1372    Label argUndefined(env);
1373    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1374    Bind(&isHeapObject);
1375    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1376    Bind(&isJsArray);
1377    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1378    Bind(&defaultConstr);
1379    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1380    Bind(&isStability);
1381    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
1382    Bind(&notCOWArray);
1383    BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath);
1384    Bind(&argUndefined);
1385    result->WriteVariable(DoSort(glue, thisValue, Boolean(false), result, exit, slowPath, hir));
1386    Jump(exit);
1387}
1388
1389void BuiltinsArrayStubBuilder::ToSorted(GateRef glue, GateRef thisValue,
1390    GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
1391{
1392    auto env = GetEnvironment();
1393    Label isHeapObject(env);
1394    Label isJsArray(env);
1395    Label defaultConstr(env);
1396    Label isStability(env);
1397    Label notCOWArray(env);
1398    Label argUndefined(env);
1399    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1400    Bind(&isHeapObject);
1401    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1402    Bind(&isJsArray);
1403    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1404    Bind(&defaultConstr);
1405    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1406    Bind(&isStability);
1407    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
1408    Bind(&notCOWArray);
1409    GateRef callbackFnHandle = GetCallArg0(numArgs);
1410    BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath);
1411    Bind(&argUndefined);
1412
1413    GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1414    GateRef receiver = NewArray(glue, thisArrLen);
1415    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1416    Label loopHead(env);
1417    Label loopEnd(env);
1418    Label next(env);
1419    Label loopExit(env);
1420    Jump(&loopHead);
1421    LoopBegin(&loopHead);
1422    {
1423        BRANCH(Int64LessThan(*i, thisArrLen), &next, &loopExit);
1424        Bind(&next);
1425        {
1426            GateRef ele = GetTaggedValueWithElementsKind(thisValue, *i);
1427            SetValueWithElementsKind(glue, receiver, ele, *i, Boolean(true),
1428                Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1429            Jump(&loopEnd);
1430        }
1431    }
1432    Bind(&loopEnd);
1433    i = Int64Add(*i, Int64(1));
1434    LoopEnd(&loopHead);
1435    Bind(&loopExit);
1436    result->WriteVariable(DoSort(glue, receiver, Boolean(true), result, exit, slowPath));
1437    Jump(exit);
1438}
1439
1440GateRef BuiltinsArrayStubBuilder::DoSort(GateRef glue, GateRef receiver, GateRef receiverState,
1441    Variable *result, Label *exit, Label *slowPath, GateRef hir)
1442{
1443    auto env = GetEnvironment();
1444    Label entry(env);
1445    env->SubCfgEntry(&entry);
1446    GateRef len = ZExtInt32ToInt64(GetArrayLength(receiver));
1447    DEFVARIABLE(i, VariableType::INT64(), Int64(1));
1448    DEFVARIABLE(presentValue, VariableType::JS_ANY(), Undefined());
1449    DEFVARIABLE(middleValue, VariableType::JS_ANY(), Undefined());
1450    DEFVARIABLE(previousValue, VariableType::JS_ANY(), Undefined());
1451    Label loopHead(env);
1452    Label loopEnd(env);
1453    Label next(env);
1454    Label loopExit(env);
1455    Jump(&loopHead);
1456    LoopBegin(&loopHead);
1457    {
1458        BRANCH(Int64LessThan(*i, len), &next, &loopExit);
1459        Bind(&next);
1460        DEFVARIABLE(beginIndex, VariableType::INT64(), Int64(0));
1461        DEFVARIABLE(endIndex, VariableType::INT64(), *i);
1462        Label presentValueIsHole(env);
1463        Label afterGettingpresentValue(env);
1464        Label presentValueHasProperty(env);
1465        Label presentValueHasException0(env);
1466        presentValue = GetTaggedValueWithElementsKind(receiver, *i);
1467        BRANCH(TaggedIsHole(*presentValue), &presentValueIsHole, &afterGettingpresentValue);
1468        Bind(&presentValueIsHole);
1469        {
1470            GateRef presentValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { receiver, IntToTaggedInt(*i) });
1471            BRANCH(TaggedIsTrue(presentValueHasProp), &presentValueHasProperty, &afterGettingpresentValue);
1472            Bind(&presentValueHasProperty);
1473            {
1474                presentValue = FastGetPropertyByIndex(glue, receiver, TruncInt64ToInt32(*i), ProfileOperation(), hir);
1475                BRANCH(HasPendingException(glue), &presentValueHasException0, &afterGettingpresentValue);
1476                Bind(&presentValueHasException0);
1477                {
1478                    result->WriteVariable(Exception());
1479                    Jump(exit);
1480                }
1481            }
1482        }
1483        Bind(&afterGettingpresentValue);
1484        {
1485            Label loopHead1(env);
1486            Label loopEnd1(env);
1487            Label next1(env);
1488            Label loopExit1(env);
1489            Jump(&loopHead1);
1490            LoopBegin(&loopHead1);
1491            {
1492                Label middleValueIsHole(env);
1493                Label afterGettingmiddleValue(env);
1494                Label middleValueHasProperty(env);
1495                Label middleValueHasException0(env);
1496                BRANCH(Int64LessThan(*beginIndex, *endIndex), &next1, &loopExit1);
1497                Bind(&next1);
1498                GateRef sum = Int64Add(*beginIndex, *endIndex);
1499                GateRef middleIndex = Int64Div(sum, Int64(2)); // 2 : half
1500                middleValue = GetTaggedValueWithElementsKind(receiver, middleIndex);
1501                BRANCH(TaggedIsHole(*middleValue), &middleValueIsHole, &afterGettingmiddleValue);
1502                Bind(&middleValueIsHole);
1503                {
1504                    GateRef middleValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty),
1505                        { receiver, IntToTaggedInt(middleIndex) });
1506                    BRANCH(TaggedIsTrue(middleValueHasProp), &middleValueHasProperty, &afterGettingmiddleValue);
1507                    Bind(&middleValueHasProperty);
1508                    {
1509                        middleValue = FastGetPropertyByIndex(glue, receiver,
1510                            TruncInt64ToInt32(middleIndex), ProfileOperation(), hir);
1511                        BRANCH(HasPendingException(glue), &middleValueHasException0, &afterGettingmiddleValue);
1512                        Bind(&middleValueHasException0);
1513                        {
1514                            result->WriteVariable(Exception());
1515                            Jump(exit);
1516                        }
1517                    }
1518                }
1519                Bind(&afterGettingmiddleValue);
1520                {
1521                    Label isInt(env);
1522                    Label notInt(env);
1523                    Label exchangeIndex(env);
1524                    GateRef middleVal = *middleValue;
1525                    GateRef presentVal = *presentValue;
1526                    DEFVARIABLE(compareResult, VariableType::INT32(), Int32(0));
1527                    GateRef intBool = LogicAndBuilder(env)
1528                                        .And(TaggedIsInt(middleVal))
1529                                        .And(TaggedIsInt(presentVal))
1530                                        .Done();
1531                    BRANCH(intBool, &isInt, &notInt);
1532                    Bind(&isInt);
1533                    {
1534                        compareResult =
1535                            CallNGCRuntime(glue, RTSTUB_ID(FastArraySort), {*middleValue, *presentValue});
1536                        Jump(&exchangeIndex);
1537                    }
1538                    Bind(&notInt);
1539                    {
1540                        Label isString(env);
1541                        GateRef strBool = LogicAndBuilder(env)
1542                                        .And(TaggedIsString(middleVal))
1543                                        .And(TaggedIsString(presentVal))
1544                                        .Done();
1545                        BRANCH(strBool, &isString, slowPath);
1546                        Bind(&isString);
1547                        {
1548                            compareResult = CallNGCRuntime(glue,
1549                                RTSTUB_ID(FastArraySortString), {glue, *middleValue, *presentValue});
1550                            Jump(&exchangeIndex);
1551                        }
1552                    }
1553                    Bind(&exchangeIndex);
1554                    {
1555                        Label less0(env);
1556                        Label greater0(env);
1557                        BRANCH(Int32LessThanOrEqual(*compareResult, Int32(0)), &less0, &greater0);
1558                        Bind(&greater0);
1559                        {
1560                            endIndex = middleIndex;
1561                            Jump(&loopEnd1);
1562                        }
1563                        Bind(&less0);
1564                        {
1565                            beginIndex = middleIndex;
1566                            beginIndex = Int64Add(*beginIndex, Int64(1));
1567                            Jump(&loopEnd1);
1568                        }
1569                    }
1570                }
1571            }
1572            Bind(&loopEnd1);
1573            LoopEnd(&loopHead1);
1574            Bind(&loopExit1);
1575
1576            Label shouldCopy(env);
1577            GateRef isGreater0 = Int64GreaterThanOrEqual(*endIndex, Int64(0));
1578            GateRef lessI = Int64LessThan(*endIndex, *i);
1579            BRANCH(BitAnd(isGreater0, lessI), &shouldCopy, &loopEnd);
1580            Bind(&shouldCopy);
1581            {
1582                DEFVARIABLE(j, VariableType::INT64(), *i);
1583                Label loopHead2(env);
1584                Label loopEnd2(env);
1585                Label next2(env);
1586                Label loopExit2(env);
1587                Label receiverIsNew(env);
1588                Label receiverIsOrigin(env);
1589                Label receiverIsNew2(env);
1590                Label receiverIsOrigin2(env);
1591                Jump(&loopHead2);
1592                LoopBegin(&loopHead2);
1593                {
1594                    Label previousValueIsHole(env);
1595                    Label afterGettingpreviousValue(env);
1596                    Label previousValueHasProperty(env);
1597                    Label previousValueHasException0(env);
1598                    BRANCH(Int64GreaterThan(*j, *endIndex), &next2, &loopExit2);
1599                    Bind(&next2);
1600                    previousValue = GetTaggedValueWithElementsKind(receiver, Int64Sub(*j, Int64(1)));
1601                    BRANCH(TaggedIsHole(*previousValue), &previousValueIsHole, &afterGettingpreviousValue);
1602                    Bind(&previousValueIsHole);
1603                    {
1604                        GateRef previousValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty),
1605                            { receiver, IntToTaggedInt(Int64Sub(*j, Int64(1))) });
1606                        BRANCH(TaggedIsTrue(previousValueHasProp),
1607                            &previousValueHasProperty, &afterGettingpreviousValue);
1608                        Bind(&previousValueHasProperty);
1609                        {
1610                            previousValue = FastGetPropertyByIndex(glue, receiver,
1611                                TruncInt64ToInt32(Int64Sub(*j, Int64(1))), ProfileOperation(), hir);
1612                            BRANCH(HasPendingException(glue), &previousValueHasException0, &afterGettingpreviousValue);
1613                            Bind(&previousValueHasException0);
1614                            {
1615                                result->WriteVariable(Exception());
1616                                Jump(exit);
1617                            }
1618                        }
1619                    }
1620                    Bind(&afterGettingpreviousValue);
1621                    {
1622                        BRANCH(receiverState, &receiverIsNew, &receiverIsOrigin);
1623                        Bind(&receiverIsNew);
1624                        SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(true),
1625                            Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1626                        Jump(&loopEnd2);
1627                        Bind(&receiverIsOrigin);
1628                        SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(false),
1629                            Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1630                        Jump(&loopEnd2);
1631                    }
1632                }
1633                Bind(&loopEnd2);
1634                j = Int64Sub(*j, Int64(1));
1635                LoopEnd(&loopHead2);
1636                Bind(&loopExit2);
1637                BRANCH(receiverState, &receiverIsNew2, &receiverIsOrigin2);
1638                Bind(&receiverIsNew2);
1639                {
1640                    SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(true),
1641                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1642                    Jump(&loopEnd);
1643                }
1644                Bind(&receiverIsOrigin2);
1645                {
1646                    SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(false),
1647                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1648                    Jump(&loopEnd);
1649                }
1650            }
1651        }
1652    }
1653    Bind(&loopEnd);
1654    i = Int64Add(*i, Int64(1));
1655    LoopEnd(&loopHead);
1656    Bind(&loopExit);
1657    env->SubCfgExit();
1658    return receiver;
1659}
1660
1661void BuiltinsArrayStubBuilder::Reduce(GateRef glue, GateRef thisValue, GateRef numArgs,
1662    Variable *result, Label *exit, Label *slowPath)
1663{
1664    auto env = GetEnvironment();
1665    DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0));
1666    Label isHeapObject(env);
1667    Label isJsArray(env);
1668    Label defaultConstr(env);
1669    Label atLeastOneArg(env);
1670    Label callbackFnHandleHeapObject(env);
1671    Label callbackFnHandleCallable(env);
1672    Label noTypeError(env);
1673
1674    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1675    Bind(&isHeapObject);
1676    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1677    Bind(&isJsArray);
1678    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1679    Bind(&defaultConstr);
1680    thisLen = GetArrayLength(thisValue);
1681    BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
1682    Bind(&atLeastOneArg);
1683    GateRef callbackFnHandle = GetCallArg0(numArgs);
1684    BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath);
1685    Bind(&callbackFnHandleHeapObject);
1686    BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath);
1687    Bind(&callbackFnHandleCallable);
1688    GateRef thisLenIsZero = Int32Equal(*thisLen, Int32(0));
1689    GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2));
1690    BRANCH(BitAnd(thisLenIsZero, numArgsLessThanTwo), slowPath, &noTypeError);
1691    Bind(&noTypeError);
1692    {
1693        DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined());
1694        DEFVARIABLE(k, VariableType::INT32(), Int32(0));
1695
1696        Label updateAccumulator(env);
1697        Label checkForStableJSArray(env);
1698
1699        BRANCH(Int64Equal(numArgs, IntPtr(2)), &updateAccumulator, slowPath); // 2: provide initialValue param
1700        Bind(&updateAccumulator);
1701        {
1702            accumulator = GetCallArg1(numArgs);
1703            Jump(&checkForStableJSArray);
1704        }
1705        Bind(&checkForStableJSArray);
1706        {
1707            Label isStableJSArray(env);
1708            Label notStableJSArray(env);
1709            BRANCH(IsStableJSArray(glue, thisValue), &isStableJSArray, &notStableJSArray);
1710            Bind(&isStableJSArray);
1711            {
1712                GateRef argsLength = Int32(4); // 4: «accumulator, kValue, k, thisValue»
1713                NewObjectStubBuilder newBuilder(this);
1714                GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
1715                Label loopHead(env);
1716                Label next(env);
1717                Label loopEnd(env);
1718                Label loopExit(env);
1719                Jump(&loopHead);
1720                LoopBegin(&loopHead);
1721                {
1722                    BRANCH(Int32LessThan(*k, *thisLen), &next, &loopExit);
1723                    Bind(&next);
1724                    {
1725                        Label updateK(env);
1726                        Label notHole(env);
1727                        Label changeThisLen(env);
1728                        Label updateCallResult(env);
1729                        GateRef elements = GetElementsArray(thisValue);
1730                        GateRef kValue = GetTaggedValueWithElementsKind(thisValue, *k);
1731                        BRANCH(TaggedIsHole(kValue), &loopEnd, &notHole);
1732                        Bind(&notHole);
1733                        {
1734                            SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
1735                            SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), kValue);
1736                            // 2 : parameter location
1737                            SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
1738                            // 3 : parameter location
1739                            SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
1740                            GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
1741                            JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
1742                            callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
1743                            CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr,
1744                                Circuit::NullGate(), callArgs);
1745                            GateRef callResult = callBuilder.JSCallDispatch();
1746                            Label hasException1(env);
1747                            Label notHasException1(env);
1748                            BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
1749                            Bind(&hasException1);
1750                            {
1751                                result->WriteVariable(Exception());
1752                                Jump(exit);
1753                            }
1754                            Bind(&notHasException1);
1755                            GateRef newLen = GetLengthOfTaggedArray(elements);
1756                            BRANCH(Int32LessThan(newLen, *thisLen), &changeThisLen, &updateCallResult);
1757                            Bind(&changeThisLen);
1758                            {
1759                                thisLen = newLen;
1760                                Jump(&updateCallResult);
1761                            }
1762                            Bind(&updateCallResult);
1763                            {
1764                                accumulator = callResult;
1765                                Jump(&loopEnd);
1766                            }
1767                        }
1768                    }
1769                }
1770                Bind(&loopEnd);
1771                {
1772                    k = Int32Add(*k, Int32(1));
1773
1774                    Label isStableJSArray1(env);
1775                    Label notStableJSArray1(env);
1776                    BRANCH(IsStableJSArray(glue, thisValue), &isStableJSArray1, &notStableJSArray1);
1777                    Bind(&notStableJSArray1);
1778                    {
1779                        Jump(&loopExit);
1780                    }
1781                    Bind(&isStableJSArray1);
1782                    LoopEnd(&loopHead, env, glue);
1783                }
1784                Bind(&loopExit);
1785                Jump(&notStableJSArray);
1786            }
1787            Bind(&notStableJSArray);
1788            {
1789                Label finish(env);
1790                Label callRT(env);
1791                BRANCH(Int32LessThan(*k, *thisLen), &callRT, &finish);
1792                Bind(&callRT);
1793                {
1794                    accumulator = CallRuntime(glue, RTSTUB_ID(JSArrayReduceUnStable), { thisValue, thisValue,
1795                        IntToTaggedInt(*k), IntToTaggedInt(*thisLen), *accumulator, callbackFnHandle });
1796                    Jump(&finish);
1797                }
1798                Bind(&finish);
1799                {
1800                    result->WriteVariable(*accumulator);
1801                    Jump(exit);
1802                }
1803            }
1804        }
1805    }
1806}
1807
1808void BuiltinsArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs,
1809    Variable *result, Label *exit, Label *slowPath)
1810{
1811    auto env = GetEnvironment();
1812    Label isHeapObject(env);
1813    Label isJsArray(env);
1814    Label isStability(env);
1815    Label defaultConstr(env);
1816    Label notCOWArray(env);
1817    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1818    Bind(&isHeapObject);
1819    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1820    Bind(&isJsArray);
1821    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1822    Bind(&defaultConstr);
1823    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1824    Bind(&isStability);
1825    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
1826    Bind(&notCOWArray);
1827
1828    GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1829    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1830    DEFVARIABLE(j, VariableType::INT64(),  Int64Sub(thisArrLen, Int64(1)));
1831
1832    GateRef hclass = LoadHClass(thisValue);
1833    GateRef kind = GetElementsKindFromHClass(hclass);
1834    Label isInt(env);
1835    Label isNotInt(env);
1836    Label notFastKind(env);
1837    GateRef isElementsKindEnabled = IsEnableElementsKind(glue);
1838    GateRef checkIntKind = LogicAndBuilder(env)
1839        .And(isElementsKindEnabled)
1840        .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::INT))))
1841        .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_INT))))
1842        .Done();
1843    BRANCH(checkIntKind, &isInt, &isNotInt);
1844    Bind(&isInt);
1845    {
1846        FastReverse(glue, thisValue, thisArrLen, ElementsKind::INT, result, exit);
1847    }
1848    Bind(&isNotInt);
1849    {
1850        Label isNumber(env);
1851        Label isNotNumber(env);
1852        GateRef checkNumberKind = LogicAndBuilder(env)
1853            .And(isElementsKindEnabled)
1854            .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::NUMBER))))
1855            .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER))))
1856            .Done();
1857        BRANCH(checkNumberKind, &isNumber, &isNotNumber);
1858        Bind(&isNumber);
1859        {
1860            FastReverse(glue, thisValue, thisArrLen, ElementsKind::NUMBER, result, exit);
1861        }
1862        Bind(&isNotNumber);
1863        {
1864            FastReverse(glue, thisValue, thisArrLen, ElementsKind::TAGGED, result, exit);
1865        }
1866    }
1867}
1868
1869void BuiltinsArrayStubBuilder::FastReverse(GateRef glue, GateRef thisValue, GateRef len,
1870    ElementsKind kind, Variable *result, Label *exit)
1871{
1872    auto env = GetEnvironment();
1873    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1874    DEFVARIABLE(j, VariableType::INT64(),  Int64Sub(len, Int64(1)));
1875    GateRef elements = GetElementsArray(thisValue);
1876    Label loopHead(env);
1877    Label loopEnd(env);
1878    Label next(env);
1879    Label loopExit(env);
1880    Jump(&loopHead);
1881    LoopBegin(&loopHead);
1882    {
1883        Label arrayValue(env);
1884        Label valueEqual(env);
1885        BRANCH(Int64LessThan(*i, *j), &next, &loopExit);
1886        Bind(&next);
1887        {
1888            if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
1889                GateRef lower = GetValueFromMutantTaggedArray(elements, *i);
1890                GateRef upper = GetValueFromMutantTaggedArray(elements, *j);
1891                FastSetValueWithElementsKind(glue, elements, upper, *i, kind);
1892                FastSetValueWithElementsKind(glue, elements, lower, *j, kind);
1893                Jump(&loopEnd);
1894            } else {
1895                GateRef lower = GetValueFromTaggedArray(elements, *i);
1896                GateRef upper = GetValueFromTaggedArray(elements, *j);
1897                FastSetValueWithElementsKind(glue, elements, upper, *i, kind);
1898                FastSetValueWithElementsKind(glue, elements, lower, *j, kind);
1899                Jump(&loopEnd);
1900            }
1901        }
1902    }
1903    Bind(&loopEnd);
1904    i = Int64Add(*i, Int64(1));
1905    j = Int64Sub(*j, Int64(1));
1906    LoopEnd(&loopHead, env, glue);
1907    Bind(&loopExit);
1908    result->WriteVariable(thisValue);
1909    Jump(exit);
1910}
1911
1912void BuiltinsArrayStubBuilder::ToReversed(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs,
1913                                          Variable* result, Label* exit, Label* slowPath)
1914{
1915    auto env = GetEnvironment();
1916    Label isHeapObject(env);
1917    Label isJsArray(env);
1918    Label defaultConstr(env);
1919    Label isStability(env);
1920    Label notCOWArray(env);
1921    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1922    Bind(&isHeapObject);
1923    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1924    Bind(&isJsArray);
1925    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1926    Bind(&defaultConstr);
1927    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1928    Bind(&isStability);
1929    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
1930    Bind(&notCOWArray);
1931    Label newArrayIsTagged(env);
1932    Label notChange(env);
1933    GateRef isElementsKindEnabled = IsEnableElementsKind(glue);
1934    DEFVARIABLE(newHClass, VariableType::JS_ANY(), LoadHClass(thisValue));
1935    GateRef kind = GetElementsKindFromHClass(LoadHClass(thisValue));
1936    BRANCH_NO_WEIGHT(LogicAndBuilder(env).And(isElementsKindEnabled).And(ElementsKindHasHole(kind)).Done(),
1937                     &newArrayIsTagged, &notChange);
1938    Bind(&newArrayIsTagged);
1939    {
1940        // If the kind has hole, we know it must be transited to TAGGED kind;
1941        // There will be no hole in the new array because hole will be converted to undefined.
1942        newHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ELEMENT_TAGGED_HCLASS_INDEX);
1943        Jump(&notChange);
1944    }
1945
1946    Bind(&notChange);
1947    GateRef thisArrLen = GetArrayLength(thisValue);
1948    GateRef receiver = NewArrayWithHClass(glue, *newHClass);
1949    GrowElementsCapacity(glue, receiver, thisArrLen);
1950    SetArrayLength(glue, receiver, thisArrLen);
1951
1952    Label afterReverse(env);
1953    Label isIntOrNumber(env);
1954    Label notIntOrNumber(env);
1955    Label isTagged(env);
1956    Label isHoleOrIntOrNumber(env);
1957    Label elementsKindEnabled(env);
1958    BRANCH_NO_WEIGHT(isElementsKindEnabled, &elementsKindEnabled, &isTagged);
1959    Bind(&elementsKindEnabled);
1960    {
1961        GateRef intOrNumber = LogicOrBuilder(env)
1962                              .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::INT))))
1963                              .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::NUMBER))))
1964                              .Done();
1965        BRANCH_NO_WEIGHT(intOrNumber, &isIntOrNumber, &notIntOrNumber);
1966        Bind(&notIntOrNumber);
1967        {
1968            GateRef holeOrIntOrNumber = LogicOrBuilder(env)
1969                                        .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_INT))))
1970                                        .Or(Int32Equal(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER))))
1971                                        .Done();
1972            BRANCH_NO_WEIGHT(holeOrIntOrNumber, &isHoleOrIntOrNumber, &isTagged);
1973        }
1974    }
1975    Bind(&isTagged);
1976    {
1977        // The old array and new array are both TaggedArray, so load and store the element directly.
1978        // And barrier is needed.
1979        DoReverse(glue, thisValue, receiver, true, false, MemoryAttribute::Default());
1980        Jump(&afterReverse);
1981    }
1982    Bind(&isIntOrNumber);
1983    {
1984        // The old array and new array are both MutantTaggedArray, so load and store the element directly.
1985        // And barrier is not needed.
1986        DoReverse(glue, thisValue, receiver, false, false, MemoryAttribute::NoBarrier());
1987        Jump(&afterReverse);
1988    }
1989    Bind(&isHoleOrIntOrNumber);
1990    {
1991        // The old array is mutant, but new array is TaggedArray, so load the value from old array with
1992        // elements kind. And set it to new array directly, And barrier is not needed.
1993        DoReverse(glue, thisValue, receiver, true, true, MemoryAttribute::NoBarrier());
1994        Jump(&afterReverse);
1995    }
1996    Bind(&afterReverse);
1997    result->WriteVariable(receiver);
1998    Jump(exit);
1999}
2000
2001void BuiltinsArrayStubBuilder::DoReverse(GateRef glue, GateRef fromArray, GateRef toArray, bool holeToUndefined,
2002                                         bool getWithKind, MemoryAttribute mAttr)
2003{
2004    auto env = GetEnvironment();
2005    Label entry(env);
2006    env->SubCfgEntry(&entry);
2007    Label loopExit(env);
2008    Label begin(env);
2009    Label body(env);
2010    Label endLoop(env);
2011
2012    GateRef fromElements = GetElementsArray(fromArray);
2013    GateRef toElements = GetElementsArray(toArray);
2014    GateRef thisArrLen = GetArrayLength(fromArray);
2015    DEFVARIABLE(index, VariableType::INT32(), Int32(0));
2016    GateRef endIndex = Int32Sub(thisArrLen, Int32(1));
2017    Jump(&begin);
2018    LoopBegin(&begin);
2019    {
2020        BRANCH_LIKELY(Int32UnsignedLessThan(*index, thisArrLen), &body, &loopExit);
2021        Bind(&body);
2022        {
2023            GateRef toIndex = Int32Sub(endIndex, *index);
2024            // The old array and new array are both TaggedArray, so load and store the element directly.
2025            // And barrier is needed.
2026            GateRef value = getWithKind ? GetTaggedValueWithElementsKind(fromArray, *index)
2027                                        : GetValueFromTaggedArray(fromElements, *index);
2028            if (holeToUndefined) {
2029                Label isHole(env);
2030                Label isNotHole(env);
2031                BRANCH_UNLIKELY(TaggedIsHole(value), &isHole, &isNotHole);
2032                Bind(&isHole);
2033                {
2034                    // The return value of toReversed() is never sparse.
2035                    // Empty slots become undefined in the returned array.
2036                    SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, Undefined(),
2037                                          MemoryAttribute::NoBarrier());
2038                    Jump(&endLoop);
2039                }
2040                Bind(&isNotHole);
2041            }
2042            SetValueToTaggedArray(VariableType::JS_ANY(), glue, toElements, toIndex, value, mAttr);
2043            Jump(&endLoop);
2044        }
2045    }
2046    Bind(&endLoop);
2047    index = Int32Add(*index, Int32(1));
2048    LoopEnd(&begin);
2049    Bind(&loopExit);
2050    env->SubCfgExit();
2051}
2052
2053GateRef BuiltinsArrayStubBuilder::IsJsArrayWithLengthLimit(GateRef glue, GateRef object,
2054    uint32_t maxLength, JsArrayRequirements requirements)
2055{
2056    auto env = GetEnvironment();
2057    Label entry(env);
2058    env->SubCfgEntry(&entry);
2059    Label isHeapObject(env);
2060    Label isJsArray(env);
2061    Label stabilityCheckPassed(env);
2062    Label defaultConstructorCheckPassed(env);
2063    Label exit(env);
2064    DEFVARIABLE(result, VariableType::BOOL(), False());
2065
2066    BRANCH(TaggedIsHeapObject(object), &isHeapObject, &exit);
2067    Bind(&isHeapObject);
2068    BRANCH(IsJsArray(object), &isJsArray, &exit);
2069    Bind(&isJsArray);
2070    if (requirements.stable) {
2071        BRANCH(IsStableJSArray(glue, object), &stabilityCheckPassed, &exit);
2072    } else {
2073        Jump(&stabilityCheckPassed);
2074    }
2075    Bind(&stabilityCheckPassed);
2076    if (requirements.defaultConstructor) {
2077        // If HasConstructor bit is set to 1, then the constructor has been modified.
2078        BRANCH(HasConstructor(object), &exit, &defaultConstructorCheckPassed);
2079    } else {
2080        Jump(&defaultConstructorCheckPassed);
2081    }
2082    Bind(&defaultConstructorCheckPassed);
2083    result.WriteVariable(Int32UnsignedLessThanOrEqual(GetArrayLength(object), Int32(maxLength)));
2084    Jump(&exit);
2085    Bind(&exit);
2086    GateRef ret = *result;
2087    env->SubCfgExit();
2088    return ret;
2089}
2090
2091void BuiltinsArrayStubBuilder::Values(GateRef glue, GateRef thisValue,
2092    [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
2093{
2094    auto env = GetEnvironment();
2095    Label isHeapObject(env);
2096    Label isJsArray(env);
2097    Label defaultConstr(env);
2098    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2099    Bind(&isHeapObject);
2100    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2101    Bind(&isJsArray);
2102    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2103    Bind(&defaultConstr);
2104    ConstantIndex iterClassIdx = ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX;
2105    GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, iterClassIdx);
2106    NewObjectStubBuilder newBuilder(this);
2107    newBuilder.SetParameters(glue, 0);
2108    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2109    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2110    GateRef prototype = GetGlobalEnvValue(VariableType::JS_POINTER(), glueGlobalEnv,
2111                                          GlobalEnv::ARRAY_ITERATOR_PROTOTYPE_INDEX);
2112    SetPrototypeToHClass(VariableType::JS_POINTER(), glue, iteratorHClass, prototype);
2113    GateRef iter = newBuilder.NewJSObject(glue, iteratorHClass);
2114    SetIteratedArrayOfArrayIterator(glue, iter, thisValue);
2115    SetNextIndexOfArrayIterator(glue, iter, Int32(0));
2116    GateRef kind = Int32(static_cast<int32_t>(IterationKind::VALUE));
2117    SetBitFieldOfArrayIterator(glue, iter, kind);
2118    result->WriteVariable(iter);
2119    Jump(exit);
2120}
2121
2122void BuiltinsArrayStubBuilder::Find(GateRef glue, GateRef thisValue, GateRef numArgs,
2123    Variable *result, Label *exit, Label *slowPath)
2124{
2125    auto env = GetEnvironment();
2126    Label isHeapObject(env);
2127    Label isJsArray(env);
2128    Label isStability(env);
2129    Label defaultConstr(env);
2130    Label notCOWArray(env);
2131    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2132    Bind(&isHeapObject);
2133    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2134    Bind(&isJsArray);
2135    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2136    Bind(&defaultConstr);
2137    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
2138    Bind(&isStability);
2139    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
2140    Bind(&notCOWArray);
2141
2142    GateRef callbackFnHandle = GetCallArg0(numArgs);
2143    Label arg0HeapObject(env);
2144    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
2145    Bind(&arg0HeapObject);
2146    Label callable(env);
2147    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
2148    Bind(&callable);
2149    GateRef argHandle = GetCallArg1(numArgs);
2150    DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
2151    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
2152    Label loopHead(env);
2153    Label loopEnd(env);
2154    Label next(env);
2155    Label loopExit(env);
2156    Jump(&loopHead);
2157    LoopBegin(&loopHead);
2158    {
2159        Label hasException0(env);
2160        Label notHasException0(env);
2161        BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
2162        Bind(&next);
2163        GateRef kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
2164        BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
2165        Bind(&hasException0);
2166        {
2167            result->WriteVariable(Exception());
2168            Jump(exit);
2169        }
2170        Bind(&notHasException0);
2171        {
2172            GateRef key = Int64ToTaggedInt(*i);
2173            Label hasException(env);
2174            Label notHasException(env);
2175            JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2176            callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue };
2177            CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
2178                Circuit::NullGate(), callArgs);
2179            GateRef retValue = callBuilder.JSCallDispatch();
2180            BRANCH(HasPendingException(glue), &hasException, &notHasException);
2181            Bind(&hasException);
2182            {
2183                result->WriteVariable(retValue);
2184                Jump(exit);
2185            }
2186            Bind(&notHasException);
2187            {
2188                Label find(env);
2189                BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
2190                Bind(&find);
2191                {
2192                    result->WriteVariable(kValue);
2193                    Jump(exit);
2194                }
2195            }
2196        }
2197    }
2198    Bind(&loopEnd);
2199    thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2200    i = Int64Add(*i, Int64(1));
2201    LoopEnd(&loopHead, env, glue);
2202    Bind(&loopExit);
2203    Jump(exit);
2204}
2205
2206void BuiltinsArrayStubBuilder::FindIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
2207    Variable *result, Label *exit, Label *slowPath)
2208{
2209    auto env = GetEnvironment();
2210    Label isHeapObject(env);
2211    Label isJsArray(env);
2212    Label defaultConstr(env);
2213    Label notCOWArray(env);
2214    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2215    Bind(&isHeapObject);
2216    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2217    Bind(&isJsArray);
2218    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2219    Bind(&defaultConstr);
2220    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
2221    Bind(&notCOWArray);
2222
2223    Label arg0HeapObject(env);
2224    Label callable(env);
2225    Label stableJSArray(env);
2226    Label notStableJSArray(env);
2227    GateRef callbackFnHandle = GetCallArg0(numArgs);
2228    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
2229    Bind(&arg0HeapObject);
2230    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
2231    Bind(&callable);
2232    result->WriteVariable(IntToTaggedPtr(Int32(-1)));
2233    GateRef argHandle = GetCallArg1(numArgs);
2234    DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
2235    BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, &notStableJSArray);
2236    Bind(&stableJSArray);
2237    {
2238        DEFVARIABLE(i, VariableType::INT64(), Int64(0));
2239        DEFVARIABLE(kValue, VariableType::JS_ANY(), Undefined());
2240        Label loopHead(env);
2241        Label loopEnd(env);
2242        Label next(env);
2243        Label loopExit(env);
2244        Jump(&loopHead);
2245        LoopBegin(&loopHead);
2246        {
2247            BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
2248            Bind(&next);
2249            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
2250            Label isHole(env);
2251            Label notHole(env);
2252            BRANCH(TaggedIsHole(*kValue), &isHole, &notHole);
2253            Bind(&isHole);
2254            {
2255                Label hasException0(env);
2256                Label notHasException0(env);
2257                GateRef res = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
2258                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
2259                Bind(&hasException0);
2260                {
2261                    result->WriteVariable(Exception());
2262                    Jump(exit);
2263                }
2264                Bind(&notHasException0);
2265                {
2266                    Label resIsHole(env);
2267                    Label resNotHole(env);
2268                    BRANCH(TaggedIsHole(res), &resIsHole, &resNotHole);
2269                    Bind(&resIsHole);
2270                    {
2271                        kValue = Undefined();
2272                        Jump(&notHole);
2273                    }
2274                    Bind(&resNotHole);{
2275                        kValue = res;
2276                        Jump(&notHole);
2277                    }
2278                }
2279            }
2280            Bind(&notHole);
2281            {
2282                GateRef key = IntToTaggedPtr(*i);
2283                Label hasException(env);
2284                Label notHasException(env);
2285                Label checkStable(env);
2286                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2287                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
2288                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
2289                    Circuit::NullGate(), callArgs);
2290                GateRef retValue = callBuilder.JSCallDispatch();
2291                BRANCH(HasPendingException(glue), &hasException, &notHasException);
2292                Bind(&hasException);
2293                {
2294                    result->WriteVariable(retValue);
2295                    Jump(exit);
2296                }
2297                Bind(&notHasException);
2298                {
2299                    Label find(env);
2300                    BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &checkStable);
2301                    Bind(&find);
2302                    {
2303                        result->WriteVariable(key);
2304                        Jump(exit);
2305                    }
2306                }
2307                Bind(&checkStable);
2308                i = Int64Add(*i, Int64(1));
2309                BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, &notStableJSArray);
2310            }
2311        }
2312        Bind(&loopEnd);
2313        thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2314        LoopEnd(&loopHead, env, glue);
2315        Bind(&loopExit);
2316        Jump(exit);
2317    }
2318    Bind(&notStableJSArray);
2319    {
2320        DEFVARIABLE(j, VariableType::INT64(), Int64(0));
2321        Label loopHead(env);
2322        Label loopEnd(env);
2323        Label next(env);
2324        Label loopExit(env);
2325        Jump(&loopHead);
2326        LoopBegin(&loopHead);
2327        {
2328            thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2329            BRANCH(Int64LessThan(*j, *thisArrLen), &next, &loopExit);
2330            Bind(&next);
2331            {
2332                Label hasException0(env);
2333                Label notHasException0(env);
2334                GateRef kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*j), ProfileOperation());
2335                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
2336                Bind(&hasException0);
2337                {
2338                    result->WriteVariable(Exception());
2339                    Jump(exit);
2340                }
2341                Bind(&notHasException0);
2342                {
2343                    GateRef key = IntToTaggedPtr(*j);
2344                    Label hasException(env);
2345                    Label notHasException(env);
2346                    JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2347                    callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue };
2348                    CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
2349                        nullptr, Circuit::NullGate(), callArgs);
2350                    GateRef retValue = callBuilder.JSCallDispatch();
2351                    BRANCH(TaggedIsException(retValue), &hasException, &notHasException);
2352                    Bind(&hasException);
2353                    {
2354                        result->WriteVariable(retValue);
2355                        Jump(exit);
2356                    }
2357                    Bind(&notHasException);
2358                    {
2359                        Label find(env);
2360                        BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
2361                        Bind(&find);
2362                        {
2363                            result->WriteVariable(key);
2364                            Jump(exit);
2365                        }
2366                    }
2367                }
2368            }
2369        }
2370        Bind(&loopEnd);
2371        thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2372        j = Int64Add(*j, Int64(1));
2373        LoopEnd(&loopHead, env, glue);
2374        Bind(&loopExit);
2375        Jump(exit);
2376    }
2377}
2378
2379void BuiltinsArrayStubBuilder::Push(GateRef glue, GateRef thisValue,
2380    GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
2381{
2382    auto env = GetEnvironment();
2383    Label isHeapObject(env);
2384    Label isJsArray(env);
2385    Label isStability(env);
2386    Label setLength(env);
2387    Label smallArgs(env);
2388    Label checkSmallArgs(env);
2389
2390    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2391    Bind(&isHeapObject);
2392    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2393    Bind(&isJsArray);
2394    Label isLengthWritable(env);
2395    BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath);
2396    Bind(&isLengthWritable);
2397
2398    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
2399    Bind(&isStability);
2400
2401    GateRef oldLength = GetArrayLength(thisValue);
2402    *result = IntToTaggedPtr(oldLength);
2403
2404    BRANCH(Int32Equal(ChangeIntPtrToInt32(numArgs), Int32(0)), exit, &checkSmallArgs);
2405    Bind(&checkSmallArgs);
2406    // now unsupport more than 2 args
2407    BRANCH(Int32LessThanOrEqual(ChangeIntPtrToInt32(numArgs), Int32(2)), &smallArgs, slowPath);
2408    Bind(&smallArgs);
2409    GateRef newLength = Int32Add(oldLength, ChangeIntPtrToInt32(numArgs));
2410
2411    DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue));
2412    GateRef capacity = GetLengthOfTaggedArray(*elements);
2413    Label grow(env);
2414    Label setValue(env);
2415    BRANCH(Int32GreaterThan(newLength, capacity), &grow, &setValue);
2416    Bind(&grow);
2417    {
2418        elements = GrowElementsCapacity(glue, thisValue, newLength);
2419        Jump(&setValue);
2420    }
2421    Bind(&setValue);
2422    {
2423        Label oneArg(env);
2424        Label twoArg(env);
2425        DEFVARIABLE(index, VariableType::INT32(), Int32(0));
2426        DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
2427        BRANCH(Int64Equal(numArgs, IntPtr(1)), &oneArg, &twoArg);  // 1 one arg
2428        Bind(&oneArg);
2429        {
2430            value = GetCallArg0(numArgs);
2431            index = Int32Add(oldLength, Int32(0));  // 0 slot index
2432            SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true),
2433                                     Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2434            Jump(&setLength);
2435        }
2436        Bind(&twoArg);
2437        {
2438            value = GetCallArg0(numArgs);
2439            index = Int32Add(oldLength, Int32(0));  // 0 slot index
2440            SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true),
2441                                     Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2442            value = GetCallArg1(numArgs);
2443            index = Int32Add(oldLength, Int32(1));  // 1 slot index
2444            SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true),
2445                                     Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2446            Jump(&setLength);
2447        }
2448    }
2449    Bind(&setLength);
2450    SetArrayLength(glue, thisValue, newLength);
2451    result->WriteVariable(IntToTaggedPtr(newLength));
2452    Jump(exit);
2453}
2454
2455GateRef BuiltinsArrayStubBuilder::IsConcatSpreadable(GateRef glue, GateRef obj)
2456{
2457    auto env = GetEnvironment();
2458    Label entry(env);
2459    env->SubCfgEntry(&entry);
2460    DEFVARIABLE(result, VariableType::BOOL(), False());
2461    Label exit(env);
2462    Label isEcmaObj(env);
2463    BRANCH(IsEcmaObject(obj), &isEcmaObj, &exit);
2464    Bind(&isEcmaObj);
2465    {
2466        GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2467        GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2468        GateRef isConcatsprKey =
2469            GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ISCONCAT_SYMBOL_INDEX);
2470        AccessObjectStubBuilder builder(this);
2471        GateRef spreadable =
2472            builder.LoadObjByValue(glue, obj, isConcatsprKey, Undefined(), Int32(0), ProfileOperation());
2473        Label isDefined(env);
2474        Label isUnDefined(env);
2475        BRANCH(TaggedIsUndefined(spreadable), &isUnDefined, &isDefined);
2476        Bind(&isUnDefined);
2477        {
2478            Label IsArray(env);
2479            BRANCH(IsJsArray(obj), &IsArray, &exit);
2480            Bind(&IsArray);
2481            result = True();
2482            Jump(&exit);
2483        }
2484        Bind(&isDefined);
2485        {
2486            result = TaggedIsTrue(spreadable);
2487            Jump(&exit);
2488        }
2489    }
2490    Bind(&exit);
2491    auto res = *result;
2492    env->SubCfgExit();
2493    return res;
2494}
2495
2496void BuiltinsArrayStubBuilder::InitializeArray(GateRef glue, GateRef count, Variable* result, GateRef intialHClass)
2497{
2498    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
2499    Store(VariableType::INT32(), glue, result->ReadVariable(), lengthOffset, TruncInt64ToInt32(count));
2500    GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2501    SetPropertyInlinedProps(glue, result->ReadVariable(), intialHClass, accessor,
2502                            Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
2503    SetExtensibleToBitfield(glue, result->ReadVariable(), true);
2504}
2505
2506GateRef BuiltinsArrayStubBuilder::NewArray(GateRef glue, GateRef count)
2507{
2508    auto env = GetEnvironment();
2509    Label entry(env);
2510    env->SubCfgEntry(&entry);
2511    DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined());
2512    Label exit(env);
2513    Label setProperties(env);
2514    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2515    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2516    auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2517    GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2518    NewObjectStubBuilder newBuilder(this);
2519    newBuilder.SetParameters(glue, 0);
2520    result = newBuilder.NewJSArrayWithSize(intialHClass, count);
2521    BRANCH(TaggedIsException(*result), &exit, &setProperties);
2522    Bind(&setProperties);
2523    {
2524        InitializeArray(glue, count, &result, intialHClass);
2525        Jump(&exit);
2526    }
2527    Bind(&exit);
2528    auto res = *result;
2529    env->SubCfgExit();
2530    return res;
2531}
2532
2533GateRef BuiltinsArrayStubBuilder::NewArrayWithHClass(GateRef glue, GateRef hclass)
2534{
2535    // New an array with zero length.
2536    auto env = GetEnvironment();
2537    Label entry(env);
2538    env->SubCfgEntry(&entry);
2539    DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined());
2540    Label exit(env);
2541    Label setProperties(env);
2542    NewObjectStubBuilder newBuilder(this);
2543    newBuilder.SetParameters(glue, Int32(0));
2544    result = newBuilder.NewJSArrayWithSize(hclass, Int32(0));
2545    BRANCH(TaggedIsException(*result), &exit, &setProperties);
2546    Bind(&setProperties);
2547    {
2548        InitializeArray(glue, Int32(0), &result, hclass);
2549        Jump(&exit);
2550    }
2551    Bind(&exit);
2552    auto res = *result;
2553    env->SubCfgExit();
2554    return res;
2555}
2556
2557
2558void BuiltinsArrayStubBuilder::Includes(GateRef glue, GateRef thisValue, GateRef numArgs,
2559    Variable *result, Label *exit, Label *slowPath)
2560{
2561    auto env = GetEnvironment();
2562    Label isDictMode(env);
2563    Label isHeapObject(env);
2564    Label isJsArray(env);
2565    Label isStableJsArray(env);
2566    Label notFound(env);
2567    Label thisLenNotZero(env);
2568    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2569    Bind(&isHeapObject);
2570    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2571    Bind(&isJsArray);
2572    BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath);
2573    Bind(&isStableJsArray);
2574    GateRef thisLen = GetArrayLength(thisValue);
2575    BRANCH(Int32Equal(thisLen, Int32(0)), &notFound, &thisLenNotZero);
2576    Bind(&thisLenNotZero);
2577    {
2578        DEFVARIABLE(fromIndex, VariableType::INT32(), Int32(0));
2579        Label getArgTwo(env);
2580        Label nextProcess(env);
2581        BRANCH(Int64Equal(numArgs, IntPtr(2)), &getArgTwo, &nextProcess); // 2: 2 parameters
2582        Bind(&getArgTwo);
2583        {
2584            Label secondArgIsInt(env);
2585            GateRef fromIndexTemp = GetCallArg1(numArgs);
2586            BRANCH(TaggedIsInt(fromIndexTemp), &secondArgIsInt, slowPath);
2587            Bind(&secondArgIsInt);
2588            fromIndex = GetInt32OfTInt(fromIndexTemp);
2589            Jump(&nextProcess);
2590        }
2591        Bind(&nextProcess);
2592        {
2593            Label atLeastOneArg(env);
2594            Label setBackZero(env);
2595            Label calculateFrom(env);
2596            Label nextCheck(env);
2597            BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
2598            Bind(&atLeastOneArg);
2599            BRANCH(Int32GreaterThanOrEqual(*fromIndex, thisLen), &notFound, &nextCheck);
2600            Bind(&nextCheck);
2601            {
2602                GateRef negThisLen = Int32Sub(Int32(0), thisLen);
2603                BRANCH(Int32LessThan(*fromIndex, negThisLen), &setBackZero, &calculateFrom);
2604                Bind(&setBackZero);
2605                {
2606                    fromIndex = Int32(0);
2607                    Jump(&calculateFrom);
2608                }
2609                Bind(&calculateFrom);
2610                {
2611                    DEFVARIABLE(from, VariableType::INT32(), Int32(0));
2612                    Label fromIndexGreaterOrEqualZero(env);
2613                    Label fromIndexLessThanZero(env);
2614                    Label startLoop(env);
2615                    BRANCH(Int32GreaterThanOrEqual(*fromIndex, Int32(0)),
2616                        &fromIndexGreaterOrEqualZero, &fromIndexLessThanZero);
2617                    Bind(&fromIndexGreaterOrEqualZero);
2618                    {
2619                        from = *fromIndex;
2620                        Jump(&startLoop);
2621                    }
2622                    Bind(&fromIndexLessThanZero);
2623                    {
2624                        Label isLenFromIndex(env);
2625                        GateRef lenFromIndexSum = Int32Add(thisLen, *fromIndex);
2626                        BRANCH(Int32GreaterThanOrEqual(lenFromIndexSum, Int32(0)), &isLenFromIndex, &startLoop);
2627                        Bind(&isLenFromIndex);
2628                        {
2629                            from = lenFromIndexSum;
2630                            Jump(&startLoop);
2631                        }
2632                    }
2633                    Bind(&startLoop);
2634                    {
2635                        GateRef searchElement = GetCallArg0(numArgs);
2636                        Label loopHead(env);
2637                        Label loopEnd(env);
2638                        Label next(env);
2639                        Label loopExit(env);
2640                        Jump(&loopHead);
2641                        LoopBegin(&loopHead);
2642                        {
2643                            BRANCH(Int32LessThan(*from, thisLen), &next, &loopExit);
2644                            Bind(&next);
2645                            {
2646                                Label notHoleOrUndefValue(env);
2647                                Label valueFound(env);
2648                                GateRef value = GetTaggedValueWithElementsKind(thisValue, *from);
2649                                GateRef isHole = TaggedIsHole(value);
2650                                GateRef isUndef = TaggedIsUndefined(value);
2651                                BRANCH(BitOr(isHole, isUndef), slowPath, &notHoleOrUndefValue);
2652                                Bind(&notHoleOrUndefValue);
2653                                GateRef valueEqual = StubBuilder::SameValueZero(glue, searchElement, value);
2654                                BRANCH(valueEqual, &valueFound, &loopEnd);
2655                                Bind(&valueFound);
2656                                {
2657                                    result->WriteVariable(TaggedTrue());
2658                                    Jump(exit);
2659                                }
2660                            }
2661                        }
2662                        Bind(&loopEnd);
2663                        from = Int32Add(*from, Int32(1));
2664                        LoopEnd(&loopHead, env, glue);
2665                        Bind(&loopExit);
2666                        Jump(&notFound);
2667                    }
2668                }
2669            }
2670        }
2671    }
2672    Bind(&notFound);
2673    {
2674        result->WriteVariable(TaggedFalse());
2675        Jump(exit);
2676    }
2677}
2678
2679void BuiltinsArrayStubBuilder::From(GateRef glue, [[maybe_unused]] GateRef thisValue, GateRef numArgs,
2680    Variable *result, Label *exit, Label *slowPath)
2681{
2682    auto env = GetEnvironment();
2683    GateRef item = GetCallArg0(numArgs);
2684    Label stringItem(env);
2685    BRANCH(TaggedIsString(item), &stringItem, slowPath);
2686    Bind(&stringItem);
2687    Label undefFn(env);
2688    GateRef fn = GetCallArg1(numArgs);
2689    BRANCH(TaggedIsUndefined(fn), &undefFn, slowPath);
2690    Bind(&undefFn);
2691    GateRef strLen = GetLengthFromString(item);
2692    Label lessStrLen(env);
2693    BRANCH(Int32LessThan(strLen, Int32(builtins::StringToListResultCache::MAX_STRING_LENGTH)), &lessStrLen, slowPath);
2694    Bind(&lessStrLen);
2695    GateRef cacheArray = CallNGCRuntime(glue, RTSTUB_ID(GetStringToListCacheArray), { glue });
2696
2697    Label cacheDef(env);
2698    BRANCH(TaggedIsUndefined(cacheArray), slowPath, &cacheDef);
2699    Bind(&cacheDef);
2700    {
2701        GateRef hash = GetHashcodeFromString(glue, item);
2702        GateRef entry = Int32And(hash, Int32Sub(Int32(builtins::StringToListResultCache::CACHE_SIZE), Int32(1)));
2703        GateRef index = Int32Mul(entry, Int32(builtins::StringToListResultCache::ENTRY_SIZE));
2704        GateRef cacheStr = GetValueFromTaggedArray(cacheArray,
2705            Int32Add(index, Int32(builtins::StringToListResultCache::STRING_INDEX)));
2706        Label cacheStrDef(env);
2707        BRANCH(TaggedIsUndefined(cacheStr), slowPath, &cacheStrDef);
2708        Bind(&cacheStrDef);
2709        Label strEqual(env);
2710        Label strSlowEqual(env);
2711        // cache str is intern
2712        BRANCH(Equal(cacheStr, item), &strEqual, &strSlowEqual);
2713        Bind(&strSlowEqual);
2714        BRANCH(FastStringEqual(glue, cacheStr, item), &strEqual, slowPath);
2715        Bind(&strEqual);
2716
2717        GateRef cacheResArray = GetValueFromTaggedArray(cacheArray,
2718            Int32Add(index, Int32(builtins::StringToListResultCache::ARRAY_INDEX)));
2719        GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2720        GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2721        auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2722        GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2723        NewObjectStubBuilder newBuilder(this);
2724        newBuilder.SetParameters(glue, 0);
2725        GateRef newArray = newBuilder.NewJSObject(glue, intialHClass);
2726        Store(VariableType::INT32(), glue, newArray, IntPtr(JSArray::LENGTH_OFFSET), strLen);
2727        GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2728        SetPropertyInlinedProps(glue, newArray, intialHClass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
2729        SetExtensibleToBitfield(glue, newArray, true);
2730
2731        SetElementsArray(VariableType::JS_ANY(), glue, newArray, cacheResArray);
2732        *result = newArray;
2733        Jump(exit);
2734    }
2735}
2736
2737GateRef BuiltinsArrayStubBuilder::CreateSpliceDeletedArray(GateRef glue, GateRef thisValue, GateRef actualDeleteCount,
2738    GateRef arrayCls, GateRef start)
2739{
2740    auto env = GetEnvironment();
2741    Label subentry(env);
2742    Label exit(env);
2743    env->SubCfgEntry(&subentry);
2744    DEFVARIABLE(result, VariableType::BOOL(), False());
2745
2746    // new delete array
2747    DEFVARIABLE(srcElements, VariableType::JS_ANY(), GetElementsArray(thisValue));
2748    NewObjectStubBuilder newBuilder(this);
2749    newBuilder.SetParameters(glue, 0);
2750    GateRef newArray = newBuilder.NewJSArrayWithSize(arrayCls, actualDeleteCount);
2751    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
2752    Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(actualDeleteCount));
2753    GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2754    SetPropertyInlinedProps(glue, newArray, arrayCls, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
2755    SetExtensibleToBitfield(glue, newArray, true);
2756    result = newArray;
2757
2758    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2759    Label loopHead(env);
2760    Label loopEnd(env);
2761    Label next(env);
2762    Label loopExit(env);
2763    Jump(&loopHead);
2764    LoopBegin(&loopHead);
2765    {
2766        BRANCH(Int32LessThan(*i, actualDeleteCount), &next, &loopExit);
2767        Bind(&next);
2768        Label setHole(env);
2769        Label setSrc(env);
2770        BRANCH(Int32GreaterThanOrEqual(Int32Add(*i, start),
2771            GetLengthOfTaggedArray(*srcElements)), &setHole, &setSrc);
2772        Bind(&setHole);
2773        {
2774            SetValueWithElementsKind(glue, newArray, Hole(), *i, Boolean(true),
2775                                     Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2776            Jump(&loopEnd);
2777        }
2778        Bind(&setSrc);
2779        {
2780            GateRef val = GetTaggedValueWithElementsKind(thisValue, Int32Add(start, *i));
2781            SetValueWithElementsKind(glue, newArray, val, *i, Boolean(true),
2782                                     Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2783            Jump(&loopEnd);
2784        }
2785    }
2786    Bind(&loopEnd);
2787    i = Int32Add(*i, Int32(1));
2788    LoopEnd(&loopHead, env, glue);
2789    Bind(&loopExit);
2790    Jump(&exit);
2791
2792    Bind(&exit);
2793    auto res = *result;
2794    env->SubCfgExit();
2795    return res;
2796}
2797
2798void BuiltinsArrayStubBuilder::Fill(GateRef glue, GateRef thisValue, GateRef numArgs,
2799    Variable *result, Label *exit, Label *slowPath)
2800{
2801    auto env = GetEnvironment();
2802    Label isHeapObject(env);
2803    Label isJsArray(env);
2804    Label isStability(env);
2805    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2806    Bind(&isHeapObject);
2807    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2808    Bind(&isJsArray);
2809    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
2810    Bind(&isStability);
2811    Label notCOWArray(env);
2812    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
2813    Bind(&notCOWArray);
2814    GateRef arrayCls = LoadHClass(thisValue);
2815    // 1. Let O be ToObject(this value).
2816    // 2 ReturnIfAbrupt(O).
2817    Label hasException(env);
2818    Label proNotCOWArray(env);
2819    GateRef prop = GetPropertiesFromJSObject(thisValue);
2820    BRANCH(IsCOWArray(prop), slowPath, &proNotCOWArray);
2821    Bind(&proNotCOWArray);
2822    // 3. Let len be ToLength(Get(O,"length")).
2823    GateRef value = GetCallArg0(numArgs);
2824    GateRef thisArrLen = GetLengthOfJSArray(thisValue);
2825    Label isDict(env);
2826    Label notDict(env);
2827    BRANCH(IsDictionaryElement(arrayCls), &isDict, &notDict);
2828    Bind(&isDict);
2829    {
2830        GateRef size = GetNumberOfElements(thisValue);
2831        BRANCH(Int32GreaterThan(Int32Sub(thisArrLen, size),
2832            TruncInt64ToInt32(IntPtr(JSObject::MAX_GAP))), slowPath, &notDict);
2833    }
2834    Bind(&notDict);
2835    // 5. let relativeStart be ToInteger(start).
2836    GateRef startArg = GetCallArg1(numArgs);
2837    // 6 ReturnIfAbrupt(relativeStart).
2838    GateRef argStart = NumberGetInt(glue, ToNumber(glue, startArg));
2839    Label notHasException3(env);
2840    BRANCH(HasPendingException(glue), &hasException, &notHasException3);
2841    Bind(&notHasException3);
2842    // 7. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
2843    DEFVARIABLE(start, VariableType::INT32(), Int32(0));
2844    Label maxStart(env);
2845    Label minStart(env);
2846    Label startExit(env);
2847    BRANCH(Int32LessThan(argStart, Int32(0)), &maxStart, &minStart);
2848    Bind(&maxStart);
2849    {
2850        GateRef tempStart = Int32Add(argStart, thisArrLen);
2851        Label bind1(env);
2852        BRANCH(Int32GreaterThan(tempStart, Int32(0)), &bind1, &startExit);
2853        Bind(&bind1);
2854        {
2855            start = tempStart;
2856            Jump(&startExit);
2857        }
2858    }
2859    Bind(&minStart);
2860    {
2861        Label bind1(env);
2862        Label bind2(env);
2863        BRANCH(Int32LessThan(argStart, thisArrLen), &bind1, &bind2);
2864        Bind(&bind1);
2865        {
2866            start = argStart;
2867            Jump(&startExit);
2868        }
2869        Bind(&bind2);
2870        {
2871            start = thisArrLen;
2872            Jump(&startExit);
2873        }
2874    }
2875    Bind(&startExit);
2876    // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
2877    GateRef endArg = GetCallArg2(numArgs);
2878    DEFVARIABLE(argEnd, VariableType::INT32(), Int32(0));
2879    Label endArgIsUndefined(env);
2880    Label endArgNotUndefined(env);
2881    Label next1(env);
2882    BRANCH(TaggedIsUndefined(endArg), &endArgIsUndefined, &endArgNotUndefined);
2883    Bind(&endArgIsUndefined);
2884    {
2885        argEnd = thisArrLen;
2886        Jump(&next1);
2887    }
2888    Bind(&endArgNotUndefined);
2889    {
2890        argEnd = NumberGetInt(glue, ToNumber(glue, endArg));
2891        // 9. ReturnIfAbrupt(relativeEnd).
2892        BRANCH(HasPendingException(glue), &hasException, &next1);
2893    }
2894    Bind(&next1);
2895
2896    // 10. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
2897    DEFVARIABLE(end, VariableType::INT32(), Int32(0));
2898    Label maxEnd(env);
2899    Label minEnd(env);
2900    Label endExit(env);
2901    BRANCH(Int32LessThan(*argEnd, Int32(0)), &maxEnd, &minEnd);
2902    Bind(&maxEnd);
2903    {
2904        GateRef tempEnd = Int32Add(*argEnd, thisArrLen);
2905        Label bind1(env);
2906        Label bind2(env);
2907        BRANCH(Int32GreaterThan(tempEnd, Int32(0)), &bind1, &endExit);
2908        Bind(&bind1);
2909        {
2910            end = tempEnd;
2911            Jump(&endExit);
2912        }
2913    }
2914    Bind(&minEnd);
2915    {
2916        Label bind1(env);
2917        Label bind2(env);
2918        BRANCH(Int32LessThan(*argEnd, thisArrLen), &bind1, &bind2);
2919        Bind(&bind1);
2920        {
2921            end = *argEnd;
2922            Jump(&endExit);
2923        }
2924        Bind(&bind2);
2925        {
2926            end = thisArrLen;
2927            Jump(&endExit);
2928        }
2929    }
2930    Bind(&endExit);
2931    // 11. Repeat, while k < final
2932    //   a. Let Pk be ToString(k).
2933    //   b. Let setStatus be Set(O, Pk, value, true).
2934    //   c. ReturnIfAbrupt(setStatus).
2935    //   d. Increase k by 1.
2936    Label argNotJsObj(env);
2937    GateRef check = LogicOrBuilder(env)
2938        .Or(TaggedIsObject(startArg))
2939        .Or(TaggedIsObject(endArg)).Done();
2940    BRANCH(check, slowPath, &argNotJsObj);
2941    Bind(&argNotJsObj);
2942    {
2943        Label newElements(env);
2944        Label defaultElements(env);
2945        Label startFill(env);
2946        GateRef elementKind = GetElementsKindFromHClass(arrayCls);
2947        TransitToElementsKind(glue, thisValue, value, elementKind);
2948        DEFVARIABLE(migratedValue, VariableType::JS_ANY(), value);
2949        DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue));
2950        GateRef mutant = IsMutantTaggedArray(*elements);
2951        GateRef elementLen = GetLengthOfTaggedArray(*elements);
2952        BRANCH(Int32GreaterThanOrEqual(elementLen, *end), &defaultElements, &newElements);
2953        Bind(&defaultElements);
2954        {
2955            Label isMutant(env);
2956            BRANCH(mutant, &isMutant, &startFill);
2957            Bind(&isMutant);
2958            {
2959                migratedValue = ConvertTaggedValueWithElementsKind(glue, value, elementKind);
2960                Jump(&startFill);
2961            }
2962        }
2963        Bind(&newElements);
2964        {
2965            Label isMutant(env);
2966            Label notMutant(env);
2967            NewObjectStubBuilder newBuilder(this);
2968            BRANCH(mutant, &isMutant, &notMutant);
2969            Bind(&isMutant);
2970            {
2971                elements = newBuilder.NewMutantTaggedArray(glue, elementLen);
2972                migratedValue = ConvertTaggedValueWithElementsKind(glue, value, elementKind);
2973                Jump(&startFill);
2974            }
2975            Bind(&notMutant);
2976            {
2977                elements = newBuilder.NewTaggedArray(glue, elementLen);
2978                Jump(&startFill);
2979            }
2980        }
2981        Bind(&startFill);
2982        Label noBarrier(env);
2983        Label needBarrier(env);
2984        Label barrierExit(env);
2985        BRANCH(mutant, &noBarrier, &needBarrier);
2986        Bind(&noBarrier);
2987        {
2988            DEFVARIABLE(idx, VariableType::INT32(), *start);
2989            Label loopHead(env);
2990            Label loopEnd(env);
2991            Label next(env);
2992            Label loopExit(env);
2993            Jump(&loopHead);
2994            LoopBegin(&loopHead);
2995            {
2996                BRANCH(Int32LessThan(*idx, *end), &next, &loopExit);
2997                Bind(&next);
2998                SetValueToTaggedArray(VariableType::JS_ANY(), glue,
2999                    *elements, *idx, *migratedValue, MemoryAttribute::NoBarrier());
3000                Jump(&loopEnd);
3001            }
3002            Bind(&loopEnd);
3003            idx = Int32Add(*idx, Int32(1));
3004            LoopEnd(&loopHead);
3005            Bind(&loopExit);
3006            Jump(&barrierExit);
3007        }
3008        Bind(&needBarrier);
3009        {
3010            DEFVARIABLE(idx, VariableType::INT32(), *start);
3011            Label loopHead(env);
3012            Label loopEnd(env);
3013            Label next(env);
3014            Label loopExit(env);
3015            Jump(&loopHead);
3016            LoopBegin(&loopHead);
3017            {
3018                BRANCH(Int32LessThan(*idx, *end), &next, &loopExit);
3019                Bind(&next);
3020                SetValueToTaggedArray(VariableType::JS_ANY(), glue, *elements, *idx, *migratedValue);
3021                Jump(&loopEnd);
3022            }
3023            Bind(&loopEnd);
3024            idx = Int32Add(*idx, Int32(1));
3025            LoopEnd(&loopHead);
3026            Bind(&loopExit);
3027            Jump(&barrierExit);
3028        }
3029        Bind(&barrierExit);
3030        SetElementsArray(VariableType::JS_POINTER(), glue, thisValue, *elements);
3031        result->WriteVariable(thisValue);
3032        Jump(exit);
3033    }
3034    Bind(&hasException);
3035    {
3036        result->WriteVariable(Exception());
3037        Jump(exit);
3038    }
3039}
3040
3041void BuiltinsArrayStubBuilder::Splice(GateRef glue, GateRef thisValue, GateRef numArgs,
3042    Variable *result, Label *exit, Label *slowPath)
3043{
3044    auto env = GetEnvironment();
3045    Label isHeapObject(env);
3046    Label isJsArray(env);
3047    Label isStability(env);
3048    Label defaultConstr(env);
3049    Label matchCls(env);
3050    Label isGeneric(env);
3051    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3052    Bind(&isHeapObject);
3053    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3054    Bind(&isJsArray);
3055    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3056    Bind(&defaultConstr);
3057    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3058    Bind(&isStability);
3059    Label notCOWArray(env);
3060    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
3061    Bind(&notCOWArray);
3062    GateRef arrayCls = LoadHClass(thisValue);
3063    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3064    Bind(&matchCls);
3065    GateRef arrayLen = GetArrayLength(thisValue);
3066    Label lessThreeArg(env);
3067
3068    DEFVARIABLE(start, VariableType::INT32(), Int32(0));
3069    DEFVARIABLE(insertCount, VariableType::INT32(), Int32(0));
3070    DEFVARIABLE(actualDeleteCount, VariableType::INT32(), Int32(0));
3071    GateRef argc = ChangeIntPtrToInt32(numArgs);
3072    BRANCH(Int32LessThanOrEqual(argc, Int32(3)), &lessThreeArg, slowPath); // 3 : three arg
3073    Bind(&lessThreeArg);
3074    {
3075        Label checkOverflow(env);
3076        Label greaterZero(env);
3077        Label greaterOne(env);
3078        Label checkGreaterOne(env);
3079        Label notOverflow(env);
3080        BRANCH(Int32GreaterThan(argc, Int32(0)), &greaterZero, &checkGreaterOne);
3081        Bind(&greaterZero);
3082        GateRef taggedStart = GetCallArg0(numArgs);
3083        Label taggedStartInt(env);
3084        BRANCH(TaggedIsInt(taggedStart), &taggedStartInt, slowPath);
3085        Bind(&taggedStartInt);
3086        {
3087            GateRef intStart = GetInt32OfTInt(taggedStart);
3088            start = CalArrayRelativePos(intStart, arrayLen);
3089        }
3090        actualDeleteCount = Int32Sub(arrayLen, *start);
3091        Jump(&checkGreaterOne);
3092        Bind(&checkGreaterOne);
3093        BRANCH(Int32GreaterThan(argc, Int32(1)), &greaterOne, &checkOverflow);
3094        Bind(&greaterOne);
3095        insertCount = Int32Sub(argc, Int32(2)); // 2 :  two args
3096        GateRef argDeleteCount = GetCallArg1(numArgs);
3097        Label argDeleteCountInt(env);
3098        BRANCH(TaggedIsInt(argDeleteCount), &argDeleteCountInt, slowPath);
3099        Bind(&argDeleteCountInt);
3100        DEFVARIABLE(deleteCount, VariableType::INT32(), TaggedGetInt(argDeleteCount));
3101        Label deleteCountLessZero(env);
3102        Label calActualDeleteCount(env);
3103        BRANCH(Int32LessThan(*deleteCount, Int32(0)), &deleteCountLessZero, &calActualDeleteCount);
3104        Bind(&deleteCountLessZero);
3105        deleteCount = Int32(0);
3106        Jump(&calActualDeleteCount);
3107        Bind(&calActualDeleteCount);
3108        actualDeleteCount = *deleteCount;
3109        Label lessArrayLen(env);
3110        BRANCH(Int32LessThan(Int32Sub(arrayLen, *start), *deleteCount), &lessArrayLen, &checkOverflow);
3111        Bind(&lessArrayLen);
3112        actualDeleteCount = Int32Sub(arrayLen, *start);
3113        Jump(&checkOverflow);
3114        Bind(&checkOverflow);
3115        BRANCH(Int64GreaterThan(Int64Sub(Int64Add(ZExtInt32ToInt64(arrayLen), ZExtInt32ToInt64(*insertCount)),
3116            ZExtInt32ToInt64(*actualDeleteCount)), Int64(base::MAX_SAFE_INTEGER)), slowPath, &notOverflow);
3117        Bind(&notOverflow);
3118        *result = CreateSpliceDeletedArray(glue, thisValue, *actualDeleteCount, arrayCls, *start);
3119        // insert Val
3120        DEFVARIABLE(srcElements, VariableType::JS_ANY(), GetElementsArray(thisValue));
3121        GateRef oldCapacity = GetLengthOfTaggedArray(*srcElements);
3122        GateRef newCapacity = Int32Add(Int32Sub(arrayLen, *actualDeleteCount), *insertCount);
3123        Label grow(env);
3124        Label copy(env);
3125        BRANCH(Int32GreaterThan(newCapacity, oldCapacity), &grow, &copy);
3126        Bind(&grow);
3127        {
3128            srcElements = GrowElementsCapacity(glue, thisValue, newCapacity);
3129            Jump(&copy);
3130        }
3131        Bind(&copy);
3132        GateRef srcElementsLen = GetLengthOfTaggedArray(*srcElements);
3133        Label insertLessDelete(env);
3134        Label insertGreaterDelete(env);
3135        Label insertCountVal(env);
3136        Label setArrayLen(env);
3137        Label trimCheck(env);
3138        BRANCH(Int32LessThan(*insertCount, *actualDeleteCount), &insertLessDelete, &insertGreaterDelete);
3139        Bind(&insertLessDelete);
3140        {
3141            {
3142                DEFVARIABLE(i, VariableType::INT32(), *start);
3143                DEFVARIABLE(ele, VariableType::JS_ANY(), Hole());
3144
3145                Label loopHead(env);
3146                Label loopEnd(env);
3147                Label next(env);
3148                Label loopExit(env);
3149                Jump(&loopHead);
3150                LoopBegin(&loopHead);
3151                {
3152                    BRANCH(Int32LessThan(*i, Int32Sub(arrayLen, *actualDeleteCount)), &next, &loopExit);
3153                    Bind(&next);
3154                    ele = Hole();
3155                    Label getSrcEle(env);
3156                    Label setEle(env);
3157                    BRANCH(Int32LessThan(Int32Add(*i, *actualDeleteCount), srcElementsLen), &getSrcEle, &setEle);
3158                    Bind(&getSrcEle);
3159                    {
3160                        ele = GetTaggedValueWithElementsKind(thisValue, Int32Add(*i, *actualDeleteCount));
3161                        Jump(&setEle);
3162                    }
3163                    Bind(&setEle);
3164                    {
3165                        Label setIndexLessLen(env);
3166                        BRANCH(Int32LessThan(Int32Add(*i, *insertCount), srcElementsLen), &setIndexLessLen, &loopEnd);
3167                        Bind(&setIndexLessLen);
3168                        {
3169                            SetValueWithElementsKind(glue, thisValue, *ele, Int32Add(*i, *insertCount), Boolean(true),
3170                                                     Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3171                            Jump(&loopEnd);
3172                        }
3173                    }
3174                }
3175                Bind(&loopEnd);
3176                i = Int32Add(*i, Int32(1));
3177                LoopEnd(&loopHead, env, glue);
3178                Bind(&loopExit);
3179                Jump(&trimCheck);
3180            }
3181
3182            Label trim(env);
3183            Label noTrim(env);
3184            Bind(&trimCheck);
3185            GateRef needTrim = LogicAndBuilder(env)
3186                .And(Int32GreaterThan(oldCapacity, newCapacity))
3187                .And(Int32GreaterThan(Int32Sub(newCapacity, oldCapacity), Int32(TaggedArray::MAX_END_UNUSED)))
3188                .Done();
3189            BRANCH(needTrim, &trim, &noTrim);
3190            Bind(&trim);
3191            {
3192                CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, *srcElements, ZExtInt32ToInt64(newCapacity)});
3193                Jump(&insertCountVal);
3194            }
3195            Bind(&noTrim);
3196            {
3197                DEFVARIABLE(idx, VariableType::INT32(), newCapacity);
3198                Label loopHead1(env);
3199                Label loopEnd1(env);
3200                Label next1(env);
3201                Label loopExit1(env);
3202                Jump(&loopHead1);
3203                LoopBegin(&loopHead1);
3204                {
3205                    BRANCH(Int32LessThan(*idx, arrayLen), &next1, &loopExit1);
3206                    Bind(&next1);
3207
3208                    Label setHole(env);
3209                    BRANCH(Int32LessThan(*idx, srcElementsLen), &setHole, &loopEnd1);
3210                    Bind(&setHole);
3211                    {
3212                        SetValueWithElementsKind(glue, thisValue, Hole(), *idx, Boolean(true),
3213                                                 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3214                        Jump(&loopEnd1);
3215                    }
3216                }
3217                Bind(&loopEnd1);
3218                idx = Int32Add(*idx, Int32(1));
3219                LoopEnd(&loopHead1);
3220                Bind(&loopExit1);
3221                Jump(&insertCountVal);
3222            }
3223            Bind(&insertGreaterDelete);
3224            {
3225                DEFVARIABLE(j, VariableType::INT32(), Int32Sub(arrayLen, *actualDeleteCount));
3226                DEFVARIABLE(ele, VariableType::JS_ANY(), Hole());
3227                Label loopHead(env);
3228                Label loopEnd(env);
3229                Label next(env);
3230                Label loopExit(env);
3231                Jump(&loopHead);
3232                LoopBegin(&loopHead);
3233                {
3234                    BRANCH(Int32GreaterThan(*j, *start), &next, &loopExit);
3235                    Bind(&next);
3236                    ele = GetTaggedValueWithElementsKind(thisValue, Int32Sub(Int32Add(*j, *actualDeleteCount),
3237                                                                             Int32(1)));
3238                    SetValueWithElementsKind(glue, thisValue, *ele, Int32Sub(Int32Add(*j, *insertCount), Int32(1)),
3239                                             Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3240                    Jump(&loopEnd);
3241                }
3242                Bind(&loopEnd);
3243                j = Int32Sub(*j, Int32(1));
3244                LoopEnd(&loopHead, env, glue);
3245                Bind(&loopExit);
3246                Jump(&insertCountVal);
3247            }
3248            Bind(&insertCountVal);
3249            {
3250                Label threeArgs(env);
3251                BRANCH(Int32Equal(ChangeIntPtrToInt32(numArgs), Int32(3)), &threeArgs, &setArrayLen); // 3 : three arg
3252                Bind(&threeArgs);
3253                {
3254                    GateRef e = GetCallArg2(numArgs);
3255                    SetValueWithElementsKind(glue, thisValue, e, *start, Boolean(true),
3256                                             Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3257                    Jump(&setArrayLen);
3258                }
3259            }
3260            Bind(&setArrayLen);
3261            SetArrayLength(glue, thisValue, newCapacity);
3262            Jump(exit);
3263        }
3264    }
3265}
3266
3267void BuiltinsArrayStubBuilder::ToSpliced(GateRef glue, GateRef thisValue, GateRef numArgs,
3268    Variable *result, Label *exit, Label *slowPath)
3269{
3270    auto env = GetEnvironment();
3271    Label isHeapObject(env);
3272    Label isJsArray(env);
3273    Label isStability(env);
3274    Label defaultConstr(env);
3275    Label matchCls(env);
3276    Label isGeneric(env);
3277    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3278    Bind(&isHeapObject);
3279    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3280    Bind(&isJsArray);
3281    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3282    Bind(&defaultConstr);
3283    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3284    Bind(&isStability);
3285    Label notCOWArray(env);
3286    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
3287    Bind(&notCOWArray);
3288    GateRef arrayCls = LoadHClass(thisValue);
3289    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3290    Bind(&matchCls);
3291    GateRef thisLen = GetArrayLength(thisValue);
3292    Label lessThreeArg(env);
3293    DEFVARIABLE(actualStart, VariableType::INT32(), Int32(0));
3294    DEFVARIABLE(actualDeleteCount, VariableType::INT32(), Int32(0));
3295    DEFVARIABLE(newLen, VariableType::INT32(), Int32(0));
3296    DEFVARIABLE(insertCount, VariableType::INT32(), Int32(0));
3297    GateRef argc = ChangeIntPtrToInt32(numArgs);
3298    // 3: max arg count
3299    BRANCH(Int32LessThanOrEqual(argc, Int32(3)), &lessThreeArg, slowPath);
3300    Bind(&lessThreeArg);
3301    {
3302        Label checkOverFlow(env);
3303        Label greaterZero(env);
3304        Label greaterOne(env);
3305        Label checkGreaterOne(env);
3306        Label notOverFlow(env);
3307        Label copyAfter(env);
3308        // 0: judge the first arg exists
3309        BRANCH(Int32GreaterThan(argc, Int32(0)), &greaterZero, &checkGreaterOne);
3310        Bind(&greaterZero);
3311        {
3312            GateRef taggedStart = GetCallArg0(numArgs);
3313            Label taggedStartInt(env);
3314            BRANCH(TaggedIsInt(taggedStart), &taggedStartInt, slowPath);
3315            Bind(&taggedStartInt);
3316            {
3317                GateRef intStart = GetInt32OfTInt(taggedStart);
3318                actualStart = CalArrayRelativePos(intStart, thisLen);
3319                actualDeleteCount = Int32Sub(thisLen, *actualStart);
3320                Jump(&checkGreaterOne);
3321            }
3322        }
3323        Bind(&checkGreaterOne);
3324        {
3325            // 1: judge the second arg exists
3326            BRANCH(Int32GreaterThan(argc, Int32(1)), &greaterOne, &checkOverFlow);
3327            Bind(&greaterOne);
3328            {
3329                // 2: arg count which is not an item
3330                insertCount = Int32Sub(argc, Int32(2));
3331                GateRef argDeleteCount = GetCallArg1(numArgs);
3332                Label argDeleteCountInt(env);
3333                BRANCH(TaggedIsInt(argDeleteCount), &argDeleteCountInt, slowPath);
3334                Bind(&argDeleteCountInt);
3335                {
3336                    DEFVARIABLE(deleteCount, VariableType::INT32(), TaggedGetInt(argDeleteCount));
3337                    Label deleteCountLessZero(env);
3338                    Label calActualDeleteCount(env);
3339                    BRANCH(Int32LessThan(*deleteCount, Int32(0)), &deleteCountLessZero, &calActualDeleteCount);
3340                    Bind(&deleteCountLessZero);
3341                    {
3342                        deleteCount = Int32(0);
3343                        Jump(&calActualDeleteCount);
3344                    }
3345                    Bind(&calActualDeleteCount);
3346                    {
3347                        actualDeleteCount = *deleteCount;
3348                        Label lessArrayLen(env);
3349                        BRANCH(Int32LessThan(Int32Sub(thisLen, *actualStart), *deleteCount),
3350                            &lessArrayLen, &checkOverFlow);
3351                        Bind(&lessArrayLen);
3352                        {
3353                            actualDeleteCount = Int32Sub(thisLen, *actualStart);
3354                            Jump(&checkOverFlow);
3355                        }
3356                    }
3357                }
3358            }
3359            Bind(&checkOverFlow);
3360            {
3361                newLen = Int32Add(Int32Sub(thisLen, *actualDeleteCount), *insertCount);
3362                BRANCH(Int64GreaterThan(ZExtInt32ToInt64(*newLen), Int64(base::MAX_SAFE_INTEGER)),
3363                    slowPath, &notOverFlow);
3364                Bind(&notOverFlow);
3365                Label newLenEmpty(env);
3366                Label newLenNotEmpty(env);
3367                BRANCH(Int32Equal(*newLen, Int32(0)), &newLenEmpty, &newLenNotEmpty);
3368                Bind(&newLenEmpty);
3369                {
3370                    NewObjectStubBuilder newBuilder(this);
3371                    result->WriteVariable(newBuilder.CreateEmptyArray(glue));
3372                    Jump(exit);
3373                }
3374                Bind(&newLenNotEmpty);
3375                {
3376                    Label copyBefore(env);
3377                    Label insertArg(env);
3378                    GateRef newArray = NewArray(glue, Int32(0));
3379                    GrowElementsCapacity(glue, newArray, *newLen);
3380                    DEFVARIABLE(oldIndex, VariableType::INT32(), Int32(0));
3381                    DEFVARIABLE(newIndex, VariableType::INT32(), Int32(0));
3382                    BRANCH(Int32GreaterThan(*actualStart, Int32(0)), &copyBefore, &insertArg);
3383                    Bind(&copyBefore);
3384                    {
3385                        Label loopHead(env);
3386                        Label loopEnd(env);
3387                        Label loopNext(env);
3388                        Label loopExit(env);
3389                        Label eleIsHole(env);
3390                        Label eleNotHole(env);
3391                        Jump(&loopHead);
3392                        LoopBegin(&loopHead);
3393                        {
3394                            BRANCH(Int32LessThan(*oldIndex, *actualStart), &loopNext, &loopExit);
3395                            Bind(&loopNext);
3396                            GateRef ele = GetTaggedValueWithElementsKind(thisValue, *oldIndex);
3397                            BRANCH(TaggedIsHole(ele), &eleIsHole, &eleNotHole);
3398                            Bind(&eleIsHole);
3399                            {
3400                                SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true),
3401                                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3402                                Jump(&loopEnd);
3403                            }
3404                            Bind(&eleNotHole);
3405                            {
3406                                SetValueWithElementsKind(glue, newArray, ele, *newIndex, Boolean(true),
3407                                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3408                                Jump(&loopEnd);
3409                            }
3410                        }
3411                        Bind(&loopEnd);
3412                        oldIndex = Int32Add(*oldIndex, Int32(1));
3413                        newIndex = Int32Add(*newIndex, Int32(1));
3414                        LoopEnd(&loopHead);
3415                        Bind(&loopExit);
3416                        Jump(&insertArg);
3417                    }
3418                    Bind(&insertArg);
3419                    {
3420                        Label insert(env);
3421                        BRANCH(Int32GreaterThan(*insertCount, Int32(0)), &insert, &copyAfter);
3422                        Bind(&insert);
3423                        {
3424                            GateRef insertNum = GetCallArg2(numArgs);
3425                            SetValueWithElementsKind(glue, newArray, insertNum, *newIndex, Boolean(true),
3426                                Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3427                            newIndex = Int32Add(*newIndex, Int32(1));
3428                            Jump(&copyAfter);
3429                        }
3430                    }
3431                    Bind(&copyAfter);
3432                    {
3433                        Label canCopyAfter(env);
3434                        Label setLength(env);
3435                        oldIndex = Int32Add(*actualStart, *actualDeleteCount);
3436                        BRANCH(Int32LessThan(*oldIndex, thisLen), &canCopyAfter, &setLength);
3437                        Bind(&canCopyAfter);
3438                        {
3439                            Label loopHead1(env);
3440                            Label loopNext1(env);
3441                            Label loopEnd1(env);
3442                            Label loopExit1(env);
3443                            Label ele1IsHole(env);
3444                            Label ele1NotHole(env);
3445                            Jump(&loopHead1);
3446                            LoopBegin(&loopHead1);
3447                            {
3448                                BRANCH(Int32LessThan(*oldIndex, thisLen), &loopNext1, &loopExit1);
3449                                Bind(&loopNext1);
3450                                GateRef ele1 = GetTaggedValueWithElementsKind(thisValue, *oldIndex);
3451                                BRANCH(TaggedIsHole(ele1), &ele1IsHole, &ele1NotHole);
3452                                Bind(&ele1IsHole);
3453                                {
3454                                    SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true),
3455                                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3456                                    Jump(&loopEnd1);
3457                                }
3458                                Bind(&ele1NotHole);
3459                                {
3460                                    SetValueWithElementsKind(glue, newArray, ele1, *newIndex, Boolean(true),
3461                                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3462                                    Jump(&loopEnd1);
3463                                }
3464                            }
3465                            Bind(&loopEnd1);
3466                            oldIndex = Int32Add(*oldIndex, Int32(1));
3467                            newIndex = Int32Add(*newIndex, Int32(1));
3468                            LoopEnd(&loopHead1);
3469                            Bind(&loopExit1);
3470                            Jump(&setLength);
3471                        }
3472                        Bind(&setLength);
3473                        {
3474                            SetArrayLength(glue, newArray, *newLen);
3475                            result->WriteVariable(newArray);
3476                            Jump(exit);
3477                        }
3478                    }
3479                }
3480            }
3481        }
3482    }
3483}
3484
3485void BuiltinsArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateRef numArgs,
3486    Variable *result, Label *exit, Label *slowPath)
3487{
3488    auto env = GetEnvironment();
3489    Label thisExists(env);
3490    Label isHeapObject(env);
3491    Label isJsArray(env);
3492    Label defaultConstr(env);
3493    Label isStability(env);
3494    Label isGeneric(env);
3495    Label notCOWArray(env);
3496    Label matchCls(env);
3497    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
3498    Bind(&thisExists);
3499    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3500    Bind(&isHeapObject);
3501    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3502    Bind(&isJsArray);
3503    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3504    Bind(&defaultConstr);
3505    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3506    Bind(&isStability);
3507    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
3508    Bind(&notCOWArray);
3509    GateRef arrayCls = LoadHClass(thisValue);
3510    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3511    Bind(&matchCls);
3512    DEFVARIABLE(startPos, VariableType::INT64(), Int64(0));
3513    DEFVARIABLE(endPos, VariableType::INT64(), Int64(0));
3514    Label targetTagExists(env);
3515    Label targetTagIsInt(env);
3516    Label startTagExists(env);
3517    Label startTagIsInt(env);
3518    Label afterCallArg1(env);
3519    Label endTagExists(env);
3520    Label endTagIsInt(env);
3521    Label afterCallArg2(env);
3522    GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
3523    BRANCH(Int64GreaterThanOrEqual(IntPtr(0), numArgs), slowPath, &targetTagExists);
3524    Bind(&targetTagExists);
3525    GateRef targetTag = GetCallArg0(numArgs);
3526    BRANCH(TaggedIsInt(targetTag), &targetTagIsInt, slowPath);
3527    Bind(&targetTagIsInt);
3528    GateRef argTarget = SExtInt32ToInt64(TaggedGetInt(targetTag));
3529    BRANCH(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &afterCallArg1, &startTagExists);
3530    Bind(&startTagExists);
3531    {
3532        GateRef startTag = GetCallArg1(numArgs);
3533        BRANCH(TaggedIsInt(startTag), &startTagIsInt, slowPath);
3534        Bind(&startTagIsInt);
3535        startPos = SExtInt32ToInt64(TaggedGetInt(startTag));
3536        Jump(&afterCallArg1);
3537    }
3538    Bind(&afterCallArg1);
3539    {
3540        endPos = thisLen;
3541        BRANCH(Int64GreaterThanOrEqual(IntPtr(2), numArgs), &afterCallArg2, &endTagExists);
3542        Bind(&endTagExists);
3543        {
3544            GateRef endTag = GetCallArg2(numArgs);
3545            BRANCH(TaggedIsInt(endTag), &endTagIsInt, slowPath);
3546            Bind(&endTagIsInt);
3547            {
3548                endPos = SExtInt32ToInt64(TaggedGetInt(endTag));
3549                Jump(&afterCallArg2);
3550            }
3551        }
3552    }
3553    Bind(&afterCallArg2);
3554    {
3555        DEFVARIABLE(copyTo, VariableType::INT64(), Int64(0));
3556        DEFVARIABLE(copyFrom, VariableType::INT64(), Int64(0));
3557        DEFVARIABLE(copyEnd, VariableType::INT64(), Int64(0));
3558        DEFVARIABLE(count, VariableType::INT64(), Int64(0));
3559        DEFVARIABLE(direction, VariableType::INT64(), Int64(0));
3560        Label calculateCountBranch1(env);
3561        Label calculateCountBranch2(env);
3562        Label afterCalculateCount(env);
3563        Label needToAdjustParam(env);
3564        Label afterAdjustParam(env);
3565        copyTo = CalculatePositionWithLength(argTarget, thisLen);
3566        copyFrom = CalculatePositionWithLength(*startPos, thisLen);
3567        copyEnd = CalculatePositionWithLength(*endPos, thisLen);
3568        BRANCH(Int64LessThan(Int64Sub(*copyEnd, *copyFrom), Int64Sub(thisLen, *copyTo)),
3569            &calculateCountBranch1, &calculateCountBranch2);
3570        Bind(&calculateCountBranch1);
3571        {
3572            count = Int64Sub(*copyEnd, *copyFrom);
3573            Jump(&afterCalculateCount);
3574        }
3575        Bind(&calculateCountBranch2);
3576        {
3577            count = Int64Sub(thisLen, *copyTo);
3578            Jump(&afterCalculateCount);
3579        }
3580
3581        Bind(&afterCalculateCount);
3582        {
3583            direction = Int64(1);
3584            GateRef copyFromVal = *copyFrom;
3585            GateRef copyToVal = *copyTo;
3586            GateRef countVal = *count;
3587            BRANCH(LogicAndBuilder(env).And(Int64LessThan(copyFromVal, copyToVal))
3588                .And(Int64LessThan(copyToVal, Int64Add(copyFromVal, countVal))).Done(),
3589                &needToAdjustParam, &afterAdjustParam);
3590            Bind(&needToAdjustParam);
3591            {
3592                direction = Int64(-1);
3593                copyFrom = Int64Sub(Int64Add(*copyFrom, *count), Int64(1));
3594                copyTo = Int64Sub(Int64Add(*copyTo, *count), Int64(1));
3595                Jump(&afterAdjustParam);
3596            }
3597
3598            Bind(&afterAdjustParam);
3599            {
3600                DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3601                Label loopHead(env);
3602                Label loopEnd(env);
3603                Label next(env);
3604                Label loopExit(env);
3605                Jump(&loopHead);
3606                LoopBegin(&loopHead);
3607                {
3608                    Label kValueIsHole(env);
3609                    Label setValue(env);
3610                    Label hasProperty(env);
3611                    Label setHole(env);
3612                    Label hasException0(env);
3613                    Label notHasException0(env);
3614                    BRANCH(Int64GreaterThan(*count, Int64(0)), &next, &loopExit);
3615                    Bind(&next);
3616                    kValue = GetTaggedValueWithElementsKind(thisValue, *copyFrom);
3617                    BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &setValue);
3618                    Bind(&kValueIsHole);
3619                    GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty),
3620                        { thisValue, IntToTaggedInt(*copyFrom) });
3621                    BRANCH(TaggedIsTrue(hasProp), &hasProperty, &setHole);
3622
3623                    Bind(&hasProperty);
3624                    kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*copyFrom), ProfileOperation());
3625                    BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
3626                    Bind(&hasException0);
3627                    {
3628                        result->WriteVariable(Exception());
3629                        Jump(exit);
3630                    }
3631                    Bind(&notHasException0);
3632                    BRANCH(TaggedIsHole(*kValue), &setHole, &setValue);
3633                    Bind(&setHole);
3634                    {
3635                        SetValueWithElementsKind(glue, thisValue, Hole(), *copyTo,
3636                            Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::DICTIONARY)));
3637                        Jump(&loopEnd);
3638                    }
3639                    Bind(&setValue);
3640                    {
3641                        SetValueWithElementsKind(glue, thisValue, *kValue, *copyTo,
3642                            Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3643                        Jump(&loopEnd);
3644                    }
3645                }
3646                Bind(&loopEnd);
3647                copyFrom = Int64Add(*copyFrom, *direction);
3648                copyTo = Int64Add(*copyTo, *direction);
3649                count = Int64Sub(*count, Int64(1));
3650                LoopEnd(&loopHead);
3651                Bind(&loopExit);
3652                result->WriteVariable(thisValue);
3653                Jump(exit);
3654            }
3655        }
3656    }
3657}
3658
3659GateRef BuiltinsArrayStubBuilder::CalculatePositionWithLength(GateRef position, GateRef length)
3660{
3661    auto env = GetEnvironment();
3662    Label entry(env);
3663    env->SubCfgEntry(&entry);
3664    DEFVARIABLE(result, VariableType::INT64(), Int64(0));
3665    Label positionLessThanZero(env);
3666    Label positionNotLessThanZero(env);
3667    Label resultNotGreaterThanZero(env);
3668    Label positionLessThanLength(env);
3669    Label positionNotLessThanLength(env);
3670    Label afterCalculatePosition(env);
3671
3672    BRANCH(Int64LessThan(position, Int64(0)), &positionLessThanZero, &positionNotLessThanZero);
3673    Bind(&positionLessThanZero);
3674    {
3675        result = Int64Add(position, length);
3676        BRANCH(Int64GreaterThan(*result, Int64(0)), &afterCalculatePosition, &resultNotGreaterThanZero);
3677        Bind(&resultNotGreaterThanZero);
3678        result = Int64(0);
3679        Jump(&afterCalculatePosition);
3680    }
3681    Bind(&positionNotLessThanZero);
3682    {
3683        BRANCH(Int64LessThan(position, length), &positionLessThanLength, &positionNotLessThanLength);
3684        Bind(&positionLessThanLength);
3685        {
3686            result = position;
3687            Jump(&afterCalculatePosition);
3688        }
3689        Bind(&positionNotLessThanLength);
3690        {
3691            result = length;
3692            Jump(&afterCalculatePosition);
3693        }
3694    }
3695    Bind(&afterCalculatePosition);
3696    auto ret = *result;
3697    env->SubCfgExit();
3698    return ret;
3699}
3700
3701void BuiltinsArrayStubBuilder::Some(GateRef glue, GateRef thisValue, GateRef numArgs,
3702    Variable *result, Label *exit, Label *slowPath)
3703{
3704    auto env = GetEnvironment();
3705    Label thisExists(env);
3706    Label isHeapObject(env);
3707    Label isJsArray(env);
3708    Label defaultConstr(env);
3709    Label isStability(env);
3710    Label notCOWArray(env);
3711    Label equalCls(env);
3712    Label matchCls(env);
3713    Label isGeneric(env);
3714    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
3715    Bind(&thisExists);
3716    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3717    Bind(&isHeapObject);
3718    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3719    Bind(&isJsArray);
3720    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3721    Bind(&defaultConstr);
3722    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3723    Bind(&isStability);
3724    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
3725    Bind(&notCOWArray);
3726    GateRef arrayCls = LoadHClass(thisValue);
3727    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3728    Bind(&matchCls);
3729    Label arg0HeapObject(env);
3730    Label callable(env);
3731    Label thisIsStable(env);
3732    Label thisNotStable(env);
3733    GateRef callbackFnHandle = GetCallArg0(numArgs);
3734    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
3735    Bind(&arg0HeapObject);
3736    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
3737    Bind(&callable);
3738    GateRef argHandle = GetCallArg1(numArgs);
3739
3740    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
3741    DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
3742    Jump(&thisIsStable);
3743
3744    Bind(&thisIsStable);
3745    {
3746        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3747        Label loopHead(env);
3748        Label loopEnd(env);
3749        Label next(env);
3750        Label loopExit(env);
3751        Jump(&loopHead);
3752        LoopBegin(&loopHead);
3753        {
3754            Label nextStep(env);
3755            Label kValueIsHole(env);
3756            Label callDispatch(env);
3757            Label hasProperty(env);
3758            Label hasException0(env);
3759            Label notHasException0(env);
3760            Label hasException1(env);
3761            Label notHasException1(env);
3762            BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
3763            Bind(&nextStep);
3764            BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
3765            Bind(&next);
3766            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
3767            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
3768            Bind(&kValueIsHole);
3769            {
3770                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
3771                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3772                Bind(&hasProperty);
3773                {
3774                    kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
3775                    BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
3776                    Bind(&hasException0);
3777                    {
3778                        result->WriteVariable(Exception());
3779                        Jump(exit);
3780                    }
3781                    Bind(&notHasException0);
3782                    {
3783                        BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3784                    }
3785                }
3786            }
3787            Bind(&callDispatch);
3788            {
3789                GateRef key = Int64ToTaggedInt(*i);
3790                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
3791                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
3792                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
3793                    Circuit::NullGate(), callArgs);
3794                GateRef retValue = callBuilder.JSCallDispatch();
3795                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
3796                Bind(&hasException1);
3797                {
3798                    result->WriteVariable(Exception());
3799                    Jump(exit);
3800                }
3801                Bind(&notHasException1);
3802                {
3803                    DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
3804                    Label changeThisLen(env);
3805                    Label afterChangeLen(env);
3806                    Label retValueIsTrue(env);
3807                    BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen);
3808                    Bind(&changeThisLen);
3809                    {
3810                        thisArrLen = *newLen;
3811                        Jump(&afterChangeLen);
3812                    }
3813                    Bind(&afterChangeLen);
3814                    {
3815                        BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd);
3816                        Bind(&retValueIsTrue);
3817                        {
3818                            result->WriteVariable(TaggedTrue());
3819                            Jump(exit);
3820                        }
3821                    }
3822                }
3823            }
3824        }
3825        Bind(&loopEnd);
3826        i = Int64Add(*i, Int64(1));
3827        LoopEnd(&loopHead);
3828        Bind(&loopExit);
3829        result->WriteVariable(TaggedFalse());
3830        Jump(exit);
3831    }
3832
3833    Bind(&thisNotStable);
3834    {
3835        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3836        Label loopHead(env);
3837        Label loopEnd(env);
3838        Label next(env);
3839        Label loopExit(env);
3840        Jump(&loopHead);
3841        LoopBegin(&loopHead);
3842        {
3843            Label hasProperty(env);
3844            Label hasException0(env);
3845            Label notHasException0(env);
3846            Label callDispatch(env);
3847            Label hasException1(env);
3848            Label notHasException1(env);
3849            BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
3850            Bind(&next);
3851            GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
3852            BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3853            Bind(&hasProperty);
3854            {
3855                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
3856                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
3857                Bind(&hasException0);
3858                {
3859                    result->WriteVariable(Exception());
3860                    Jump(exit);
3861                }
3862                Bind(&notHasException0);
3863                {
3864                    BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3865                    Bind(&callDispatch);
3866                    {
3867                        GateRef key = Int64ToTaggedInt(*i);
3868                        JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
3869                        callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
3870                        CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
3871                            nullptr, Circuit::NullGate(), callArgs);
3872                        GateRef retValue = callBuilder.JSCallDispatch();
3873                        BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
3874                        Bind(&hasException1);
3875                        {
3876                            result->WriteVariable(Exception());
3877                            Jump(exit);
3878                        }
3879                        Bind(&notHasException1);
3880                        {
3881                            Label retValueIsTrue(env);
3882                            BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd);
3883                            Bind(&retValueIsTrue);
3884                            {
3885                                result->WriteVariable(TaggedTrue());
3886                                Jump(exit);
3887                            }
3888                        }
3889                    }
3890                }
3891            }
3892        }
3893        Bind(&loopEnd);
3894        i = Int64Add(*i, Int64(1));
3895        LoopEnd(&loopHead);
3896        Bind(&loopExit);
3897        result->WriteVariable(TaggedFalse());
3898        Jump(exit);
3899    }
3900}
3901
3902void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef numArgs,
3903    Variable *result, Label *exit, Label *slowPath)
3904{
3905    auto env = GetEnvironment();
3906    Label thisExists(env);
3907    Label isHeapObject(env);
3908    Label isJsArray(env);
3909    Label defaultConstr(env);
3910    Label isStability(env);
3911    Label notCOWArray(env);
3912    Label equalCls(env);
3913    Label arg0HeapObject(env);
3914    Label callable(env);
3915    Label matchCls(env);
3916    Label isGeneric(env);
3917    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
3918    Bind(&thisExists);
3919    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3920    Bind(&isHeapObject);
3921    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3922    Bind(&isJsArray);
3923    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3924    Bind(&defaultConstr);
3925    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3926    Bind(&isStability);
3927    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
3928    Bind(&notCOWArray);
3929    GateRef arrayCls = LoadHClass(thisValue);
3930    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3931    Bind(&matchCls);
3932    GateRef callbackFnHandle = GetCallArg0(numArgs);
3933    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
3934    Bind(&arg0HeapObject);
3935    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
3936    Bind(&callable);
3937
3938    Label thisIsStable(env);
3939    Label thisNotStable(env);
3940    GateRef argHandle = GetCallArg1(numArgs);
3941    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
3942    DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
3943    Jump(&thisIsStable);
3944
3945    Bind(&thisIsStable);
3946    {
3947        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3948        Label loopHead(env);
3949        Label loopEnd(env);
3950        Label next(env);
3951        Label loopExit(env);
3952        Jump(&loopHead);
3953        LoopBegin(&loopHead);
3954        {
3955            Label nextStep(env);
3956            Label kValueIsHole(env);
3957            Label callDispatch(env);
3958            Label hasProperty(env);
3959            Label hasException0(env);
3960            Label notHasException0(env);
3961            Label hasException1(env);
3962            Label notHasException1(env);
3963            BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
3964            Bind(&nextStep);
3965            BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
3966            Bind(&next);
3967            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
3968            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
3969            Bind(&kValueIsHole);
3970            {
3971                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
3972                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3973                Bind(&hasProperty);
3974                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
3975                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
3976                Bind(&hasException0);
3977                {
3978                    result->WriteVariable(Exception());
3979                    Jump(exit);
3980                }
3981                Bind(&notHasException0);
3982                BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3983            }
3984            Bind(&callDispatch);
3985            {
3986                GateRef key = Int64ToTaggedInt(*i);
3987                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
3988                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
3989                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
3990                    Circuit::NullGate(), callArgs);
3991                GateRef retValue = callBuilder.JSCallDispatch();
3992                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
3993                Bind(&hasException1);
3994                {
3995                    result->WriteVariable(Exception());
3996                    Jump(exit);
3997                }
3998                Bind(&notHasException1);
3999                {
4000                    DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4001                    Label changeThisLen(env);
4002                    Label afterChangeLen(env);
4003                    Label retValueIsFalse(env);
4004                    BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen);
4005                    Bind(&changeThisLen);
4006                    {
4007                        thisArrLen = *newLen;
4008                        Jump(&afterChangeLen);
4009                    }
4010                    Bind(&afterChangeLen);
4011                    {
4012                        BRANCH(TaggedIsFalse(FastToBoolean(retValue)), &retValueIsFalse, &loopEnd);
4013                        Bind(&retValueIsFalse);
4014                        result->WriteVariable(TaggedFalse());
4015                        Jump(exit);
4016                    }
4017                }
4018            }
4019        }
4020        Bind(&loopEnd);
4021        i = Int64Add(*i, Int64(1));
4022        LoopEnd(&loopHead);
4023        Bind(&loopExit);
4024        result->WriteVariable(TaggedTrue());
4025        Jump(exit);
4026    }
4027
4028    Bind(&thisNotStable);
4029    {
4030        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4031        Label loopHead(env);
4032        Label loopEnd(env);
4033        Label next(env);
4034        Label loopExit(env);
4035        Jump(&loopHead);
4036        LoopBegin(&loopHead);
4037        {
4038            Label hasProperty(env);
4039            Label hasException0(env);
4040            Label notHasException0(env);
4041            Label callDispatch(env);
4042            Label hasException1(env);
4043            Label notHasException1(env);
4044            BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
4045            Bind(&next);
4046            GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4047            BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
4048            Bind(&hasProperty);
4049            kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4050            BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4051            Bind(&hasException0);
4052            {
4053                result->WriteVariable(Exception());
4054                Jump(exit);
4055            }
4056            Bind(&notHasException0);
4057            {
4058                BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
4059                Bind(&callDispatch);
4060                GateRef key = Int64ToTaggedInt(*i);
4061                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4062                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4063                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4064                    Circuit::NullGate(), callArgs);
4065                GateRef retValue = callBuilder.JSCallDispatch();
4066                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4067                Bind(&hasException1);
4068                {
4069                    result->WriteVariable(Exception());
4070                    Jump(exit);
4071                }
4072                Bind(&notHasException1);
4073                {
4074                    Label retValueIsFalse(env);
4075                    BRANCH(TaggedIsFalse(FastToBoolean(retValue)), &retValueIsFalse, &loopEnd);
4076                    Bind(&retValueIsFalse);
4077                    result->WriteVariable(TaggedFalse());
4078                    Jump(exit);
4079                }
4080            }
4081        }
4082        Bind(&loopEnd);
4083        i = Int64Add(*i, Int64(1));
4084        LoopEnd(&loopHead);
4085        Bind(&loopExit);
4086        result->WriteVariable(TaggedTrue());
4087        Jump(exit);
4088    }
4089}
4090
4091void BuiltinsArrayStubBuilder::ReduceRight(GateRef glue, GateRef thisValue, GateRef numArgs,
4092    Variable *result, Label *exit, Label *slowPath)
4093{
4094    auto env = GetEnvironment();
4095    Label thisExists(env);
4096    Label isHeapObject(env);
4097    Label isJsArray(env);
4098    Label defaultConstr(env);
4099    Label isStability(env);
4100    Label notCOWArray(env);
4101    Label equalCls(env);
4102    Label matchCls(env);
4103    Label isGeneric(env);
4104    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
4105    Bind(&thisExists);
4106    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
4107    Bind(&isHeapObject);
4108    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
4109    Bind(&isJsArray);
4110    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
4111    Bind(&defaultConstr);
4112    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
4113    Bind(&isStability);
4114    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
4115    Bind(&notCOWArray);
4116    GateRef arrayCls = LoadHClass(thisValue);
4117    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
4118    Bind(&matchCls);
4119    DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0));
4120    DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined());
4121    DEFVARIABLE(k, VariableType::INT32(), Int32(0));
4122    Label atLeastOneArg(env);
4123    Label callbackFnHandleHeapObject(env);
4124    Label callbackFnHandleCallable(env);
4125    Label updateAccumulator(env);
4126    Label thisIsStable(env);
4127    Label thisNotStable(env);
4128    thisLen = GetArrayLength(thisValue);
4129    BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
4130    Bind(&atLeastOneArg);
4131    GateRef callbackFnHandle = GetCallArg0(numArgs);
4132    BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath);
4133    Bind(&callbackFnHandleHeapObject);
4134    BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath);
4135    Bind(&callbackFnHandleCallable);
4136    GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2));                 // 2: callbackFn initialValue
4137    k = Int32Sub(*thisLen, Int32(1));
4138    BRANCH(numArgsLessThanTwo, slowPath, &updateAccumulator);           // 2: callbackFn initialValue
4139    Bind(&updateAccumulator);
4140    accumulator = GetCallArg1(numArgs);
4141    Jump(&thisIsStable);
4142
4143    Bind(&thisIsStable);
4144    {
4145        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4146        GateRef argsLength = Int32(4);
4147        NewObjectStubBuilder newBuilder(this);
4148        GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
4149        Label loopHead(env);
4150        Label next(env);
4151        Label loopEnd(env);
4152        Label loopExit(env);
4153        Jump(&loopHead);
4154        LoopBegin(&loopHead);
4155        {
4156            Label nextStep(env);
4157            Label kValueIsHole(env);
4158            Label callDispatch(env);
4159            Label hasProperty(env);
4160            Label hasException0(env);
4161            Label notHasException0(env);
4162            Label hasException1(env);
4163            Label notHasException1(env);
4164            GateRef thisLenVal = *thisLen;
4165            BRANCH(LogicAndBuilder(env).And(IsStableJSArray(glue, thisValue))
4166                .And(Int32Equal(thisLenVal, GetArrayLength(thisValue))).Done(),
4167                &nextStep, &thisNotStable);
4168            Bind(&nextStep);
4169            BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit);
4170            Bind(&next);
4171            kValue = GetTaggedValueWithElementsKind(thisValue, *k);
4172            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
4173            Bind(&kValueIsHole);
4174            {
4175                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) });
4176                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
4177                Bind(&hasProperty);
4178                kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation());
4179                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4180                Bind(&hasException0);
4181                result->WriteVariable(Exception());
4182                Jump(exit);
4183                Bind(&notHasException0);
4184                BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
4185            }
4186            Bind(&callDispatch);
4187            {
4188                // callback param 0: accumulator
4189                SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
4190                // callback param 1: currentValue
4191                SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue);
4192                // callback param 2: index
4193                SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
4194                // callback param 3: array
4195                SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
4196                GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
4197                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
4198                callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
4199                CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr, Circuit::NullGate(),
4200                    callArgs);
4201                GateRef callResult = callBuilder.JSCallDispatch();
4202                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4203                Bind(&hasException1);
4204                {
4205                    result->WriteVariable(Exception());
4206                    Jump(exit);
4207                }
4208
4209                Bind(&notHasException1);
4210                {
4211                    accumulator = callResult;
4212                    Jump(&loopEnd);
4213                }
4214            }
4215        }
4216        Bind(&loopEnd);
4217        k = Int32Sub(*k, Int32(1));
4218        LoopEnd(&loopHead);
4219        Bind(&loopExit);
4220        result->WriteVariable(*accumulator);
4221        Jump(exit);
4222    }
4223
4224    Bind(&thisNotStable);
4225    {
4226        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4227        GateRef argsLength = Int32(4);
4228        NewObjectStubBuilder newBuilder(this);
4229        GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
4230        Label loopHead(env);
4231        Label next(env);
4232        Label loopEnd(env);
4233        Label loopExit(env);
4234        Jump(&loopHead);
4235        LoopBegin(&loopHead);
4236        {
4237            Label hasProperty(env);
4238            Label hasException0(env);
4239            Label notHasException0(env);
4240            Label callDispatch(env);
4241            Label hasException1(env);
4242            Label notHasException1(env);
4243            BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit);
4244            Bind(&next);
4245            GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) });
4246            BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
4247            Bind(&hasProperty);
4248            kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation());
4249            BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4250            Bind(&hasException0);
4251            result->WriteVariable(Exception());
4252            Jump(exit);
4253            Bind(&notHasException0);
4254            BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
4255            Bind(&callDispatch);
4256            {
4257                // callback param 0: accumulator
4258                SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
4259                // callback param 1: currentValue
4260                SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue);
4261                // callback param 2: index
4262                SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
4263                // callback param 3: array
4264                SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
4265                GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
4266                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
4267                callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
4268                CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr, Circuit::NullGate(),
4269                    callArgs);
4270                GateRef callResult = callBuilder.JSCallDispatch();
4271                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4272                Bind(&hasException1);
4273                {
4274                    result->WriteVariable(Exception());
4275                    Jump(exit);
4276                }
4277
4278                Bind(&notHasException1);
4279                {
4280                    accumulator = callResult;
4281                    Jump(&loopEnd);
4282                }
4283            }
4284        }
4285        Bind(&loopEnd);
4286        k = Int32Sub(*k, Int32(1));
4287        LoopEnd(&loopHead);
4288        Bind(&loopExit);
4289        result->WriteVariable(*accumulator);
4290        Jump(exit);
4291    }
4292}
4293
4294void BuiltinsArrayStubBuilder::FindLastIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
4295    Variable *result, Label *exit, Label *slowPath)
4296{
4297    auto env = GetEnvironment();
4298    Label thisExists(env);
4299    Label isHeapObject(env);
4300    Label isJsArray(env);
4301    Label defaultConstr(env);
4302    Label isStability(env);
4303    Label notCOWArray(env);
4304    Label equalCls(env);
4305    Label isGeneric(env);
4306    Label matchCls(env);
4307    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
4308    Bind(&thisExists);
4309    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
4310    Bind(&isHeapObject);
4311    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
4312    Bind(&isJsArray);
4313    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
4314    Bind(&defaultConstr);
4315    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
4316    Bind(&isStability);
4317    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
4318    Bind(&notCOWArray);
4319    GateRef arrayCls = LoadHClass(thisValue);
4320    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
4321    Bind(&matchCls);
4322    Label arg0HeapObject(env);
4323    Label callable(env);
4324    Label thisIsStable(env);
4325    Label thisNotStable(env);
4326    GateRef callbackFnHandle = GetCallArg0(numArgs);
4327    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
4328    Bind(&arg0HeapObject);
4329    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
4330    Bind(&callable);
4331    GateRef argHandle = GetCallArg1(numArgs);
4332
4333    DEFVARIABLE(i, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1)));
4334    Jump(&thisIsStable);
4335
4336    Bind(&thisIsStable);
4337    {
4338        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4339        Label loopHead(env);
4340        Label loopEnd(env);
4341        Label next(env);
4342        Label loopExit(env);
4343        Jump(&loopHead);
4344        LoopBegin(&loopHead);
4345        {
4346            Label nextStep(env);
4347            Label kValueIsHole(env);
4348            Label callDispatch(env);
4349            Label hasProperty(env);
4350            Label hasException0(env);
4351            Label notHasException0(env);
4352            Label useUndefined(env);
4353            Label hasException1(env);
4354            Label notHasException1(env);
4355            BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
4356            Bind(&nextStep);
4357            BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4358            Bind(&next);
4359            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
4360            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
4361            Bind(&kValueIsHole);
4362            {
4363                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4364                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4365                Bind(&hasProperty);
4366                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4367                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4368                Bind(&hasException0);
4369                {
4370                    result->WriteVariable(Exception());
4371                    Jump(exit);
4372                }
4373                Bind(&notHasException0);
4374                {
4375                    BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4376                    Bind(&useUndefined);
4377                    kValue = Undefined();
4378                    Jump(&callDispatch);
4379                }
4380            }
4381            Bind(&callDispatch);
4382            {
4383                GateRef key = Int64ToTaggedInt(*i);
4384                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4385                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4386                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4387                    Circuit::NullGate(), callArgs);
4388                GateRef retValue = callBuilder.JSCallDispatch();
4389                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4390                Bind(&hasException1);
4391                {
4392                    result->WriteVariable(Exception());
4393                    Jump(exit);
4394                }
4395
4396                Bind(&notHasException1);
4397                {
4398                    DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4399                    Label checkRetValue(env);
4400                    Label find(env);
4401                    BRANCH(Int64LessThan(*newLen, Int64Add(*i, Int64(1))), &thisNotStable, &checkRetValue);
4402                    Bind(&checkRetValue);
4403                    BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4404                    Bind(&find);
4405                    result->WriteVariable(IntToTaggedPtr(*i));
4406                    Jump(exit);
4407                }
4408            }
4409        }
4410        Bind(&loopEnd);
4411        i = Int64Sub(*i, Int64(1));
4412        LoopEnd(&loopHead);
4413        Bind(&loopExit);
4414        result->WriteVariable(IntToTaggedPtr(Int32(-1)));
4415        Jump(exit);
4416    }
4417
4418    Bind(&thisNotStable);
4419    {
4420        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4421        Label loopHead(env);
4422        Label loopEnd(env);
4423        Label next(env);
4424        Label loopExit(env);
4425        Jump(&loopHead);
4426        LoopBegin(&loopHead);
4427        {
4428            Label hasProperty(env);
4429            Label hasException0(env);
4430            Label notHasException0(env);
4431            Label useUndefined(env);
4432            Label callDispatch(env);
4433            Label hasException1(env);
4434            Label notHasException1(env);
4435            BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4436            Bind(&next);
4437            GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4438            BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4439            Bind(&hasProperty);
4440            kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4441            BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4442            Bind(&hasException0);
4443            {
4444                result->WriteVariable(Exception());
4445                Jump(exit);
4446            }
4447            Bind(&notHasException0);
4448            {
4449                BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4450                Bind(&useUndefined);
4451                kValue = Undefined();
4452                Jump(&callDispatch);
4453                Bind(&callDispatch);
4454                GateRef key = Int64ToTaggedInt(*i);
4455                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4456                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4457                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4458                    Circuit::NullGate(), callArgs);
4459                GateRef retValue = callBuilder.JSCallDispatch();
4460                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4461                Bind(&hasException1);
4462                {
4463                    result->WriteVariable(Exception());
4464                    Jump(exit);
4465                }
4466
4467                Bind(&notHasException1);
4468                {
4469                    Label find(env);
4470                    BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4471                    Bind(&find);
4472                    result->WriteVariable(IntToTaggedPtr(*i));
4473                    Jump(exit);
4474                }
4475            }
4476        }
4477        Bind(&loopEnd);
4478        i = Int64Sub(*i, Int64(1));
4479        LoopEnd(&loopHead);
4480        Bind(&loopExit);
4481        result->WriteVariable(IntToTaggedPtr(Int32(-1)));
4482        Jump(exit);
4483    }
4484}
4485
4486void BuiltinsArrayStubBuilder::FindLast(GateRef glue, GateRef thisValue, GateRef numArgs,
4487    Variable *result, Label *exit, Label *slowPath)
4488{
4489    auto env = GetEnvironment();
4490    Label thisExists(env);
4491    Label isHeapObject(env);
4492    Label isJsArray(env);
4493    Label defaultConstr(env);
4494    Label isStability(env);
4495    Label notCOWArray(env);
4496    Label equalCls(env);
4497    Label matchCls(env);
4498    Label isGeneric(env);
4499    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
4500    Bind(&thisExists);
4501    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
4502    Bind(&isHeapObject);
4503    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
4504    Bind(&isJsArray);
4505    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
4506    Bind(&defaultConstr);
4507    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
4508    Bind(&isStability);
4509    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
4510    Bind(&notCOWArray);
4511    GateRef arrayCls = LoadHClass(thisValue);
4512    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
4513    Bind(&matchCls);
4514    Label arg0HeapObject(env);
4515    Label callable(env);
4516    Label thisIsStable(env);
4517    Label thisNotStable(env);
4518    GateRef callbackFnHandle = GetCallArg0(numArgs);
4519    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
4520    Bind(&arg0HeapObject);
4521    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
4522    Bind(&callable);
4523    GateRef argHandle = GetCallArg1(numArgs);
4524
4525    DEFVARIABLE(i, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1)));
4526    Jump(&thisIsStable);
4527
4528    Bind(&thisIsStable);
4529    {
4530        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4531        Label loopHead(env);
4532        Label loopEnd(env);
4533        Label next(env);
4534        Label loopExit(env);
4535        Jump(&loopHead);
4536        LoopBegin(&loopHead);
4537        {
4538            Label nextStep(env);
4539            Label kValueIsHole(env);
4540            Label callDispatch(env);
4541            Label hasProperty(env);
4542            Label hasException0(env);
4543            Label notHasException0(env);
4544            Label useUndefined(env);
4545            Label hasException1(env);
4546            Label notHasException1(env);
4547            BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
4548            Bind(&nextStep);
4549            BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4550            Bind(&next);
4551            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
4552            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
4553            Bind(&kValueIsHole);
4554            {
4555                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4556                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4557                Bind(&hasProperty);
4558                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4559                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4560                Bind(&hasException0);
4561                {
4562                    result->WriteVariable(Exception());
4563                    Jump(exit);
4564                }
4565                Bind(&notHasException0);
4566                {
4567                    BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4568                    Bind(&useUndefined);
4569                    kValue = Undefined();
4570                    Jump(&callDispatch);
4571                }
4572            }
4573            Bind(&callDispatch);
4574            {
4575                GateRef key = Int64ToTaggedInt(*i);
4576                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4577                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4578                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4579                    Circuit::NullGate(), callArgs);
4580                GateRef retValue = callBuilder.JSCallDispatch();
4581                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4582                Bind(&hasException1);
4583                {
4584                    result->WriteVariable(Exception());
4585                    Jump(exit);
4586                }
4587
4588                Bind(&notHasException1);
4589                {
4590                    DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4591                    Label checkRetValue(env);
4592                    Label find(env);
4593                    BRANCH(Int64LessThan(*newLen, Int64Add(*i, Int64(1))), &thisNotStable, &checkRetValue);
4594                    Bind(&checkRetValue);
4595                    BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4596                    Bind(&find);
4597                    result->WriteVariable(*kValue);
4598                    Jump(exit);
4599                }
4600            }
4601        }
4602        Bind(&loopEnd);
4603        i = Int64Sub(*i, Int64(1));
4604        LoopEnd(&loopHead);
4605        Bind(&loopExit);
4606        Jump(exit);
4607    }
4608
4609    Bind(&thisNotStable);
4610    {
4611        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4612        Label loopHead(env);
4613        Label loopEnd(env);
4614        Label next(env);
4615        Label loopExit(env);
4616        Jump(&loopHead);
4617        LoopBegin(&loopHead);
4618        {
4619            Label hasProperty(env);
4620            Label hasException0(env);
4621            Label notHasException0(env);
4622            Label useUndefined(env);
4623            Label callDispatch(env);
4624            Label hasException1(env);
4625            Label notHasException1(env);
4626            BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4627            Bind(&next);
4628            GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4629            BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4630            Bind(&hasProperty);
4631            kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4632            BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4633            Bind(&hasException0);
4634            {
4635                result->WriteVariable(Exception());
4636                Jump(exit);
4637            }
4638            Bind(&notHasException0);
4639            {
4640                BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4641                Bind(&useUndefined);
4642                {
4643                    kValue = Undefined();
4644                    Jump(&callDispatch);
4645                }
4646                Bind(&callDispatch);
4647                {
4648                    GateRef key = Int64ToTaggedInt(*i);
4649                    JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4650                    callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4651                    CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
4652                        nullptr, Circuit::NullGate(), callArgs);
4653                    GateRef retValue = callBuilder.JSCallDispatch();
4654                    BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4655                    Bind(&hasException1);
4656                    {
4657                        result->WriteVariable(Exception());
4658                        Jump(exit);
4659                    }
4660
4661                    Bind(&notHasException1);
4662                    {
4663                        Label find(env);
4664                        BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4665                        Bind(&find);
4666                        result->WriteVariable(*kValue);
4667                        Jump(exit);
4668                    }
4669                }
4670            }
4671        }
4672        Bind(&loopEnd);
4673        i = Int64Sub(*i, Int64(1));
4674        LoopEnd(&loopHead);
4675        Bind(&loopExit);
4676        Jump(exit);
4677    }
4678}
4679
4680void BuiltinsArrayStubBuilder::FastCreateArrayWithArgv(GateRef glue, Variable *res, GateRef argc,
4681                                                       GateRef hclass, Label *exit)
4682{
4683    auto env = GetEnvironment();
4684    NewObjectStubBuilder newBuilder(this);
4685    newBuilder.SetParameters(glue, 0);
4686
4687    // create elements from argv
4688    GateRef len = TruncInt64ToInt32(argc);
4689    GateRef elements = newBuilder.NewTaggedArray(glue, len);
4690
4691    // set value
4692    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
4693    DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
4694#if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
4695    DEFVARIABLE(elementKind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::GENERIC)));
4696#else
4697    DEFVARIABLE(elementKind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::HOLE)));
4698#endif
4699    Label loopHead(env);
4700    Label loopEnd(env);
4701    Label setValue(env);
4702    Label loopExit(env);
4703    Jump(&loopHead);
4704    LoopBegin(&loopHead);
4705    {
4706        BRANCH(Int64LessThan(*i, argc), &setValue, &loopExit);
4707        Bind(&setValue);
4708        Label isHole(env);
4709        Label notHole(env);
4710        value = GetArgFromArgv(*i);
4711        elementKind = Int32Or(TaggedToElementKind(*value), *elementKind);
4712        BRANCH(TaggedIsHole(*value), &isHole, &notHole);
4713        Bind(&isHole);
4714        value = TaggedUndefined();
4715        Jump(&notHole);
4716        Bind(&notHole);
4717        SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, *i, *value);
4718        i = Int64Add(*i, Int64(1));
4719        Jump(&loopEnd);
4720    }
4721    Bind(&loopEnd);
4722    LoopEnd(&loopHead);
4723    Bind(&loopExit);
4724
4725    // create array object
4726    GateRef arr = newBuilder.NewJSObject(glue, hclass);
4727    res->WriteVariable(arr);
4728    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
4729    Store(VariableType::INT32(), glue, arr, lengthOffset, len);
4730    GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
4731    SetPropertyInlinedProps(glue, arr, hclass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4732    SetExtensibleToBitfield(glue, arr, true);
4733    SetElementsArray(VariableType::JS_POINTER(), glue, arr, elements);
4734
4735    // set elementkind if needed
4736    Label enabledElementsKind(env);
4737    BRANCH(IsEnableElementsKind(glue), &enabledElementsKind, exit);
4738    Bind(&enabledElementsKind);
4739    CallRuntime(glue, RTSTUB_ID(UpdateHClassForElementsKind), { arr, *elementKind });
4740    Jump(exit);
4741}
4742
4743void BuiltinsArrayStubBuilder::GenArrayConstructor(GateRef glue, GateRef nativeCode,
4744    GateRef func, GateRef newTarget, GateRef thisValue, GateRef numArgs)
4745{
4746    auto env = GetEnvironment();
4747    DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
4748
4749    Label newTargetIsHeapObject(env);
4750    Label newTargetIsJSFunction(env);
4751    Label slowPath(env);
4752    Label slowPath1(env);
4753    Label exit(env);
4754
4755    BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
4756    Bind(&newTargetIsHeapObject);
4757    BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
4758    Bind(&newTargetIsJSFunction);
4759    {
4760        Label fastGetHclass(env);
4761        Label intialHClassIsHClass(env);
4762        GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
4763        GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
4764        auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
4765        BRANCH(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath1);
4766        Bind(&fastGetHclass);
4767        GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
4768        DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0));
4769        BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1);
4770        Bind(&intialHClassIsHClass);
4771        {
4772            Label noArg(env);
4773            Label hasArg(env);
4774            Label arrayCreate(env);
4775            BRANCH(Int64Equal(numArgs, IntPtr(0)), &noArg, &hasArg);
4776            Bind(&noArg);
4777            {
4778                Jump(&arrayCreate);
4779            }
4780            Bind(&hasArg);
4781            {
4782                Label hasOneArg(env);
4783                Label multiArg(env);
4784                BRANCH(Int64Equal(numArgs, IntPtr(1)), &hasOneArg, &multiArg);
4785                Bind(&hasOneArg);
4786                {
4787                    Label argIsNumber(env);
4788                    GateRef arg0 = GetArgFromArgv(IntPtr(0), numArgs, true);
4789                    BRANCH(TaggedIsNumber(arg0), &argIsNumber, &slowPath);
4790                    Bind(&argIsNumber);
4791                    {
4792                        Label argIsInt(env);
4793                        Label argIsDouble(env);
4794                        BRANCH(TaggedIsInt(arg0), &argIsInt, &argIsDouble);
4795                        Bind(&argIsInt);
4796                        {
4797                            Label validIntLength(env);
4798                            GateRef intLen = GetInt64OfTInt(arg0);
4799                            GateRef isGEZero = Int64GreaterThanOrEqual(intLen, Int64(0));
4800                            GateRef isLEMaxLen = Int64LessThanOrEqual(intLen, Int64(JSArray::MAX_ARRAY_INDEX));
4801                            BRANCH(BitAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath);
4802                            Bind(&validIntLength);
4803                            {
4804                                arrayLength = intLen;
4805                                Jump(&arrayCreate);
4806                            }
4807                        }
4808                        Bind(&argIsDouble);
4809                        {
4810                            Label validDoubleLength(env);
4811                            GateRef doubleLength = GetDoubleOfTDouble(arg0);
4812                            GateRef doubleToInt = DoubleToInt(glue, doubleLength);
4813                            GateRef intToDouble = CastInt64ToFloat64(SExtInt32ToInt64(doubleToInt));
4814                            GateRef doubleEqual = DoubleEqual(doubleLength, intToDouble);
4815                            GateRef doubleLEMaxLen =
4816                                DoubleLessThanOrEqual(doubleLength, Double(JSArray::MAX_ARRAY_INDEX));
4817                            BRANCH(BitAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath);
4818                            Bind(&validDoubleLength);
4819                            {
4820                                arrayLength = SExtInt32ToInt64(doubleToInt);
4821                                Jump(&arrayCreate);
4822                            }
4823                        }
4824                    }
4825                }
4826                Bind(&multiArg);
4827                {
4828                    Label lengthValid(env);
4829                    BRANCH(Int64LessThan(numArgs, IntPtr(JSObject::MAX_GAP)), &lengthValid, &slowPath);
4830                    Bind(&lengthValid);
4831                    {
4832                        FastCreateArrayWithArgv(glue, &res, numArgs, intialHClass, &exit);
4833                    }
4834                }
4835            }
4836            Bind(&arrayCreate);
4837            {
4838                Label lengthValid(env);
4839                BRANCH(Int64GreaterThan(*arrayLength, Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid);
4840                Bind(&lengthValid);
4841                {
4842                    NewObjectStubBuilder newBuilder(this);
4843                    newBuilder.SetParameters(glue, 0);
4844                    res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength);
4845                    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
4846                    Store(VariableType::INT32(), glue, *res, lengthOffset, TruncInt64ToInt32(*arrayLength));
4847                    GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
4848                                                              ConstantIndex::ARRAY_LENGTH_ACCESSOR);
4849                    SetPropertyInlinedProps(glue, *res, intialHClass, accessor,
4850                                            Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4851                    SetExtensibleToBitfield(glue, *res, true);
4852                    Jump(&exit);
4853                }
4854            }
4855        }
4856        Bind(&slowPath1);
4857        {
4858            GateRef argv = GetArgv();
4859            res = CallBuiltinRuntimeWithNewTarget(glue,
4860                { glue, nativeCode, func, thisValue, numArgs, argv, newTarget });
4861            Jump(&exit);
4862        }
4863    }
4864    Bind(&slowPath);
4865    {
4866        GateRef argv = GetArgv();
4867        res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true);
4868        Jump(&exit);
4869    }
4870
4871    Bind(&exit);
4872    Return(*res);
4873}
4874
4875void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef numArgs,
4876    Variable *result, Label *exit, Label *slowPath)
4877{
4878    auto env = GetEnvironment();
4879    Label thisExists(env);
4880    Label isHeapObject(env);
4881    Label isJsArray(env);
4882    Label defaultConstr(env);
4883    Label isStability(env);
4884    Label notCOWArray(env);
4885    Label equalCls(env);
4886    Label matchCls(env);
4887    Label isGeneric(env);
4888    BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
4889    Bind(&thisExists);
4890    BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
4891    Bind(&isHeapObject);
4892    BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
4893    Bind(&isJsArray);
4894    BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
4895    Bind(&defaultConstr);
4896    BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
4897    Bind(&isStability);
4898    BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
4899    Bind(&notCOWArray);
4900    GateRef arrayCls = LoadHClass(thisValue);
4901    ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
4902    Bind(&matchCls);
4903    Label arg0HeapObject(env);
4904    Label callable(env);
4905    Label thisIsStable(env);
4906    Label thisNotStable(env);
4907    Label doFlat(env);
4908    GateRef callbackFnHandle = GetCallArg0(numArgs);
4909    BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
4910    Bind(&arg0HeapObject);
4911    BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
4912    Bind(&callable);
4913    GateRef argHandle = GetCallArg1(numArgs);
4914
4915    DEFVARIABLE(i, VariableType::INT64(), Int64(0));
4916    DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4917    DEFVARIABLE(newArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4918    GateRef mappedArray = NewArray(glue, *thisArrLen);
4919    BRANCH(IsStableJSArray(glue, thisValue), &thisIsStable, &thisNotStable);
4920
4921    Bind(&thisIsStable);
4922    {
4923        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4924        Label loopHead(env);
4925        Label loopEnd(env);
4926        Label next(env);
4927        Label loopExit(env);
4928        Jump(&loopHead);
4929        LoopBegin(&loopHead);
4930        {
4931            Label nextStep(env);
4932            Label kValueIsHole(env);
4933            Label callDispatch(env);
4934            Label hasProperty(env);
4935            Label changeNewArrLen(env);
4936            Label hasException0(env);
4937            Label notHasException0(env);
4938            Label hasException1(env);
4939            Label notHasException1(env);
4940            BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
4941            Bind(&nextStep);
4942            BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
4943            Bind(&next);
4944            kValue = GetTaggedValueWithElementsKind(thisValue, *i);
4945            BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
4946            Bind(&kValueIsHole);
4947            {
4948                GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4949                BRANCH(TaggedIsTrue(hasProp), &hasProperty, &changeNewArrLen);
4950                Bind(&hasProperty);
4951                {
4952                    kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4953                    BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
4954                    Bind(&hasException0);
4955                    {
4956                        result->WriteVariable(Exception());
4957                        Jump(exit);
4958                    }
4959                    Bind(&notHasException0);
4960                    {
4961                        BRANCH(TaggedIsHole(*kValue), &changeNewArrLen, &callDispatch);
4962                    }
4963                }
4964                Bind(&changeNewArrLen);
4965                {
4966                    newArrLen = Int64Sub(*newArrLen, Int64(1));
4967                    Jump(&loopEnd);
4968                }
4969            }
4970            Bind(&callDispatch);
4971            {
4972                GateRef key = Int64ToTaggedInt(*i);
4973                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4974                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4975                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4976                    Circuit::NullGate(), callArgs);
4977                GateRef retValue = callBuilder.JSCallDispatch();
4978                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
4979                Bind(&hasException1);
4980                {
4981                    result->WriteVariable(Exception());
4982                    Jump(exit);
4983                }
4984                Bind(&notHasException1);
4985                {
4986                    DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4987                    Label changeThisLen(env);
4988                    Label afterChangeLen(env);
4989                    Label retValueIsHeapObject(env);
4990                    Label retValueIsJsArray(env);
4991                    BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen);
4992                    Bind(&changeThisLen);
4993                    {
4994                        newArrLen = Int64Sub(*newArrLen, Int64Sub(*thisArrLen, *newLen));
4995                        thisArrLen = *newLen;
4996                        Jump(&afterChangeLen);
4997                    }
4998                    Bind(&afterChangeLen);
4999                    {
5000                        SetValueWithElementsKind(glue, mappedArray, retValue, *i, Boolean(true),
5001                            Int32(static_cast<uint32_t>(ElementsKind::NONE)));
5002                        BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &loopEnd);
5003                        Bind(&retValueIsHeapObject);
5004                        {
5005                            BRANCH(IsJsArray(retValue), &retValueIsJsArray, &loopEnd);
5006                        }
5007                        Bind(&retValueIsJsArray);
5008                        {
5009                            GateRef elementsNum =
5010                            ZExtInt32ToInt64(GetNumberOfElements(retValue)); // newArray only contains non-hole elements
5011                            newArrLen = Int64Sub(Int64Add(*newArrLen, elementsNum), Int64(1));
5012                            Jump(&loopEnd);
5013                        }
5014                    }
5015                }
5016            }
5017        }
5018        Bind(&loopEnd);
5019        i = Int64Add(*i, Int64(1));
5020        LoopEnd(&loopHead);
5021        Bind(&loopExit);
5022        Jump(&doFlat);
5023    }
5024
5025    Bind(&thisNotStable);
5026    {
5027        DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
5028        Label loopHead(env);
5029        Label loopEnd(env);
5030        Label next(env);
5031        Label loopExit(env);
5032        Jump(&loopHead);
5033        LoopBegin(&loopHead);
5034        {
5035            Label hasProperty(env);
5036            Label changeNewArrLen(env);
5037            Label hasException0(env);
5038            Label notHasException0(env);
5039            Label callDispatch(env);
5040            Label hasException1(env);
5041            Label notHasException1(env);
5042            BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
5043            Bind(&next);
5044            GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
5045            BRANCH(TaggedIsTrue(hasProp), &hasProperty, &changeNewArrLen);
5046            Bind(&hasProperty);
5047            {
5048                kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
5049                BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
5050                Bind(&hasException0);
5051                {
5052                    result->WriteVariable(Exception());
5053                    Jump(exit);
5054                }
5055                Bind(&notHasException0);
5056                {
5057                    BRANCH(TaggedIsHole(*kValue), &changeNewArrLen, &callDispatch);
5058                }
5059            }
5060            Bind(&changeNewArrLen);
5061            {
5062                newArrLen = Int64Sub(*newArrLen, Int64(1));
5063                Jump(&loopEnd);
5064            }
5065            Bind(&callDispatch);
5066            {
5067                GateRef key = Int64ToTaggedInt(*i);
5068                JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
5069                callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
5070                CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
5071                    Circuit::NullGate(), callArgs);
5072                GateRef retValue = callBuilder.JSCallDispatch();
5073                BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
5074                Bind(&hasException1);
5075                {
5076                    result->WriteVariable(Exception());
5077                    Jump(exit);
5078                }
5079                Bind(&notHasException1);
5080                {
5081                    Label retValueIsHeapObject(env);
5082                    Label retValueIsJsArray(env);
5083                    SetValueWithElementsKind(glue, mappedArray, retValue, *i, Boolean(true),
5084                        Int32(static_cast<uint32_t>(ElementsKind::NONE)));
5085                    BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &loopEnd);
5086                    Bind(&retValueIsHeapObject);
5087                    {
5088                        BRANCH(IsJsArray(retValue), &retValueIsJsArray, &loopEnd);
5089                    }
5090                    Bind(&retValueIsJsArray);
5091                    {
5092                        GateRef elementsNum =
5093                            ZExtInt32ToInt64(GetNumberOfElements(retValue)); // newArray only contains non-hole elements
5094                        newArrLen = Int64Sub(Int64Add(*newArrLen, elementsNum), Int64(1));
5095                        Jump(&loopEnd);
5096                    }
5097                }
5098            }
5099        }
5100        Bind(&loopEnd);
5101        i = Int64Add(*i, Int64(1));
5102        LoopEnd(&loopHead);
5103        Bind(&loopExit);
5104        Jump(&doFlat);
5105    }
5106
5107    Bind(&doFlat);
5108    {
5109        i = Int64(0);
5110        DEFVARIABLE(j, VariableType::INT64(), Int64(0));
5111        DEFVARIABLE(retValueItem, VariableType::JS_ANY(), Hole());
5112        GateRef newArray = NewArray(glue, *newArrLen);
5113        Label loopHead2(env);
5114        Label loopEnd2(env);
5115        Label next2(env);
5116        Label loopExit2(env);
5117        Jump(&loopHead2);
5118        LoopBegin(&loopHead2);
5119        {
5120            Label nextStep(env);
5121            Label retValueIsHeapObject(env);
5122            Label retValueIsJsArray(env);
5123            Label retValueIsNotJsArray(env);
5124            BRANCH(Int64LessThan(*i, *thisArrLen), &next2, &loopExit2);
5125            Bind(&next2);
5126            GateRef retValue = GetTaggedValueWithElementsKind(mappedArray, *i);
5127            BRANCH(TaggedIsHole(retValue), &loopEnd2, &nextStep);
5128            Bind(&nextStep);
5129            BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &retValueIsNotJsArray);
5130            Bind(&retValueIsHeapObject);
5131            {
5132                BRANCH(IsJsArray(retValue), &retValueIsJsArray, &retValueIsNotJsArray);
5133                Bind(&retValueIsJsArray);
5134                {
5135                    Label retValueIsStableArray(env);
5136                    Label retValueNotStableArray(env);
5137                    GateRef retValueIsStable = IsStableJSArray(glue, retValue);
5138                    GateRef arrLen = ZExtInt32ToInt64(GetArrayLength(retValue));
5139                    DEFVARIABLE(k, VariableType::INT64(), Int64(0));
5140                    Label loopHead3(env);
5141                    Label loopEnd3(env);
5142                    Label next3(env);
5143                    Label loopExit3(env);
5144                    Label setValue(env);
5145                    Label itemExist(env);
5146                    Jump(&loopHead3);
5147                    LoopBegin(&loopHead3);
5148                    {
5149                        BRANCH(Int64LessThan(*k, arrLen), &next3, &loopExit3);
5150                        Bind(&next3);
5151                        BRANCH(retValueIsStable, &retValueIsStableArray, &retValueNotStableArray);
5152                        Bind(&retValueIsStableArray);
5153                        retValueItem = GetTaggedValueWithElementsKind(retValue, *k);
5154                        BRANCH(TaggedIsHole(*retValueItem), &loopEnd3, &setValue);
5155                        Bind(&retValueNotStableArray);
5156                        GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { retValue, IntToTaggedInt(*k) });
5157                        BRANCH(TaggedIsTrue(hasProp), &itemExist, &loopEnd3);
5158                        Bind(&itemExist);
5159                        retValueItem =
5160                            FastGetPropertyByIndex(glue, retValue, TruncInt64ToInt32(*k), ProfileOperation());
5161                        Jump(&setValue);
5162                        Bind(&setValue);
5163                        SetValueWithElementsKind(glue, newArray, *retValueItem, *j, Boolean(true),
5164                            Int32(static_cast<uint32_t>(ElementsKind::NONE)));
5165                        j = Int64Add(*j, Int64(1));
5166                        Jump(&loopEnd3);
5167                    }
5168                    Bind(&loopEnd3);
5169                    k = Int64Add(*k, Int64(1));
5170                    LoopEnd(&loopHead3);
5171                    Bind(&loopExit3);
5172                    Jump(&loopEnd2);
5173                }
5174            }
5175            Bind(&retValueIsNotJsArray);
5176            {
5177                SetValueWithElementsKind(glue, newArray, retValue, *j, Boolean(true),
5178                    Int32(static_cast<uint32_t>(ElementsKind::NONE)));
5179                j = Int64Add(*j, Int64(1));
5180                Jump(&loopEnd2);
5181            }
5182        }
5183        Bind(&loopEnd2);
5184        i = Int64Add(*i, Int64(1));
5185        LoopEnd(&loopHead2);
5186        Bind(&loopExit2);
5187        result->WriteVariable(newArray);
5188        Jump(exit);
5189    }
5190}
5191
5192void BuiltinsArrayStubBuilder::IsArray([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef thisValue,
5193    GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
5194{
5195    auto env = GetEnvironment();
5196    GateRef obj = GetCallArg0(numArgs);
5197    Label isHeapObj(env);
5198    Label notHeapObj(env);
5199    BRANCH(TaggedIsHeapObject(obj), &isHeapObj, &notHeapObj);
5200    Bind(&isHeapObj);
5201    {
5202        Label isJSArray(env);
5203        Label notJSArray(env);
5204        GateRef objectType = GetObjectType(LoadHClass(obj));
5205        BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))), &isJSArray, &notJSArray);
5206        Bind(&isJSArray);
5207        {
5208            result->WriteVariable(TaggedTrue());
5209            Jump(exit);
5210        }
5211        Bind(&notJSArray);
5212        BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_PROXY))), slowPath, &notHeapObj);
5213    }
5214    Bind(&notHeapObj);
5215    {
5216        result->WriteVariable(TaggedFalse());
5217        Jump(exit);
5218    }
5219}
5220}  // namespace panda::ecmascript::kungfu
5221