1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/compiler/new_object_stub_builder.h"
17
18#include "ecmascript/compiler/builtins/builtins_function_stub_builder.h"
19#include "ecmascript/compiler/builtins/builtins_proxy_stub_builder.h"
20#include "ecmascript/compiler/number_gate_info.h"
21#include "ecmascript/compiler/stub_builder-inl.h"
22#include "ecmascript/compiler/stub_builder.h"
23#include "ecmascript/ecma_string.h"
24#include "ecmascript/global_env.h"
25#include "ecmascript/global_env_constants.h"
26#include "ecmascript/js_arguments.h"
27#include "ecmascript/js_object.h"
28#include "ecmascript/js_thread.h"
29#include "ecmascript/lexical_env.h"
30#include "ecmascript/mem/mem.h"
31#include "ecmascript/js_array_iterator.h"
32#include "ecmascript/js_map_iterator.h"
33#include "ecmascript/js_set_iterator.h"
34#include "ecmascript/js_set.h"
35#include "ecmascript/js_map.h"
36
37namespace panda::ecmascript::kungfu {
38void NewObjectStubBuilder::NewLexicalEnv(Variable *result, Label *exit, GateRef numSlots, GateRef parent)
39{
40    auto env = GetEnvironment();
41
42    auto length = Int32Add(numSlots, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
43    size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length));
44    // Be careful. NO GC is allowed when initization is not complete.
45    Label hasPendingException(env);
46    Label noException(env);
47    auto hclass = GetGlobalConstantValue(
48        VariableType::JS_POINTER(), glue_, ConstantIndex::ENV_CLASS_INDEX);
49    AllocateInYoung(result, &hasPendingException, &noException, hclass);
50    Bind(&noException);
51    {
52        StoreHClass(glue_, result->ReadVariable(), hclass);
53        Label afterInitialize(env);
54        InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
55            result->ReadVariable(), Hole(), Int32(LexicalEnv::RESERVED_ENV_LENGTH), length);
56        Bind(&afterInitialize);
57        SetValueToTaggedArray(VariableType::INT64(),
58            glue_, result->ReadVariable(), Int32(LexicalEnv::SCOPE_INFO_INDEX), Hole());
59        SetValueToTaggedArray(VariableType::JS_POINTER(),
60            glue_, result->ReadVariable(), Int32(LexicalEnv::PARENT_ENV_INDEX), parent);
61        Jump(exit);
62    }
63    Bind(&hasPendingException);
64    {
65        Jump(exit);
66    }
67}
68
69GateRef NewObjectStubBuilder::NewJSArrayWithSize(GateRef hclass, GateRef size)
70{
71    auto env = GetEnvironment();
72    Label entry(env);
73    Label exit(env);
74    env->SubCfgEntry(&entry);
75
76    GateRef result = NewJSObject(glue_, hclass);
77    Label enabledElementsKind(env);
78    Label notEmptyArray(env);
79    Label initObj(env);
80    GateRef isElementsKindEnabled = IsEnableElementsKind(glue_);
81    BRANCH(isElementsKindEnabled, &enabledElementsKind, &initObj);
82    Bind(&enabledElementsKind);
83    {
84        // For new Array(Len), the elementsKind should be Hole
85        BRANCH(Equal(TruncInt64ToInt32(size), Int32(0)), &initObj, &notEmptyArray);
86        Bind(&notEmptyArray);
87        {
88            #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
89            GateRef holeKindArrayClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue_,
90                                                                ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX);
91            StoreHClass(glue_, result, holeKindArrayClass);
92            #else
93            GateRef holeKindArrayClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue_,
94                                                                ConstantIndex::ELEMENT_HOLE_HCLASS_INDEX);
95            StoreHClass(glue_, result, holeKindArrayClass);
96            #endif
97            Jump(&initObj);
98        }
99    }
100    Bind(&initObj);
101    DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
102    NewTaggedArrayChecked(&array, TruncInt64ToInt32(size), &exit);
103    Bind(&exit);
104    auto arrayRet = *array;
105    env->SubCfgExit();
106    SetElementsArray(VariableType::JS_POINTER(), glue_, result, arrayRet);
107    return result;
108}
109
110GateRef NewObjectStubBuilder::NewJSFunctionByHClass(GateRef glue,
111    GateRef method, GateRef hclass, FunctionKind targetKind)
112{
113    GateRef result = NewJSObject(glue, hclass);
114    SetExtensibleToBitfield(glue, hclass, true);
115    GateRef kind = GetFuncKind(method);
116    BuiltinsFunctionStubBuilder builtinsFunctionStubBuilder(this);
117    builtinsFunctionStubBuilder.InitializeJSFunction(glue, result, kind, targetKind);
118    builtinsFunctionStubBuilder.InitializeFunctionWithMethod(glue, result, method, hclass);
119    return result;
120}
121
122GateRef NewObjectStubBuilder::NewSFunctionByHClass(GateRef glue,
123    GateRef method, GateRef hclass, FunctionKind targetKind)
124{
125    GateRef result = result = NewSObject(glue, hclass);
126    GateRef kind = GetFuncKind(method);
127    BuiltinsFunctionStubBuilder builtinsFunctionStubBuilder(this);
128    builtinsFunctionStubBuilder.InitializeSFunction(glue, result, kind, targetKind);
129    builtinsFunctionStubBuilder.InitializeFunctionWithMethod(glue, result, method, hclass);
130    return result;
131}
132
133GateRef NewObjectStubBuilder::CloneJSFunction(GateRef glue, GateRef value)
134{
135    GateRef hclass = LoadHClass(value);
136    GateRef method = GetMethodFromFunction(value);
137    GateRef cloneFunc = NewJSFunctionByHClass(glue, method, hclass);
138    GateRef length = GetPropertyInlinedProps(value, hclass,
139                                             Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX));
140    SetPropertyInlinedProps(glue, value, hclass, length,
141                            Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX),
142                            VariableType::JS_ANY());
143    SetLengthToFunction(glue, cloneFunc, GetLengthFromFunction(value));
144    SetModuleToFunction(glue, cloneFunc, GetModuleFromFunction(value));
145    return cloneFunc;
146}
147
148GateRef NewObjectStubBuilder::CloneProperties(GateRef glue, GateRef currentEnv,
149    GateRef elements, GateRef obj)
150{
151    auto env = GetEnvironment();
152    Label entry(env);
153    env->SubCfgEntry(&entry);
154    Label exit(env);
155    Label isZero(env);
156    Label notZero(env);
157    Label initialize(env);
158    Label afterInitialize(env);
159    Label begin(env);
160    Label body(env);
161    Label isJSFunction(env);
162    Label notJSFunction(env);
163    Label endLoop(env);
164    Label isJSFCondition(env);
165
166    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
167    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
168    GateRef length = GetLengthOfTaggedArray(elements);
169    BRANCH(Int32Equal(length, Int32(0)), &isZero, &notZero);
170    Bind(&isZero);
171    {
172        result = GetEmptyArray(glue);
173        Jump(&exit);
174    }
175    Bind(&notZero);
176    {
177        GateRef hclass = LoadHClass(elements);
178        size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length));
179        HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
180    }
181    Bind(&initialize);
182    {
183        GateRef hclass = LoadHClass(elements);
184        Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass);
185        InitializeTaggedArrayWithSpeicalValue(&afterInitialize, result.ReadVariable(), Hole(), Int32(0), length);
186    }
187    Bind(&afterInitialize);
188    {
189        Jump(&begin);
190    }
191    LoopBegin(&begin);
192    {
193        BRANCH(Int32UnsignedLessThan(*i, length), &body, &exit);
194        Bind(&body);
195        {
196            GateRef value = GetValueFromTaggedArray(elements, *i);
197            BRANCH(TaggedIsHeapObject(value), &isJSFCondition, &notJSFunction);
198            Bind(&isJSFCondition);
199            {
200                BRANCH(IsJSFunction(value), &isJSFunction, &notJSFunction);
201            }
202            Bind(&isJSFunction);
203            {
204                GateRef newFunc = CloneJSFunction(glue, value);
205                SetLexicalEnvToFunction(glue, newFunc, currentEnv);
206                SetHomeObjectToFunction(glue, newFunc, obj);
207                SetValueToTaggedArray(VariableType::JS_ANY(), glue, *result, *i, newFunc);
208                Jump(&endLoop);
209            }
210            Bind(&notJSFunction);
211            {
212                SetValueToTaggedArray(VariableType::JS_ANY(), glue, *result, *i, value);
213                Jump(&endLoop);
214            }
215            Bind(&endLoop);
216            i = Int32Add(*i, Int32(1));
217            LoopEnd(&begin);
218        }
219    }
220
221    Bind(&exit);
222    auto ret = *result;
223    env->SubCfgExit();
224    return ret;
225}
226
227GateRef NewObjectStubBuilder::NewAccessorData(GateRef glue)
228{
229    auto env = GetEnvironment();
230    Label entry(env);
231    env->SubCfgEntry(&entry);
232    Label exit(env);
233    Label noException(env);
234
235    GateRef hclass = GetGlobalConstantValue(
236        VariableType::JS_POINTER(), glue, ConstantIndex::ACCESSOR_DATA_CLASS_INDEX);
237    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
238    size_ = GetObjectSizeFromHClass(hclass);
239    HeapAlloc(&result, &noException, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
240    Bind(&noException);
241    {
242        Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass);
243        Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::GETTER_OFFSET), Undefined());
244        Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::SETTER_OFFSET), Undefined());
245        Jump(&exit);
246    }
247
248    Bind(&exit);
249    auto ret = *result;
250    env->SubCfgExit();
251    return ret;
252}
253
254GateRef NewObjectStubBuilder::CloneObjectLiteral(GateRef glue, GateRef literal, GateRef currentEnv)
255{
256    auto env = GetEnvironment();
257    Label entry(env);
258    env->SubCfgEntry(&entry);
259    // canShareHClass is true default
260    GateRef hclass = LoadHClass(literal);
261    Label exit(env);
262    Label less(env);
263    Label greater(env);
264    Label startLoop(env);
265    Label begin(env);
266    Label body(env);
267    Label isTaggedRep(env);
268    Label notTaggedRep(env);
269    Label isJSFunction(env);
270    Label notJSFunction(env);
271    Label endLoop(env);
272    Label isAccessorData(env);
273    Label notAccessorData(env);
274    Label middleCondition(env);
275    Label isJSFCondition(env);
276    Label isACCCondition(env);
277    Label isAccessorJudgment(env);
278
279    DEFVARIABLE(length, VariableType::INT32(), Int32(0));
280    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
281    DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
282    GateRef result = NewJSObject(glue, hclass);
283
284    GateRef elements = GetElementsArray(literal);
285    GateRef newElements = CloneProperties(glue, currentEnv, elements, result);
286    SetElementsArray(VariableType::JS_ANY(), glue, result, newElements);
287
288    GateRef properties = GetPropertiesArray(literal);
289    GateRef newProperties = CloneProperties(glue, currentEnv, properties, result);
290    SetPropertiesArray(VariableType::JS_ANY(), glue, result, newProperties);
291
292    GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
293    GateRef numberOfProps = GetNumberOfPropsFromHClass(hclass);
294    BRANCH(Int32UnsignedLessThan(inlineProps, numberOfProps), &less, &greater);
295    Bind(&less);
296    {
297        length = inlineProps;
298        Jump(&startLoop);
299    }
300    Bind(&greater);
301    {
302        length = numberOfProps;
303        Jump(&startLoop);
304    }
305    Bind(&startLoop);
306    {
307        Jump(&begin);
308    }
309    LoopBegin(&begin);
310    {
311        BRANCH(Int32UnsignedLessThan(*i, *length), &body, &exit);
312        Bind(&body);
313        {
314            GateRef layout = GetLayoutFromHClass(hclass);
315            value = GetPropertyInlinedProps(literal, hclass, *i);
316            GateRef attr = GetPropAttrFromLayoutInfo(layout, *i);
317            BRANCH(BoolNot(IsTaggedRepInPropAttr(attr)), &notTaggedRep, &middleCondition);
318        }
319        Bind(&middleCondition);
320        {
321            BRANCH(TaggedIsHeapObject(*value), &isJSFCondition, &isTaggedRep);
322        }
323        Bind(&isJSFCondition);
324        {
325            BRANCH(IsJSFunction(*value), &isJSFunction, &isAccessorJudgment);
326        }
327        Bind(&isAccessorJudgment);
328        {
329            BRANCH(Int32Equal(GetObjectType(LoadHClass(*value)), Int32(static_cast<int32_t>(JSType::ACCESSOR_DATA))),
330                &isAccessorData, &isTaggedRep);
331        }
332        Bind(&isJSFunction);
333        {
334            GateRef newFunc = CloneJSFunction(glue, *value);
335            SetLexicalEnvToFunction(glue, newFunc, currentEnv);
336            SetHomeObjectToFunction(glue, newFunc, result);
337            SetPropertyInlinedProps(glue, result, hclass, newFunc, *i,
338                VariableType::JS_ANY());
339            Jump(&endLoop);
340        }
341        Bind(&isAccessorData);
342        {
343            auto objLiteral = NewAccessorData(glue);
344            value = objLiteral;
345            Jump(&isTaggedRep);
346        }
347        Bind(&notTaggedRep);
348        {
349            SetPropertyInlinedProps(glue, result, hclass, *value, *i,
350                VariableType::JS_ANY(), MemoryAttribute::NoBarrier());
351            Jump(&endLoop);
352        }
353        Bind(&isTaggedRep);
354        {
355            SetPropertyInlinedProps(glue, result, hclass, *value, *i);
356            Jump(&endLoop);
357        }
358        Bind(&endLoop);
359        i = Int32Add(*i, Int32(1));
360        LoopEnd(&begin);
361    }
362    Bind(&exit);
363    auto ret = result;
364    env->SubCfgExit();
365    return ret;
366}
367
368GateRef NewObjectStubBuilder::CreateObjectHavingMethod(GateRef glue, GateRef literal, GateRef currentEnv)
369{
370    auto env = GetEnvironment();
371    Label entry(env);
372    env->SubCfgEntry(&entry);
373    Label isPendingException(env);
374    Label exit(env);
375    auto objLiteral = CloneObjectLiteral(glue, literal, currentEnv);
376    DEFVARIABLE(result, VariableType::JS_ANY(), objLiteral);
377    BRANCH(HasPendingException(glue), &isPendingException, &exit);
378    Bind(&isPendingException);
379    {
380        result = Exception();
381        Jump(&exit);
382    }
383    Bind(&exit);
384    auto ret = *result;
385    env->SubCfgExit();
386    return ret;
387}
388
389void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass)
390{
391    auto env = GetEnvironment();
392
393    size_ = GetObjectSizeFromHClass(hclass);
394    // Be careful. NO GC is allowed when initization is not complete.
395    Label hasPendingException(env);
396    Label noException(env);
397    AllocateInYoung(result, &hasPendingException, &noException, hclass);
398    Bind(&noException);
399    {
400        StoreHClass(glue_, result->ReadVariable(), hclass);
401        DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
402        Label isTS(env);
403        Label initialize(env);
404        BRANCH(IsTSHClass(hclass), &isTS, &initialize);
405        Bind(&isTS);
406        {
407            // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist,
408            // to follow ECMA spec.
409            initValue = Hole();
410            Jump(&initialize);
411        }
412        Bind(&initialize);
413        Label afterInitialize(env);
414        InitializeWithSpeicalValue(&afterInitialize,
415            result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_),
416            MemoryAttribute::NoBarrier());
417        Bind(&afterInitialize);
418        auto emptyArray = GetGlobalConstantValue(
419            VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
420        SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
421        SetPropertiesArray(VariableType::INT64(),
422                           glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
423        SetElementsArray(VariableType::INT64(),
424                         glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
425        Jump(exit);
426    }
427    Bind(&hasPendingException);
428    {
429        Jump(exit);
430    }
431}
432
433void NewObjectStubBuilder::NewSObject(Variable *result, Label *exit, GateRef hclass)
434{
435    auto env = GetEnvironment();
436
437    size_ = GetObjectSizeFromHClass(hclass);
438    Label afterAllocate(env);
439    AllocateInSOld(result, &afterAllocate, hclass);
440    Bind(&afterAllocate);
441    {
442        StoreHClass(glue_, result->ReadVariable(), hclass);
443        DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
444        Label isTS(env);
445        Label initialize(env);
446        BRANCH(IsTSHClass(hclass), &isTS, &initialize);
447        Bind(&isTS);
448        {
449            // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist,
450            // to follow ECMA spec.
451            initValue = Hole();
452            Jump(&initialize);
453        }
454        Bind(&initialize);
455        Label afterInitialize(env);
456        InitializeWithSpeicalValue(&afterInitialize,
457            result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_),
458            MemoryAttribute::NoBarrier());
459        Bind(&afterInitialize);
460        auto emptyArray = GetGlobalConstantValue(
461            VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
462        SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
463        SetPropertiesArray(VariableType::INT64(),
464                           glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
465        SetElementsArray(VariableType::INT64(),
466                         glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
467        Jump(exit);
468    }
469}
470
471GateRef NewObjectStubBuilder::NewJSProxy(GateRef glue, GateRef target, GateRef handler)
472{
473    auto env = GetEnvironment();
474    Label entry(env);
475    env->SubCfgEntry(&entry);
476    Label exit(env);
477    Label isCallable(env);
478    Label notCallable(env);
479    Label noException(env);
480    Label allocateProxy(env);
481
482    DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
483    DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
484    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
485    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
486    GateRef objectFunctionPrototype = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
487                                                        GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX);
488    GateRef emptyObject = OrdinaryNewJSObjectCreate(glue, objectFunctionPrototype);
489    BRANCH(IsCallable(target), &isCallable, &notCallable);
490    Bind(&isCallable);
491    {
492        Label isConstructor(env);
493        Label notConstructor(env);
494        BRANCH(IsConstructor(target), &isConstructor, &notConstructor);
495        Bind(&isConstructor);
496        {
497            hclass = GetGlobalConstantValue(
498                VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_CONSTRUCT_CLASS_INDEX);
499            Jump(&allocateProxy);
500        }
501        Bind(&notConstructor);
502        {
503            hclass = GetGlobalConstantValue(
504                VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_CALLABLE_CLASS_INDEX);
505            Jump(&allocateProxy);
506        }
507    }
508    Bind(&notCallable);
509    {
510        hclass = GetGlobalConstantValue(
511            VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_ORDINARY_CLASS_INDEX);
512        Jump(&allocateProxy);
513    }
514    Bind(&allocateProxy);
515    {
516        size_ = GetObjectSizeFromHClass(*hclass);
517        AllocateInYoung(&result, &exit, &noException, *hclass);
518    }
519    Bind(&noException);
520    {
521        GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
522        Store(VariableType::INT64(), glue, *result, hashOffset, Int64(JSTaggedValue(0).GetRawData()));
523        GateRef proxyMethod = GetGlobalConstantValue(
524            VariableType::JS_POINTER(), glue, ConstantIndex::PROXY_METHOD_INDEX);
525        StoreHClassWithoutBarrier(glue_, *result, *hclass);
526        BuiltinsProxyStubBuilder builtinsProxyStubBuilder(this);
527        builtinsProxyStubBuilder.SetMethod(glue, *result, proxyMethod);
528        builtinsProxyStubBuilder.SetTarget(glue, *result, target);
529        builtinsProxyStubBuilder.SetHandler(glue, *result, handler);
530        builtinsProxyStubBuilder.SetPrivateField(glue, *result, emptyObject);
531        builtinsProxyStubBuilder.SetIsRevoked(glue, *result, False());
532        Jump(&exit);
533    }
534    Bind(&exit);
535    auto ret = *result;
536    env->SubCfgExit();
537    return ret;
538}
539
540void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass, GateRef size)
541{
542    auto env = GetEnvironment();
543    size_ = size;
544    Label initialize(env);
545    HeapAlloc(result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
546    Bind(&initialize);
547    StoreHClassWithoutBarrier(glue_, result->ReadVariable(), hclass);
548    DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
549    Label afterInitialize(env);
550    InitializeWithSpeicalValue(&afterInitialize,
551        result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_),
552        MemoryAttribute::NoBarrier());
553    Bind(&afterInitialize);
554    auto emptyArray = GetGlobalConstantValue(
555        VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
556    SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
557    SetPropertiesArray(VariableType::INT64(),
558                       glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
559    SetElementsArray(VariableType::INT64(),
560                     glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
561    Jump(exit);
562}
563
564GateRef NewObjectStubBuilder::NewJSObject(GateRef glue, GateRef hclass)
565{
566    auto env = GetEnvironment();
567    Label entry(env);
568    env->SubCfgEntry(&entry);
569    Label exit(env);
570
571    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
572    SetGlue(glue);
573    NewJSObject(&result, &exit, hclass);
574
575    Bind(&exit);
576    auto ret = *result;
577    env->SubCfgExit();
578    return ret;
579}
580
581GateRef NewObjectStubBuilder::NewSObject(GateRef glue, GateRef hclass)
582{
583    auto env = GetEnvironment();
584    Label entry(env);
585    env->SubCfgEntry(&entry);
586    Label exit(env);
587
588    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
589    SetGlue(glue);
590    NewSObject(&result, &exit, hclass);
591
592    Bind(&exit);
593    auto ret = *result;
594    env->SubCfgExit();
595    return ret;
596}
597
598void NewObjectStubBuilder::NewTaggedArrayChecked(Variable *result, GateRef len, Label *exit)
599{
600    auto env = GetEnvironment();
601    Label overflow(env);
602    Label notOverflow(env);
603    BRANCH(Int32UnsignedGreaterThan(len, Int32(INT32_MAX)), &overflow, &notOverflow);
604    Bind(&overflow);
605    {
606        GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax));
607        CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
608        result->WriteVariable(Exception());
609        Jump(exit);
610    }
611    Bind(&notOverflow);
612    size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len));
613    // Be careful. NO GC is allowed when initization is not complete.
614    Label noException(env);
615    auto hclass = GetGlobalConstantValue(
616        VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_CLASS_INDEX);
617    AllocateInYoung(result, exit, &noException, hclass);
618    Bind(&noException);
619    {
620        StoreBuiltinHClass(glue_, result->ReadVariable(), hclass);
621        Label afterInitialize(env);
622        InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
623            result->ReadVariable(), Hole(), Int32(0), len);
624        Bind(&afterInitialize);
625        Jump(exit);
626    }
627}
628
629void NewObjectStubBuilder::NewMutantTaggedArrayChecked(Variable *result, GateRef len, Label *exit)
630{
631    auto env = GetEnvironment();
632    size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len));
633    Label afterAllocate(env);
634    auto hclass = GetGlobalConstantValue(
635        VariableType::JS_POINTER(), glue_, ConstantIndex::MUTANT_TAGGED_ARRAY_CLASS_INDEX);
636    // Be careful. NO GC is allowed when initization is not complete.
637    AllocateInYoung(result, &afterAllocate, hclass);
638    Bind(&afterAllocate);
639    Label noException(env);
640    BRANCH(TaggedIsException(result->ReadVariable()), exit, &noException);
641    Bind(&noException);
642    {
643        StoreHClass(glue_, result->ReadVariable(), hclass);
644        Label afterInitialize(env);
645        InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
646            result->ReadVariable(), SpecialHole(), Int32(0), len);
647        Bind(&afterInitialize);
648        Jump(exit);
649    }
650}
651
652GateRef NewObjectStubBuilder::NewTaggedArray(GateRef glue, GateRef len)
653{
654    auto env = GetEnvironment();
655    Label entry(env);
656    env->SubCfgEntry(&entry);
657    Label exit(env);
658    Label isEmpty(env);
659    Label notEmpty(env);
660
661    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
662    SetGlue(glue);
663    BRANCH(Int32Equal(len, Int32(0)), &isEmpty, &notEmpty);
664    Bind(&isEmpty);
665    {
666        result = GetGlobalConstantValue(
667            VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
668        Jump(&exit);
669    }
670    Bind(&notEmpty);
671    {
672        Label next(env);
673        Label slowPath(env);
674        BRANCH(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath);
675        Bind(&next);
676        {
677            NewTaggedArrayChecked(&result, len, &exit);
678        }
679        Bind(&slowPath);
680        {
681            result = CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(len) });
682            Jump(&exit);
683        }
684    }
685
686    Bind(&exit);
687    auto ret = *result;
688    env->SubCfgExit();
689    return ret;
690}
691
692GateRef NewObjectStubBuilder::NewMutantTaggedArray(GateRef glue, GateRef len)
693{
694    auto env = GetEnvironment();
695    Label entry(env);
696    env->SubCfgEntry(&entry);
697    Label exit(env);
698    Label isEmpty(env);
699    Label notEmpty(env);
700
701    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
702    SetGlue(glue);
703    BRANCH(Int32Equal(len, Int32(0)), &isEmpty, &notEmpty);
704    Bind(&isEmpty);
705    {
706        result = GetGlobalConstantValue(
707            VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
708        Jump(&exit);
709    }
710    Bind(&notEmpty);
711    {
712        Label next(env);
713        Label slowPath(env);
714        BRANCH(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath);
715        Bind(&next);
716        {
717            NewMutantTaggedArrayChecked(&result, len, &exit);
718        }
719        Bind(&slowPath);
720        {
721            result = CallRuntime(glue_, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedInt(len) });
722            Jump(&exit);
723        }
724    }
725
726    Bind(&exit);
727    auto ret = *result;
728    env->SubCfgExit();
729    return ret;
730}
731
732void NewObjectStubBuilder::ExtendArray(Variable *res, GateRef glue, GateRef elements,
733                                       GateRef newLen, Label *exit, RegionSpaceFlag spaceType, bool isMutantArray)
734{
735    auto env = GetEnvironment();
736    SetGlue(glue);
737    DEFVARIABLE(index, VariableType::INT32(), Int32(0));
738    DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
739    size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(newLen));
740    // Be careful. NO GC is allowed when initization is not complete.
741    Label allocArray(env);
742    Label afterAllocate(env);
743    auto hclass = GetGlobalConstantValue(
744        VariableType::JS_POINTER(), glue_,
745        isMutantArray ? ConstantIndex::MUTANT_TAGGED_ARRAY_CLASS_INDEX : ConstantIndex::ARRAY_CLASS_INDEX);
746    HeapAlloc(&array, &allocArray, spaceType, hclass);
747    Bind(&allocArray);
748    {
749        StoreBuiltinHClass(glue_, array.ReadVariable(), hclass);
750        InitializeTaggedArrayWithSpeicalValue(&afterAllocate,
751            array.ReadVariable(), isMutantArray ? SpecialHole() : Hole(), Int32(0), newLen);
752    }
753    Bind(&afterAllocate);
754    Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen);
755    GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements);
756    Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
757    GateRef oldL = GetLengthOfTaggedArray(elements);
758    Label loopHead(env);
759    Label loopEnd(env);
760    Label afterLoop(env);
761    Label storeValue(env);
762    Jump(&loopHead);
763    LoopBegin(&loopHead);
764    {
765        BRANCH(Int32UnsignedLessThan(*index, oldL), &storeValue, &afterLoop);
766        Bind(&storeValue);
767        {
768            if (isMutantArray) {
769                GateRef value = GetValueFromMutantTaggedArray(elements, *index);
770                SetValueToTaggedArray(VariableType::INT64(), glue, *array, *index, value);
771            } else {
772                GateRef value = GetValueFromTaggedArray(elements, *index);
773                SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, *index, value);
774            }
775            index = Int32Add(*index, Int32(1));
776            Jump(&loopEnd);
777        }
778    }
779    Bind(&loopEnd);
780    LoopEnd(&loopHead, env, glue);
781    Bind(&afterLoop);
782    {
783        *res = *array;
784        Jump(exit);
785    }
786}
787
788GateRef NewObjectStubBuilder::ExtendArrayCheck(GateRef glue, GateRef elements, GateRef newLen,
789                                               RegionSpaceFlag spaceType)
790{
791    auto env = GetEnvironment();
792    Label subEntry(env);
793    env->SubCfgEntry(&subEntry);
794    SetGlue(glue);
795    Label extendMutantArray(env);
796    Label extendNormalArray(env);
797    Label exit(env);
798    DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
799    BRANCH(IsMutantTaggedArray(elements),
800        &extendMutantArray, &extendNormalArray);
801    Bind(&extendNormalArray);
802    ExtendArray(&res, glue, elements, newLen, &exit, spaceType);
803    Bind(&extendMutantArray);
804    ExtendArray(&res, glue, elements, newLen, &exit, spaceType, true);
805    Bind(&exit);
806    auto ret = *res;
807    env->SubCfgExit();
808    return ret;
809}
810
811GateRef NewObjectStubBuilder::CopyArray(GateRef glue, GateRef elements, GateRef oldLen,
812                                        GateRef newLen, RegionSpaceFlag spaceType)
813{
814    auto env = GetEnvironment();
815    Label subEntry(env);
816    env->SubCfgEntry(&subEntry);
817    Label exit(env);
818    DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
819    NewObjectStubBuilder newBuilder(this);
820    Label emptyArray(env);
821    Label notEmptyArray(env);
822    BRANCH(Int32Equal(newLen, Int32(0)), &emptyArray, &notEmptyArray);
823    Bind(&emptyArray);
824    result = GetEmptyArray(glue);
825    Jump(&exit);
826    Bind(&notEmptyArray);
827    {
828        Label extendArray(env);
829        Label notExtendArray(env);
830        BRANCH(Int32GreaterThan(newLen, oldLen), &extendArray, &notExtendArray);
831        Bind(&extendArray);
832        {
833            result = ExtendArrayCheck(glue, elements, newLen, spaceType);
834            Jump(&exit);
835        }
836        Bind(&notExtendArray);
837        {
838            DEFVARIABLE(array, VariableType::JS_ANY(), elements);
839            Label isMutantTaggedArray(env);
840            Label isNotMutantTaggedArray(env);
841            Label afterInitializeElements(env);
842            GateRef checkIsMutantTaggedArray = IsMutantTaggedArray(*array);
843            BRANCH(checkIsMutantTaggedArray, &isMutantTaggedArray, &isNotMutantTaggedArray);
844            Bind(&isMutantTaggedArray);
845            {
846                array = newBuilder.NewMutantTaggedArray(glue, newLen);
847                Jump(&afterInitializeElements);
848            }
849            Bind(&isNotMutantTaggedArray);
850            {
851                array = newBuilder.NewTaggedArray(glue, newLen);
852                Jump(&afterInitializeElements);
853            }
854            Bind(&afterInitializeElements);
855            Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen);
856            GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements);
857            Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
858            Label afterCopy(env);
859
860            Label copyToTaggedArray(env);
861            Label copyToMutantTaggedArray(env);
862            BRANCH(checkIsMutantTaggedArray, &copyToMutantTaggedArray, &copyToTaggedArray);
863            Bind(&copyToTaggedArray);
864            {
865                ArrayCopy<NotOverlap>(glue, GetDataPtrInTaggedArray(elements), GetDataPtrInTaggedArray(*array),
866                                      newLen);
867                Jump(&afterCopy);
868            }
869            Bind(&copyToMutantTaggedArray);
870            {
871                ArrayCopy<NotOverlap>(glue, GetDataPtrInTaggedArray(elements), GetDataPtrInTaggedArray(*array), newLen,
872                                      MemoryAttribute::NoBarrier());
873                Jump(&afterCopy);
874            }
875            Bind(&afterCopy);
876            {
877                result = *array;
878                Jump(&exit);
879            }
880        }
881    }
882    Bind(&exit);
883    auto ret = *result;
884    env->SubCfgExit();
885    return ret;
886}
887
888GateRef NewObjectStubBuilder::NewJSForinIterator(GateRef glue, GateRef receiver, GateRef keys, GateRef cachedHclass)
889{
890    auto env = GetEnvironment();
891    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
892    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
893    GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FOR_IN_ITERATOR_CLASS_INDEX);
894    GateRef iter = NewJSObject(glue, hclass);
895    // init JSForinIterator
896    SetObjectOfForInIterator(glue, iter, receiver);
897    SetCachedHclassOfForInIterator(glue, iter, cachedHclass);
898    SetKeysOfForInIterator(glue, iter, keys);
899    SetIndexOfForInIterator(glue, iter, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE));
900    GateRef length = GetLengthOfTaggedArray(keys);
901    SetLengthOfForInIterator(glue, iter, length);
902    return iter;
903}
904
905GateRef NewObjectStubBuilder::LoadHClassFromMethod(GateRef glue, GateRef method)
906{
907    auto env = GetEnvironment();
908    Label entry(env);
909    env->SubCfgEntry(&entry);
910    DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
911    GateRef kind = GetFuncKind(method);
912    Label exit(env);
913    Label defaultLabel(env);
914    Label isNormal(env);
915    Label notNormal(env);
916    Label isAsync(env);
917    Label notAsync(env);
918
919    Label labelBuffer[2] = { Label(env), Label(env) };
920    Label labelBuffer1[3] = { Label(env), Label(env), Label(env) };
921    int64_t valueBuffer[2] = {
922        static_cast<int64_t>(FunctionKind::NORMAL_FUNCTION), static_cast<int64_t>(FunctionKind::ARROW_FUNCTION) };
923    int64_t valueBuffer1[3] = {
924        static_cast<int64_t>(FunctionKind::BASE_CONSTRUCTOR), static_cast<int64_t>(FunctionKind::GENERATOR_FUNCTION),
925        static_cast<int64_t>(FunctionKind::ASYNC_GENERATOR_FUNCTION) };
926    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
927    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
928    BRANCH(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ARROW_FUNCTION))),
929        &isNormal, &notNormal);
930    Bind(&isNormal);
931    {
932        // 2 : this switch has 2 case
933        Switch(kind, &defaultLabel, valueBuffer, labelBuffer, 2);
934        Bind(&labelBuffer[0]);
935        {
936            hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITH_PROTO);
937            Jump(&exit);
938        }
939        Bind(&labelBuffer[1]);
940        {
941            hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITHOUT_PROTO);
942            Jump(&exit);
943        }
944    }
945    Bind(&notNormal);
946    {
947        BRANCH(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ASYNC_FUNCTION))),
948            &isAsync, &notAsync);
949        Bind(&isAsync);
950        {
951            hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ASYNC_FUNCTION_CLASS);
952            Jump(&exit);
953        }
954        Bind(&notAsync);
955        {
956            // 3 : this switch has 3 case
957            Switch(kind, &defaultLabel, valueBuffer1, labelBuffer1, 3);
958            Bind(&labelBuffer1[0]);
959            {
960                hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITH_PROTO);
961                Jump(&exit);
962            }
963            Bind(&labelBuffer1[1]);
964            {
965                hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::GENERATOR_FUNCTION_CLASS);
966                Jump(&exit);
967            }
968            // 2 : index of kind
969            Bind(&labelBuffer1[2]);
970            {
971                hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
972                                           GlobalEnv::ASYNC_GENERATOR_FUNCTION_CLASS);
973                Jump(&exit);
974            }
975        }
976    }
977    Bind(&defaultLabel);
978    {
979        FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
980        Jump(&exit);
981    }
982    Bind(&exit);
983    auto ret = *hclass;
984    env->SubCfgExit();
985    return ret;
986}
987
988GateRef NewObjectStubBuilder::LoadSHClassFromMethod(GateRef glue, GateRef method)
989{
990    auto env = GetEnvironment();
991    Label entry(env);
992    env->SubCfgEntry(&entry);
993    DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
994    GateRef kind = GetFuncKind(method);
995    Label exit(env);
996    Label isSendableFunc(env);
997    Label isNotSendableFunc(env);
998    Label isNormal(env);
999    Label notNormal(env);
1000
1001    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1002    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1003    BRANCH(IsSendableFunction(method), &isSendableFunc, &isNotSendableFunc);
1004    Bind(&isSendableFunc);
1005    {
1006        BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(FunctionKind::BASE_CONSTRUCTOR))), &isNormal, &notNormal);
1007        Bind(&isNormal);
1008        {
1009            hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1010                                       GlobalEnv::SHARED_FUNCTION_CLASS_WITH_PROTO);
1011            Jump(&exit);
1012        }
1013        Bind(&notNormal);
1014        {
1015            hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1016                                       GlobalEnv::SHARED_ASYNC_FUNCTION_CLASS);
1017            Jump(&exit);
1018        }
1019    }
1020    Bind(&isNotSendableFunc);
1021    {
1022        FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1023        Jump(&exit);
1024    }
1025    Bind(&exit);
1026    auto ret = *hclass;
1027    env->SubCfgExit();
1028    return ret;
1029}
1030
1031GateRef NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef method, FunctionKind targetKind)
1032{
1033    GateRef hclass = LoadHClassFromMethod(glue, method);
1034    return NewJSFunctionByHClass(glue, method, hclass, targetKind);
1035}
1036
1037GateRef NewObjectStubBuilder::NewJSSendableFunction(GateRef glue, GateRef method, FunctionKind targetKind)
1038{
1039    GateRef hclass = LoadSHClassFromMethod(glue, method);
1040    return NewSFunctionByHClass(glue, method, hclass, targetKind);
1041}
1042
1043void NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef jsFunc, GateRef index, GateRef length, GateRef lexEnv,
1044                                         Variable *result, Label *success, Label *failed, GateRef slotId,
1045                                         FunctionKind targetKind)
1046{
1047    auto env = GetEnvironment();
1048    Label hasException(env);
1049    Label notException(env);
1050    Label isSendableFunc(env);
1051    Label isNotSendableFunc(env);
1052    Label afterSendableFunc(env);
1053    GateRef constPool = GetConstPoolFromFunction(jsFunc);
1054    SetGlue(glue);
1055    result->WriteVariable(DefineFunc(glue, constPool, index, targetKind));
1056    BRANCH(HasPendingException(glue), &hasException, &notException);
1057    Bind(&hasException);
1058    {
1059        Jump(failed);
1060    }
1061    Bind(&notException);
1062    {
1063        GateRef module = GetModuleFromFunction(jsFunc);
1064        SetLengthToFunction(glue, result->ReadVariable(), length);
1065        BRANCH(IsSendableFunction(GetMethodFromFunction(result->ReadVariable())), &isSendableFunc, &isNotSendableFunc);
1066        Bind(&isSendableFunc);
1067        {
1068            GateRef smodule = CallRuntime(glue, RTSTUB_ID(GetSharedModule), { module });
1069            SetSendableEnvToModule(glue, smodule, GetSendableEnvFromModule(module));
1070            SetModuleToFunction(glue, result->ReadVariable(), smodule);
1071            Jump(&afterSendableFunc);
1072        }
1073        Bind(&isNotSendableFunc);
1074        {
1075            SetLexicalEnvToFunction(glue, result->ReadVariable(), lexEnv);
1076            SetModuleToFunction(glue, result->ReadVariable(), module);
1077            SetHomeObjectToFunction(glue, result->ReadVariable(), GetHomeObjectFromFunction(jsFunc));
1078#if ECMASCRIPT_ENABLE_IC
1079            SetProfileTypeInfoCellToFunction(jsFunc, result->ReadVariable(), slotId);
1080#endif
1081            Jump(&afterSendableFunc);
1082        }
1083        Bind(&afterSendableFunc);
1084        Jump(success);
1085    }
1086}
1087
1088void NewObjectStubBuilder::SetProfileTypeInfoCellToFunction(GateRef jsFunc, GateRef definedFunc, GateRef slotId)
1089{
1090    auto env = GetEnvironment();
1091    Label entry(env);
1092    env->SubCfgEntry(&entry);
1093    Label isValidSlotId(env);
1094    Label exit(env);
1095
1096    BRANCH(Equal(slotId, Int32(ProfileTypeInfo::INVALID_SLOT_INDEX)), &exit, &isValidSlotId);
1097    Bind(&isValidSlotId);
1098    {
1099        Label isUndefined(env);
1100        Label notUndefined(env);
1101        DEFVARIABLE(profileTypeInfo, VariableType::JS_ANY(), GetProfileTypeInfo(jsFunc));
1102        BRANCH(TaggedIsUndefined(*profileTypeInfo), &isUndefined, &notUndefined);
1103        Bind(&isUndefined);
1104        {
1105            profileTypeInfo = CallRuntime(glue_, RTSTUB_ID(UpdateHotnessCounter), { jsFunc });
1106            Jump(&notUndefined);
1107        }
1108        Bind(&notUndefined);
1109        {
1110            UpdateProfileTypeInfoCellToFunction(glue_, definedFunc, *profileTypeInfo, slotId);
1111            Jump(&exit);
1112        }
1113    }
1114    Bind(&exit);
1115    env->SubCfgExit();
1116    return;
1117}
1118
1119GateRef NewObjectStubBuilder::NewJSBoundFunction(GateRef glue, GateRef target, GateRef boundThis, GateRef args)
1120{
1121    auto env = GetEnvironment();
1122    Label subentry(env);
1123    env->SubCfgEntry(&subentry);
1124    Label exit(env);
1125    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1126
1127    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1128    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1129    GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::BOUND_FUNCTION_CLASS);
1130    result = NewJSObject(glue, hclass);
1131    GateRef nameAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1132                                                  ConstantIndex::FUNCTION_NAME_ACCESSOR);
1133    SetPropertyInlinedProps(glue, *result, hclass, nameAccessor,
1134                            Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
1135                            MemoryAttribute::NoBarrier());
1136    GateRef lengthAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1137                                                    ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
1138    SetPropertyInlinedProps(glue, *result, hclass, lengthAccessor,
1139                            Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
1140                            MemoryAttribute::NoBarrier());
1141    SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_TARGET_OFFSET, target);
1142    SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_THIS_OFFSET, boundThis);
1143    SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_ARGUMENTS_OFFSET, args);
1144    GateRef method = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1145                                            ConstantIndex::BOUND_FUNCTION_METHOD_INDEX);
1146    SetMethodToFunction(glue, *result, method);
1147
1148    Label targetIsHeapObject(env);
1149    Label targetIsConstructor(env);
1150    BRANCH(TaggedIsHeapObject(target), &targetIsHeapObject, &exit);
1151    Bind(&targetIsHeapObject);
1152    BRANCH(IsConstructor(target), &targetIsConstructor, &exit);
1153    Bind(&targetIsConstructor);
1154    {
1155        GateRef resultHClass = LoadHClass(*result);
1156        SetHClassBit<JSHClass::ConstructorBit>(glue, resultHClass, Int32(1));
1157        Jump(&exit);
1158    }
1159
1160    Bind(&exit);
1161    auto ret = *result;
1162    env->SubCfgExit();
1163    return ret;
1164}
1165
1166GateRef NewObjectStubBuilder::EnumerateObjectProperties(GateRef glue, GateRef obj)
1167{
1168    auto env = GetEnvironment();
1169    Label entry(env);
1170    env->SubCfgEntry(&entry);
1171    Label exit(env);
1172    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1173    DEFVARIABLE(object, VariableType::JS_ANY(), Undefined());
1174
1175    Label isString(env);
1176    Label isNotString(env);
1177    Label afterObjectTransform(env);
1178    Label slowpath(env);
1179    Label empty(env);
1180    Label tryGetEnumCache(env);
1181    Label cacheHit(env);
1182    BRANCH(TaggedIsString(obj), &isString, &isNotString);
1183    Bind(&isString);
1184    {
1185        object = CallRuntime(glue, RTSTUB_ID(PrimitiveStringCreate), { obj });
1186        Jump(&afterObjectTransform);
1187    }
1188    Bind(&isNotString);
1189    {
1190        object = ToPrototypeOrObj(glue, obj);
1191        Jump(&afterObjectTransform);
1192    }
1193    Bind(&afterObjectTransform);
1194    BRANCH(TaggedIsUndefinedOrNull(*object), &empty, &tryGetEnumCache);
1195    Bind(&tryGetEnumCache);
1196    GateRef enumCache = TryGetEnumCache(glue, *object);
1197    BRANCH(TaggedIsUndefined(enumCache), &slowpath, &cacheHit);
1198    Bind(&cacheHit);
1199    {
1200        GateRef hclass = LoadHClass(*object);
1201        result = NewJSForinIterator(glue, *object, enumCache, hclass);
1202        Jump(&exit);
1203    }
1204    Bind(&empty);
1205    {
1206        GateRef emptyArray = GetEmptyArray(glue);
1207        result = NewJSForinIterator(glue, Undefined(), emptyArray, Undefined());
1208        Jump(&exit);
1209    }
1210
1211    Bind(&slowpath);
1212    {
1213        result = CallRuntime(glue, RTSTUB_ID(GetPropIteratorSlowpath), { *object });
1214        Jump(&exit);
1215    }
1216    Bind(&exit);
1217    auto ret = *result;
1218    env->SubCfgExit();
1219    return ret;
1220}
1221
1222void NewObjectStubBuilder::FillArgumentsList(GateRef argumentsList,
1223    GateRef sp, GateRef startIdx, GateRef numArgs)
1224{
1225    auto env = GetEnvironment();
1226    Label entry(env);
1227    env->SubCfgEntry(&entry);
1228    Label exit(env);
1229
1230    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1231    Label setArgumentsBegin(env);
1232    Label setArgumentsAgain(env);
1233    Label setArgumentsEnd(env);
1234    BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
1235    LoopBegin(&setArgumentsBegin);
1236    GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
1237    GateRef argument = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx));
1238    SetValueToTaggedArray(VariableType::JS_ANY(), glue_, argumentsList, *i, argument);
1239    i = Int32Add(*i, Int32(1));
1240    BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
1241    Bind(&setArgumentsAgain);
1242    LoopEnd(&setArgumentsBegin);
1243    Bind(&setArgumentsEnd);
1244    Jump(&exit);
1245    Bind(&exit);
1246    env->SubCfgExit();
1247    return;
1248}
1249
1250GateRef NewObjectStubBuilder::NewArgumentsListObj(GateRef numArgs)
1251{
1252    auto env = GetEnvironment();
1253    Label entry(env);
1254    env->SubCfgEntry(&entry);
1255    Label exit(env);
1256    Label setHClass(env);
1257    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1258    size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(numArgs));
1259    GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1260                                                ConstantIndex::ARRAY_CLASS_INDEX);
1261    AllocateInYoung(&result, &exit, &setHClass, arrayClass);
1262    Bind(&setHClass);
1263    StoreHClass(glue_, *result, arrayClass);
1264    Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::LENGTH_OFFSET), numArgs);
1265    Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0));
1266    Jump(&exit);
1267    Bind(&exit);
1268    auto ret = *result;
1269    env->SubCfgExit();
1270    return ret;
1271}
1272
1273void NewObjectStubBuilder::NewArgumentsList(Variable *result, Label *exit,
1274    GateRef sp, GateRef startIdx, GateRef numArgs)
1275{
1276    auto env = GetEnvironment();
1277    Label hasException(env);
1278    Label notException(env);
1279
1280    GateRef argumentsList = NewArgumentsListObj(numArgs);
1281    result->WriteVariable(argumentsList);
1282    Branch(TaggedIsException(argumentsList), &hasException, &notException);
1283    Bind(&hasException);
1284    Jump(exit);
1285    Bind(&notException);
1286    FillArgumentsList(argumentsList, sp, startIdx, numArgs);
1287    Jump(exit);
1288}
1289
1290void NewObjectStubBuilder::NewArgumentsObj(Variable *result, Label *exit,
1291    GateRef argumentsList, GateRef numArgs)
1292{
1293    auto env = GetEnvironment();
1294
1295    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1296    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset);
1297    GateRef argumentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1298                                               GlobalEnv::ARGUMENTS_CLASS);
1299    Label afterNewObject(env);
1300    NewJSObject(result, &afterNewObject, argumentsClass);
1301    Bind(&afterNewObject);
1302    Label setArgumentsObjProperties(env);
1303    BRANCH(TaggedIsException(result->ReadVariable()), exit, &setArgumentsObjProperties);
1304    Bind(&setArgumentsObjProperties);
1305    SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, IntToTaggedInt(numArgs),
1306                            Int32(JSArguments::LENGTH_INLINE_PROPERTY_INDEX));
1307    SetElementsArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), argumentsList);
1308    GateRef arrayProtoValuesFunction = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1309                                                         GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
1310    SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, arrayProtoValuesFunction,
1311                            Int32(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX));
1312    GateRef accessorCaller = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1313                                               GlobalEnv::ARGUMENTS_CALLER_ACCESSOR);
1314    SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCaller,
1315                            Int32(JSArguments::CALLER_INLINE_PROPERTY_INDEX));
1316    GateRef accessorCallee = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1317                                               GlobalEnv::ARGUMENTS_CALLEE_ACCESSOR);
1318    SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCallee,
1319                            Int32(JSArguments::CALLEE_INLINE_PROPERTY_INDEX));
1320    Jump(exit);
1321}
1322
1323void NewObjectStubBuilder::AssignRestArg(Variable *result, Label *exit,
1324    GateRef sp, GateRef startIdx, GateRef numArgs, GateRef intialHClass)
1325{
1326    auto env = GetEnvironment();
1327    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1328    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1329    Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, TruncInt64ToInt32(numArgs));
1330    GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1331    SetPropertyInlinedProps(glue_, result->ReadVariable(), intialHClass, accessor,
1332                            Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
1333    SetExtensibleToBitfield(glue_, result->ReadVariable(), true);
1334    Label setArgumentsBegin(env);
1335    Label setArgumentsAgain(env);
1336    Label setArgumentsEnd(env);
1337    GateRef elements = GetElementsArray(result->ReadVariable());
1338    BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
1339    LoopBegin(&setArgumentsBegin);
1340    {
1341        GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
1342        GateRef receiver = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx));
1343        SetValueToTaggedArray(VariableType::JS_ANY(), glue_, elements, *i, receiver);
1344        i = Int32Add(*i, Int32(1));
1345        BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
1346        Bind(&setArgumentsAgain);
1347    }
1348    LoopEnd(&setArgumentsBegin);
1349    Bind(&setArgumentsEnd);
1350    Jump(exit);
1351}
1352
1353void NewObjectStubBuilder::NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj,
1354                                             GateRef hclass, GateRef trackInfo, bool isEmptyArray)
1355{
1356    auto env = GetEnvironment();
1357    Label initializeArray(env);
1358    Label afterInitialize(env);
1359    HeapAlloc(result, &initializeArray, spaceType, hclass);
1360    Bind(&initializeArray);
1361    Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(0), hclass);
1362    InitializeWithSpeicalValue(&afterInitialize, result->ReadVariable(), Undefined(), Int32(JSArray::SIZE),
1363                               TruncInt64ToInt32(size_), MemoryAttribute::NoBarrier());
1364    Bind(&afterInitialize);
1365    GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
1366    Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()));
1367
1368    GateRef propertiesOffset = IntPtr(JSObject::PROPERTIES_OFFSET);
1369    GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
1370    GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1371    GateRef trackInfoOffset = IntPtr(JSArray::TRACK_INFO_OFFSET);
1372    if (isEmptyArray) {
1373        Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, obj);
1374        Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, obj);
1375        Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, Int32(0));
1376    } else {
1377        auto newProperties = Load(VariableType::JS_POINTER(), obj, propertiesOffset);
1378        Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, newProperties);
1379
1380        auto newElements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
1381        Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, newElements);
1382
1383        GateRef arrayLength = Load(VariableType::INT32(), obj, lengthOffset);
1384        Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, arrayLength);
1385    }
1386    Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), trackInfoOffset, trackInfo);
1387
1388    auto accessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1389    SetPropertyInlinedProps(glue_, result->ReadVariable(), hclass, accessor,
1390        Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_POINTER(), MemoryAttribute::NoBarrier());
1391    Jump(exit);
1392}
1393
1394void NewObjectStubBuilder::HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef hclass)
1395{
1396    switch (spaceType) {
1397        case RegionSpaceFlag::IN_YOUNG_SPACE:
1398            AllocateInYoung(result, exit, hclass);
1399            break;
1400        case RegionSpaceFlag::IN_SHARED_OLD_SPACE:
1401            AllocateInSOld(result, exit, hclass);
1402            break;
1403        default:
1404            *result = CallRuntime(glue_, RTSTUB_ID(HeapAlloc),
1405                { Int64ToTaggedInt(size_), hclass, IntToTaggedInt(Int64(spaceType))});
1406            break;
1407    }
1408}
1409
1410void NewObjectStubBuilder::AllocateInSOldPrologue([[maybe_unused]] Variable *result,
1411    Label *callRuntime, [[maybe_unused]] Label *exit)
1412{
1413    auto env = GetEnvironment();
1414    Label success(env);
1415    Label next(env);
1416
1417#ifdef ARK_ASAN_ON
1418    Jump(callRuntime);
1419#else
1420#ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
1421    auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
1422    auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
1423    BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next);
1424    Bind(&next);
1425#endif
1426    auto topOffset = JSThread::GlueData::GetSOldSpaceAllocationTopAddressOffset(env->Is32Bit());
1427    auto endOffset = JSThread::GlueData::GetSOldSpaceAllocationEndAddressOffset(env->Is32Bit());
1428    auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
1429    auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
1430    auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0));
1431    auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0));
1432    auto newTop = PtrAdd(top, size_);
1433    BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success);
1434    Bind(&success);
1435    {
1436        Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop);
1437        if (env->Is32Bit()) {
1438            top = ZExtInt32ToInt64(top);
1439        }
1440        result->WriteVariable(top);
1441        Jump(exit);
1442    }
1443#endif
1444}
1445
1446void NewObjectStubBuilder::AllocateInSOld(Variable *result, Label *exit, GateRef hclass)
1447{
1448    auto env = GetEnvironment();
1449    Label callRuntime(env);
1450    AllocateInSOldPrologue(result, &callRuntime, exit);
1451    Bind(&callRuntime);
1452    {
1453        DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1454        ret = CallRuntime(glue_, RTSTUB_ID(AllocateInSOld), {IntToTaggedInt(size_), hclass});
1455        result->WriteVariable(*ret);
1456        Jump(exit);
1457    }
1458}
1459
1460void NewObjectStubBuilder::AllocateInYoungPrologue([[maybe_unused]] Variable *result,
1461    Label *callRuntime, [[maybe_unused]] Label *exit)
1462{
1463    auto env = GetEnvironment();
1464    Label success(env);
1465    Label next(env);
1466
1467#ifdef ARK_ASAN_ON
1468    Jump(callRuntime);
1469#else
1470#ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
1471    auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
1472    auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
1473    BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next);
1474    Bind(&next);
1475#endif
1476    auto topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(env->Is32Bit());
1477    auto endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(env->Is32Bit());
1478    auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
1479    auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
1480    auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0));
1481    auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0));
1482    auto newTop = PtrAdd(top, size_);
1483    BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success);
1484    Bind(&success);
1485    {
1486        Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop, MemoryAttribute::NoBarrier());
1487        if (env->Is32Bit()) {
1488            top = ZExtInt32ToInt64(top);
1489        }
1490        result->WriteVariable(top);
1491        Jump(exit);
1492    }
1493#endif
1494}
1495
1496void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *exit, GateRef hclass)
1497{
1498    auto env = GetEnvironment();
1499    Label callRuntime(env);
1500    AllocateInYoungPrologue(result, &callRuntime, exit);
1501    Bind(&callRuntime);
1502    {
1503        DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1504        ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
1505            Int64ToTaggedInt(size_), hclass });
1506        result->WriteVariable(*ret);
1507        Jump(exit);
1508    }
1509}
1510
1511void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *error, Label *noError, GateRef hclass)
1512{
1513    auto env = GetEnvironment();
1514    Label callRuntime(env);
1515    AllocateInYoungPrologue(result, &callRuntime, noError);
1516    Bind(&callRuntime);
1517    {
1518        DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1519        ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
1520            Int64ToTaggedInt(size_), hclass });
1521        result->WriteVariable(*ret);
1522        BRANCH(TaggedIsException(*ret), error, noError);
1523    }
1524}
1525
1526GateRef NewObjectStubBuilder::NewTrackInfo(GateRef glue, GateRef cachedHClass, GateRef cachedFunc,
1527                                           RegionSpaceFlag spaceFlag, GateRef arraySize)
1528{
1529    auto env = GetEnvironment();
1530    Label entry(env);
1531    env->SubCfgEntry(&entry);
1532
1533    Label initialize(env);
1534    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1535    auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::TRACK_INFO_CLASS_INDEX);
1536    GateRef size = GetObjectSizeFromHClass(hclass);
1537    SetParameters(glue, size);
1538    HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
1539    Bind(&initialize);
1540    Store(VariableType::JS_POINTER(), glue_, *result, IntPtr(0), hclass);
1541    GateRef cachedHClassOffset = IntPtr(TrackInfo::CACHED_HCLASS_OFFSET);
1542    Store(VariableType::JS_POINTER(), glue, *result, cachedHClassOffset, cachedHClass);
1543    GateRef cachedFuncOffset = IntPtr(TrackInfo::CACHED_FUNC_OFFSET);
1544    GateRef weakCachedFunc = env->GetBuilder()->CreateWeakRef(cachedFunc);
1545    Store(VariableType::JS_POINTER(), glue, *result, cachedFuncOffset, weakCachedFunc);
1546    GateRef arrayLengthOffset = IntPtr(TrackInfo::ARRAY_LENGTH_OFFSET);
1547    Store(VariableType::INT32(), glue, *result, arrayLengthOffset, arraySize);
1548    SetSpaceFlagToTrackInfo(glue, *result, Int32(spaceFlag));
1549    auto elementsKind = GetElementsKindFromHClass(cachedHClass);
1550    SetElementsKindToTrackInfo(glue, *result, elementsKind);
1551    auto ret = *result;
1552    env->SubCfgExit();
1553    return ret;
1554}
1555
1556void NewObjectStubBuilder::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef value, GateRef start,
1557                                                      GateRef end, MemoryAttribute mAttr)
1558{
1559    {
1560        ASM_ASSERT(GET_MESSAGE_STRING_ID(InitializeWithSpeicalValue),
1561                   Int32Equal(Int32Mod(Int32Sub(end, start), Int32(JSTaggedValue::TaggedTypeSize())), Int32(0)));
1562    }
1563    auto env = GetEnvironment();
1564    Label begin(env);
1565    Label storeValue(env);
1566    Label endLoop(env);
1567    Label storeHead(env);
1568    Label enterLoop(env);
1569    DEFVARIABLE(startOffset, VariableType::INT32(), start);
1570    const auto tSize = static_cast<int32_t>(JSTaggedValue::TaggedTypeSize());
1571    static_assert((tSize & (tSize - 1)) == 0 && "tSize must be power of 2");
1572    GateRef length = Int32Sub(end, start);
1573    GateRef remainder = Int32And(length, Int32(LOOP_UNROLL_FACTOR * tSize - 1));
1574    BRANCH(Int32NotEqual(remainder, Int32(0)), &storeHead, &enterLoop);
1575    Bind(&storeHead);
1576    {
1577        // Now use 2 as loop unroll factor, so only store once if reminder is not 0.
1578        // But if using other loop unroll factor, the store head should also be refactored.
1579        Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(start), value, mAttr);
1580        startOffset = Int32Add(start, Int32(tSize));
1581        Jump(&enterLoop);
1582    }
1583    Bind(&enterLoop);
1584    {
1585        Jump(&begin);
1586    }
1587    LoopBegin(&begin);
1588    {
1589        BRANCH(Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
1590        Bind(&storeValue);
1591        {
1592            auto off = *startOffset;
1593            for (auto i = 0; i < LOOP_UNROLL_FACTOR; i++) {
1594                Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(off), value, mAttr);
1595                off = Int32Add(off, Int32(tSize));
1596            }
1597            startOffset = Int32Add(*startOffset, Int32(LOOP_UNROLL_FACTOR * tSize));
1598            Jump(&endLoop);
1599        }
1600        Bind(&endLoop);
1601        LoopEnd(&begin);
1602    }
1603}
1604
1605void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit,
1606    GateRef array, GateRef value, GateRef start, GateRef length)
1607{
1608    Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::LENGTH_OFFSET), length);
1609    Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0));
1610    auto offset = Int32Mul(start, Int32(JSTaggedValue::TaggedTypeSize()));
1611    auto dataOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
1612    offset = Int32Mul(length, Int32(JSTaggedValue::TaggedTypeSize()));
1613    auto endOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
1614    InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset);
1615}
1616
1617void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
1618{
1619    auto env = GetEnvironment();
1620    if (compressed) {
1621        size_ = AlignUp(ComputeSizeUtf8(ZExtInt32ToPtr(length)),
1622            IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1623    } else {
1624        size_ = AlignUp(ComputeSizeUtf16(ZExtInt32ToPtr(length)),
1625            IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1626    }
1627    Label afterAllocate(env);
1628    GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1629                                                 ConstantIndex::LINE_STRING_CLASS_INDEX);
1630    AllocateInSOld(result, &afterAllocate, stringClass);
1631
1632    Bind(&afterAllocate);
1633    StoreHClass(glue_, result->ReadVariable(), stringClass);
1634    SetLength(glue_, result->ReadVariable(), length, compressed);
1635    SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
1636    Jump(exit);
1637}
1638
1639void NewObjectStubBuilder::AllocSlicedStringObject(Variable *result, Label *exit, GateRef from, GateRef length,
1640    FlatStringStubBuilder *flatString)
1641{
1642    auto env = GetEnvironment();
1643
1644    size_ = AlignUp(IntPtr(SlicedString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1645    Label afterAllocate(env);
1646    GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1647                                                 ConstantIndex::SLICED_STRING_CLASS_INDEX);
1648    AllocateInSOld(result, &afterAllocate, stringClass);
1649
1650    Bind(&afterAllocate);
1651    StoreHClass(glue_, result->ReadVariable(), stringClass);
1652    GateRef mixLength = Load(VariableType::INT32(), flatString->GetFlatString(), IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1653    GateRef isCompressed = Int32And(Int32(EcmaString::STRING_COMPRESSED_BIT), mixLength);
1654    SetLength(glue_, result->ReadVariable(), length, isCompressed);
1655    SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
1656    BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
1657    builtinsStringStubBuilder.StoreParent(glue_, result->ReadVariable(), flatString->GetFlatString());
1658    builtinsStringStubBuilder.StoreStartIndex(glue_, result->ReadVariable(),
1659        Int32Add(from, flatString->GetStartIndex()));
1660    builtinsStringStubBuilder.StoreHasBackingStore(glue_, result->ReadVariable(), Int32(0));
1661    Jump(exit);
1662}
1663
1664void NewObjectStubBuilder::AllocTreeStringObject(Variable *result, Label *exit, GateRef first, GateRef second,
1665    GateRef length, bool compressed)
1666{
1667    auto env = GetEnvironment();
1668
1669    size_ = AlignUp(IntPtr(TreeEcmaString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1670    Label afterAllocate(env);
1671    GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1672                                                 ConstantIndex::TREE_STRING_CLASS_INDEX);
1673    AllocateInSOld(result, &afterAllocate, stringClass);
1674
1675    Bind(&afterAllocate);
1676    StoreHClass(glue_, result->ReadVariable(), stringClass);
1677    SetLength(glue_, result->ReadVariable(), length, compressed);
1678    SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
1679    Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::FIRST_OFFSET), first);
1680    Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::SECOND_OFFSET), second);
1681    Jump(exit);
1682}
1683
1684GateRef NewObjectStubBuilder::FastNewThisObject(GateRef glue, GateRef ctor)
1685{
1686    auto env = GetEnvironment();
1687    Label entry(env);
1688    env->SubCfgEntry(&entry);
1689    Label exit(env);
1690    Label isHeapObject(env);
1691    Label callRuntime(env);
1692    Label checkJSObject(env);
1693    Label newObject(env);
1694    Label isJSObject(env);
1695
1696    DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1697    auto protoOrHclass = Load(VariableType::JS_ANY(), ctor,
1698        IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1699    BRANCH(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &callRuntime);
1700    Bind(&isHeapObject);
1701    BRANCH(IsJSHClass(protoOrHclass), &checkJSObject, &callRuntime);
1702    Bind(&checkJSObject);
1703    auto objectType = GetObjectType(protoOrHclass);
1704    BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))), &isJSObject, &callRuntime);
1705    Bind(&isJSObject);
1706    {
1707        auto funcProto = GetPrototypeFromHClass(protoOrHclass);
1708        BRANCH(IsEcmaObject(funcProto), &newObject, &callRuntime);
1709    }
1710    Bind(&newObject);
1711    {
1712        SetParameters(glue, 0);
1713        NewJSObject(&thisObj, &exit, protoOrHclass);
1714    }
1715    Bind(&callRuntime);
1716    {
1717        thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor, Undefined()});
1718        Jump(&exit);
1719    }
1720    Bind(&exit);
1721    auto ret = *thisObj;
1722    env->SubCfgExit();
1723    return ret;
1724}
1725
1726GateRef NewObjectStubBuilder::FastSuperAllocateThis(GateRef glue, GateRef superCtor, GateRef newTarget)
1727{
1728    auto env = GetEnvironment();
1729    Label entry(env);
1730    env->SubCfgEntry(&entry);
1731    Label exit(env);
1732    Label isHeapObject(env);
1733    Label checkJSObject(env);
1734    Label callRuntime(env);
1735    Label newObject(env);
1736    Label isFunction(env);
1737
1738    BRANCH(IsJSFunction(newTarget), &isFunction, &callRuntime);
1739    Bind(&isFunction);
1740    DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1741    DEFVARIABLE(protoOrHclass, VariableType::JS_ANY(), Undefined());
1742    protoOrHclass = Load(VariableType::JS_ANY(), newTarget,
1743        IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1744    BRANCH(TaggedIsHeapObject(*protoOrHclass), &isHeapObject, &callRuntime);
1745    Bind(&isHeapObject);
1746    BRANCH(IsJSHClass(*protoOrHclass), &checkJSObject, &callRuntime);
1747    Bind(&checkJSObject);
1748    auto objectType = GetObjectType(*protoOrHclass);
1749    BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))),
1750        &newObject, &callRuntime);
1751    Bind(&newObject);
1752    {
1753        SetParameters(glue, 0);
1754        NewJSObject(&thisObj, &exit, *protoOrHclass);
1755    }
1756    Bind(&callRuntime);
1757    {
1758        thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {superCtor, newTarget});
1759        Jump(&exit);
1760    }
1761    Bind(&exit);
1762    auto ret = *thisObj;
1763    env->SubCfgExit();
1764    return ret;
1765}
1766
1767GateRef NewObjectStubBuilder::NewThisObjectChecked(GateRef glue, GateRef ctor)
1768{
1769    auto env = GetEnvironment();
1770    Label entry(env);
1771    env->SubCfgEntry(&entry);
1772    Label exit(env);
1773
1774    Label ctorIsHeapObject(env);
1775    Label ctorIsJSFunction(env);
1776    Label fastPath(env);
1777    Label slowPath(env);
1778    Label ctorIsBase(env);
1779
1780    DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1781
1782    BRANCH(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath);
1783    Bind(&ctorIsHeapObject);
1784    BRANCH(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath);
1785    Bind(&ctorIsJSFunction);
1786    BRANCH(IsConstructor(ctor), &fastPath, &slowPath);
1787    Bind(&fastPath);
1788    {
1789        BRANCH(IsBase(ctor), &ctorIsBase, &exit);
1790        Bind(&ctorIsBase);
1791        {
1792            thisObj = FastNewThisObject(glue, ctor);
1793            Jump(&exit);
1794        }
1795    }
1796    Bind(&slowPath);
1797    {
1798        thisObj = Hole();
1799        Jump(&exit);
1800    }
1801    Bind(&exit);
1802    auto ret = *thisObj;
1803    env->SubCfgExit();
1804    return ret;
1805}
1806
1807// The caller should ensure that the IC slot for LoadTrackInfo is valid (slotId is not 0xff or slotValue is not Hole).
1808GateRef NewObjectStubBuilder::LoadTrackInfo(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo,
1809    GateRef profileTypeInfo, GateRef slotId, GateRef slotValue, GateRef arrayLiteral, ProfileOperation callback)
1810{
1811    auto env = GetEnvironment();
1812    Label entry(env);
1813    env->SubCfgEntry(&entry);
1814    Label exit(env);
1815    DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
1816
1817    Label uninitialized(env);
1818    Label fastpath(env);
1819    BRANCH(TaggedIsHeapObject(slotValue), &fastpath, &uninitialized);
1820    Bind(&fastpath);
1821    {
1822        ret = slotValue;
1823        Jump(&exit);
1824    }
1825    Bind(&uninitialized);
1826    {
1827        auto hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, arrayLiteral, callback);
1828        // emptyarray
1829        if (arrayLiteral == Circuit::NullGate()) {
1830            ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, Int32(0));
1831        } else {
1832            GateRef arrayLength = GetArrayLength(arrayLiteral);
1833            ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, arrayLength);
1834        }
1835
1836        SetValueToTaggedArray(VariableType::JS_POINTER(), glue, profileTypeInfo, slotId, *ret);
1837        callback.TryPreDump();
1838        Jump(&exit);
1839    }
1840    Bind(&exit);
1841    auto result = *ret;
1842    env->SubCfgExit();
1843    return result;
1844}
1845
1846GateRef NewObjectStubBuilder::LoadArrayHClassSlowPath(
1847    GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo, GateRef arrayLiteral, ProfileOperation callback)
1848{
1849    auto env = GetEnvironment();
1850    Label entry(env);
1851    env->SubCfgEntry(&entry);
1852    Label exit(env);
1853    Label originLoad(env);
1854
1855    DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
1856
1857    auto hcIndexInfos = LoadHCIndexInfosFromConstPool(jsFunc);
1858    auto indexInfosLength = GetLengthOfTaggedArray(hcIndexInfos);
1859    Label aotLoad(env);
1860    BRANCH(Int32Equal(indexInfosLength, Int32(0)), &originLoad, &aotLoad);
1861    Bind(&aotLoad);
1862    {
1863        GateRef traceId = 0;
1864        if (traceIdInfo.isPc) {
1865            auto pfAddr = LoadPfHeaderFromConstPool(jsFunc);
1866            traceId = TruncPtrToInt32(PtrSub(traceIdInfo.pc, pfAddr));
1867        } else {
1868            traceId = traceIdInfo.traceId;
1869        }
1870
1871        GateRef hcIndex = LoadHCIndexFromConstPool(hcIndexInfos, indexInfosLength, traceId, &originLoad);
1872        GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
1873            IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit())));
1874        GateRef offset = Int32Mul(Int32(sizeof(JSTaggedValue)), hcIndex);
1875        ret = Load(VariableType::JS_POINTER(), gConstAddr, offset);
1876        Jump(&exit);
1877    }
1878    Bind(&originLoad);
1879    {
1880        // emptyarray
1881        if (arrayLiteral == Circuit::NullGate()) {
1882            if (callback.IsEmpty()) {
1883                GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1884                GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1885                auto arrayFunc =
1886                    GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
1887                ret = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1888            } else {
1889                ret =
1890                    GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
1891            }
1892        } else {
1893            ret = LoadHClass(arrayLiteral);
1894        }
1895        Jump(&exit);
1896    }
1897    Bind(&exit);
1898    auto result = *ret;
1899    env->SubCfgExit();
1900    return result;
1901}
1902
1903GateRef NewObjectStubBuilder::CreateEmptyArrayCommon(GateRef glue, GateRef hclass, GateRef trackInfo)
1904{
1905    auto env = GetEnvironment();
1906    Label entry(env);
1907    env->SubCfgEntry(&entry);
1908    Label exit(env);
1909
1910    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1911
1912    GateRef size = GetObjectSizeFromHClass(hclass);
1913    GateRef emptyArray = GetGlobalConstantValue(
1914        VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
1915    SetParameters(glue, size);
1916    NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, emptyArray, hclass, trackInfo, true);
1917    Bind(&exit);
1918    GateRef ret = *result;
1919    env->SubCfgExit();
1920    return ret;
1921}
1922
1923GateRef NewObjectStubBuilder::CreateEmptyObject(GateRef glue)
1924{
1925    auto env = GetEnvironment();
1926    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1927    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1928    GateRef objectFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX);
1929    GateRef hclass = Load(VariableType::JS_POINTER(), objectFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1930    return NewJSObject(glue, hclass);
1931}
1932
1933GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue)
1934{
1935    auto env = GetEnvironment();
1936    DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
1937    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1938    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1939    GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
1940    GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1941    return CreateEmptyArrayCommon(glue, hclass, *trackInfo);
1942}
1943
1944GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo,
1945    GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
1946{
1947    auto env = GetEnvironment();
1948    Label entry(env);
1949    env->SubCfgEntry(&entry);
1950
1951    DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
1952    DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
1953    Label slowpath(env);
1954    Label mayFastpath(env);
1955    Label createArray(env);
1956    Label profileNotUndefined(env);
1957    BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined);
1958    Bind(&profileNotUndefined);
1959    GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
1960    BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath);
1961    Bind(&mayFastpath);
1962    {
1963        trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo,
1964            slotId, slotValue, Circuit::NullGate(), callback);
1965        hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
1966        trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
1967        Jump(&createArray);
1968    }
1969    Bind(&slowpath);
1970    {
1971        hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, Circuit::NullGate(), callback);
1972        Jump(&createArray);
1973    }
1974    Bind(&createArray);
1975    GateRef result = CreateEmptyArrayCommon(glue, *hclass, *trackInfo);
1976    env->SubCfgExit();
1977    return result;
1978}
1979
1980GateRef NewObjectStubBuilder::CreateArrayWithBuffer(GateRef glue, GateRef index, GateRef jsFunc,
1981    TraceIdInfo traceIdInfo, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
1982{
1983    auto env = GetEnvironment();
1984    Label entry(env);
1985    env->SubCfgEntry(&entry);
1986    Label exit(env);
1987
1988    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1989    DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
1990    DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
1991
1992    GateRef method = GetMethodFromFunction(jsFunc);
1993    GateRef constPool = Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
1994    GateRef module = GetModuleFromFunction(jsFunc);
1995
1996    auto obj = GetArrayLiteralFromConstPool(glue, constPool, index, module);
1997
1998    Label slowpath(env);
1999    Label mayFastpath(env);
2000    Label createArray(env);
2001    Label profileNotUndefined(env);
2002    BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined);
2003    Bind(&profileNotUndefined);
2004    GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
2005    BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath);
2006    Bind(&mayFastpath);
2007    {
2008        trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo, slotId, slotValue, obj, callback);
2009        hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
2010        trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
2011        Jump(&createArray);
2012    }
2013    Bind(&slowpath);
2014    {
2015        hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, obj, callback);
2016        Jump(&createArray);
2017    }
2018    Bind(&createArray);
2019    GateRef size = GetObjectSizeFromHClass(*hclass);
2020
2021    SetParameters(glue, size);
2022    NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, obj, *hclass, *trackInfo, false);
2023
2024    Bind(&exit);
2025    auto ret = *result;
2026    env->SubCfgExit();
2027    return ret;
2028}
2029
2030template <typename IteratorType, typename CollectionType>
2031void NewObjectStubBuilder::CreateJSCollectionIterator(
2032    Variable *result, Label *exit, GateRef thisValue, GateRef kind)
2033{
2034    ASSERT_PRINT((std::is_same_v<IteratorType, JSSetIterator> || std::is_same_v<IteratorType, JSMapIterator>),
2035        "IteratorType must be JSSetIterator or JSMapIterator type");
2036    auto env = GetEnvironment();
2037    ConstantIndex iterClassIdx = static_cast<ConstantIndex>(0);
2038    int32_t iterOffset = 0;       // ITERATED_SET_OFFSET
2039    size_t linkedOffset = 0;      // LINKED_MAP_OFFSET
2040    if constexpr (std::is_same_v<IteratorType, JSSetIterator>) {
2041        iterClassIdx = ConstantIndex::JS_SET_ITERATOR_CLASS_INDEX;
2042        iterOffset = IteratorType::ITERATED_SET_OFFSET;
2043        linkedOffset = CollectionType::LINKED_SET_OFFSET;
2044        size_ = IntPtr(JSSetIterator::SIZE);
2045    } else {
2046        iterClassIdx = ConstantIndex::JS_MAP_ITERATOR_CLASS_INDEX;
2047        iterOffset = IteratorType::ITERATED_MAP_OFFSET;
2048        linkedOffset = CollectionType::LINKED_MAP_OFFSET;
2049        size_ = IntPtr(JSMapIterator::SIZE);
2050    }
2051    GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx);
2052
2053    Label noException(env);
2054    // Be careful. NO GC is allowed when initization is not complete.
2055    AllocateInYoung(result, exit, &noException, iteratorHClass);
2056    Bind(&noException);
2057    {
2058        StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass);
2059        SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
2060        auto emptyArray = GetGlobalConstantValue(
2061            VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
2062        SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2063        SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2064
2065        // GetLinked
2066        GateRef linked = Load(VariableType::JS_ANY(), thisValue, IntPtr(linkedOffset));
2067        // SetIterated
2068        GateRef iteratorOffset = IntPtr(iterOffset);
2069        Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, linked,
2070              MemoryAttribute::UnknownBarrier());
2071
2072        // SetIteratorNextIndex
2073        GateRef nextIndexOffset = IntPtr(IteratorType::NEXT_INDEX_OFFSET);
2074        Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0));
2075
2076        // SetIterationKind
2077        GateRef kindBitfieldOffset = IntPtr(IteratorType::BIT_FIELD_OFFSET);
2078        Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind);
2079        Jump(exit);
2080    }
2081}
2082
2083template void NewObjectStubBuilder::CreateJSCollectionIterator<JSSetIterator, JSSet>(
2084    Variable *result, Label *exit, GateRef set, GateRef kind);
2085template void NewObjectStubBuilder::CreateJSCollectionIterator<JSMapIterator, JSMap>(
2086    Variable *result, Label *exit, GateRef set, GateRef kind);
2087
2088void NewObjectStubBuilder::CreateJSTypedArrayIterator(Variable *result, Label *exit, GateRef thisValue, GateRef kind)
2089{
2090    auto env = GetEnvironment();
2091    size_ = IntPtr(JSArrayIterator::SIZE);
2092
2093    ConstantIndex iterClassIdx = ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX;
2094    GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx);
2095
2096    Label thisExists(env);
2097    Label isEcmaObject(env);
2098    Label isTypedArray(env);
2099    Label throwTypeError(env);
2100
2101    BRANCH(TaggedIsUndefinedOrNullOrHole(thisValue), &throwTypeError, &thisExists);
2102    Bind(&thisExists);
2103    BRANCH(IsEcmaObject(thisValue), &isEcmaObject, &throwTypeError);
2104    Bind(&isEcmaObject);
2105    BRANCH(IsTypedArray(thisValue), &isTypedArray, &throwTypeError);
2106    Bind(&isTypedArray);
2107
2108    Label noException(env);
2109    // Be careful. NO GC is allowed when initization is not complete.
2110    AllocateInYoung(result, exit, &noException, iteratorHClass);
2111    Bind(&noException);
2112    {
2113        StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass);
2114        SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
2115        auto emptyArray = GetGlobalConstantValue(
2116            VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
2117        SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2118        SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2119
2120        GateRef iteratorOffset = IntPtr(JSArrayIterator::ITERATED_ARRAY_OFFSET);
2121        Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, thisValue,
2122              MemoryAttribute::NeedBarrier());
2123
2124        // SetIteratorNextIndex
2125        GateRef nextIndexOffset = IntPtr(JSArrayIterator::NEXT_INDEX_OFFSET);
2126        Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0));
2127
2128        // SetIterationKind
2129        GateRef kindBitfieldOffset = IntPtr(JSArrayIterator::BIT_FIELD_OFFSET);
2130        Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind);
2131        Jump(exit);
2132    }
2133
2134    Bind(&throwTypeError);
2135    {
2136        GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotTypedArray));
2137        CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2138        result->WriteVariable(Exception());
2139        Jump(exit);
2140    }
2141}
2142
2143GateRef NewObjectStubBuilder::NewTaggedSubArray(GateRef glue, GateRef srcTypedArray,
2144    GateRef elementSize, GateRef newLength, GateRef beginIndex, GateRef arrayCls, GateRef buffer)
2145{
2146    auto env = GetEnvironment();
2147    Label entry(env);
2148    env->SubCfgEntry(&entry);
2149    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2150    GateRef constructorName = Load(VariableType::JS_POINTER(), srcTypedArray,
2151        IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
2152    GateRef srcByteOffset = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
2153    GateRef contentType = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
2154    GateRef beginByteOffset = Int32Add(srcByteOffset, Int32Mul(beginIndex, elementSize));
2155
2156    GateRef obj = NewJSObject(glue, arrayCls);
2157    result = obj;
2158    GateRef newByteLength = Int32Mul(elementSize, newLength);
2159    Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), buffer);
2160    Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), constructorName);
2161    Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2162    Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), beginByteOffset);
2163    Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), newLength);
2164    Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
2165    auto ret = *result;
2166    env->SubCfgExit();
2167    return ret;
2168}
2169
2170GateRef NewObjectStubBuilder::NewTypedArray(GateRef glue, GateRef srcTypedArray, GateRef srcType, GateRef length)
2171{
2172    auto env = GetEnvironment();
2173    Label entry(env);
2174    env->SubCfgEntry(&entry);
2175
2176    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2177    Label slowPath(env);
2178    Label defaultConstr(env);
2179    Label markerCellValid(env);
2180    Label isProtoChangeMarker(env);
2181    Label accessorNotChanged(env);
2182    Label exit(env);
2183    BRANCH(HasConstructor(srcTypedArray), &slowPath, &defaultConstr);
2184    Bind(&defaultConstr);
2185    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2186    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2187    GateRef markerCell = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2188        GlobalEnv::TYPED_ARRAY_SPECIES_PROTECT_DETECTOR_INDEX);
2189    BRANCH(IsMarkerCellValid(markerCell), &markerCellValid, &slowPath);
2190    Bind(&markerCellValid);
2191    GateRef marker = GetProtoChangeMarkerFromHClass(LoadHClass(srcTypedArray));
2192    BRANCH(TaggedIsProtoChangeMarker(marker), &isProtoChangeMarker, &accessorNotChanged);
2193    Bind(&isProtoChangeMarker);
2194    BRANCH(GetAccessorHasChanged(marker), &slowPath, &accessorNotChanged);
2195
2196    Bind(&accessorNotChanged);
2197    {
2198        DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2199        Label next(env);
2200        GateRef hclass = LoadHClass(srcTypedArray);
2201        GateRef obj = NewJSObject(glue, hclass);
2202        result = obj;
2203        GateRef ctorName = Load(VariableType::JS_POINTER(), srcTypedArray,
2204            IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
2205        GateRef elementSize = GetElementSizeFromType(glue, srcType);
2206        GateRef newByteLength = Int32Mul(elementSize, length);
2207        GateRef contentType = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
2208        BRANCH(Int32LessThanOrEqual(newByteLength, Int32(RangeInfo::TYPED_ARRAY_ONHEAP_MAX)), &next, &slowPath);
2209        Bind(&next);
2210        {
2211            Label sameObjectSize(env);
2212            Label newByteArrayExit(env);
2213            GateRef onHeapHClass = GetOnHeapHClassFromType(glue, srcType);
2214            GateRef originalHClassObjectSize = GetObjectSizeFromHClass(hclass);
2215            GateRef onHeapHClassObjectSize = GetObjectSizeFromHClass(onHeapHClass);
2216            BRANCH(Equal(originalHClassObjectSize, onHeapHClassObjectSize), &sameObjectSize, &slowPath);
2217            Bind(&sameObjectSize);
2218            NewByteArray(&buffer, &newByteArrayExit, elementSize, length);
2219            Bind(&newByteArrayExit);
2220            StoreHClass(glue, obj, onHeapHClass);
2221            Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2222            Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), ctorName);
2223            Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2224            Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), Int32(0));
2225            Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length);
2226            Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
2227            Jump(&exit);
2228        }
2229    }
2230
2231    Bind(&slowPath);
2232    {
2233        result = CallRuntime(glue, RTSTUB_ID(TypedArraySpeciesCreate),
2234            { srcTypedArray, IntToTaggedInt(Int32(1)), IntToTaggedInt(length) });
2235        Jump(&exit);
2236    }
2237
2238    Bind(&exit);
2239    auto ret = *result;
2240    env->SubCfgExit();
2241    return ret;
2242}
2243
2244// use NewJSObjectByConstructor need to InitializeJSObject by type
2245GateRef NewObjectStubBuilder::NewJSObjectByConstructor(GateRef glue, GateRef constructor, GateRef newTarget)
2246{
2247    auto env = GetEnvironment();
2248    Label entry(env);
2249    env->SubCfgEntry(&entry);
2250    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2251    DEFVARIABLE(jshclass, VariableType::JS_ANY(), Undefined());
2252    Label exit(env);
2253    Label slowPath(env);
2254    Label newObj(env);
2255    Label isValid(env);
2256    Label checkIsJSShared(env);
2257    Label constructorIsShared(env);
2258    SetGlue(glue);
2259    BRANCH(IntPtrEqual(constructor, newTarget), &isValid, &checkIsJSShared);
2260    Bind(&checkIsJSShared);
2261    BRANCH(IsJSShared(constructor), &constructorIsShared, &isValid);
2262    Bind(&constructorIsShared);
2263    {
2264        BRANCH(IsJSShared(newTarget), &isValid, &slowPath);
2265    }
2266    Bind(&isValid);
2267    {
2268        Label hasFunctionPrototype(env);
2269        Label notHasFunctionPrototype(env);
2270        BRANCH(HasFunctionPrototype(constructor), &hasFunctionPrototype, &notHasFunctionPrototype);
2271        Bind(&hasFunctionPrototype);
2272        {
2273            GateRef proto = GetCtorPrototype(constructor);
2274            BRANCH(IsEcmaObject(proto), &notHasFunctionPrototype, &slowPath);
2275        }
2276        Bind(&notHasFunctionPrototype);
2277        {
2278            Label isEqual(env);
2279            Label isHClass(env);
2280            BRANCH(IntPtrEqual(constructor, newTarget), &isEqual, &slowPath);
2281            Bind(&isEqual);
2282            GateRef protoOrHClass = GetProtoOrHClass(constructor);
2283            BRANCH(IsJSHClass(protoOrHClass), &isHClass, &slowPath);
2284            Bind(&isHClass);
2285            jshclass = protoOrHClass;
2286            Jump(&newObj);
2287        }
2288    }
2289    Bind(&newObj);
2290    {
2291        Label notShared(env);
2292        BRANCH(IsJSShared(*jshclass), &slowPath, &notShared);
2293        Bind(&notShared);
2294        {
2295            result = NewJSObject(glue, *jshclass);
2296            Jump(&exit);
2297        }
2298    }
2299    Bind(&slowPath);
2300    {
2301        result = CallRuntime(glue, RTSTUB_ID(NewJSObjectByConstructor), { constructor, newTarget });
2302        Jump(&exit);
2303    }
2304
2305    Bind(&exit);
2306    auto ret = *result;
2307    env->SubCfgExit();
2308    return ret;
2309}
2310
2311GateRef NewObjectStubBuilder::NewFloat32ArrayObj(GateRef glue, GateRef glueGlobalEnv)
2312{
2313    GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2314                                          GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX);
2315    GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2316    GateRef obj = NewJSObject(glue, hclass);
2317    return obj;
2318}
2319
2320GateRef NewObjectStubBuilder::NewFloat32ArrayWithSize(GateRef glue, GateRef size)
2321{
2322    auto env = GetEnvironment();
2323    Label entry(env);
2324    env->SubCfgEntry(&entry);
2325    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2326    DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2327    Label exit(env);
2328    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2329    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2330    GateRef obj = NewFloat32ArrayObj(glue, glueGlobalEnv);
2331    result = obj;
2332    GateRef ctorName = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
2333                                              ConstantIndex::FLOAT32_ARRAY_STRING_INDEX);
2334    GateRef elementSize = Int32(4);  // 4: float32 primtype's byte length
2335    GateRef newByteLength = Int32Mul(size, elementSize);
2336    GateRef contentType = Int32(static_cast<int32_t>(ContentType::Number));
2337    {
2338        Label newByteArrayExit(env);
2339        NewByteArray(&buffer, &newByteArrayExit, elementSize, size);
2340        Bind(&newByteArrayExit);
2341        GateRef onHeapHClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2342                                                 GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2343        StoreHClass(glue, obj, onHeapHClass);
2344        Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2345        Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET),
2346              ctorName, MemoryAttribute::NoBarrier());
2347        Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET),
2348              newByteLength, MemoryAttribute::NoBarrier());
2349        Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET),
2350              Int32(0), MemoryAttribute::NoBarrier());
2351        Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET),
2352              size, MemoryAttribute::NoBarrier());
2353        Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET),
2354              contentType, MemoryAttribute::NoBarrier());
2355        Jump(&exit);
2356    }
2357    Bind(&exit);
2358    auto ret = *result;
2359    env->SubCfgExit();
2360    return ret;
2361}
2362
2363GateRef NewObjectStubBuilder::NewTypedArrayFromCtor(GateRef glue, GateRef ctor, GateRef length, Label *slowPath)
2364{
2365    auto env = GetEnvironment();
2366    Label entry(env);
2367    env->SubCfgEntry(&entry);
2368
2369    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2370    Label thisObjIsECmaObject(env);
2371    Label thisObjIsFastTypedArray(env);
2372    Label defaultConstr(env);
2373    Label exit(env);
2374
2375    GateRef thisObj = FastNewThisObject(glue, ctor);
2376    result = thisObj;
2377    GateRef arrayType = GetObjectType(LoadHClass(thisObj));
2378
2379    BRANCH(IsEcmaObject(thisObj), &thisObjIsECmaObject, slowPath);
2380    Bind(&thisObjIsECmaObject);
2381    BRANCH(IsFastTypeArray(arrayType), &thisObjIsFastTypedArray, slowPath);
2382    Bind(&thisObjIsFastTypedArray);
2383    BRANCH(HasConstructor(thisObj), slowPath, &defaultConstr);
2384    Bind(&defaultConstr);
2385
2386    DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2387    GateRef elementSize = GetElementSizeFromType(glue, arrayType);
2388    GateRef newByteLength = Int32Mul(elementSize, length);
2389    Label newByteArrayExit(env);
2390    NewByteArray(&buffer, &newByteArrayExit, elementSize, length);
2391    Bind(&newByteArrayExit);
2392    Store(VariableType::JS_POINTER(), glue, thisObj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2393    Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2394    Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length);
2395    Jump(&exit);
2396
2397    Bind(&exit);
2398    auto ret = *result;
2399    env->SubCfgExit();
2400    return ret;
2401}
2402
2403void NewObjectStubBuilder::NewByteArray(Variable *result, Label *exit, GateRef elementSize, GateRef length)
2404{
2405    auto env = GetEnvironment();
2406
2407    Label noError(env);
2408    Label initializeExit(env);
2409    GateRef size = AlignUp(ComputeTaggedTypedArraySize(ZExtInt32ToPtr(elementSize), ZExtInt32ToPtr(length)),
2410        IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
2411    size_ = size;
2412    auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::BYTE_ARRAY_CLASS_INDEX);
2413    AllocateInYoung(result, exit, &noError, hclass);
2414    Bind(&noError);
2415    {
2416        StoreBuiltinHClass(glue_, result->ReadVariable(), hclass);
2417        auto startOffset = Int32(ByteArray::DATA_OFFSET);
2418        static_assert(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT) == 8);
2419        InitializeWithSpeicalValue(&initializeExit, result->ReadVariable(), Int64(0), startOffset,
2420                                   TruncPtrToInt32(size));
2421        Bind(&initializeExit);
2422        Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::ARRAY_LENGTH_OFFSET), length);
2423        Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::BYTE_LENGTH_OFFSET), elementSize);
2424        Jump(exit);
2425    }
2426}
2427
2428GateRef NewObjectStubBuilder::NewProfileTypeInfoCell(GateRef glue, GateRef value)
2429{
2430    auto env = GetEnvironment();
2431    Label entry(env);
2432    env->SubCfgEntry(&entry);
2433
2434    Label initialize(env);
2435    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2436    auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
2437                                         ConstantIndex::PROFILE_TYPE_INFO_CELL_0_CLASS_INDEX);
2438    GateRef size = GetObjectSizeFromHClass(hclass);
2439    SetParameters(glue, size);
2440    HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
2441    Bind(&initialize);
2442    StoreHClassWithoutBarrier(glue, *result, hclass);
2443    SetValueToProfileTypeInfoCell(glue, *result, value);
2444    GateRef machineCodeOffset = IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET);
2445    Store(VariableType::JS_POINTER(), glue, *result, machineCodeOffset, Hole());
2446    GateRef handleOffset = IntPtr(ProfileTypeInfoCell::HANDLE_OFFSET);
2447    Store(VariableType::JS_POINTER(), glue, *result, handleOffset, Undefined());
2448
2449    auto ret = *result;
2450    env->SubCfgExit();
2451    return ret;
2452}
2453
2454GateRef NewObjectStubBuilder::GetElementSizeFromType(GateRef glue, GateRef type)
2455{
2456    auto env = GetEnvironment();
2457    Label entry(env);
2458    env->SubCfgEntry(&entry);
2459
2460    DEFVARIABLE(result, VariableType::INT32(), Int32(0));
2461    Label defaultLabel(env);
2462    Label exit(env);
2463    Label labelBuffer[11] = {
2464        Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
2465        Label(env), Label(env), Label(env), Label(env), Label(env) };
2466    int64_t valueBuffer[11] = {
2467        static_cast<int64_t>(JSType::JS_INT8_ARRAY),
2468        static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
2469        static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY),
2470        static_cast<int64_t>(JSType::JS_INT16_ARRAY),
2471        static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
2472        static_cast<int64_t>(JSType::JS_INT32_ARRAY),
2473        static_cast<int64_t>(JSType::JS_UINT32_ARRAY),
2474        static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
2475        static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY),
2476        static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY),
2477        static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) };
2478
2479    // 11 : this switch has 11 case
2480    Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11);
2481    // 0 : index of this buffer
2482    Bind(&labelBuffer[0]);
2483    {
2484        // 1 : the elementSize of this type is 1
2485        result = Int32(1);
2486        Jump(&exit);
2487    }
2488    // 1 : index of this buffer
2489    Bind(&labelBuffer[1]);
2490    {
2491        // 1 : the elementSize of this type is 1
2492        result = Int32(1);
2493        Jump(&exit);
2494    }
2495    // 2 : index of this buffer
2496    Bind(&labelBuffer[2]);
2497    {
2498        // 1 : the elementSize of this type is 1
2499        result = Int32(1);
2500        Jump(&exit);
2501    }
2502    // 3 : index of this buffer
2503    Bind(&labelBuffer[3]);
2504    {
2505        // 2 : the elementSize of this type is 2
2506        result = Int32(2);
2507        Jump(&exit);
2508    }
2509    // 4 : index of this buffer
2510    Bind(&labelBuffer[4]);
2511    {
2512        // 2 : the elementSize of this type is 2
2513        result = Int32(2);
2514        Jump(&exit);
2515    }
2516    // 5 : index of this buffer
2517    Bind(&labelBuffer[5]);
2518    {
2519        // 4 : the elementSize of this type is 4
2520        result = Int32(4);
2521        Jump(&exit);
2522    }
2523    // 6 : index of this buffer
2524    Bind(&labelBuffer[6]);
2525    {
2526        // 4 : the elementSize of this type is 4
2527        result = Int32(4);
2528        Jump(&exit);
2529    }
2530    // 7 : index of this buffer
2531    Bind(&labelBuffer[7]);
2532    {
2533        // 4 : the elementSize of this type is 4
2534        result = Int32(4);
2535        Jump(&exit);
2536    }
2537    // 8 : index of this buffer
2538    Bind(&labelBuffer[8]);
2539    {
2540        // 8 : the elementSize of this type is 8
2541        result = Int32(8);
2542        Jump(&exit);
2543    }
2544    // 9 : index of this buffer
2545    Bind(&labelBuffer[9]);
2546    {
2547        // 8 : the elementSize of this type is 8
2548        result = Int32(8);
2549        Jump(&exit);
2550    }
2551    // 10 : index of this buffer
2552    Bind(&labelBuffer[10]);
2553    {
2554        // 8 : the elementSize of this type is 8
2555        result = Int32(8);
2556        Jump(&exit);
2557    }
2558    Bind(&defaultLabel);
2559    {
2560        FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
2561        Jump(&exit);
2562    }
2563
2564    Bind(&exit);
2565    auto ret = *result;
2566    env->SubCfgExit();
2567    return ret;
2568}
2569
2570GateRef NewObjectStubBuilder::GetOnHeapHClassFromType(GateRef glue, GateRef type)
2571{
2572    auto env = GetEnvironment();
2573    Label entry(env);
2574    env->SubCfgEntry(&entry);
2575
2576    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2577    GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2578    GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2579    Label defaultLabel(env);
2580    Label exit(env);
2581    Label labelBuffer[11] = {
2582        Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
2583        Label(env), Label(env), Label(env), Label(env), Label(env) };
2584    int64_t valueBuffer[11] = {
2585        static_cast<int64_t>(JSType::JS_INT8_ARRAY),
2586        static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
2587        static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY),
2588        static_cast<int64_t>(JSType::JS_INT16_ARRAY),
2589        static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
2590        static_cast<int64_t>(JSType::JS_INT32_ARRAY),
2591        static_cast<int64_t>(JSType::JS_UINT32_ARRAY),
2592        static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
2593        static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY),
2594        static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY),
2595        static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) };
2596
2597    // 11 : this switch has 11 case
2598    Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11);
2599    // 0 : index of this buffer
2600    Bind(&labelBuffer[0]);
2601    {
2602        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2603            GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2604        Jump(&exit);
2605    }
2606    // 1 : index of this buffer
2607    Bind(&labelBuffer[1]);
2608    {
2609        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2610            GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2611        Jump(&exit);
2612    }
2613    // 2 : index of this buffer
2614    Bind(&labelBuffer[2]);
2615    {
2616        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2617            GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2618        Jump(&exit);
2619    }
2620    // 3 : index of this buffer
2621    Bind(&labelBuffer[3]);
2622    {
2623        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2624            GlobalEnv::INT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2625        Jump(&exit);
2626    }
2627    // 4 : index of this buffer
2628    Bind(&labelBuffer[4]);
2629    {
2630        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2631            GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2632        Jump(&exit);
2633    }
2634    // 5 : index of this buffer
2635    Bind(&labelBuffer[5]);
2636    {
2637        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2638            GlobalEnv::INT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2639        Jump(&exit);
2640    }
2641    // 6 : index of this buffer
2642    Bind(&labelBuffer[6]);
2643    {
2644        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2645            GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2646        Jump(&exit);
2647    }
2648    // 7 : index of this buffer
2649    Bind(&labelBuffer[7]);
2650    {
2651        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2652            GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2653        Jump(&exit);
2654    }
2655    // 8 : index of this buffer
2656    Bind(&labelBuffer[8]);
2657    {
2658        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2659            GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2660        Jump(&exit);
2661    }
2662    // 9 : index of this buffer
2663    Bind(&labelBuffer[9]);
2664    {
2665        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2666            GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2667        Jump(&exit);
2668    }
2669    // 10 : index of this buffer
2670    Bind(&labelBuffer[10]);
2671    {
2672        result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2673            GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2674        Jump(&exit);
2675    }
2676    Bind(&defaultLabel);
2677    {
2678        FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
2679        Jump(&exit);
2680    }
2681
2682    Bind(&exit);
2683    auto ret = *result;
2684    env->SubCfgExit();
2685    return ret;
2686}
2687}  // namespace panda::ecmascript::kungfu
2688