• 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     BRANCH(TaggedIsString(obj), &isString, &isNotString);
1238     Bind(&isString);
1239     {
1240         object = CallRuntime(glue, RTSTUB_ID(PrimitiveStringCreate), { obj });
1241         Jump(&afterObjectTransform);
1242     }
1243     Bind(&isNotString);
1244     {
1245         object = ToPrototypeOrObj(glue, obj);
1246         Jump(&afterObjectTransform);
1247     }
1248     Bind(&afterObjectTransform);
1249     BRANCH(TaggedIsUndefinedOrNull(*object), &empty, &tryGetEnumCache);
1250     Bind(&tryGetEnumCache);
1251     GateRef enumCache = TryGetEnumCache(glue, *object);
1252     BRANCH(TaggedIsUndefined(enumCache), &slowpath, &cacheHit);
1253     Bind(&cacheHit);
1254     {
1255         GateRef hclass = LoadHClass(*object);
1256         result = NewJSForinIterator(glue, *object, enumCache, hclass);
1257         Jump(&exit);
1258     }
1259     Bind(&empty);
1260     {
1261         GateRef emptyArray = GetEmptyArray(glue);
1262         result = NewJSForinIterator(glue, Undefined(), emptyArray, Undefined());
1263         Jump(&exit);
1264     }
1265 
1266     Bind(&slowpath);
1267     {
1268         result = CallRuntime(glue, RTSTUB_ID(GetPropIteratorSlowpath), { *object });
1269         Jump(&exit);
1270     }
1271     Bind(&exit);
1272     auto ret = *result;
1273     env->SubCfgExit();
1274     return ret;
1275 }
1276 
FillArgumentsList(GateRef argumentsList,GateRef sp,GateRef startIdx,GateRef numArgs)1277 void NewObjectStubBuilder::FillArgumentsList(GateRef argumentsList,
1278     GateRef sp, GateRef startIdx, GateRef numArgs)
1279 {
1280     auto env = GetEnvironment();
1281     Label entry(env);
1282     env->SubCfgEntry(&entry);
1283     Label exit(env);
1284 
1285     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1286     Label setArgumentsBegin(env);
1287     Label setArgumentsAgain(env);
1288     Label setArgumentsEnd(env);
1289     BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
1290     LoopBegin(&setArgumentsBegin);
1291     GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
1292     GateRef argument = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx));
1293     SetValueToTaggedArray(VariableType::JS_ANY(), glue_, argumentsList, *i, argument);
1294     i = Int32Add(*i, Int32(1));
1295     BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
1296     Bind(&setArgumentsAgain);
1297     LoopEnd(&setArgumentsBegin);
1298     Bind(&setArgumentsEnd);
1299     Jump(&exit);
1300     Bind(&exit);
1301     env->SubCfgExit();
1302     return;
1303 }
1304 
NewArgumentsListObj(GateRef numArgs)1305 GateRef NewObjectStubBuilder::NewArgumentsListObj(GateRef numArgs)
1306 {
1307     auto env = GetEnvironment();
1308     Label entry(env);
1309     env->SubCfgEntry(&entry);
1310     Label exit(env);
1311     Label setHClass(env);
1312     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1313     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(numArgs));
1314     GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1315                                                 ConstantIndex::ARRAY_CLASS_INDEX);
1316     AllocateInYoung(&result, &exit, &setHClass, arrayClass);
1317     Bind(&setHClass);
1318     StoreHClass(glue_, *result, arrayClass);
1319     Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::LENGTH_OFFSET), numArgs);
1320     Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0));
1321     Jump(&exit);
1322     Bind(&exit);
1323     auto ret = *result;
1324     env->SubCfgExit();
1325     return ret;
1326 }
1327 
NewArgumentsList(Variable * result,Label * exit,GateRef sp,GateRef startIdx,GateRef numArgs)1328 void NewObjectStubBuilder::NewArgumentsList(Variable *result, Label *exit,
1329     GateRef sp, GateRef startIdx, GateRef numArgs)
1330 {
1331     auto env = GetEnvironment();
1332     Label hasException(env);
1333     Label notException(env);
1334 
1335     GateRef argumentsList = NewArgumentsListObj(numArgs);
1336     result->WriteVariable(argumentsList);
1337     Branch(TaggedIsException(argumentsList), &hasException, &notException);
1338     Bind(&hasException);
1339     Jump(exit);
1340     Bind(&notException);
1341     FillArgumentsList(argumentsList, sp, startIdx, numArgs);
1342     Jump(exit);
1343 }
1344 
NewArgumentsObj(Variable * result,Label * exit,GateRef argumentsList,GateRef numArgs)1345 void NewObjectStubBuilder::NewArgumentsObj(Variable *result, Label *exit,
1346     GateRef argumentsList, GateRef numArgs)
1347 {
1348     auto env = GetEnvironment();
1349 
1350     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1351     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset);
1352     GateRef argumentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1353                                                GlobalEnv::ARGUMENTS_CLASS);
1354     Label afterNewObject(env);
1355     NewJSObject(result, &afterNewObject, argumentsClass);
1356     Bind(&afterNewObject);
1357     Label setArgumentsObjProperties(env);
1358     BRANCH(TaggedIsException(result->ReadVariable()), exit, &setArgumentsObjProperties);
1359     Bind(&setArgumentsObjProperties);
1360     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, IntToTaggedInt(numArgs),
1361                             Int32(JSArguments::LENGTH_INLINE_PROPERTY_INDEX));
1362     SetElementsArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), argumentsList);
1363     GateRef arrayProtoValuesFunction = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1364                                                          GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
1365     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, arrayProtoValuesFunction,
1366                             Int32(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX));
1367     GateRef accessorCaller = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1368                                                GlobalEnv::ARGUMENTS_CALLER_ACCESSOR);
1369     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCaller,
1370                             Int32(JSArguments::CALLER_INLINE_PROPERTY_INDEX));
1371     GateRef accessorCallee = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
1372                                                GlobalEnv::ARGUMENTS_CALLEE_ACCESSOR);
1373     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCallee,
1374                             Int32(JSArguments::CALLEE_INLINE_PROPERTY_INDEX));
1375     Jump(exit);
1376 }
1377 
AssignRestArg(Variable * result,Label * exit,GateRef sp,GateRef startIdx,GateRef numArgs,GateRef intialHClass)1378 void NewObjectStubBuilder::AssignRestArg(Variable *result, Label *exit,
1379     GateRef sp, GateRef startIdx, GateRef numArgs, GateRef intialHClass)
1380 {
1381     auto env = GetEnvironment();
1382     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1383     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1384     Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, TruncInt64ToInt32(numArgs));
1385     GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1386     SetPropertyInlinedProps(glue_, result->ReadVariable(), intialHClass, accessor,
1387                             Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
1388     SetExtensibleToBitfield(glue_, result->ReadVariable(), true);
1389     Label setArgumentsBegin(env);
1390     Label setArgumentsAgain(env);
1391     Label setArgumentsEnd(env);
1392     GateRef elements = GetElementsArray(result->ReadVariable());
1393     BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
1394     LoopBegin(&setArgumentsBegin);
1395     {
1396         GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
1397         GateRef receiver = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx));
1398         SetValueToTaggedArray(VariableType::JS_ANY(), glue_, elements, *i, receiver);
1399         i = Int32Add(*i, Int32(1));
1400         BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
1401         Bind(&setArgumentsAgain);
1402     }
1403     LoopEnd(&setArgumentsBegin);
1404     Bind(&setArgumentsEnd);
1405     Jump(exit);
1406 }
1407 
NewJSArrayLiteral(Variable * result,Label * exit,RegionSpaceFlag spaceType,GateRef obj,GateRef hclass,GateRef trackInfo,bool isEmptyArray)1408 void NewObjectStubBuilder::NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj,
1409                                              GateRef hclass, GateRef trackInfo, bool isEmptyArray)
1410 {
1411     auto env = GetEnvironment();
1412     Label initializeArray(env);
1413     Label afterInitialize(env);
1414     HeapAlloc(result, &initializeArray, spaceType, hclass);
1415     Bind(&initializeArray);
1416     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(0), hclass);
1417     InitializeWithSpeicalValue(&afterInitialize, result->ReadVariable(), Undefined(), Int32(JSArray::SIZE),
1418                                TruncInt64ToInt32(size_), MemoryAttribute::NoBarrier());
1419     Bind(&afterInitialize);
1420     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
1421     Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()));
1422 
1423     GateRef propertiesOffset = IntPtr(JSObject::PROPERTIES_OFFSET);
1424     GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
1425     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1426     GateRef trackInfoOffset = IntPtr(JSArray::TRACK_INFO_OFFSET);
1427     if (isEmptyArray) {
1428         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, obj);
1429         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, obj);
1430         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, Int32(0));
1431     } else {
1432         auto newProperties = Load(VariableType::JS_POINTER(), obj, propertiesOffset);
1433         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, newProperties);
1434 
1435         auto newElements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
1436         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, newElements);
1437 
1438         GateRef arrayLength = Load(VariableType::INT32(), obj, lengthOffset);
1439         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, arrayLength);
1440     }
1441     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), trackInfoOffset, trackInfo);
1442 
1443     auto accessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1444     SetPropertyInlinedProps(glue_, result->ReadVariable(), hclass, accessor,
1445         Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_POINTER(), MemoryAttribute::NoBarrier());
1446     Jump(exit);
1447 }
1448 
HeapAlloc(Variable * result,Label * exit,RegionSpaceFlag spaceType,GateRef hclass)1449 void NewObjectStubBuilder::HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef hclass)
1450 {
1451     switch (spaceType) {
1452         case RegionSpaceFlag::IN_YOUNG_SPACE:
1453             AllocateInYoung(result, exit, hclass);
1454             break;
1455         default:
1456             break;
1457     }
1458 }
1459 
AllocateInSOldPrologue(Variable * result,Label * callRuntime,Label * exit)1460 void NewObjectStubBuilder::AllocateInSOldPrologue(Variable *result, Label *callRuntime, Label *exit)
1461 {
1462     auto env = GetEnvironment();
1463     Label success(env);
1464     Label next(env);
1465 
1466 #ifdef ARK_ASAN_ON
1467     Jump(callRuntime);
1468 #else
1469 #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
1470     auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
1471     auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
1472     BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next);
1473     Bind(&next);
1474 #endif
1475     auto topOffset = JSThread::GlueData::GetSOldSpaceAllocationTopAddressOffset(env->Is32Bit());
1476     auto endOffset = JSThread::GlueData::GetSOldSpaceAllocationEndAddressOffset(env->Is32Bit());
1477     auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
1478     auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
1479     auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0));
1480     auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0));
1481     auto newTop = PtrAdd(top, size_);
1482     BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success);
1483     Bind(&success);
1484     {
1485         Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop);
1486         if (env->Is32Bit()) {
1487             top = ZExtInt32ToInt64(top);
1488         }
1489         result->WriteVariable(top);
1490         Jump(exit);
1491     }
1492 #endif
1493 }
1494 
AllocateInSOld(Variable * result,Label * exit,GateRef hclass)1495 void NewObjectStubBuilder::AllocateInSOld(Variable *result, Label *exit, GateRef hclass)
1496 {
1497     auto env = GetEnvironment();
1498     Label callRuntime(env);
1499     AllocateInSOldPrologue(result, &callRuntime, exit);
1500     Bind(&callRuntime);
1501     {
1502         DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1503         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInSOld), {IntToTaggedInt(size_), hclass});
1504         result->WriteVariable(*ret);
1505         Jump(exit);
1506     }
1507 }
1508 
AllocateInYoungPrologue(Variable * result,Label * callRuntime,Label * exit)1509 void NewObjectStubBuilder::AllocateInYoungPrologue(Variable *result, Label *callRuntime, Label *exit)
1510 {
1511     auto env = GetEnvironment();
1512     Label success(env);
1513     Label next(env);
1514 
1515 #ifdef ARK_ASAN_ON
1516     Jump(callRuntime);
1517 #else
1518 #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
1519     auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
1520     auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
1521     BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next);
1522     Bind(&next);
1523 #endif
1524     auto topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(env->Is32Bit());
1525     auto endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(env->Is32Bit());
1526     auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
1527     auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
1528     auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0));
1529     auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0));
1530     auto newTop = PtrAdd(top, size_);
1531     BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success);
1532     Bind(&success);
1533     {
1534         Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop, MemoryAttribute::NoBarrier());
1535         if (env->Is32Bit()) {
1536             top = ZExtInt32ToInt64(top);
1537         }
1538         result->WriteVariable(top);
1539         Jump(exit);
1540     }
1541 #endif
1542 }
1543 
AllocateInYoung(Variable * result,Label * exit,GateRef hclass)1544 void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *exit, GateRef hclass)
1545 {
1546     auto env = GetEnvironment();
1547     Label callRuntime(env);
1548     AllocateInYoungPrologue(result, &callRuntime, exit);
1549     Bind(&callRuntime);
1550     {
1551         DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1552         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
1553             Int64ToTaggedInt(size_), hclass });
1554         result->WriteVariable(*ret);
1555         Jump(exit);
1556     }
1557 }
1558 
AllocateInYoung(Variable * result,Label * error,Label * noError,GateRef hclass)1559 void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *error, Label *noError, GateRef hclass)
1560 {
1561     auto env = GetEnvironment();
1562     Label callRuntime(env);
1563     AllocateInYoungPrologue(result, &callRuntime, noError);
1564     Bind(&callRuntime);
1565     {
1566         DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1567         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
1568             Int64ToTaggedInt(size_), hclass });
1569         result->WriteVariable(*ret);
1570         BRANCH(TaggedIsException(*ret), error, noError);
1571     }
1572 }
1573 
NewTrackInfo(GateRef glue,GateRef cachedHClass,GateRef cachedFunc,RegionSpaceFlag spaceFlag,GateRef arraySize)1574 GateRef NewObjectStubBuilder::NewTrackInfo(GateRef glue, GateRef cachedHClass, GateRef cachedFunc,
1575                                            RegionSpaceFlag spaceFlag, GateRef arraySize)
1576 {
1577     auto env = GetEnvironment();
1578     Label entry(env);
1579     env->SubCfgEntry(&entry);
1580 
1581     Label initialize(env);
1582     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1583     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::TRACK_INFO_CLASS_INDEX);
1584     GateRef size = GetObjectSizeFromHClass(hclass);
1585     SetParameters(glue, size);
1586     HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
1587     Bind(&initialize);
1588     Store(VariableType::JS_POINTER(), glue_, *result, IntPtr(0), hclass);
1589     GateRef cachedHClassOffset = IntPtr(TrackInfo::CACHED_HCLASS_OFFSET);
1590     Store(VariableType::JS_POINTER(), glue, *result, cachedHClassOffset, cachedHClass);
1591     GateRef cachedFuncOffset = IntPtr(TrackInfo::CACHED_FUNC_OFFSET);
1592     GateRef weakCachedFunc = env->GetBuilder()->CreateWeakRef(cachedFunc);
1593     Store(VariableType::JS_POINTER(), glue, *result, cachedFuncOffset, weakCachedFunc);
1594     GateRef arrayLengthOffset = IntPtr(TrackInfo::ARRAY_LENGTH_OFFSET);
1595     Store(VariableType::INT32(), glue, *result, arrayLengthOffset, arraySize);
1596     SetSpaceFlagToTrackInfo(glue, *result, Int32(spaceFlag));
1597     auto elementsKind = GetElementsKindFromHClass(cachedHClass);
1598     SetElementsKindToTrackInfo(glue, *result, elementsKind);
1599     auto ret = *result;
1600     env->SubCfgExit();
1601     return ret;
1602 }
1603 
InitializeWithSpeicalValue(Label * exit,GateRef object,GateRef value,GateRef start,GateRef end,MemoryAttribute mAttr)1604 void NewObjectStubBuilder::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef value, GateRef start,
1605                                                       GateRef end, MemoryAttribute mAttr)
1606 {
1607     {
1608         ASM_ASSERT(GET_MESSAGE_STRING_ID(InitializeWithSpeicalValue),
1609                    Int32Equal(Int32Mod(Int32Sub(end, start), Int32(JSTaggedValue::TaggedTypeSize())), Int32(0)));
1610     }
1611     auto env = GetEnvironment();
1612     Label begin(env);
1613     Label storeValue(env);
1614     Label endLoop(env);
1615     Label storeHead(env);
1616     Label enterLoop(env);
1617     DEFVARIABLE(startOffset, VariableType::INT32(), start);
1618     const auto tSize = static_cast<int32_t>(JSTaggedValue::TaggedTypeSize());
1619     static_assert((tSize & (tSize - 1)) == 0 && "tSize must be power of 2");
1620     GateRef length = Int32Sub(end, start);
1621     GateRef remainder = Int32And(length, Int32(LOOP_UNROLL_FACTOR * tSize - 1));
1622     BRANCH(Int32NotEqual(remainder, Int32(0)), &storeHead, &enterLoop);
1623     Bind(&storeHead);
1624     {
1625         // Now use 2 as loop unroll factor, so only store once if reminder is not 0.
1626         // But if using other loop unroll factor, the store head should also be refactored.
1627         Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(start), value, mAttr);
1628         startOffset = Int32Add(start, Int32(tSize));
1629         Jump(&enterLoop);
1630     }
1631     Bind(&enterLoop);
1632     {
1633         Jump(&begin);
1634     }
1635     LoopBegin(&begin);
1636     {
1637         BRANCH(Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
1638         Bind(&storeValue);
1639         {
1640             auto off = *startOffset;
1641             for (auto i = 0; i < LOOP_UNROLL_FACTOR; i++) {
1642                 Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(off), value, mAttr);
1643                 off = Int32Add(off, Int32(tSize));
1644             }
1645             startOffset = Int32Add(*startOffset, Int32(LOOP_UNROLL_FACTOR * tSize));
1646             Jump(&endLoop);
1647         }
1648         Bind(&endLoop);
1649         LoopEnd(&begin);
1650     }
1651 }
1652 
InitializeTaggedArrayWithSpeicalValue(Label * exit,GateRef array,GateRef value,GateRef start,GateRef length)1653 void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit,
1654     GateRef array, GateRef value, GateRef start, GateRef length)
1655 {
1656     Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::LENGTH_OFFSET), length);
1657     Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0));
1658     auto offset = Int32Mul(start, Int32(JSTaggedValue::TaggedTypeSize()));
1659     auto dataOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
1660     offset = Int32Mul(length, Int32(JSTaggedValue::TaggedTypeSize()));
1661     auto endOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
1662     InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset);
1663 }
1664 
AllocLineStringObject(Variable * result,Label * exit,GateRef length,bool compressed)1665 void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
1666 {
1667     auto env = GetEnvironment();
1668     if (compressed) {
1669         size_ = AlignUp(ComputeSizeUtf8(ZExtInt32ToPtr(length)),
1670             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1671     } else {
1672         size_ = AlignUp(ComputeSizeUtf16(ZExtInt32ToPtr(length)),
1673             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1674     }
1675     Label afterAllocate(env);
1676     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1677                                                  ConstantIndex::LINE_STRING_CLASS_INDEX);
1678     AllocateInSOld(result, &afterAllocate, stringClass);
1679 
1680     Bind(&afterAllocate);
1681     StoreHClass(glue_, result->ReadVariable(), stringClass);
1682     SetLength(glue_, result->ReadVariable(), length, compressed);
1683     SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
1684     Jump(exit);
1685 }
1686 
AllocSlicedStringObject(Variable * result,Label * exit,GateRef from,GateRef length,FlatStringStubBuilder * flatString)1687 void NewObjectStubBuilder::AllocSlicedStringObject(Variable *result, Label *exit, GateRef from, GateRef length,
1688     FlatStringStubBuilder *flatString)
1689 {
1690     auto env = GetEnvironment();
1691 
1692     size_ = AlignUp(IntPtr(SlicedString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1693     Label afterAllocate(env);
1694     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1695                                                  ConstantIndex::SLICED_STRING_CLASS_INDEX);
1696     AllocateInSOld(result, &afterAllocate, stringClass);
1697 
1698     Bind(&afterAllocate);
1699     StoreHClass(glue_, result->ReadVariable(), stringClass);
1700     GateRef mixLength = Load(VariableType::INT32(), flatString->GetFlatString(), IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1701     GateRef isCompressed = Int32And(Int32(EcmaString::STRING_COMPRESSED_BIT), mixLength);
1702     SetLength(glue_, result->ReadVariable(), length, isCompressed);
1703     SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
1704     BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
1705     builtinsStringStubBuilder.StoreParent(glue_, result->ReadVariable(), flatString->GetFlatString());
1706     builtinsStringStubBuilder.StoreStartIndex(glue_, result->ReadVariable(),
1707         Int32Add(from, flatString->GetStartIndex()));
1708     builtinsStringStubBuilder.StoreHasBackingStore(glue_, result->ReadVariable(), Int32(0));
1709     Jump(exit);
1710 }
1711 
AllocTreeStringObject(Variable * result,Label * exit,GateRef first,GateRef second,GateRef length,bool compressed)1712 void NewObjectStubBuilder::AllocTreeStringObject(Variable *result, Label *exit, GateRef first, GateRef second,
1713     GateRef length, bool compressed)
1714 {
1715     auto env = GetEnvironment();
1716 
1717     size_ = AlignUp(IntPtr(TreeEcmaString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1718     Label afterAllocate(env);
1719     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1720                                                  ConstantIndex::TREE_STRING_CLASS_INDEX);
1721     AllocateInSOld(result, &afterAllocate, stringClass);
1722 
1723     Bind(&afterAllocate);
1724     StoreHClass(glue_, result->ReadVariable(), stringClass);
1725     SetLength(glue_, result->ReadVariable(), length, compressed);
1726     SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
1727     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::FIRST_OFFSET), first);
1728     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::SECOND_OFFSET), second);
1729     Jump(exit);
1730 }
1731 
FastNewThisObject(GateRef glue,GateRef ctor)1732 GateRef NewObjectStubBuilder::FastNewThisObject(GateRef glue, GateRef ctor)
1733 {
1734     auto env = GetEnvironment();
1735     Label entry(env);
1736     env->SubCfgEntry(&entry);
1737     Label exit(env);
1738     Label isHeapObject(env);
1739     Label callRuntime(env);
1740     Label checkJSObject(env);
1741     Label newObject(env);
1742     Label isJSObject(env);
1743 
1744     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1745     auto protoOrHclass = Load(VariableType::JS_ANY(), ctor,
1746         IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1747     BRANCH(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &callRuntime);
1748     Bind(&isHeapObject);
1749     BRANCH(IsJSHClass(protoOrHclass), &checkJSObject, &callRuntime);
1750     Bind(&checkJSObject);
1751     auto objectType = GetObjectType(protoOrHclass);
1752     BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))), &isJSObject, &callRuntime);
1753     Bind(&isJSObject);
1754     {
1755         auto funcProto = GetPrototypeFromHClass(protoOrHclass);
1756         BRANCH(IsEcmaObject(funcProto), &newObject, &callRuntime);
1757     }
1758     Bind(&newObject);
1759     {
1760         SetParameters(glue, 0);
1761         NewJSObject(&thisObj, &exit, protoOrHclass);
1762     }
1763     Bind(&callRuntime);
1764     {
1765         thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor, Undefined()});
1766         Jump(&exit);
1767     }
1768     Bind(&exit);
1769     auto ret = *thisObj;
1770     env->SubCfgExit();
1771     return ret;
1772 }
1773 
FastSuperAllocateThis(GateRef glue,GateRef superCtor,GateRef newTarget)1774 GateRef NewObjectStubBuilder::FastSuperAllocateThis(GateRef glue, GateRef superCtor, GateRef newTarget)
1775 {
1776     auto env = GetEnvironment();
1777     Label entry(env);
1778     env->SubCfgEntry(&entry);
1779     Label exit(env);
1780     Label isHeapObject(env);
1781     Label checkJSObject(env);
1782     Label callRuntime(env);
1783     Label newObject(env);
1784     Label isFunction(env);
1785 
1786     BRANCH(IsJSFunction(newTarget), &isFunction, &callRuntime);
1787     Bind(&isFunction);
1788     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1789     DEFVARIABLE(protoOrHclass, VariableType::JS_ANY(), Undefined());
1790     protoOrHclass = Load(VariableType::JS_ANY(), newTarget,
1791         IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1792     BRANCH(TaggedIsHeapObject(*protoOrHclass), &isHeapObject, &callRuntime);
1793     Bind(&isHeapObject);
1794     BRANCH(IsJSHClass(*protoOrHclass), &checkJSObject, &callRuntime);
1795     Bind(&checkJSObject);
1796     auto objectType = GetObjectType(*protoOrHclass);
1797     BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))),
1798         &newObject, &callRuntime);
1799     Bind(&newObject);
1800     {
1801         SetParameters(glue, 0);
1802         NewJSObject(&thisObj, &exit, *protoOrHclass);
1803     }
1804     Bind(&callRuntime);
1805     {
1806         thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {superCtor, newTarget});
1807         Jump(&exit);
1808     }
1809     Bind(&exit);
1810     auto ret = *thisObj;
1811     env->SubCfgExit();
1812     return ret;
1813 }
1814 
NewThisObjectChecked(GateRef glue,GateRef ctor)1815 GateRef NewObjectStubBuilder::NewThisObjectChecked(GateRef glue, GateRef ctor)
1816 {
1817     auto env = GetEnvironment();
1818     Label entry(env);
1819     env->SubCfgEntry(&entry);
1820     Label exit(env);
1821 
1822     Label ctorIsHeapObject(env);
1823     Label ctorIsJSFunction(env);
1824     Label fastPath(env);
1825     Label slowPath(env);
1826     Label ctorIsBase(env);
1827 
1828     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1829 
1830     BRANCH(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath);
1831     Bind(&ctorIsHeapObject);
1832     BRANCH(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath);
1833     Bind(&ctorIsJSFunction);
1834     BRANCH(IsConstructor(ctor), &fastPath, &slowPath);
1835     Bind(&fastPath);
1836     {
1837         BRANCH(IsBase(ctor), &ctorIsBase, &exit);
1838         Bind(&ctorIsBase);
1839         {
1840             thisObj = FastNewThisObject(glue, ctor);
1841             Jump(&exit);
1842         }
1843     }
1844     Bind(&slowPath);
1845     {
1846         thisObj = Hole();
1847         Jump(&exit);
1848     }
1849     Bind(&exit);
1850     auto ret = *thisObj;
1851     env->SubCfgExit();
1852     return ret;
1853 }
1854 
1855 // 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)1856 GateRef NewObjectStubBuilder::LoadTrackInfo(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo,
1857     GateRef profileTypeInfo, GateRef slotId, GateRef slotValue, GateRef arrayLiteral, ProfileOperation callback)
1858 {
1859     auto env = GetEnvironment();
1860     Label entry(env);
1861     env->SubCfgEntry(&entry);
1862     Label exit(env);
1863     DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
1864 
1865     Label uninitialized(env);
1866     Label fastpath(env);
1867     BRANCH(TaggedIsHeapObject(slotValue), &fastpath, &uninitialized);
1868     Bind(&fastpath);
1869     {
1870         ret = slotValue;
1871         Jump(&exit);
1872     }
1873     Bind(&uninitialized);
1874     {
1875         auto hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, arrayLiteral, callback);
1876         // emptyarray
1877         if (arrayLiteral == Circuit::NullGate()) {
1878             ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, Int32(0));
1879         } else {
1880             GateRef arrayLength = GetArrayLength(arrayLiteral);
1881             ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, arrayLength);
1882         }
1883 
1884         SetValueToTaggedArray(VariableType::JS_POINTER(), glue, profileTypeInfo, slotId, *ret);
1885         callback.TryPreDump();
1886         Jump(&exit);
1887     }
1888     Bind(&exit);
1889     auto result = *ret;
1890     env->SubCfgExit();
1891     return result;
1892 }
1893 
LoadArrayHClassSlowPath(GateRef glue,GateRef jsFunc,TraceIdInfo traceIdInfo,GateRef arrayLiteral,ProfileOperation callback)1894 GateRef NewObjectStubBuilder::LoadArrayHClassSlowPath(
1895     GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo, GateRef arrayLiteral, ProfileOperation callback)
1896 {
1897     auto env = GetEnvironment();
1898     Label entry(env);
1899     env->SubCfgEntry(&entry);
1900     Label exit(env);
1901     Label originLoad(env);
1902 
1903     DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
1904 
1905     auto hcIndexInfos = LoadHCIndexInfosFromConstPool(jsFunc);
1906     auto indexInfosLength = GetLengthOfTaggedArray(hcIndexInfos);
1907     Label aotLoad(env);
1908     BRANCH(Int32Equal(indexInfosLength, Int32(0)), &originLoad, &aotLoad);
1909     Bind(&aotLoad);
1910     {
1911         GateRef traceId = 0;
1912         if (traceIdInfo.isPc) {
1913             auto pfAddr = LoadPfHeaderFromConstPool(jsFunc);
1914             traceId = TruncPtrToInt32(PtrSub(traceIdInfo.pc, pfAddr));
1915         } else {
1916             traceId = traceIdInfo.traceId;
1917         }
1918 
1919         GateRef hcIndex = LoadHCIndexFromConstPool(hcIndexInfos, indexInfosLength, traceId, &originLoad);
1920         GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
1921             IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit())));
1922         GateRef offset = Int32Mul(Int32(sizeof(JSTaggedValue)), hcIndex);
1923         ret = Load(VariableType::JS_POINTER(), gConstAddr, offset);
1924         Jump(&exit);
1925     }
1926     Bind(&originLoad);
1927     {
1928         // emptyarray
1929         if (arrayLiteral == Circuit::NullGate()) {
1930             if (callback.IsEmpty()) {
1931                 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1932                 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1933                 auto arrayFunc =
1934                     GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
1935                 ret = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1936             } else {
1937                 ret =
1938                     GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
1939             }
1940         } else {
1941             ret = LoadHClass(arrayLiteral);
1942         }
1943         Jump(&exit);
1944     }
1945     Bind(&exit);
1946     auto result = *ret;
1947     env->SubCfgExit();
1948     return result;
1949 }
1950 
CreateEmptyArrayCommon(GateRef glue,GateRef hclass,GateRef trackInfo)1951 GateRef NewObjectStubBuilder::CreateEmptyArrayCommon(GateRef glue, GateRef hclass, GateRef trackInfo)
1952 {
1953     auto env = GetEnvironment();
1954     Label entry(env);
1955     env->SubCfgEntry(&entry);
1956     Label exit(env);
1957 
1958     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1959 
1960     GateRef size = GetObjectSizeFromHClass(hclass);
1961     GateRef emptyArray = GetGlobalConstantValue(
1962         VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
1963     SetParameters(glue, size);
1964     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, emptyArray, hclass, trackInfo, true);
1965     Bind(&exit);
1966     GateRef ret = *result;
1967     env->SubCfgExit();
1968     return ret;
1969 }
1970 
CreateEmptyObject(GateRef glue)1971 GateRef NewObjectStubBuilder::CreateEmptyObject(GateRef glue)
1972 {
1973     auto env = GetEnvironment();
1974     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1975     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1976     GateRef objectFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX);
1977     GateRef hclass = Load(VariableType::JS_POINTER(), objectFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1978     return NewJSObject(glue, hclass);
1979 }
1980 
CreateEmptyArray(GateRef glue)1981 GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue)
1982 {
1983     auto env = GetEnvironment();
1984     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
1985     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1986     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1987     GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
1988     GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1989     return CreateEmptyArrayCommon(glue, hclass, *trackInfo);
1990 }
1991 
CreateEmptyArray(GateRef glue,GateRef jsFunc,TraceIdInfo traceIdInfo,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)1992 GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo,
1993     GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
1994 {
1995     auto env = GetEnvironment();
1996     Label entry(env);
1997     env->SubCfgEntry(&entry);
1998 
1999     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
2000     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
2001     Label slowpath(env);
2002     Label mayFastpath(env);
2003     Label createArray(env);
2004     Label profileNotUndefined(env);
2005     BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined);
2006     Bind(&profileNotUndefined);
2007     GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
2008     BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath);
2009     Bind(&mayFastpath);
2010     {
2011         trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo,
2012             slotId, slotValue, Circuit::NullGate(), callback);
2013         hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
2014         trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
2015         Jump(&createArray);
2016     }
2017     Bind(&slowpath);
2018     {
2019         hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, Circuit::NullGate(), callback);
2020         Jump(&createArray);
2021     }
2022     Bind(&createArray);
2023     GateRef result = CreateEmptyArrayCommon(glue, *hclass, *trackInfo);
2024     env->SubCfgExit();
2025     return result;
2026 }
2027 
CreateArrayWithBuffer(GateRef glue,GateRef index,GateRef jsFunc,TraceIdInfo traceIdInfo,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)2028 GateRef NewObjectStubBuilder::CreateArrayWithBuffer(GateRef glue, GateRef index, GateRef jsFunc,
2029     TraceIdInfo traceIdInfo, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
2030 {
2031     auto env = GetEnvironment();
2032     Label entry(env);
2033     env->SubCfgEntry(&entry);
2034     Label exit(env);
2035 
2036     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2037     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
2038     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
2039 
2040     GateRef method = GetMethodFromFunction(jsFunc);
2041     GateRef constPool = Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
2042     GateRef module = GetModuleFromFunction(jsFunc);
2043 
2044     auto obj = GetArrayLiteralFromConstPool(glue, constPool, index, module);
2045 
2046     Label slowpath(env);
2047     Label mayFastpath(env);
2048     Label createArray(env);
2049     Label profileNotUndefined(env);
2050     BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined);
2051     Bind(&profileNotUndefined);
2052     GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
2053     BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath);
2054     Bind(&mayFastpath);
2055     {
2056         trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo, slotId, slotValue, obj, callback);
2057         hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
2058         trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
2059         Jump(&createArray);
2060     }
2061     Bind(&slowpath);
2062     {
2063         hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, obj, callback);
2064         Jump(&createArray);
2065     }
2066     Bind(&createArray);
2067     GateRef size = GetObjectSizeFromHClass(*hclass);
2068 
2069     SetParameters(glue, size);
2070     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, obj, *hclass, *trackInfo, false);
2071 
2072     Bind(&exit);
2073     auto ret = *result;
2074     env->SubCfgExit();
2075     return ret;
2076 }
2077 
2078 template <typename IteratorType, typename CollectionType>
CreateJSCollectionIterator(Variable * result,Label * exit,GateRef thisValue,GateRef kind)2079 void NewObjectStubBuilder::CreateJSCollectionIterator(
2080     Variable *result, Label *exit, GateRef thisValue, GateRef kind)
2081 {
2082     ASSERT_PRINT((std::is_same_v<IteratorType, JSSetIterator> || std::is_same_v<IteratorType, JSMapIterator>),
2083         "IteratorType must be JSSetIterator or JSMapIterator type");
2084     auto env = GetEnvironment();
2085     ConstantIndex iterClassIdx = static_cast<ConstantIndex>(0);
2086     int32_t iterOffset = 0;       // ITERATED_SET_OFFSET
2087     size_t linkedOffset = 0;      // LINKED_MAP_OFFSET
2088     if constexpr (std::is_same_v<IteratorType, JSSetIterator>) {
2089         iterClassIdx = ConstantIndex::JS_SET_ITERATOR_CLASS_INDEX;
2090         iterOffset = IteratorType::ITERATED_SET_OFFSET;
2091         linkedOffset = CollectionType::LINKED_SET_OFFSET;
2092         size_ = IntPtr(JSSetIterator::SIZE);
2093     } else {
2094         iterClassIdx = ConstantIndex::JS_MAP_ITERATOR_CLASS_INDEX;
2095         iterOffset = IteratorType::ITERATED_MAP_OFFSET;
2096         linkedOffset = CollectionType::LINKED_MAP_OFFSET;
2097         size_ = IntPtr(JSMapIterator::SIZE);
2098     }
2099     GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx);
2100 
2101     Label noException(env);
2102     // Be careful. NO GC is allowed when initization is not complete.
2103     AllocateInYoung(result, exit, &noException, iteratorHClass);
2104     Bind(&noException);
2105     {
2106         StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass);
2107         GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
2108         Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()));
2109         auto emptyArray = GetGlobalConstantValue(
2110             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
2111         SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2112         SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2113 
2114         // GetLinked
2115         GateRef linked = Load(VariableType::JS_ANY(), thisValue, IntPtr(linkedOffset));
2116         // SetIterated
2117         GateRef iteratorOffset = IntPtr(iterOffset);
2118         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, linked,
2119               MemoryAttribute::UnknownBarrier());
2120 
2121         // SetIteratorNextIndex
2122         GateRef nextIndexOffset = IntPtr(IteratorType::NEXT_INDEX_OFFSET);
2123         Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0));
2124 
2125         // SetIterationKind
2126         GateRef kindBitfieldOffset = IntPtr(IteratorType::BIT_FIELD_OFFSET);
2127         Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind);
2128         Jump(exit);
2129     }
2130 }
2131 
2132 template void NewObjectStubBuilder::CreateJSCollectionIterator<JSSetIterator, JSSet>(
2133     Variable *result, Label *exit, GateRef set, GateRef kind);
2134 template void NewObjectStubBuilder::CreateJSCollectionIterator<JSMapIterator, JSMap>(
2135     Variable *result, Label *exit, GateRef set, GateRef kind);
2136 
CreateJSTypedArrayIterator(Variable * result,Label * exit,GateRef thisValue,GateRef kind)2137 void NewObjectStubBuilder::CreateJSTypedArrayIterator(Variable *result, Label *exit, GateRef thisValue, GateRef kind)
2138 {
2139     auto env = GetEnvironment();
2140     size_ = IntPtr(JSArrayIterator::SIZE);
2141 
2142     ConstantIndex iterClassIdx = ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX;
2143     GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx);
2144 
2145     Label thisExists(env);
2146     Label isEcmaObject(env);
2147     Label isTypedArray(env);
2148     Label throwTypeError(env);
2149 
2150     BRANCH(TaggedIsUndefinedOrNullOrHole(thisValue), &throwTypeError, &thisExists);
2151     Bind(&thisExists);
2152     BRANCH(IsEcmaObject(thisValue), &isEcmaObject, &throwTypeError);
2153     Bind(&isEcmaObject);
2154     BRANCH(IsTypedArray(thisValue), &isTypedArray, &throwTypeError);
2155     Bind(&isTypedArray);
2156 
2157     Label noException(env);
2158     // Be careful. NO GC is allowed when initization is not complete.
2159     AllocateInYoung(result, exit, &noException, iteratorHClass);
2160     Bind(&noException);
2161     {
2162         StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass);
2163         GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
2164         Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()));
2165         auto emptyArray = GetGlobalConstantValue(
2166             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
2167         SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2168         SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
2169 
2170         GateRef iteratorOffset = IntPtr(JSArrayIterator::ITERATED_ARRAY_OFFSET);
2171         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, thisValue,
2172               MemoryAttribute::NeedBarrier());
2173 
2174         // SetIteratorNextIndex
2175         GateRef nextIndexOffset = IntPtr(JSArrayIterator::NEXT_INDEX_OFFSET);
2176         Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0));
2177 
2178         // SetIterationKind
2179         GateRef kindBitfieldOffset = IntPtr(JSArrayIterator::BIT_FIELD_OFFSET);
2180         Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind);
2181         Jump(exit);
2182     }
2183 
2184     Bind(&throwTypeError);
2185     {
2186         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotTypedArray));
2187         CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2188         result->WriteVariable(Exception());
2189         Jump(exit);
2190     }
2191 }
2192 
NewTaggedSubArray(GateRef glue,GateRef srcTypedArray,GateRef elementSize,GateRef newLength,GateRef beginIndex,GateRef arrayCls,GateRef buffer)2193 GateRef NewObjectStubBuilder::NewTaggedSubArray(GateRef glue, GateRef srcTypedArray,
2194     GateRef elementSize, GateRef newLength, GateRef beginIndex, GateRef arrayCls, GateRef buffer)
2195 {
2196     auto env = GetEnvironment();
2197     Label entry(env);
2198     env->SubCfgEntry(&entry);
2199     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2200     GateRef constructorName = Load(VariableType::JS_POINTER(), srcTypedArray,
2201         IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
2202     GateRef srcByteOffset = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
2203     GateRef contentType = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
2204     GateRef beginByteOffset = Int32Add(srcByteOffset, Int32Mul(beginIndex, elementSize));
2205 
2206     GateRef obj = NewJSObject(glue, arrayCls);
2207     result = obj;
2208     GateRef newByteLength = Int32Mul(elementSize, newLength);
2209     Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), buffer);
2210     Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), constructorName);
2211     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2212     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), beginByteOffset);
2213     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), newLength);
2214     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
2215     auto ret = *result;
2216     env->SubCfgExit();
2217     return ret;
2218 }
2219 
NewTypedArray(GateRef glue,GateRef srcTypedArray,GateRef srcType,GateRef length)2220 GateRef NewObjectStubBuilder::NewTypedArray(GateRef glue, GateRef srcTypedArray, GateRef srcType, GateRef length)
2221 {
2222     auto env = GetEnvironment();
2223     Label entry(env);
2224     env->SubCfgEntry(&entry);
2225 
2226     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2227     Label slowPath(env);
2228     Label defaultConstr(env);
2229     Label markerCellValid(env);
2230     Label isProtoChangeMarker(env);
2231     Label accessorNotChanged(env);
2232     Label exit(env);
2233     BRANCH(HasConstructor(srcTypedArray), &slowPath, &defaultConstr);
2234     Bind(&defaultConstr);
2235     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2236     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2237     GateRef markerCell = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2238         GlobalEnv::TYPED_ARRAY_SPECIES_PROTECT_DETECTOR_INDEX);
2239     BRANCH(IsMarkerCellValid(markerCell), &markerCellValid, &slowPath);
2240     Bind(&markerCellValid);
2241     GateRef marker = GetProtoChangeMarkerFromHClass(LoadHClass(srcTypedArray));
2242     BRANCH(TaggedIsProtoChangeMarker(marker), &isProtoChangeMarker, &accessorNotChanged);
2243     Bind(&isProtoChangeMarker);
2244     BRANCH(GetAccessorHasChanged(marker), &slowPath, &accessorNotChanged);
2245 
2246     Bind(&accessorNotChanged);
2247     {
2248         DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2249         Label next(env);
2250         GateRef hclass = LoadHClass(srcTypedArray);
2251         GateRef obj = NewJSObject(glue, hclass);
2252         result = obj;
2253         GateRef ctorName = Load(VariableType::JS_POINTER(), srcTypedArray,
2254             IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
2255         GateRef elementSize = GetElementSizeFromType(glue, srcType);
2256         GateRef newByteLength = Int32Mul(elementSize, length);
2257         GateRef contentType = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
2258         BRANCH(Int32LessThanOrEqual(newByteLength, Int32(RangeInfo::TYPED_ARRAY_ONHEAP_MAX)), &next, &slowPath);
2259         Bind(&next);
2260         {
2261             Label sameObjectSize(env);
2262             Label newByteArrayExit(env);
2263             GateRef onHeapHClass = GetOnHeapHClassFromType(glue, srcType);
2264             GateRef originalHClassObjectSize = GetObjectSizeFromHClass(hclass);
2265             GateRef onHeapHClassObjectSize = GetObjectSizeFromHClass(onHeapHClass);
2266             BRANCH(Equal(originalHClassObjectSize, onHeapHClassObjectSize), &sameObjectSize, &slowPath);
2267             Bind(&sameObjectSize);
2268             NewByteArray(&buffer, &newByteArrayExit, elementSize, length);
2269             Bind(&newByteArrayExit);
2270             StoreHClass(glue, obj, onHeapHClass);
2271             Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2272             Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), ctorName);
2273             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2274             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), Int32(0));
2275             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length);
2276             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
2277             Jump(&exit);
2278         }
2279     }
2280 
2281     Bind(&slowPath);
2282     {
2283         result = CallRuntime(glue, RTSTUB_ID(TypedArraySpeciesCreate),
2284             { srcTypedArray, IntToTaggedInt(Int32(1)), IntToTaggedInt(length) });
2285         Jump(&exit);
2286     }
2287 
2288     Bind(&exit);
2289     auto ret = *result;
2290     env->SubCfgExit();
2291     return ret;
2292 }
2293 
NewFloat32ArrayObj(GateRef glue,GateRef glueGlobalEnv)2294 GateRef NewObjectStubBuilder::NewFloat32ArrayObj(GateRef glue, GateRef glueGlobalEnv)
2295 {
2296     GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2297                                           GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX);
2298     GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2299     GateRef obj = NewJSObject(glue, hclass);
2300     return obj;
2301 }
2302 
NewFloat32ArrayWithSize(GateRef glue,GateRef size)2303 GateRef NewObjectStubBuilder::NewFloat32ArrayWithSize(GateRef glue, GateRef size)
2304 {
2305     auto env = GetEnvironment();
2306     Label entry(env);
2307     env->SubCfgEntry(&entry);
2308     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2309     DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2310     Label exit(env);
2311     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2312     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2313     GateRef obj = NewFloat32ArrayObj(glue, glueGlobalEnv);
2314     result = obj;
2315     GateRef ctorName = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
2316                                               ConstantIndex::FLOAT32_ARRAY_STRING_INDEX);
2317     GateRef elementSize = Int32(4);  // 4: float32 primtype's byte length
2318     GateRef newByteLength = Int32Mul(size, elementSize);
2319     GateRef contentType = Int32(static_cast<int32_t>(ContentType::Number));
2320     {
2321         Label newByteArrayExit(env);
2322         NewByteArray(&buffer, &newByteArrayExit, elementSize, size);
2323         Bind(&newByteArrayExit);
2324         GateRef onHeapHClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2325                                                  GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2326         StoreHClass(glue, obj, onHeapHClass);
2327         Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2328         Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET),
2329               ctorName, MemoryAttribute::NoBarrier());
2330         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET),
2331               newByteLength, MemoryAttribute::NoBarrier());
2332         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET),
2333               Int32(0), MemoryAttribute::NoBarrier());
2334         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET),
2335               size, MemoryAttribute::NoBarrier());
2336         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET),
2337               contentType, MemoryAttribute::NoBarrier());
2338         Jump(&exit);
2339     }
2340     Bind(&exit);
2341     auto ret = *result;
2342     env->SubCfgExit();
2343     return ret;
2344 }
2345 
NewTypedArrayFromCtor(GateRef glue,GateRef ctor,GateRef length,Label * slowPath)2346 GateRef NewObjectStubBuilder::NewTypedArrayFromCtor(GateRef glue, GateRef ctor, GateRef length, Label *slowPath)
2347 {
2348     auto env = GetEnvironment();
2349     Label entry(env);
2350     env->SubCfgEntry(&entry);
2351 
2352     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2353     Label thisObjIsECmaObject(env);
2354     Label thisObjIsFastTypedArray(env);
2355     Label defaultConstr(env);
2356     Label exit(env);
2357 
2358     GateRef thisObj = FastNewThisObject(glue, ctor);
2359     result = thisObj;
2360     GateRef arrayType = GetObjectType(LoadHClass(thisObj));
2361 
2362     BRANCH(IsEcmaObject(thisObj), &thisObjIsECmaObject, slowPath);
2363     Bind(&thisObjIsECmaObject);
2364     BRANCH(IsFastTypeArray(arrayType), &thisObjIsFastTypedArray, slowPath);
2365     Bind(&thisObjIsFastTypedArray);
2366     BRANCH(HasConstructor(thisObj), slowPath, &defaultConstr);
2367     Bind(&defaultConstr);
2368 
2369     DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2370     GateRef elementSize = GetElementSizeFromType(glue, arrayType);
2371     GateRef newByteLength = Int32Mul(elementSize, length);
2372     Label newByteArrayExit(env);
2373     NewByteArray(&buffer, &newByteArrayExit, elementSize, length);
2374     Bind(&newByteArrayExit);
2375     Store(VariableType::JS_POINTER(), glue, thisObj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2376     Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2377     Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length);
2378     Jump(&exit);
2379 
2380     Bind(&exit);
2381     auto ret = *result;
2382     env->SubCfgExit();
2383     return ret;
2384 }
2385 
NewByteArray(Variable * result,Label * exit,GateRef elementSize,GateRef length)2386 void NewObjectStubBuilder::NewByteArray(Variable *result, Label *exit, GateRef elementSize, GateRef length)
2387 {
2388     auto env = GetEnvironment();
2389 
2390     Label noError(env);
2391     Label initializeExit(env);
2392     GateRef size = AlignUp(ComputeTaggedTypedArraySize(ZExtInt32ToPtr(elementSize), ZExtInt32ToPtr(length)),
2393         IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
2394     size_ = size;
2395     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::BYTE_ARRAY_CLASS_INDEX);
2396     AllocateInYoung(result, exit, &noError, hclass);
2397     Bind(&noError);
2398     {
2399         StoreBuiltinHClass(glue_, result->ReadVariable(), hclass);
2400         auto startOffset = Int32(ByteArray::DATA_OFFSET);
2401         static_assert(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT) == 8);
2402         InitializeWithSpeicalValue(&initializeExit, result->ReadVariable(), Int64(0), startOffset,
2403                                    TruncPtrToInt32(size));
2404         Bind(&initializeExit);
2405         Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::ARRAY_LENGTH_OFFSET), length);
2406         Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::BYTE_LENGTH_OFFSET), elementSize);
2407         Jump(exit);
2408     }
2409 }
2410 
NewProfileTypeInfoCell(GateRef glue,GateRef value)2411 GateRef NewObjectStubBuilder::NewProfileTypeInfoCell(GateRef glue, GateRef value)
2412 {
2413     auto env = GetEnvironment();
2414     Label entry(env);
2415     env->SubCfgEntry(&entry);
2416 
2417     Label initialize(env);
2418     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2419     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
2420                                          ConstantIndex::PROFILE_TYPE_INFO_CELL_0_CLASS_INDEX);
2421     GateRef size = GetObjectSizeFromHClass(hclass);
2422     SetParameters(glue, size);
2423     HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
2424     Bind(&initialize);
2425     StoreHClassWithoutBarrier(glue, *result, hclass);
2426     SetValueToProfileTypeInfoCell(glue, *result, value);
2427     GateRef machineCodeOffset = IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET);
2428     Store(VariableType::JS_POINTER(), glue, *result, machineCodeOffset, Hole());
2429     GateRef handleOffset = IntPtr(ProfileTypeInfoCell::HANDLE_OFFSET);
2430     Store(VariableType::JS_POINTER(), glue, *result, handleOffset, Undefined());
2431     GateRef extraInfoMapOffset = IntPtr(ProfileTypeInfoCell::EXTRA_INFO_MAP_OFFSET);
2432     Store(VariableType::JS_POINTER(), glue, *result, extraInfoMapOffset, Undefined());
2433 
2434     auto ret = *result;
2435     env->SubCfgExit();
2436     return ret;
2437 }
2438 
GetElementSizeFromType(GateRef glue,GateRef type)2439 GateRef NewObjectStubBuilder::GetElementSizeFromType(GateRef glue, GateRef type)
2440 {
2441     auto env = GetEnvironment();
2442     Label entry(env);
2443     env->SubCfgEntry(&entry);
2444 
2445     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
2446     Label defaultLabel(env);
2447     Label exit(env);
2448     Label labelBuffer[11] = {
2449         Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
2450         Label(env), Label(env), Label(env), Label(env), Label(env) };
2451     int64_t valueBuffer[11] = {
2452         static_cast<int64_t>(JSType::JS_INT8_ARRAY),
2453         static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
2454         static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY),
2455         static_cast<int64_t>(JSType::JS_INT16_ARRAY),
2456         static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
2457         static_cast<int64_t>(JSType::JS_INT32_ARRAY),
2458         static_cast<int64_t>(JSType::JS_UINT32_ARRAY),
2459         static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
2460         static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY),
2461         static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY),
2462         static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) };
2463 
2464     // 11 : this switch has 11 case
2465     Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11);
2466     // 0 : index of this buffer
2467     Bind(&labelBuffer[0]);
2468     {
2469         // 1 : the elementSize of this type is 1
2470         result = Int32(1);
2471         Jump(&exit);
2472     }
2473     // 1 : index of this buffer
2474     Bind(&labelBuffer[1]);
2475     {
2476         // 1 : the elementSize of this type is 1
2477         result = Int32(1);
2478         Jump(&exit);
2479     }
2480     // 2 : index of this buffer
2481     Bind(&labelBuffer[2]);
2482     {
2483         // 1 : the elementSize of this type is 1
2484         result = Int32(1);
2485         Jump(&exit);
2486     }
2487     // 3 : index of this buffer
2488     Bind(&labelBuffer[3]);
2489     {
2490         // 2 : the elementSize of this type is 2
2491         result = Int32(2);
2492         Jump(&exit);
2493     }
2494     // 4 : index of this buffer
2495     Bind(&labelBuffer[4]);
2496     {
2497         // 2 : the elementSize of this type is 2
2498         result = Int32(2);
2499         Jump(&exit);
2500     }
2501     // 5 : index of this buffer
2502     Bind(&labelBuffer[5]);
2503     {
2504         // 4 : the elementSize of this type is 4
2505         result = Int32(4);
2506         Jump(&exit);
2507     }
2508     // 6 : index of this buffer
2509     Bind(&labelBuffer[6]);
2510     {
2511         // 4 : the elementSize of this type is 4
2512         result = Int32(4);
2513         Jump(&exit);
2514     }
2515     // 7 : index of this buffer
2516     Bind(&labelBuffer[7]);
2517     {
2518         // 4 : the elementSize of this type is 4
2519         result = Int32(4);
2520         Jump(&exit);
2521     }
2522     // 8 : index of this buffer
2523     Bind(&labelBuffer[8]);
2524     {
2525         // 8 : the elementSize of this type is 8
2526         result = Int32(8);
2527         Jump(&exit);
2528     }
2529     // 9 : index of this buffer
2530     Bind(&labelBuffer[9]);
2531     {
2532         // 8 : the elementSize of this type is 8
2533         result = Int32(8);
2534         Jump(&exit);
2535     }
2536     // 10 : index of this buffer
2537     Bind(&labelBuffer[10]);
2538     {
2539         // 8 : the elementSize of this type is 8
2540         result = Int32(8);
2541         Jump(&exit);
2542     }
2543     Bind(&defaultLabel);
2544     {
2545         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
2546         Jump(&exit);
2547     }
2548 
2549     Bind(&exit);
2550     auto ret = *result;
2551     env->SubCfgExit();
2552     return ret;
2553 }
2554 
GetOnHeapHClassFromType(GateRef glue,GateRef type)2555 GateRef NewObjectStubBuilder::GetOnHeapHClassFromType(GateRef glue, GateRef type)
2556 {
2557     auto env = GetEnvironment();
2558     Label entry(env);
2559     env->SubCfgEntry(&entry);
2560 
2561     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2562     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2563     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2564     Label defaultLabel(env);
2565     Label exit(env);
2566     Label labelBuffer[11] = {
2567         Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
2568         Label(env), Label(env), Label(env), Label(env), Label(env) };
2569     int64_t valueBuffer[11] = {
2570         static_cast<int64_t>(JSType::JS_INT8_ARRAY),
2571         static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
2572         static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY),
2573         static_cast<int64_t>(JSType::JS_INT16_ARRAY),
2574         static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
2575         static_cast<int64_t>(JSType::JS_INT32_ARRAY),
2576         static_cast<int64_t>(JSType::JS_UINT32_ARRAY),
2577         static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
2578         static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY),
2579         static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY),
2580         static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) };
2581 
2582     // 11 : this switch has 11 case
2583     Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11);
2584     // 0 : index of this buffer
2585     Bind(&labelBuffer[0]);
2586     {
2587         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2588             GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2589         Jump(&exit);
2590     }
2591     // 1 : index of this buffer
2592     Bind(&labelBuffer[1]);
2593     {
2594         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2595             GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2596         Jump(&exit);
2597     }
2598     // 2 : index of this buffer
2599     Bind(&labelBuffer[2]);
2600     {
2601         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2602             GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2603         Jump(&exit);
2604     }
2605     // 3 : index of this buffer
2606     Bind(&labelBuffer[3]);
2607     {
2608         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2609             GlobalEnv::INT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2610         Jump(&exit);
2611     }
2612     // 4 : index of this buffer
2613     Bind(&labelBuffer[4]);
2614     {
2615         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2616             GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2617         Jump(&exit);
2618     }
2619     // 5 : index of this buffer
2620     Bind(&labelBuffer[5]);
2621     {
2622         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2623             GlobalEnv::INT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2624         Jump(&exit);
2625     }
2626     // 6 : index of this buffer
2627     Bind(&labelBuffer[6]);
2628     {
2629         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2630             GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2631         Jump(&exit);
2632     }
2633     // 7 : index of this buffer
2634     Bind(&labelBuffer[7]);
2635     {
2636         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2637             GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2638         Jump(&exit);
2639     }
2640     // 8 : index of this buffer
2641     Bind(&labelBuffer[8]);
2642     {
2643         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2644             GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2645         Jump(&exit);
2646     }
2647     // 9 : index of this buffer
2648     Bind(&labelBuffer[9]);
2649     {
2650         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2651             GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2652         Jump(&exit);
2653     }
2654     // 10 : index of this buffer
2655     Bind(&labelBuffer[10]);
2656     {
2657         result = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
2658             GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2659         Jump(&exit);
2660     }
2661     Bind(&defaultLabel);
2662     {
2663         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
2664         Jump(&exit);
2665     }
2666 
2667     Bind(&exit);
2668     auto ret = *result;
2669     env->SubCfgExit();
2670     return ret;
2671 }
2672 }  // namespace panda::ecmascript::kungfu
2673