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