• 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 "common_components/heap/allocator/alloc_buffer.h"
19 #include "ecmascript/compiler/builtins/builtins_function_stub_builder.h"
20 #include "ecmascript/compiler/builtins/builtins_proxy_stub_builder.h"
21 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
22 #include "ecmascript/compiler/number_gate_info.h"
23 #include "ecmascript/global_env.h"
24 #include "ecmascript/js_arguments.h"
25 #include "ecmascript/js_thread.h"
26 #include "ecmascript/lexical_env.h"
27 #include "ecmascript/js_array_iterator.h"
28 #include "ecmascript/js_map_iterator.h"
29 #include "ecmascript/js_set_iterator.h"
30 #include "ecmascript/js_set.h"
31 #include "ecmascript/js_map.h"
32 
33 namespace panda::ecmascript::kungfu {
NewLexicalEnv(Variable * result,Label * exit,GateRef numSlots,GateRef parent)34 void NewObjectStubBuilder::NewLexicalEnv(Variable *result, Label *exit, GateRef numSlots, GateRef parent)
35 {
36     auto env = GetEnvironment();
37 
38     auto length = Int32Add(numSlots, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
39     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length));
40     // Be careful. NO GC is allowed when initization is not complete.
41     Label hasPendingException(env);
42     Label noException(env);
43     auto hclass = GetGlobalConstantValue(
44         VariableType::JS_POINTER(), glue_, ConstantIndex::LEXICAL_ENV_CLASS_INDEX);
45     AllocateInYoung(result, &hasPendingException, &noException, hclass);
46     Bind(&noException);
47     {
48         StoreHClass(glue_, result->ReadVariable(), hclass);
49         Label afterInitialize(env);
50         InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
51             result->ReadVariable(), Hole(), Int32(LexicalEnv::RESERVED_ENV_LENGTH), length);
52         Bind(&afterInitialize);
53         SetValueToTaggedArray(VariableType::INT64(),
54             glue_, result->ReadVariable(), Int32(LexicalEnv::SCOPE_INFO_INDEX), Hole());
55         SetValueToTaggedArray(VariableType::JS_POINTER(),
56             glue_, result->ReadVariable(), Int32(LexicalEnv::PARENT_ENV_INDEX), parent);
57         // currentEnv is LexicalEnv/GlobalEnv for normal function, and is SFunctionEnv for SharedFunction.
58         GateRef globalEnv = GetValueFromTaggedArray(glue_, parent, Int32(BaseEnv::GLOBAL_ENV_INDEX));
59         Label isHole(env);
60         Label notHole(env);
61         BRANCH_UNLIKELY(TaggedIsHole(globalEnv), &isHole, &notHole);
62         Bind(&isHole);
63         // get globalenv from thread
64         SetValueToTaggedArray(VariableType::JS_POINTER(),
65             glue_, result->ReadVariable(), Int32(LexicalEnv::GLOBAL_ENV_INDEX), GetGlobalEnv(glue_));
66         Jump(exit);
67         Bind(&notHole);
68         SetValueToTaggedArray(VariableType::JS_POINTER(),
69             glue_, result->ReadVariable(), Int32(LexicalEnv::GLOBAL_ENV_INDEX), globalEnv);
70         Jump(exit);
71     }
72     Bind(&hasPendingException);
73     {
74         Jump(exit);
75     }
76 }
77 
NewJSArrayWithSize(GateRef hclass,GateRef size)78 GateRef NewObjectStubBuilder::NewJSArrayWithSize(GateRef hclass, GateRef size)
79 {
80     auto env = GetEnvironment();
81     Label entry(env);
82     Label exit(env);
83     env->SubCfgEntry(&entry);
84 
85     GateRef result = NewJSObject(glue_, hclass);
86     Label enabledElementsKind(env);
87     Label notEmptyArray(env);
88     Label initObj(env);
89     BRANCH(IsEnableElementsKind(glue_), &enabledElementsKind, &initObj);
90     Bind(&enabledElementsKind);
91     {
92         // For new Array(Len), the elementsKind should be Hole
93         BRANCH(Equal(TruncInt64ToInt32(size), Int32(0)), &initObj, &notEmptyArray);
94         Bind(&notEmptyArray);
95         {
96             GateRef globalEnv = GetCurrentGlobalEnv();
97             #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
98             GateRef holeKindArrayClass =
99                 GetGlobalEnvValue(VariableType::JS_ANY(), glue_, globalEnv,
100                     static_cast<size_t>(GlobalEnvField::ELEMENT_HOLE_TAGGED_HCLASS_INDEX));
101             StoreHClass(glue_, result, holeKindArrayClass);
102             #else
103             GateRef holeKindArrayClass =
104                 GetGlobalEnvValue(VariableType::JS_ANY(), glue_, globalEnv,
105                     static_cast<size_t>(GlobalEnvField::ELEMENT_HOLE_HCLASS_INDEX));
106             StoreHClass(glue_, result, holeKindArrayClass);
107             #endif
108             Jump(&initObj);
109         }
110     }
111     Bind(&initObj);
112     DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
113     NewTaggedArrayChecked(&array, TruncInt64ToInt32(size), &exit);
114     Bind(&exit);
115     auto arrayRet = *array;
116     env->SubCfgExit();
117     SetElementsArray(VariableType::JS_POINTER(), glue_, result, arrayRet);
118     return result;
119 }
120 
NewJSArrayWithHClass(GateRef hclass,GateRef length)121 GateRef NewObjectStubBuilder::NewJSArrayWithHClass(GateRef hclass, GateRef length)
122 {
123     auto env = GetEnvironment();
124     Label entry(env);
125     Label exit(env);
126     env->SubCfgEntry(&entry);
127     GateRef result = NewJSObject(glue_, hclass);
128     Label enabledMutantArray(env);
129     Label initObj(env);
130     DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
131     BRANCH_UNLIKELY(IsEnableMutantArray(glue_), &enabledMutantArray, &initObj);
132     Bind(&enabledMutantArray);
133     {
134         Label initMutantArray(env);
135         GateRef kind = GetElementsKindFromHClass(hclass);
136         GateRef needMutant = BitOr(ElementsKindIsIntOrHoleInt(kind), ElementsKindIsNumOrHoleNum(kind));
137         BRANCH_NO_WEIGHT(needMutant, &initMutantArray, &initObj);
138         Bind(&initMutantArray);
139         {
140             NewMutantTaggedArrayChecked(&array, length, &exit);
141         }
142     }
143     Bind(&initObj);
144     NewTaggedArrayChecked(&array, length, &exit);
145     Bind(&exit);
146     auto arrayRet = *array;
147     env->SubCfgExit();
148     SetElementsArray(VariableType::JS_POINTER(), glue_, result, arrayRet);
149     return result;
150 }
151 
NewJSFunctionByHClass(GateRef glue,GateRef method,GateRef hclass,FunctionKind targetKind)152 GateRef NewObjectStubBuilder::NewJSFunctionByHClass(GateRef glue,
153     GateRef method, GateRef hclass, FunctionKind targetKind)
154 {
155     GateRef result = NewJSObject(glue, hclass);
156     SetExtensibleToBitfield(glue, hclass, true);
157     GateRef kind = GetFuncKind(method);
158     BuiltinsFunctionStubBuilder builtinsFunctionStubBuilder(this, GetCurrentGlobalEnv());
159     builtinsFunctionStubBuilder.InitializeJSFunction(glue, result, kind, targetKind);
160     builtinsFunctionStubBuilder.InitializeFunctionWithMethod(glue, result, method, hclass);
161     return result;
162 }
163 
NewSFunctionByHClass(GateRef glue,GateRef method,GateRef hclass,FunctionKind targetKind)164 GateRef NewObjectStubBuilder::NewSFunctionByHClass(GateRef glue,
165     GateRef method, GateRef hclass, FunctionKind targetKind)
166 {
167     GateRef result = result = NewSObject(glue, hclass);
168     GateRef kind = GetFuncKind(method);
169     BuiltinsFunctionStubBuilder builtinsFunctionStubBuilder(this, GetCurrentGlobalEnv());
170     builtinsFunctionStubBuilder.InitializeSFunction(glue, result, kind, targetKind);
171     builtinsFunctionStubBuilder.InitializeFunctionWithMethod(glue, result, method, hclass);
172     return result;
173 }
174 
CloneJSFunction(GateRef glue,GateRef value)175 GateRef NewObjectStubBuilder::CloneJSFunction(GateRef glue, GateRef value)
176 {
177     GateRef hclass = LoadHClass(glue, value);
178     GateRef method = GetMethodFromFunction(glue, value);
179     GateRef cloneFunc = NewJSFunctionByHClass(glue, method, hclass);
180     GateRef length = GetPropertyInlinedProps(glue, value, hclass,
181                                              Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX));
182     SetPropertyInlinedProps(glue, value, hclass, length,
183                             Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX),
184                             VariableType::JS_ANY());
185     SetLengthToFunction(glue, cloneFunc, GetLengthFromFunction(value));
186     SetModuleToFunction(glue, cloneFunc, GetModuleFromFunction(glue, value));
187     return cloneFunc;
188 }
189 
CloneProperties(GateRef glue,GateRef currentEnv,GateRef elements,GateRef obj)190 GateRef NewObjectStubBuilder::CloneProperties(GateRef glue, GateRef currentEnv,
191     GateRef elements, GateRef obj)
192 {
193     auto env = GetEnvironment();
194     Label entry(env);
195     env->SubCfgEntry(&entry);
196     Label exit(env);
197     Label isZero(env);
198     Label notZero(env);
199     Label initialize(env);
200     Label afterInitialize(env);
201     Label begin(env);
202     Label body(env);
203     Label isJSFunction(env);
204     Label notJSFunction(env);
205     Label endLoop(env);
206     Label isJSFCondition(env);
207 
208     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
209     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
210     GateRef length = GetLengthOfTaggedArray(elements);
211     BRANCH(Int32Equal(length, Int32(0)), &isZero, &notZero);
212     Bind(&isZero);
213     {
214         result = GetEmptyArray(glue);
215         Jump(&exit);
216     }
217     Bind(&notZero);
218     {
219         GateRef hclass = LoadHClass(glue, elements);
220         size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length));
221         HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
222     }
223     Bind(&initialize);
224     {
225         GateRef hclass = LoadHClass(glue, elements);
226         Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass);
227         InitializeTaggedArrayWithSpeicalValue(&afterInitialize, result.ReadVariable(), Hole(), Int32(0), length);
228     }
229     Bind(&afterInitialize);
230     {
231         Jump(&begin);
232     }
233     LoopBegin(&begin);
234     {
235         BRANCH(Int32UnsignedLessThan(*i, length), &body, &exit);
236         Bind(&body);
237         {
238             GateRef value = GetValueFromTaggedArray(glue, elements, *i);
239             BRANCH(TaggedIsHeapObject(value), &isJSFCondition, &notJSFunction);
240             Bind(&isJSFCondition);
241             {
242                 BRANCH(IsJSFunction(glue, value), &isJSFunction, &notJSFunction);
243             }
244             Bind(&isJSFunction);
245             {
246                 GateRef newFunc = CloneJSFunction(glue, value);
247                 SetLexicalEnvToFunction(glue, newFunc, currentEnv);
248                 SetHomeObjectToFunction(glue, newFunc, obj);
249                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *result, *i, newFunc);
250                 Jump(&endLoop);
251             }
252             Bind(&notJSFunction);
253             {
254                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *result, *i, value);
255                 Jump(&endLoop);
256             }
257             Bind(&endLoop);
258             i = Int32Add(*i, Int32(1));
259             LoopEnd(&begin);
260         }
261     }
262 
263     Bind(&exit);
264     auto ret = *result;
265     env->SubCfgExit();
266     return ret;
267 }
268 
NewAccessorData(GateRef glue)269 GateRef NewObjectStubBuilder::NewAccessorData(GateRef glue)
270 {
271     auto env = GetEnvironment();
272     Label entry(env);
273     env->SubCfgEntry(&entry);
274     Label exit(env);
275     Label noException(env);
276 
277     GateRef hclass = GetGlobalConstantValue(
278         VariableType::JS_POINTER(), glue, ConstantIndex::ACCESSOR_DATA_CLASS_INDEX);
279     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
280     size_ = GetObjectSizeFromHClass(hclass);
281     HeapAlloc(&result, &noException, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
282     Bind(&noException);
283     {
284         Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass);
285         Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::GETTER_OFFSET), Undefined());
286         Store(VariableType::JS_ANY(), glue, *result, IntPtr(AccessorData::SETTER_OFFSET), Undefined());
287         Jump(&exit);
288     }
289 
290     Bind(&exit);
291     auto ret = *result;
292     env->SubCfgExit();
293     return ret;
294 }
295 
CloneObjectLiteral(GateRef glue,GateRef literal,GateRef currentEnv)296 GateRef NewObjectStubBuilder::CloneObjectLiteral(GateRef glue, GateRef literal, GateRef currentEnv)
297 {
298     auto env = GetEnvironment();
299     Label entry(env);
300     env->SubCfgEntry(&entry);
301     // canShareHClass is true default
302     GateRef hclass = LoadHClass(glue, literal);
303     Label exit(env);
304     Label less(env);
305     Label greater(env);
306     Label startLoop(env);
307     Label begin(env);
308     Label body(env);
309     Label isTaggedRep(env);
310     Label notTaggedRep(env);
311     Label isJSFunction(env);
312     Label notJSFunction(env);
313     Label endLoop(env);
314     Label isAccessorData(env);
315     Label notAccessorData(env);
316     Label middleCondition(env);
317     Label isJSFCondition(env);
318     Label isACCCondition(env);
319     Label isAccessorJudgment(env);
320 
321     DEFVARIABLE(length, VariableType::INT32(), Int32(0));
322     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
323     DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
324     GateRef result = NewJSObject(glue, hclass);
325 
326     GateRef elements = GetElementsArray(glue, literal);
327     GateRef newElements = CloneProperties(glue, currentEnv, elements, result);
328     SetElementsArray(VariableType::JS_ANY(), glue, result, newElements);
329 
330     GateRef properties = GetPropertiesArray(glue, literal);
331     GateRef newProperties = CloneProperties(glue, currentEnv, properties, result);
332     SetPropertiesArray(VariableType::JS_ANY(), glue, result, newProperties);
333 
334     GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
335     GateRef numberOfProps = GetNumberOfPropsFromHClass(hclass);
336     BRANCH(Int32UnsignedLessThan(inlineProps, numberOfProps), &less, &greater);
337     Bind(&less);
338     {
339         length = inlineProps;
340         Jump(&startLoop);
341     }
342     Bind(&greater);
343     {
344         length = numberOfProps;
345         Jump(&startLoop);
346     }
347     Bind(&startLoop);
348     {
349         Jump(&begin);
350     }
351     LoopBegin(&begin);
352     {
353         BRANCH(Int32UnsignedLessThan(*i, *length), &body, &exit);
354         Bind(&body);
355         {
356             GateRef layout = GetLayoutFromHClass(glue, hclass);
357             value = GetPropertyInlinedProps(glue, literal, hclass, *i);
358             GateRef attr = GetPropAttrFromLayoutInfo(glue, layout, *i);
359             BRANCH(BoolNot(IsTaggedRepInPropAttr(attr)), &notTaggedRep, &middleCondition);
360         }
361         Bind(&middleCondition);
362         {
363             BRANCH(TaggedIsHeapObject(*value), &isJSFCondition, &isTaggedRep);
364         }
365         Bind(&isJSFCondition);
366         {
367             BRANCH(IsJSFunction(glue, *value), &isJSFunction, &isAccessorJudgment);
368         }
369         Bind(&isAccessorJudgment);
370         {
371             BRANCH(Int32Equal(GetObjectType(LoadHClass(glue, *value)),
372                 Int32(static_cast<int32_t>(JSType::ACCESSOR_DATA))),
373                 &isAccessorData, &isTaggedRep);
374         }
375         Bind(&isJSFunction);
376         {
377             GateRef newFunc = CloneJSFunction(glue, *value);
378             SetLexicalEnvToFunction(glue, newFunc, currentEnv);
379             SetHomeObjectToFunction(glue, newFunc, result);
380             SetPropertyInlinedProps(glue, result, hclass, newFunc, *i,
381                 VariableType::JS_ANY());
382             Jump(&endLoop);
383         }
384         Bind(&isAccessorData);
385         {
386             auto objLiteral = NewAccessorData(glue);
387             value = objLiteral;
388             Jump(&isTaggedRep);
389         }
390         Bind(&notTaggedRep);
391         {
392             SetPropertyInlinedProps(glue, result, hclass, *value, *i,
393                 VariableType::JS_ANY(), MemoryAttribute::NoBarrier());
394             Jump(&endLoop);
395         }
396         Bind(&isTaggedRep);
397         {
398             SetPropertyInlinedProps(glue, result, hclass, *value, *i);
399             Jump(&endLoop);
400         }
401         Bind(&endLoop);
402         i = Int32Add(*i, Int32(1));
403         LoopEnd(&begin);
404     }
405     Bind(&exit);
406     auto ret = result;
407     env->SubCfgExit();
408     return ret;
409 }
410 
CreateObjectHavingMethod(GateRef glue,GateRef literal,GateRef currentEnv)411 GateRef NewObjectStubBuilder::CreateObjectHavingMethod(GateRef glue, GateRef literal, GateRef currentEnv)
412 {
413     auto env = GetEnvironment();
414     Label entry(env);
415     env->SubCfgEntry(&entry);
416     Label isPendingException(env);
417     Label exit(env);
418     auto objLiteral = CloneObjectLiteral(glue, literal, currentEnv);
419     DEFVARIABLE(result, VariableType::JS_ANY(), objLiteral);
420     BRANCH(HasPendingException(glue), &isPendingException, &exit);
421     Bind(&isPendingException);
422     {
423         result = Exception();
424         Jump(&exit);
425     }
426     Bind(&exit);
427     auto ret = *result;
428     env->SubCfgExit();
429     return ret;
430 }
431 
NewJSObject(Variable * result,Label * exit,GateRef hclass)432 void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass)
433 {
434     auto env = GetEnvironment();
435 
436     size_ = GetObjectSizeFromHClass(hclass);
437     // Be careful. NO GC is allowed when initization is not complete.
438     Label hasPendingException(env);
439     Label noException(env);
440     AllocateInYoung(result, &hasPendingException, &noException, hclass);
441     Bind(&noException);
442     {
443         StoreHClass(glue_, result->ReadVariable(), hclass);
444         DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
445         Label isAOT(env);
446         Label initialize(env);
447         Label inProgress(env);
448         Label notInProgress(env);
449         GateRef isObjSizeTrackingInProgress = IsObjSizeTrackingInProgress(hclass);
450         Branch(isObjSizeTrackingInProgress, &inProgress, &notInProgress);
451         Bind(&inProgress);
452         {
453             initValue = GetGlobalConstantValue(
454                 VariableType::JS_POINTER(), glue_, ConstantIndex::FREE_OBJECT_WITH_NONE_FIELD_CLASS_INDEX);
455             Jump(&initialize);
456         }
457         Bind(&notInProgress);
458         BRANCH(IsAOTHClass(hclass), &isAOT, &initialize);
459         Bind(&isAOT);
460         {
461             // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist,
462             // to follow ECMA spec.
463             initValue = Hole();
464             Jump(&initialize);
465         }
466         Bind(&initialize);
467         Label afterInitialize(env);
468         InitializeWithSpeicalValue(&afterInitialize,
469             result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_),
470             MemoryAttribute::NoBarrier());
471         Bind(&afterInitialize);
472         Label objSizeTrackingStep(env);
473         InitializeObject(result);
474         Branch(isObjSizeTrackingInProgress, &objSizeTrackingStep, exit);
475         Bind(&objSizeTrackingStep);
476         {
477             Label checkNext(env);
478             BRANCH_UNLIKELY(LoadPrimitive(VariableType::BOOL(), glue_,
479                                           IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
480                             exit, &checkNext);
481             Bind(&checkNext);
482             Label calcuFinalCount(env);
483             GateRef count = GetConstructionCounter(hclass);
484             GateRef nextCount = Int32Sub(count, Int32(1));
485             SetConstructionCounter(glue_, hclass, nextCount);
486             Branch(Int32Equal(nextCount, Int32(0)), &calcuFinalCount, exit);
487             Bind(&calcuFinalCount);
488             {
489                 CallNGCRuntime(glue_, RTSTUB_ID(FinishObjSizeTracking), { glue_, hclass });
490                 Jump(exit);
491             }
492         }
493     }
494     Bind(&hasPendingException);
495     {
496         Jump(exit);
497     }
498 }
499 
NewSObject(Variable * result,Label * exit,GateRef hclass)500 void NewObjectStubBuilder::NewSObject(Variable *result, Label *exit, GateRef hclass)
501 {
502     auto env = GetEnvironment();
503 
504     size_ = GetObjectSizeFromHClass(hclass);
505     Label afterAllocate(env);
506     AllocateInSOld(result, &afterAllocate, hclass);
507     Bind(&afterAllocate);
508     {
509         StoreHClass(glue_, result->ReadVariable(), hclass);
510         DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
511         Label isAOT(env);
512         Label initialize(env);
513         BRANCH(IsAOTHClass(hclass), &isAOT, &initialize);
514         Bind(&isAOT);
515         {
516             // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist,
517             // to follow ECMA spec.
518             initValue = Hole();
519             Jump(&initialize);
520         }
521         Bind(&initialize);
522         Label afterInitialize(env);
523         InitializeWithSpeicalValue(&afterInitialize,
524             result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_),
525             MemoryAttribute::NoBarrier());
526         Bind(&afterInitialize);
527         InitializeObject(result);
528         Jump(exit);
529     }
530 }
531 
NewJSProxy(GateRef glue,GateRef target,GateRef handler)532 GateRef NewObjectStubBuilder::NewJSProxy(GateRef glue, GateRef target, GateRef handler)
533 {
534     auto env = GetEnvironment();
535     Label entry(env);
536     env->SubCfgEntry(&entry);
537     Label exit(env);
538     Label isCallable(env);
539     Label notCallable(env);
540     Label noException(env);
541     Label allocateProxy(env);
542 
543     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
544     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
545     GateRef globalEnv = GetCurrentGlobalEnv();
546     GateRef objectFunctionPrototype = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
547                                                         GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX);
548     GateRef emptyObject = OrdinaryNewJSObjectCreate(glue, objectFunctionPrototype);
549     BRANCH(IsCallable(glue, target), &isCallable, &notCallable);
550     Bind(&isCallable);
551     {
552         Label isConstructor(env);
553         Label notConstructor(env);
554         BRANCH(IsConstructor(glue, target), &isConstructor, &notConstructor);
555         Bind(&isConstructor);
556         {
557             hclass = GetGlobalConstantValue(
558                 VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_CONSTRUCT_CLASS_INDEX);
559             Jump(&allocateProxy);
560         }
561         Bind(&notConstructor);
562         {
563             hclass = GetGlobalConstantValue(
564                 VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_CALLABLE_CLASS_INDEX);
565             Jump(&allocateProxy);
566         }
567     }
568     Bind(&notCallable);
569     {
570         hclass = GetGlobalConstantValue(
571             VariableType::JS_POINTER(), glue, ConstantIndex::JS_PROXY_ORDINARY_CLASS_INDEX);
572         Jump(&allocateProxy);
573     }
574     Bind(&allocateProxy);
575     {
576         size_ = GetObjectSizeFromHClass(*hclass);
577         AllocateInYoung(&result, &exit, &noException, *hclass);
578     }
579     Bind(&noException);
580     {
581         GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
582         Store(VariableType::INT64(), glue, *result, hashOffset, Int64(JSTaggedValue(0).GetRawData()));
583         GateRef proxyMethod = GetGlobalConstantValue(
584             VariableType::JS_POINTER(), glue, ConstantIndex::PROXY_METHOD_INDEX);
585         StoreHClass(glue_, *result, *hclass, MemoryAttribute::NoBarrier());
586         BuiltinsProxyStubBuilder builtinsProxyStubBuilder(this, globalEnv);
587         builtinsProxyStubBuilder.SetMethod(glue, *result, proxyMethod);
588         builtinsProxyStubBuilder.SetTarget(glue, *result, target);
589         builtinsProxyStubBuilder.SetHandler(glue, *result, handler);
590         builtinsProxyStubBuilder.SetPrivateField(glue, *result, emptyObject);
591         builtinsProxyStubBuilder.SetIsRevoked(glue, *result, False());
592         Jump(&exit);
593     }
594     Bind(&exit);
595     auto ret = *result;
596     env->SubCfgExit();
597     return ret;
598 }
599 
DefineFuncForJit(GateRef glue,GateRef method,GateRef hclass,FunctionKind targetKind)600 GateRef NewObjectStubBuilder::DefineFuncForJit(GateRef glue, GateRef method, GateRef hclass, FunctionKind targetKind)
601 {
602     auto env = GetEnvironment();
603     Label subentry(env);
604     env->SubCfgEntry(&subentry);
605     Label exit(env);
606     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
607 
608     Label initialize(env);
609     NewJSObject(&result, &initialize, hclass, GetObjectSizeFromHClass(hclass));
610     Bind(&initialize);
611     SetExtensibleToBitfield(glue, hclass, true);
612     GateRef func = *result;
613 
614     SetProtoOrHClassToFunction(glue, func, Hole(), MemoryAttribute::NoBarrier());
615     SetWorkNodePointerToFunction(glue, func, NullPtr(), MemoryAttribute::NoBarrier());
616 
617     if (targetKind == FunctionKind::BASE_CONSTRUCTOR) {
618         auto funcprotoAccessor =
619             GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::FUNCTION_PROTOTYPE_ACCESSOR);
620         Store(VariableType::JS_ANY(), glue, func,
621               IntPtr(JSFunction::GetInlinedPropertyOffset(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX)),
622               funcprotoAccessor, MemoryAttribute::NoBarrier());
623     } else {
624         ASSERT(targetKind == FunctionKind::ARROW_FUNCTION || targetKind == FunctionKind::NORMAL_FUNCTION);
625     }
626     auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::FUNCTION_NAME_ACCESSOR);
627     Store(VariableType::JS_ANY(), glue, func,
628           IntPtr(JSFunction::GetInlinedPropertyOffset(JSFunction::NAME_INLINE_PROPERTY_INDEX)), funcAccessor,
629           MemoryAttribute::NoBarrier());
630     funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
631     Store(VariableType::JS_ANY(), glue, func,
632           IntPtr(JSFunction::GetInlinedPropertyOffset(JSFunction::LENGTH_INLINE_PROPERTY_INDEX)), funcAccessor,
633           MemoryAttribute::NoBarrier());
634 
635     SetCallableToBitfield(glue, hclass, true);
636     SetMethodToFunction(glue, func, method);
637     SetBitFieldToFunction(glue, func, Int32(0), MemoryAttribute::NoBarrier());
638     SetMachineCodeToFunction(glue, func, Undefined(), MemoryAttribute::NoBarrier());
639     SetCodeEntryToFunctionFromMethod(glue, func, method);
640     Jump(&exit);
641     Bind(&exit);
642     auto ret = *result;
643     env->SubCfgExit();
644     return ret;
645 }
646 
NewJSObject(Variable * result,Label * exit,GateRef hclass,GateRef size)647 void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass, GateRef size)
648 {
649     auto env = GetEnvironment();
650     size_ = size;
651     Label initialize(env);
652     HeapAlloc(result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
653     Bind(&initialize);
654     StoreHClass(glue_, result->ReadVariable(), hclass, MemoryAttribute::NoBarrier());
655     DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
656     Label afterInitialize(env);
657     InitializeWithSpeicalValue(&afterInitialize,
658         result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_),
659         MemoryAttribute::NoBarrier());
660     Bind(&afterInitialize);
661     InitializeObject(result);
662     Jump(exit);
663 }
664 
NewJSObject(GateRef glue,GateRef hclass,GateRef size)665 GateRef NewObjectStubBuilder::NewJSObject(GateRef glue, GateRef hclass, GateRef size)
666 {
667     auto env = GetEnvironment();
668     Label entry(env);
669     env->SubCfgEntry(&entry);
670     Label exit(env);
671 
672     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
673     SetParameters(glue, size);
674     NewJSObject(&result, &exit, hclass, size);
675 
676     Bind(&exit);
677     auto ret = *result;
678     env->SubCfgExit();
679     return ret;
680 }
681 
NewJSObject(GateRef glue,GateRef hclass)682 GateRef NewObjectStubBuilder::NewJSObject(GateRef glue, GateRef hclass)
683 {
684     auto env = GetEnvironment();
685     Label entry(env);
686     env->SubCfgEntry(&entry);
687     Label exit(env);
688 
689     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
690     SetGlue(glue);
691     NewJSObject(&result, &exit, hclass);
692 
693     Bind(&exit);
694     auto ret = *result;
695     env->SubCfgExit();
696     return ret;
697 }
698 
NewSObject(GateRef glue,GateRef hclass)699 GateRef NewObjectStubBuilder::NewSObject(GateRef glue, GateRef hclass)
700 {
701     auto env = GetEnvironment();
702     Label entry(env);
703     env->SubCfgEntry(&entry);
704     Label exit(env);
705 
706     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
707     SetGlue(glue);
708     NewSObject(&result, &exit, hclass);
709 
710     Bind(&exit);
711     auto ret = *result;
712     env->SubCfgExit();
713     return ret;
714 }
715 
NewTaggedArrayChecked(Variable * result,GateRef len,Label * exit)716 void NewObjectStubBuilder::NewTaggedArrayChecked(Variable *result, GateRef len, Label *exit)
717 {
718     auto env = GetEnvironment();
719     Label overflow(env);
720     Label notOverflow(env);
721     BRANCH(Int32UnsignedGreaterThan(len, Int32(INT32_MAX)), &overflow, &notOverflow);
722     Bind(&overflow);
723     {
724         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax));
725         CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
726         result->WriteVariable(Exception());
727         Jump(exit);
728     }
729     Bind(&notOverflow);
730     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len));
731     // Be careful. NO GC is allowed when initization is not complete.
732     Label noException(env);
733     auto hclass = GetGlobalConstantValue(
734         VariableType::JS_POINTER(), glue_, ConstantIndex::TAGGED_ARRAY_CLASS_INDEX);
735     AllocateInYoung(result, exit, &noException, hclass);
736     Bind(&noException);
737     {
738         StoreBuiltinHClass(glue_, result->ReadVariable(), hclass);
739         Label afterInitialize(env);
740         InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
741             result->ReadVariable(), Hole(), Int32(0), len);
742         Bind(&afterInitialize);
743         Jump(exit);
744     }
745 }
746 
NewMutantTaggedArrayChecked(Variable * result,GateRef len,Label * exit)747 void NewObjectStubBuilder::NewMutantTaggedArrayChecked(Variable *result, GateRef len, Label *exit)
748 {
749     auto env = GetEnvironment();
750     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len));
751     Label afterAllocate(env);
752     auto hclass = GetGlobalConstantValue(
753         VariableType::JS_POINTER(), glue_, ConstantIndex::MUTANT_TAGGED_ARRAY_CLASS_INDEX);
754     // Be careful. NO GC is allowed when initization is not complete.
755     AllocateInYoung(result, &afterAllocate, hclass);
756     Bind(&afterAllocate);
757     Label noException(env);
758     BRANCH(TaggedIsException(result->ReadVariable()), exit, &noException);
759     Bind(&noException);
760     {
761         StoreHClass(glue_, result->ReadVariable(), hclass);
762         Label afterInitialize(env);
763         InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
764             result->ReadVariable(), SpecialHole(), Int32(0), len);
765         Bind(&afterInitialize);
766         Jump(exit);
767     }
768 }
769 
NewTaggedArray(GateRef glue,GateRef len)770 GateRef NewObjectStubBuilder::NewTaggedArray(GateRef glue, GateRef len)
771 {
772     auto env = GetEnvironment();
773     Label entry(env);
774     env->SubCfgEntry(&entry);
775     Label exit(env);
776     Label isEmpty(env);
777     Label notEmpty(env);
778 
779     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
780     SetGlue(glue);
781     BRANCH(Int32Equal(len, Int32(0)), &isEmpty, &notEmpty);
782     Bind(&isEmpty);
783     {
784         result = GetGlobalConstantValue(
785             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
786         Jump(&exit);
787     }
788     Bind(&notEmpty);
789     {
790         Label next(env);
791         Label slowPath(env);
792         BRANCH(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath);
793         Bind(&next);
794         {
795             NewTaggedArrayChecked(&result, len, &exit);
796         }
797         Bind(&slowPath);
798         {
799             result = CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(len) });
800             Jump(&exit);
801         }
802     }
803 
804     Bind(&exit);
805     auto ret = *result;
806     env->SubCfgExit();
807     return ret;
808 }
809 
NewMutantTaggedArray(GateRef glue,GateRef len)810 GateRef NewObjectStubBuilder::NewMutantTaggedArray(GateRef glue, GateRef len)
811 {
812     auto env = GetEnvironment();
813     Label entry(env);
814     env->SubCfgEntry(&entry);
815     Label exit(env);
816     Label isEmpty(env);
817     Label notEmpty(env);
818 
819     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
820     SetGlue(glue);
821     BRANCH(Int32Equal(len, Int32(0)), &isEmpty, &notEmpty);
822     Bind(&isEmpty);
823     {
824         result = GetGlobalConstantValue(
825             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
826         Jump(&exit);
827     }
828     Bind(&notEmpty);
829     {
830         Label next(env);
831         Label slowPath(env);
832         BRANCH(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath);
833         Bind(&next);
834         {
835             NewMutantTaggedArrayChecked(&result, len, &exit);
836         }
837         Bind(&slowPath);
838         {
839             result = CallRuntime(glue_, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedInt(len) });
840             Jump(&exit);
841         }
842     }
843 
844     Bind(&exit);
845     auto ret = *result;
846     env->SubCfgExit();
847     return ret;
848 }
849 
ExtendArray(Variable * res,GateRef glue,GateRef elements,GateRef newLen,Label * exit,RegionSpaceFlag spaceType,bool isMutantArray)850 void NewObjectStubBuilder::ExtendArray(Variable *res, GateRef glue, GateRef elements,
851                                        GateRef newLen, Label *exit, RegionSpaceFlag spaceType, bool isMutantArray)
852 {
853     auto env = GetEnvironment();
854     SetGlue(glue);
855     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
856     DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
857     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(newLen));
858     // Be careful. NO GC is allowed when initization is not complete.
859     Label allocArray(env);
860     Label afterAllocate(env);
861     auto hclass = GetGlobalConstantValue(
862         VariableType::JS_POINTER(), glue_,
863         isMutantArray ? ConstantIndex::MUTANT_TAGGED_ARRAY_CLASS_INDEX : ConstantIndex::TAGGED_ARRAY_CLASS_INDEX);
864     HeapAlloc(&array, &allocArray, spaceType, hclass);
865     Bind(&allocArray);
866     StoreBuiltinHClass(glue_, array.ReadVariable(), hclass);
867     Store(VariableType::INT32(), glue_, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen);
868     GateRef oldExtractLen = GetExtraLengthOfTaggedArray(elements);
869     Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
870     GateRef oldL = GetLengthOfTaggedArray(elements);
871     Label afterCopy(env);
872     GateRef startOffset = Int32Mul(oldL, Int32(JSTaggedValue::TaggedTypeSize()));
873     GateRef endOffset = Int32Mul(newLen, Int32(JSTaggedValue::TaggedTypeSize()));
874     GateRef srcDataPtr = GetDataPtrInTaggedArray(elements);
875     GateRef dstDataPtr = GetDataPtrInTaggedArray(*array);
876     if (isMutantArray) {
877         ArrayCopy(glue, elements, srcDataPtr, *array, dstDataPtr, oldL, Boolean(false), DifferentArray);
878         InitializeWithSpeicalValue(&afterCopy, dstDataPtr, SpecialHole(), startOffset,
879                                    endOffset, MemoryAttribute::NoBarrier());
880     } else {
881         ArrayCopy(glue, elements, srcDataPtr, *array, dstDataPtr, oldL, Boolean(true), DifferentArray);
882         InitializeWithSpeicalValue(&afterCopy, dstDataPtr, Hole(), startOffset, endOffset,
883                                    MemoryAttribute::NoBarrier());
884     }
885     Bind(&afterCopy);
886     {
887         *res = *array;
888         Jump(exit);
889     }
890 }
891 
ExtendArrayCheck(GateRef glue,GateRef elements,GateRef newLen,RegionSpaceFlag spaceType)892 GateRef NewObjectStubBuilder::ExtendArrayCheck(GateRef glue, GateRef elements, GateRef newLen,
893                                                RegionSpaceFlag spaceType)
894 {
895     auto env = GetEnvironment();
896     Label subEntry(env);
897     env->SubCfgEntry(&subEntry);
898     SetGlue(glue);
899     Label extendMutantArray(env);
900     Label extendNormalArray(env);
901     Label exit(env);
902     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
903     BRANCH(IsMutantTaggedArray(glue, elements),
904            &extendMutantArray, &extendNormalArray);
905     Bind(&extendNormalArray);
906     ExtendArray(&res, glue, elements, newLen, &exit, spaceType);
907     Bind(&extendMutantArray);
908     ExtendArray(&res, glue, elements, newLen, &exit, spaceType, true);
909     Bind(&exit);
910     auto ret = *res;
911     env->SubCfgExit();
912     return ret;
913 }
914 
ExtendArrayWithOptimizationCheck(GateRef glue,GateRef elements,GateRef newLen)915 GateRef NewObjectStubBuilder::ExtendArrayWithOptimizationCheck(GateRef glue, GateRef elements, GateRef newLen)
916 {
917     auto env = GetEnvironment();
918     Label subEntry(env);
919     env->SubCfgEntry(&subEntry);
920     SetGlue(glue);
921     DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
922     GateRef checkIsMutantTaggedArray = IsMutantTaggedArray(glue, elements);
923     Label exit(env);
924     Label next(env);
925     Label slowPath(env);
926     BRANCH(Int32UnsignedLessThan(newLen, Int32(MAX_EXTEND_ARRAY_LENGTH)), &slowPath, &next);
927     Bind(&slowPath);
928     {
929         array = ExtendArrayCheck(glue, elements, newLen);
930         Jump(&exit);
931     }
932     Bind(&next);
933     {
934         Label extendMutantArray(env);
935         Label extendNormalArray(env);
936         Label afterCreate(env);
937         GateRef oldExtractLen = GetExtraLengthOfTaggedArray(elements);
938         GateRef oldL = GetLengthOfTaggedArray(elements);
939         BRANCH(checkIsMutantTaggedArray, &extendMutantArray, &extendNormalArray);
940         Bind(&extendMutantArray);
941         {
942             array = CallRuntime(glue_, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedInt(newLen) });
943             Jump(&afterCreate);
944         }
945         Bind(&extendNormalArray);
946         {
947             array = CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(newLen) });
948             Jump(&afterCreate);
949         }
950         Bind(&afterCreate);
951         Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen);
952         Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
953         ArrayCopy(glue, elements, GetDataPtrInTaggedArray(elements), *array,
954             GetDataPtrInTaggedArray(*array), oldL, BoolNot(checkIsMutantTaggedArray), DifferentArray);
955         Jump(&exit);
956     }
957     Bind(&exit);
958     auto ret = *array;
959     env->SubCfgExit();
960     return ret;
961 }
962 
CopyArray(GateRef glue,GateRef elements,GateRef oldLen,GateRef newLen,RegionSpaceFlag spaceType)963 GateRef NewObjectStubBuilder::CopyArray(GateRef glue, GateRef elements, GateRef oldLen,
964                                         GateRef newLen, RegionSpaceFlag spaceType)
965 {
966     auto env = GetEnvironment();
967     Label subEntry(env);
968     env->SubCfgEntry(&subEntry);
969     Label exit(env);
970     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
971     Label emptyArray(env);
972     Label notEmptyArray(env);
973     BRANCH(Int32Equal(newLen, Int32(0)), &emptyArray, &notEmptyArray);
974     Bind(&emptyArray);
975     result = GetEmptyArray(glue);
976     Jump(&exit);
977     Bind(&notEmptyArray);
978     {
979         Label extendArray(env);
980         Label notExtendArray(env);
981         BRANCH(Int32UnsignedGreaterThan(newLen, oldLen), &extendArray, &notExtendArray);
982         Bind(&extendArray);
983         {
984             result = ExtendArrayCheck(glue, elements, newLen, spaceType);
985             Jump(&exit);
986         }
987         Bind(&notExtendArray);
988         {
989             DEFVARIABLE(array, VariableType::JS_ANY(), elements);
990             Label isMutantTaggedArray(env);
991             Label isNotMutantTaggedArray(env);
992             Label afterInitializeElements(env);
993             GateRef checkIsMutantTaggedArray = IsMutantTaggedArray(glue, *array);
994             BRANCH(checkIsMutantTaggedArray, &isMutantTaggedArray, &isNotMutantTaggedArray);
995             Bind(&isMutantTaggedArray);
996             {
997                 array = NewMutantTaggedArray(glue, newLen);
998                 Jump(&afterInitializeElements);
999             }
1000             Bind(&isNotMutantTaggedArray);
1001             {
1002                 array = NewTaggedArray(glue, newLen);
1003                 Jump(&afterInitializeElements);
1004             }
1005             Bind(&afterInitializeElements);
1006             Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen);
1007             GateRef oldExtractLen = GetExtraLengthOfTaggedArray(elements);
1008             Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
1009             ArrayCopy(glue, elements, GetDataPtrInTaggedArray(elements), *array,
1010                       GetDataPtrInTaggedArray(*array), newLen, BoolNot(checkIsMutantTaggedArray), DifferentArray);
1011             result = *array;
1012             Jump(&exit);
1013         }
1014     }
1015     Bind(&exit);
1016     auto ret = *result;
1017     env->SubCfgExit();
1018     return ret;
1019 }
1020 
NewJSForinIterator(GateRef glue,GateRef receiver,GateRef keys,GateRef cachedHClass,GateRef EnumCacheKind)1021 GateRef NewObjectStubBuilder::NewJSForinIterator(GateRef glue, GateRef receiver, GateRef keys, GateRef cachedHClass,
1022                                                  GateRef EnumCacheKind)
1023 {
1024     GateRef globalEnv = GetCurrentGlobalEnv();
1025     GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
1026                                        GlobalEnv::FOR_IN_ITERATOR_CLASS_INDEX);
1027     GateRef iter = NewJSObject(glue, hclass);
1028     // init JSForinIterator
1029     SetObjectOfForInIterator(glue, iter, receiver);
1030     SetCachedHClassOfForInIterator(glue, iter, cachedHClass);
1031     SetKeysOfForInIterator(glue, iter, keys);
1032     SetIndexOfForInIterator(glue, iter, Int32(0));
1033     SetCacheKindForInIterator(glue, iter, EnumCacheKind);
1034     GateRef length = GetLengthOfTaggedArray(keys);
1035     SetLengthOfForInIterator(glue, iter, length);
1036     return iter;
1037 }
1038 
LoadHClassFromMethod(GateRef glue,GateRef method)1039 GateRef NewObjectStubBuilder::LoadHClassFromMethod(GateRef glue, GateRef method)
1040 {
1041     auto env = GetEnvironment();
1042     Label entry(env);
1043     env->SubCfgEntry(&entry);
1044     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
1045     GateRef kind = GetFuncKind(method);
1046     Label exit(env);
1047     Label defaultLabel(env);
1048     Label isNormal(env);
1049     Label notNormal(env);
1050     Label isAsync(env);
1051     Label notAsync(env);
1052 
1053     Label labelBuffer[2] = { Label(env), Label(env) };
1054     Label labelBuffer1[3] = { Label(env), Label(env), Label(env) };
1055     int64_t valueBuffer[2] = {
1056         static_cast<int64_t>(FunctionKind::NORMAL_FUNCTION), static_cast<int64_t>(FunctionKind::ARROW_FUNCTION) };
1057     int64_t valueBuffer1[3] = {
1058         static_cast<int64_t>(FunctionKind::BASE_CONSTRUCTOR), static_cast<int64_t>(FunctionKind::GENERATOR_FUNCTION),
1059         static_cast<int64_t>(FunctionKind::ASYNC_GENERATOR_FUNCTION) };
1060     GateRef globalEnv = GetCurrentGlobalEnv();
1061     BRANCH(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ARROW_FUNCTION))),
1062         &isNormal, &notNormal);
1063     Bind(&isNormal);
1064     {
1065         // 2 : this switch has 2 case
1066         Switch(kind, &defaultLabel, valueBuffer, labelBuffer, 2);
1067         Bind(&labelBuffer[0]);
1068         {
1069             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::FUNCTION_CLASS_WITH_PROTO);
1070             Jump(&exit);
1071         }
1072         Bind(&labelBuffer[1]);
1073         {
1074             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
1075                                        GlobalEnv::FUNCTION_CLASS_WITHOUT_PROTO);
1076             Jump(&exit);
1077         }
1078     }
1079     Bind(&notNormal);
1080     {
1081         BRANCH(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ASYNC_FUNCTION))),
1082             &isAsync, &notAsync);
1083         Bind(&isAsync);
1084         {
1085             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::ASYNC_FUNCTION_CLASS);
1086             Jump(&exit);
1087         }
1088         Bind(&notAsync);
1089         {
1090             // 3 : this switch has 3 case
1091             Switch(kind, &defaultLabel, valueBuffer1, labelBuffer1, 3);
1092             Bind(&labelBuffer1[0]);
1093             {
1094                 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
1095                                            GlobalEnv::FUNCTION_CLASS_WITH_PROTO);
1096                 Jump(&exit);
1097             }
1098             Bind(&labelBuffer1[1]);
1099             {
1100                 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
1101                                            GlobalEnv::GENERATOR_FUNCTION_CLASS);
1102                 Jump(&exit);
1103             }
1104             // 2 : index of kind
1105             Bind(&labelBuffer1[2]);
1106             {
1107                 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
1108                                            GlobalEnv::ASYNC_GENERATOR_FUNCTION_CLASS);
1109                 Jump(&exit);
1110             }
1111         }
1112     }
1113     Bind(&defaultLabel);
1114     {
1115         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1116         Jump(&exit);
1117     }
1118     Bind(&exit);
1119     auto ret = *hclass;
1120     env->SubCfgExit();
1121     return ret;
1122 }
1123 
LoadSHClassFromMethod(GateRef glue,GateRef method)1124 GateRef NewObjectStubBuilder::LoadSHClassFromMethod(GateRef glue, GateRef method)
1125 {
1126     auto env = GetEnvironment();
1127     Label entry(env);
1128     env->SubCfgEntry(&entry);
1129     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
1130     GateRef kind = GetFuncKind(method);
1131     Label exit(env);
1132     Label isSendableFunc(env);
1133     Label isNotSendableFunc(env);
1134     Label isNormal(env);
1135     Label notNormal(env);
1136 
1137     GateRef globalEnv = GetCurrentGlobalEnv();
1138     BRANCH(IsSendableFunction(method), &isSendableFunc, &isNotSendableFunc);
1139     Bind(&isSendableFunc);
1140     {
1141         BRANCH(Int32Equal(kind, Int32(static_cast<int32_t>(FunctionKind::BASE_CONSTRUCTOR))), &isNormal, &notNormal);
1142         Bind(&isNormal);
1143         {
1144             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
1145                                        GlobalEnv::SHARED_FUNCTION_CLASS_WITH_PROTO);
1146             Jump(&exit);
1147         }
1148         Bind(&notNormal);
1149         {
1150             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
1151                                        GlobalEnv::SHARED_ASYNC_FUNCTION_CLASS);
1152             Jump(&exit);
1153         }
1154     }
1155     Bind(&isNotSendableFunc);
1156     {
1157         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
1158         Jump(&exit);
1159     }
1160     Bind(&exit);
1161     auto ret = *hclass;
1162     env->SubCfgExit();
1163     return ret;
1164 }
1165 
NewJSFunction(GateRef glue,GateRef method,FunctionKind targetKind)1166 GateRef NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef method, FunctionKind targetKind)
1167 {
1168     GateRef hclass = LoadHClassFromMethod(glue, method);
1169     return NewJSFunctionByHClass(glue, method, hclass, targetKind);
1170 }
1171 
NewJSSendableFunction(GateRef glue,GateRef method,FunctionKind targetKind)1172 GateRef NewObjectStubBuilder::NewJSSendableFunction(GateRef glue, GateRef method, FunctionKind targetKind)
1173 {
1174     GateRef hclass = LoadSHClassFromMethod(glue, method);
1175     return NewSFunctionByHClass(glue, method, hclass, targetKind);
1176 }
1177 
NewJSFunction(GateRef glue,GateRef jsFunc,GateRef index,GateRef length,GateRef lexEnv,Variable * result,Label * success,Label * failed,GateRef slotId,FunctionKind targetKind)1178 void NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef jsFunc, GateRef index, GateRef length, GateRef lexEnv,
1179                                          Variable *result, Label *success, Label *failed, GateRef slotId,
1180                                          FunctionKind targetKind)
1181 {
1182     auto env = GetEnvironment();
1183     Label hasException(env);
1184     Label notException(env);
1185     Label isSendableFunc(env);
1186     Label isNotSendableFunc(env);
1187     Label afterSendableFunc(env);
1188     GateRef constPool = GetConstPoolFromFunction(glue, jsFunc);
1189     SetGlue(glue);
1190     result->WriteVariable(DefineFunc(glue, constPool, index, targetKind));
1191     BRANCH(HasPendingException(glue), &hasException, &notException);
1192     Bind(&hasException);
1193     {
1194         Jump(failed);
1195     }
1196     Bind(&notException);
1197     {
1198         GateRef module = GetModuleFromFunction(glue, jsFunc);
1199         SetLengthToFunction(glue, result->ReadVariable(), length);
1200         BRANCH(IsSendableFunction(GetMethodFromFunction(glue, result->ReadVariable())),
1201             &isSendableFunc, &isNotSendableFunc);
1202         Bind(&isSendableFunc);
1203         {
1204             GateRef smodule = CallRuntime(glue, RTSTUB_ID(GetSharedModule), { module });
1205             SetSendableEnvToModule(glue, smodule, GetSendableEnvFromModule(glue, module));
1206             SetModuleToFunction(glue, result->ReadVariable(), smodule);
1207             GateRef emptySFuncEnv = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
1208                                                            ConstantIndex::EMPTY_SFUNCTION_ENV_INDEX);
1209             SetLexicalEnvToFunction(glue, result->ReadVariable(), emptySFuncEnv);
1210             Jump(&afterSendableFunc);
1211         }
1212         Bind(&isNotSendableFunc);
1213         {
1214             SetLexicalEnvToFunction(glue, result->ReadVariable(), lexEnv);
1215             SetModuleToFunction(glue, result->ReadVariable(), module);
1216             SetHomeObjectToFunction(glue, result->ReadVariable(), GetHomeObjectFromFunction(glue, jsFunc));
1217 #if ECMASCRIPT_ENABLE_IC
1218             SetProfileTypeInfoCellToFunction(jsFunc, result->ReadVariable(), slotId);
1219 #endif
1220             Jump(&afterSendableFunc);
1221         }
1222         Bind(&afterSendableFunc);
1223         Jump(success);
1224     }
1225 }
1226 
NewJSFunction(GateRef glue,GateRef method,GateRef homeObject)1227 GateRef NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef method, GateRef homeObject)
1228 {
1229     ASM_ASSERT(GET_MESSAGE_STRING_ID(IsEcmaObject), TaggedObjectIsEcmaObject(glue, homeObject));
1230 
1231     GateRef globalEnv = GetCurrentGlobalEnv();
1232     GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::FUNCTION_CLASS_WITHOUT_PROTO);
1233 
1234     GateRef jsFunc = NewJSFunctionByHClass(glue, method, hclass);
1235     SetHomeObjectToFunction(glue, jsFunc, homeObject);
1236     ASM_ASSERT(GET_MESSAGE_STRING_ID(HasPendingException), BoolNot(HasPendingException(glue)));
1237     return jsFunc;
1238 }
1239 
DefineMethod(GateRef glue,GateRef method,GateRef homeObject,GateRef length,GateRef lexEnv,GateRef module)1240 GateRef NewObjectStubBuilder::DefineMethod(GateRef glue, GateRef method, GateRef homeObject, GateRef length,
1241                                            GateRef lexEnv, GateRef module)
1242 {
1243     GateRef func = NewJSFunction(glue, method, homeObject);
1244 
1245     SetLengthToFunction(glue, func, length);
1246     SetLexicalEnvToFunction(glue, func, lexEnv);
1247     SetModuleToFunction(glue, func, module);
1248     return func;
1249 }
1250 
NewJSFunctionForJit(GateRef glue,GateRef jsFunc,GateRef hclass,GateRef method,GateRef length,GateRef lexEnv,Variable * result,Label * success,Label * failed,GateRef slotId,FunctionKind targetKind)1251 void NewObjectStubBuilder::NewJSFunctionForJit(GateRef glue, GateRef jsFunc, GateRef hclass, GateRef method,
1252                                                GateRef length, GateRef lexEnv, Variable *result, Label *success,
1253                                                Label *failed, GateRef slotId, FunctionKind targetKind)
1254 {
1255     auto env = GetEnvironment();
1256     Label hasException(env);
1257     Label notException(env);
1258     Label isSendableFunc(env);
1259     Label isNotSendableFunc(env);
1260     Label afterSendableFunc(env);
1261     Label slotValueUpdate(env);
1262     Label slotValueNotUndefined(env);
1263     Label profileTypeInfoEnd(env);
1264     SetGlue(glue);
1265     result->WriteVariable(DefineFuncForJit(glue, method, hclass, targetKind));
1266     BRANCH(HasPendingException(glue), &hasException, &notException);
1267     Bind(&hasException);
1268     {
1269         Jump(failed);
1270     }
1271     Bind(&notException);
1272     {
1273         GateRef module = GetModuleFromFunction(glue, jsFunc);
1274         SetLengthToFunction(glue, result->ReadVariable(), length);
1275         SetLexicalEnvToFunction(glue, result->ReadVariable(), lexEnv);
1276         SetModuleToFunction(glue, result->ReadVariable(), module);
1277         SetHomeObjectToFunction(glue, result->ReadVariable(), GetHomeObjectFromFunction(glue, jsFunc));
1278 #if ECMASCRIPT_ENABLE_IC
1279         GateRef profileTypeInfo = GetProfileTypeInfo(glue, jsFunc);
1280         GateRef slotValue = GetValueFromTaggedArray(glue, profileTypeInfo, slotId);
1281 
1282         BRANCH(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
1283         Bind(&slotValueUpdate);
1284         {
1285             GateRef newProfileTypeInfoCell = NewProfileTypeInfoCell(glue, Undefined());
1286             SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
1287             SetRawProfileTypeInfoToFunction(glue, result->ReadVariable(), newProfileTypeInfoCell);
1288             Jump(&profileTypeInfoEnd);
1289         }
1290         Bind(&slotValueNotUndefined);
1291         {
1292             UpdateProfileTypeInfoCellType(glue, slotValue);
1293             SetRawProfileTypeInfoToFunction(glue, result->ReadVariable(), slotValue);
1294             TryToJitReuseCompiledFunc(glue, result->ReadVariable(), slotValue);
1295             Jump(&profileTypeInfoEnd);
1296         }
1297         Bind(&profileTypeInfoEnd);
1298 #endif
1299         Jump(success);
1300     }
1301 }
1302 
SetProfileTypeInfoCellToFunction(GateRef jsFunc,GateRef definedFunc,GateRef slotId)1303 void NewObjectStubBuilder::SetProfileTypeInfoCellToFunction(GateRef jsFunc, GateRef definedFunc, GateRef slotId)
1304 {
1305     auto env = GetEnvironment();
1306     Label entry(env);
1307     env->SubCfgEntry(&entry);
1308     Label isValidSlotId(env);
1309     Label exit(env);
1310 
1311     BRANCH(Equal(slotId, Int32(ProfileTypeInfo::INVALID_SLOT_INDEX)), &exit, &isValidSlotId);
1312     Bind(&isValidSlotId);
1313     {
1314         Label isUndefined(env);
1315         Label notUndefined(env);
1316         DEFVARIABLE(profileTypeInfo, VariableType::JS_ANY(), GetProfileTypeInfo(glue_, jsFunc));
1317         BRANCH(TaggedIsUndefined(*profileTypeInfo), &isUndefined, &notUndefined);
1318         Bind(&isUndefined);
1319         {
1320             profileTypeInfo = CallRuntime(glue_, RTSTUB_ID(UpdateHotnessCounter), { jsFunc });
1321             Jump(&notUndefined);
1322         }
1323         Bind(&notUndefined);
1324         {
1325             UpdateProfileTypeInfoCellToFunction(glue_, definedFunc, *profileTypeInfo, slotId);
1326             Jump(&exit);
1327         }
1328     }
1329     Bind(&exit);
1330     env->SubCfgExit();
1331     return;
1332 }
1333 
NewJSBoundFunction(GateRef glue,GateRef target,GateRef boundThis,GateRef args)1334 GateRef NewObjectStubBuilder::NewJSBoundFunction(GateRef glue, GateRef target, GateRef boundThis, GateRef args)
1335 {
1336     auto env = GetEnvironment();
1337     Label subentry(env);
1338     env->SubCfgEntry(&subentry);
1339     Label exit(env);
1340     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1341 
1342     GateRef globalEnv = GetCurrentGlobalEnv();
1343     GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::BOUND_FUNCTION_CLASS);
1344     result = NewJSObject(glue, hclass);
1345     GateRef nameAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1346                                                   ConstantIndex::FUNCTION_NAME_ACCESSOR);
1347     Store(VariableType::JS_POINTER(), glue, *result,
1348           IntPtr(JSBoundFunction::GetInlinedPropertyOffset(JSFunction::NAME_INLINE_PROPERTY_INDEX)), nameAccessor,
1349           MemoryAttribute::NoBarrier());
1350     GateRef lengthAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1351                                                     ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
1352     Store(VariableType::JS_POINTER(), glue, *result,
1353           IntPtr(JSBoundFunction::GetInlinedPropertyOffset(JSFunction::LENGTH_INLINE_PROPERTY_INDEX)), lengthAccessor,
1354           MemoryAttribute::NoBarrier());
1355     SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_TARGET_OFFSET, target);
1356     SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_THIS_OFFSET, boundThis);
1357     SetJSObjectTaggedField(glue, *result, JSBoundFunction::BOUND_ARGUMENTS_OFFSET, args);
1358     GateRef method = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1359                                             ConstantIndex::BOUND_FUNCTION_METHOD_INDEX);
1360     SetMethodToFunction(glue, *result, method);
1361     SetNativePointerToFunctionFromMethod(glue, *result, method);
1362 
1363     Label targetIsHeapObject(env);
1364     Label targetIsConstructor(env);
1365     BRANCH(TaggedIsHeapObject(target), &targetIsHeapObject, &exit);
1366     Bind(&targetIsHeapObject);
1367     BRANCH(IsConstructor(glue, target), &targetIsConstructor, &exit);
1368     Bind(&targetIsConstructor);
1369     {
1370         GateRef resultHClass = LoadHClass(glue, *result);
1371         SetHClassBit<JSHClass::ConstructorBit>(glue, resultHClass, Int32(1));
1372         Jump(&exit);
1373     }
1374 
1375     Bind(&exit);
1376     auto ret = *result;
1377     env->SubCfgExit();
1378     return ret;
1379 }
1380 
EnumerateObjectProperties(GateRef glue,GateRef obj)1381 GateRef NewObjectStubBuilder::EnumerateObjectProperties(GateRef glue, GateRef obj)
1382 {
1383     auto env = GetEnvironment();
1384     Label entry(env);
1385     env->SubCfgEntry(&entry);
1386     Label exit(env);
1387     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1388     DEFVARIABLE(object, VariableType::JS_ANY(), Undefined());
1389 
1390     Label isString(env);
1391     Label isNotString(env);
1392     Label afterObjectTransform(env);
1393     Label slowpath(env);
1394     Label empty(env);
1395     Label tryGetEnumCache(env);
1396     Label cacheHit(env);
1397     Label checkNativePointer(env);
1398     BRANCH(TaggedIsString(glue, obj), &isString, &isNotString);
1399     Bind(&isString);
1400     {
1401         object = CallRuntime(glue, RTSTUB_ID(PrimitiveStringCreate), { obj });
1402         Jump(&afterObjectTransform);
1403     }
1404     Bind(&isNotString);
1405     {
1406         object = ToPrototypeOrObj(glue, obj);
1407         Jump(&afterObjectTransform);
1408     }
1409     Bind(&afterObjectTransform);
1410     BRANCH(TaggedIsUndefinedOrNull(*object), &empty, &checkNativePointer);
1411     Bind(&checkNativePointer);
1412     BRANCH(IsNativePointer(glue, *object), &empty, &tryGetEnumCache);
1413     Bind(&tryGetEnumCache);
1414     GateRef enumCacheAll = TryGetEnumCache(glue, *object);
1415     BRANCH(TaggedIsUndefined(enumCacheAll), &slowpath, &cacheHit);
1416     Bind(&cacheHit);
1417     {
1418         GateRef hclass = LoadHClass(glue, *object);
1419         GateRef enumCache = GetEnumCacheFromHClass(glue, hclass);
1420         result = NewJSForinIterator(glue, *object, enumCacheAll, hclass,
1421             GetEnumCacheKindFromEnumCache(enumCache));
1422         Jump(&exit);
1423     }
1424     Bind(&empty);
1425     {
1426         GateRef emptyArray = GetEmptyArray(glue);
1427         result = NewJSForinIterator(glue, Undefined(), emptyArray, Undefined(),
1428                                     Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE)));
1429         Jump(&exit);
1430     }
1431 
1432     Bind(&slowpath);
1433     {
1434         result = CallRuntime(glue, RTSTUB_ID(GetPropIteratorSlowpath), { *object });
1435         Jump(&exit);
1436     }
1437     Bind(&exit);
1438     auto ret = *result;
1439     env->SubCfgExit();
1440     return ret;
1441 }
1442 
FillArgumentsList(GateRef argumentsList,GateRef sp,GateRef startIdx,GateRef numArgs)1443 void NewObjectStubBuilder::FillArgumentsList(GateRef argumentsList,
1444     GateRef sp, GateRef startIdx, GateRef numArgs)
1445 {
1446     auto env = GetEnvironment();
1447     Label entry(env);
1448     env->SubCfgEntry(&entry);
1449     Label exit(env);
1450 
1451     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1452     Label setArgumentsBegin(env);
1453     Label setArgumentsAgain(env);
1454     Label setArgumentsEnd(env);
1455     BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
1456     LoopBegin(&setArgumentsBegin);
1457     GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
1458     GateRef argument = LoadPrimitive(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx));
1459     SetValueToTaggedArray(VariableType::JS_ANY(), glue_, argumentsList, *i, argument);
1460     i = Int32Add(*i, Int32(1));
1461     BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
1462     Bind(&setArgumentsAgain);
1463     LoopEnd(&setArgumentsBegin);
1464     Bind(&setArgumentsEnd);
1465     Jump(&exit);
1466     Bind(&exit);
1467     env->SubCfgExit();
1468     return;
1469 }
1470 
NewArgumentsListObj(GateRef numArgs)1471 GateRef NewObjectStubBuilder::NewArgumentsListObj(GateRef numArgs)
1472 {
1473     auto env = GetEnvironment();
1474     Label entry(env);
1475     env->SubCfgEntry(&entry);
1476     Label exit(env);
1477     Label setHClass(env);
1478     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1479     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(numArgs));
1480     GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1481                                                 ConstantIndex::TAGGED_ARRAY_CLASS_INDEX);
1482     AllocateInYoung(&result, &exit, &setHClass, arrayClass);
1483     Bind(&setHClass);
1484     StoreHClass(glue_, *result, arrayClass);
1485     Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::LENGTH_OFFSET), numArgs);
1486     Store(VariableType::INT32(), glue_, *result, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0));
1487     Jump(&exit);
1488     Bind(&exit);
1489     auto ret = *result;
1490     env->SubCfgExit();
1491     return ret;
1492 }
1493 
NewArgumentsList(Variable * result,Label * exit,GateRef sp,GateRef startIdx,GateRef numArgs)1494 void NewObjectStubBuilder::NewArgumentsList(Variable *result, Label *exit,
1495     GateRef sp, GateRef startIdx, GateRef numArgs)
1496 {
1497     auto env = GetEnvironment();
1498     Label hasException(env);
1499     Label notException(env);
1500 
1501     GateRef argumentsList = NewArgumentsListObj(numArgs);
1502     result->WriteVariable(argumentsList);
1503     Branch(TaggedIsException(argumentsList), &hasException, &notException);
1504     Bind(&hasException);
1505     Jump(exit);
1506     Bind(&notException);
1507     FillArgumentsList(argumentsList, sp, startIdx, numArgs);
1508     Jump(exit);
1509 }
1510 
NewArgumentsObj(Variable * result,Label * exit,GateRef argumentsList,GateRef numArgs)1511 void NewObjectStubBuilder::NewArgumentsObj(Variable *result, Label *exit,
1512     GateRef argumentsList, GateRef numArgs)
1513 {
1514     auto env = GetEnvironment();
1515 
1516     GateRef globalEnv = GetCurrentGlobalEnv();
1517     GateRef argumentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glue_, globalEnv,
1518                                                GlobalEnv::ARGUMENTS_CLASS);
1519     Label afterNewObject(env);
1520     NewJSObject(result, &afterNewObject, argumentsClass);
1521     Bind(&afterNewObject);
1522     Label setArgumentsObjProperties(env);
1523     BRANCH(TaggedIsException(result->ReadVariable()), exit, &setArgumentsObjProperties);
1524     Bind(&setArgumentsObjProperties);
1525     Store(VariableType::JS_ANY(), glue_, result->ReadVariable(),
1526           IntPtr(JSArguments::GetInlinedPropertyOffset(JSArguments::LENGTH_INLINE_PROPERTY_INDEX)),
1527           IntToTaggedInt(numArgs));
1528     SetElementsArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), argumentsList);
1529     GateRef arrayProtoValuesFunction = GetGlobalEnvValue(VariableType::JS_ANY(), glue_, globalEnv,
1530                                                          GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
1531     Store(VariableType::JS_ANY(), glue_, result->ReadVariable(),
1532           IntPtr(JSArguments::GetInlinedPropertyOffset(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX)),
1533           arrayProtoValuesFunction);
1534     GateRef accessorCaller = GetGlobalEnvValue(VariableType::JS_ANY(), glue_, globalEnv,
1535                                                GlobalEnv::ARGUMENTS_CALLER_ACCESSOR);
1536     Store(VariableType::JS_ANY(), glue_, result->ReadVariable(),
1537           IntPtr(JSArguments::GetInlinedPropertyOffset(JSArguments::CALLER_INLINE_PROPERTY_INDEX)),
1538           accessorCaller);
1539     GateRef accessorCallee = GetGlobalEnvValue(VariableType::JS_ANY(), glue_, globalEnv,
1540                                                GlobalEnv::ARGUMENTS_CALLEE_ACCESSOR);
1541     Store(VariableType::JS_ANY(), glue_, result->ReadVariable(),
1542           IntPtr(JSArguments::GetInlinedPropertyOffset(JSArguments::CALLEE_INLINE_PROPERTY_INDEX)),
1543           accessorCallee);
1544     Jump(exit);
1545 }
1546 
AssignRestArg(Variable * result,Label * exit,GateRef sp,GateRef startIdx,GateRef numArgs)1547 void NewObjectStubBuilder::AssignRestArg(Variable *result, Label *exit,
1548     GateRef sp, GateRef startIdx, GateRef numArgs)
1549 {
1550     auto env = GetEnvironment();
1551     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1552     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1553     Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, TruncInt64ToInt32(numArgs));
1554     GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1555     Store(VariableType::JS_ANY(), glue_, result->ReadVariable(),
1556           IntPtr(JSArray::GetInlinedPropertyOffset(JSArray::LENGTH_INLINE_PROPERTY_INDEX)), accessor);
1557     SetExtensibleToBitfield(glue_, result->ReadVariable(), true);
1558     Label setArgumentsBegin(env);
1559     Label setArgumentsAgain(env);
1560     Label setArgumentsEnd(env);
1561     GateRef elements = GetElementsArray(glue_, result->ReadVariable());
1562     BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
1563     LoopBegin(&setArgumentsBegin);
1564     {
1565         GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
1566         GateRef receiver = LoadPrimitive(VariableType::JS_ANY(), sp,
1567                                          PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), idx));
1568         SetValueToTaggedArray(VariableType::JS_ANY(), glue_, elements, *i, receiver);
1569         i = Int32Add(*i, Int32(1));
1570         BRANCH(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
1571         Bind(&setArgumentsAgain);
1572     }
1573     LoopEnd(&setArgumentsBegin);
1574     Bind(&setArgumentsEnd);
1575     Jump(exit);
1576 }
1577 
NewJSArrayLiteral(Variable * result,Label * exit,RegionSpaceFlag spaceType,GateRef obj,GateRef hclass,GateRef trackInfo,bool isEmptyArray)1578 void NewObjectStubBuilder::NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj,
1579                                              GateRef hclass, GateRef trackInfo, bool isEmptyArray)
1580 {
1581     auto env = GetEnvironment();
1582     Label initializeArray(env);
1583     Label afterInitialize(env);
1584     HeapAlloc(result, &initializeArray, spaceType, hclass);
1585     Bind(&initializeArray);
1586     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(0), hclass);
1587     InitializeWithSpeicalValue(&afterInitialize, result->ReadVariable(), Undefined(), Int32(JSArray::SIZE),
1588                                TruncInt64ToInt32(size_), MemoryAttribute::NoBarrier());
1589     Bind(&afterInitialize);
1590     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
1591     Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()),
1592           MemoryAttribute::NoBarrier());
1593 
1594     GateRef propertiesOffset = IntPtr(JSObject::PROPERTIES_OFFSET);
1595     GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
1596     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1597     GateRef trackInfoOffset = IntPtr(JSArray::TRACK_INFO_OFFSET);
1598     if (isEmptyArray) {
1599         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, obj,
1600               MemoryAttribute::NoBarrier());
1601         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, obj,
1602               MemoryAttribute::NoBarrier());
1603         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, Int32(0),
1604               MemoryAttribute::NoBarrier());
1605     } else {
1606         auto newProperties = Load(VariableType::JS_POINTER(), glue_, obj, propertiesOffset);
1607         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, newProperties);
1608 
1609         auto newElements = Load(VariableType::JS_POINTER(), glue_, obj, elementsOffset);
1610         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, newElements);
1611 
1612         GateRef arrayLength = LoadPrimitive(VariableType::INT32(), obj, lengthOffset);
1613         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, arrayLength,
1614               MemoryAttribute::NoBarrier());
1615     }
1616     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), trackInfoOffset, trackInfo);
1617 
1618     auto accessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1619     SetPropertyInlinedProps(glue_, result->ReadVariable(), hclass, accessor,
1620         Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_POINTER(), MemoryAttribute::NoBarrier());
1621     Jump(exit);
1622 }
1623 
HeapAlloc(Variable * result,Label * exit,RegionSpaceFlag spaceType,GateRef hclass)1624 void NewObjectStubBuilder::HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef hclass)
1625 {
1626     switch (spaceType) {
1627         case RegionSpaceFlag::IN_YOUNG_SPACE:
1628             AllocateInYoung(result, exit, hclass);
1629             break;
1630         case RegionSpaceFlag::IN_SHARED_OLD_SPACE:
1631             AllocateInSOld(result, exit, hclass);
1632             break;
1633         default:
1634             *result = CallRuntime(glue_, RTSTUB_ID(HeapAlloc),
1635                 { Int64ToTaggedInt(size_), hclass, IntToTaggedInt(Int64(spaceType))});
1636             break;
1637     }
1638 }
1639 
AllocateInSOldPrologue(Variable * result,Label * callRuntime,Label * exit)1640 void NewObjectStubBuilder::AllocateInSOldPrologue([[maybe_unused]] Variable *result,
1641     Label *callRuntime, [[maybe_unused]] Label *exit)
1642 {
1643     auto env = GetEnvironment();
1644     Label next(env);
1645 
1646 #if defined(ARK_ASAN_ON)
1647     Jump(callRuntime);
1648 #else
1649 #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
1650     auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
1651     auto isStartHeapSampling = LoadPrimitive(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
1652     BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next);
1653     Bind(&next);
1654 #endif
1655     Label isCMCGC(env);
1656     Label notCMCGC(env);
1657     BRANCH_UNLIKELY(
1658         LoadPrimitive(VariableType::BOOL(), glue_, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
1659         &isCMCGC, &notCMCGC);
1660     Bind(&isCMCGC);
1661     {
1662         AllocateInSOldPrologueImplForCMCGC(result, callRuntime, exit);
1663     }
1664     Bind(&notCMCGC);
1665     {
1666         AllocateInSOldPrologueImpl(result, callRuntime, exit);
1667     }
1668 #endif
1669 }
1670 
AllocateInSOldPrologueImpl(Variable * result,Label * callRuntime,Label * exit)1671 void NewObjectStubBuilder::AllocateInSOldPrologueImpl([[maybe_unused]] Variable *result,
1672     Label *callRuntime, [[maybe_unused]] Label *exit)
1673 {
1674     auto env = GetEnvironment();
1675     Label success(env);
1676     auto topOffset = JSThread::GlueData::GetSOldSpaceAllocationTopAddressOffset(env->Is32Bit());
1677     auto endOffset = JSThread::GlueData::GetSOldSpaceAllocationEndAddressOffset(env->Is32Bit());
1678     auto topAddress = LoadPrimitive(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
1679     auto endAddress = LoadPrimitive(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
1680     auto top = LoadPrimitive(VariableType::JS_POINTER(), topAddress, IntPtr(0));
1681     auto end = LoadPrimitive(VariableType::JS_POINTER(), endAddress, IntPtr(0));
1682     auto newTop = PtrAdd(top, size_);
1683     BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success);
1684     Bind(&success);
1685     {
1686         Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop);
1687         if (env->Is32Bit()) {
1688             top = ZExtInt32ToInt64(top);
1689         }
1690         result->WriteVariable(top);
1691         Jump(exit);
1692     }
1693 }
1694 
AllocateInSOldPrologueImplForCMCGC(Variable * result,Label * callRuntime,Label * exit)1695 void NewObjectStubBuilder::AllocateInSOldPrologueImplForCMCGC(Variable *result, Label *callRuntime, Label *exit)
1696 {
1697     auto env = GetEnvironment();
1698     Label success(env);
1699 
1700     auto allocBufferOffset = JSThread::GlueData::GetAllocBufferOffset(env->Is32Bit());
1701     auto allocBufferAddress = LoadPrimitive(VariableType::NATIVE_POINTER(), glue_, IntPtr(allocBufferOffset));
1702     auto tlOldRegion = LoadPrimitive(VariableType::NATIVE_POINTER(), allocBufferAddress,
1703                                      IntPtr(common::AllocationBuffer::GetTLOldRegionOffset()));
1704     auto allocPtr =
1705         LoadPrimitive(VariableType::JS_POINTER(), tlOldRegion, IntPtr(common::RegionDesc::GetAllocPtrOffset()));
1706     auto regionEnd =
1707         LoadPrimitive(VariableType::JS_POINTER(), tlOldRegion, IntPtr(common::RegionDesc::GetRegionEndOffset()));
1708     auto newAllocPtr = PtrAdd(allocPtr, size_);
1709     BRANCH(IntPtrGreaterThan(newAllocPtr, regionEnd), callRuntime, &success);
1710     Bind(&success);
1711     {
1712         Store(VariableType::NATIVE_POINTER(), glue_, tlOldRegion, IntPtr(0), newAllocPtr, MemoryAttribute::NoBarrier());
1713         if (env->Is32Bit()) {
1714             allocPtr = ZExtInt32ToInt64(allocPtr);
1715         }
1716         result->WriteVariable(allocPtr);
1717         Jump(exit);
1718     }
1719 }
1720 
AllocateInSOld(Variable * result,Label * exit,GateRef hclass)1721 void NewObjectStubBuilder::AllocateInSOld(Variable *result, Label *exit, GateRef hclass)
1722 {
1723     // disable fastpath for now
1724     auto env = GetEnvironment();
1725     Label callRuntime(env);
1726     AllocateInSOldPrologue(result, &callRuntime, exit);
1727     Bind(&callRuntime);
1728     {
1729         DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1730         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInSOld), {IntToTaggedInt(size_), hclass});
1731         result->WriteVariable(*ret);
1732         Jump(exit);
1733     }
1734 }
1735 
AllocateInYoungPrologueImplForCMCGC(Variable * result,Label * callRuntime,Label * exit)1736 void NewObjectStubBuilder::AllocateInYoungPrologueImplForCMCGC(Variable *result, Label *callRuntime, Label *exit)
1737 {
1738     auto env = GetEnvironment();
1739     Label success(env);
1740 
1741     auto allocBufferOffset = JSThread::GlueData::GetAllocBufferOffset(env->Is32Bit());
1742     auto allocBufferAddress = LoadPrimitive(VariableType::NATIVE_POINTER(), glue_, IntPtr(allocBufferOffset));
1743     auto tlRegion = LoadPrimitive(VariableType::NATIVE_POINTER(), allocBufferAddress,
1744                                   IntPtr(common::AllocationBuffer::GetTLRegionOffset()));
1745     auto allocPtr =
1746         LoadPrimitive(VariableType::JS_POINTER(), tlRegion, IntPtr(common::RegionDesc::GetAllocPtrOffset()));
1747     auto regionEnd =
1748         LoadPrimitive(VariableType::JS_POINTER(), tlRegion, IntPtr(common::RegionDesc::GetRegionEndOffset()));
1749     auto newAllocPtr = PtrAdd(allocPtr, size_);
1750     BRANCH(IntPtrGreaterThan(newAllocPtr, regionEnd), callRuntime, &success);
1751     Bind(&success);
1752     {
1753         Store(VariableType::NATIVE_POINTER(), glue_, tlRegion, IntPtr(0), newAllocPtr, MemoryAttribute::NoBarrier());
1754         if (env->Is32Bit()) {
1755             allocPtr = ZExtInt32ToInt64(allocPtr);
1756         }
1757         result->WriteVariable(allocPtr);
1758         Jump(exit);
1759     }
1760 }
1761 
AllocateInYoungPrologueImpl(Variable * result,Label * callRuntime,Label * exit)1762 void NewObjectStubBuilder::AllocateInYoungPrologueImpl(Variable *result, Label *callRuntime, Label *exit)
1763 {
1764     auto env = GetEnvironment();
1765     Label success(env);
1766 
1767     auto topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(env->Is32Bit());
1768     auto endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(env->Is32Bit());
1769     auto topAddress = LoadPrimitive(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
1770     auto endAddress = LoadPrimitive(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
1771     auto top = LoadPrimitive(VariableType::JS_POINTER(), topAddress, IntPtr(0));
1772     auto end = LoadPrimitive(VariableType::JS_POINTER(), endAddress, IntPtr(0));
1773     auto newTop = PtrAdd(top, size_);
1774     BRANCH(IntPtrGreaterThan(newTop, end), callRuntime, &success);
1775     Bind(&success);
1776     {
1777         Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop, MemoryAttribute::NoBarrier());
1778         if (env->Is32Bit()) {
1779             top = ZExtInt32ToInt64(top);
1780         }
1781         result->WriteVariable(top);
1782         Jump(exit);
1783     }
1784 }
1785 
AllocateInYoungPrologue(Variable * result,Label * callRuntime,Label * exit)1786 void NewObjectStubBuilder::AllocateInYoungPrologue([[maybe_unused]] Variable *result,
1787     Label *callRuntime, [[maybe_unused]] Label *exit)
1788 {
1789     auto env = GetEnvironment();
1790     Label next(env);
1791 #if defined(ARK_ASAN_ON)
1792     Jump(callRuntime);
1793 #else
1794 #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
1795     auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
1796     auto isStartHeapSampling = LoadPrimitive(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
1797     BRANCH(TaggedIsTrue(isStartHeapSampling), callRuntime, &next);
1798     Bind(&next);
1799 #endif
1800     Label isCMCGC(env);
1801     Label notCMCGC(env);
1802     BRANCH_UNLIKELY(
1803         LoadPrimitive(VariableType::BOOL(), glue_, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))),
1804         &isCMCGC, &notCMCGC);
1805     Bind(&isCMCGC);
1806     {
1807         AllocateInYoungPrologueImplForCMCGC(result, callRuntime, exit);
1808     }
1809     Bind(&notCMCGC);
1810     {
1811         AllocateInYoungPrologueImpl(result, callRuntime, exit);
1812     }
1813 #endif
1814 }
1815 
AllocateInYoung(Variable * result,Label * exit,GateRef hclass)1816 void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *exit, GateRef hclass)
1817 {
1818     auto env = GetEnvironment();
1819     Label callRuntime(env);
1820     AllocateInYoungPrologue(result, &callRuntime, exit);
1821     Bind(&callRuntime);
1822     {
1823         DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1824         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
1825             Int64ToTaggedInt(size_), hclass });
1826         result->WriteVariable(*ret);
1827         Jump(exit);
1828     }
1829 }
1830 
AllocateInYoung(Variable * result,Label * error,Label * noError,GateRef hclass)1831 void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *error, Label *noError, GateRef hclass)
1832 {
1833     auto env = GetEnvironment();
1834     Label callRuntime(env);
1835     AllocateInYoungPrologue(result, &callRuntime, noError);
1836     Bind(&callRuntime);
1837     {
1838         DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
1839         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
1840             Int64ToTaggedInt(size_), hclass });
1841         result->WriteVariable(*ret);
1842         BRANCH(TaggedIsException(*ret), error, noError);
1843     }
1844 }
1845 
NewTrackInfo(GateRef glue,GateRef cachedHClass,GateRef cachedFunc,RegionSpaceFlag spaceFlag,GateRef arraySize)1846 GateRef NewObjectStubBuilder::NewTrackInfo(GateRef glue, GateRef cachedHClass, GateRef cachedFunc,
1847                                            RegionSpaceFlag spaceFlag, GateRef arraySize)
1848 {
1849     auto env = GetEnvironment();
1850     Label entry(env);
1851     env->SubCfgEntry(&entry);
1852 
1853     Label initialize(env);
1854     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1855     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::TRACK_INFO_CLASS_INDEX);
1856     GateRef size = GetObjectSizeFromHClass(hclass);
1857     SetParameters(glue, size);
1858     HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
1859     Bind(&initialize);
1860     Store(VariableType::JS_POINTER(), glue_, *result, IntPtr(0), hclass);
1861     GateRef cachedHClassOffset = IntPtr(TrackInfo::CACHED_HCLASS_OFFSET);
1862     Store(VariableType::JS_POINTER(), glue, *result, cachedHClassOffset, cachedHClass);
1863     GateRef cachedFuncOffset = IntPtr(TrackInfo::CACHED_FUNC_OFFSET);
1864     GateRef weakCachedFunc = env->GetBuilder()->CreateWeakRef(cachedFunc);
1865     Store(VariableType::JS_POINTER(), glue, *result, cachedFuncOffset, weakCachedFunc);
1866     GateRef arrayLengthOffset = IntPtr(TrackInfo::ARRAY_LENGTH_OFFSET);
1867     Store(VariableType::INT32(), glue, *result, arrayLengthOffset, arraySize);
1868     SetSpaceFlagToTrackInfo(glue, *result, Int32(spaceFlag));
1869     auto elementsKind = GetElementsKindFromHClass(cachedHClass);
1870     SetElementsKindToTrackInfo(glue, *result, elementsKind);
1871     auto ret = *result;
1872     env->SubCfgExit();
1873     return ret;
1874 }
1875 
InitializeWithSpeicalValue(Label * exit,GateRef object,GateRef value,GateRef start,GateRef end,MemoryAttribute mAttr)1876 void NewObjectStubBuilder::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef value, GateRef start,
1877                                                       GateRef end, MemoryAttribute mAttr)
1878 {
1879     {
1880         ASM_ASSERT(GET_MESSAGE_STRING_ID(InitializeWithSpeicalValue),
1881                    Int32Equal(Int32Mod(Int32Sub(end, start), Int32(JSTaggedValue::TaggedTypeSize())), Int32(0)));
1882     }
1883     auto env = GetEnvironment();
1884     Label begin(env);
1885     Label storeValue(env);
1886     Label endLoop(env);
1887     Label storeHead(env);
1888     Label enterLoop(env);
1889     DEFVARIABLE(startOffset, VariableType::INT32(), start);
1890     const auto tSize = static_cast<int32_t>(JSTaggedValue::TaggedTypeSize());
1891     static_assert((tSize & (tSize - 1)) == 0 && "tSize must be power of 2");
1892     GateRef length = Int32Sub(end, start);
1893     GateRef remainder = Int32And(length, Int32(LOOP_UNROLL_FACTOR * tSize - 1));
1894     BRANCH(Int32NotEqual(remainder, Int32(0)), &storeHead, &enterLoop);
1895     Bind(&storeHead);
1896     {
1897         // Now use 2 as loop unroll factor, so only store once if reminder is not 0.
1898         // But if using other loop unroll factor, the store head should also be refactored.
1899         Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(start), value, mAttr);
1900         startOffset = Int32Add(start, Int32(tSize));
1901         Jump(&enterLoop);
1902     }
1903     Bind(&enterLoop);
1904     {
1905         Jump(&begin);
1906     }
1907     LoopBegin(&begin);
1908     {
1909         BRANCH(Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
1910         Bind(&storeValue);
1911         {
1912             auto off = *startOffset;
1913             for (auto i = 0; i < LOOP_UNROLL_FACTOR; i++) {
1914                 Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(off), value, mAttr);
1915                 off = Int32Add(off, Int32(tSize));
1916             }
1917             startOffset = Int32Add(*startOffset, Int32(LOOP_UNROLL_FACTOR * tSize));
1918             Jump(&endLoop);
1919         }
1920         Bind(&endLoop);
1921         LoopEnd(&begin);
1922     }
1923 }
1924 
InitializeTaggedArrayWithSpeicalValue(Label * exit,GateRef array,GateRef value,GateRef start,GateRef length)1925 void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit,
1926     GateRef array, GateRef value, GateRef start, GateRef length)
1927 {
1928     Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::LENGTH_OFFSET), length);
1929     Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), Int32(0));
1930     auto offset = Int32Mul(start, Int32(JSTaggedValue::TaggedTypeSize()));
1931     auto dataOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
1932     offset = Int32Mul(length, Int32(JSTaggedValue::TaggedTypeSize()));
1933     auto endOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
1934     InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset, MemoryAttribute::NoBarrier());
1935 }
1936 
InitializeObject(Variable * result)1937 void NewObjectStubBuilder::InitializeObject(Variable *result)
1938 {
1939     auto emptyArray =
1940         GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
1941     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
1942     Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()),
1943           MemoryAttribute::NoBarrier());
1944     SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
1945     SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray, MemoryAttribute::NoBarrier());
1946 }
1947 
AllocLineStringObject(Variable * result,Label * exit,GateRef length,bool compressed)1948 void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
1949 {
1950     auto env = GetEnvironment();
1951     if (compressed) {
1952         size_ = AlignUp(ComputeSizeUtf8(ZExtInt32ToPtr(length)),
1953             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1954     } else {
1955         size_ = AlignUp(ComputeSizeUtf16(ZExtInt32ToPtr(length)),
1956             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1957     }
1958     Label afterAllocate(env);
1959     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1960                                                  ConstantIndex::LINE_STRING_CLASS_INDEX);
1961     AllocateInSOld(result, &afterAllocate, stringClass);
1962 
1963     Bind(&afterAllocate);
1964     StoreHClass(glue_, result->ReadVariable(), stringClass);
1965     InitStringLengthAndFlags(glue_, result->ReadVariable(), length, compressed);
1966     SetMixHashcode(glue_, result->ReadVariable(), Int32(0));
1967     Jump(exit);
1968 }
1969 
AllocSlicedStringObject(Variable * result,Label * exit,GateRef from,GateRef length,FlatStringStubBuilder * flatString)1970 void NewObjectStubBuilder::AllocSlicedStringObject(Variable *result, Label *exit, GateRef from, GateRef length,
1971     FlatStringStubBuilder *flatString)
1972 {
1973     auto env = GetEnvironment();
1974 
1975     size_ = AlignUp(IntPtr(SlicedString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
1976     Label afterAllocate(env);
1977     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
1978                                                  ConstantIndex::SLICED_STRING_CLASS_INDEX);
1979     AllocateInSOld(result, &afterAllocate, stringClass);
1980 
1981     Bind(&afterAllocate);
1982     StoreHClass(glue_, result->ReadVariable(), stringClass);
1983     GateRef mixLength = LoadPrimitive(VariableType::INT32(), flatString->GetFlatString(),
1984                                       IntPtr(BaseString::LENGTH_AND_FLAGS_OFFSET));
1985     GateRef compressedStatus = TruncInt32ToInt1(Int32And(Int32((1 << BaseString::CompressedStatusBit::SIZE) - 1),
1986                                                          mixLength));
1987     InitStringLengthAndFlags(glue_, result->ReadVariable(), length, BoolNot(compressedStatus));
1988     // decode compressedStatus to bool
1989 
1990     SetMixHashcode(glue_, result->ReadVariable(), Int32(0));
1991     BuiltinsStringStubBuilder builtinsStringStubBuilder(this, GetCurrentGlobalEnv());
1992     builtinsStringStubBuilder.StoreParent(glue_, result->ReadVariable(), flatString->GetFlatString());
1993     builtinsStringStubBuilder.StoreStartIndexAndBackingStore(glue_, result->ReadVariable(),
1994                                                              Int32Add(from, flatString->GetStartIndex()),
1995                                                              Boolean(false));
1996     Jump(exit);
1997 }
1998 
AllocTreeStringObject(Variable * result,Label * exit,GateRef first,GateRef second,GateRef length,bool compressed)1999 void NewObjectStubBuilder::AllocTreeStringObject(Variable *result, Label *exit, GateRef first, GateRef second,
2000     GateRef length, bool compressed)
2001 {
2002     auto env = GetEnvironment();
2003 
2004     size_ = AlignUp(IntPtr(TreeString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
2005     Label afterAllocate(env);
2006     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
2007                                                  ConstantIndex::TREE_STRING_CLASS_INDEX);
2008     AllocateInSOld(result, &afterAllocate, stringClass);
2009 
2010     Bind(&afterAllocate);
2011     StoreHClass(glue_, result->ReadVariable(), stringClass);
2012     InitStringLengthAndFlags(glue_, result->ReadVariable(), length, compressed);
2013     SetMixHashcode(glue_, result->ReadVariable(), Int32(0));
2014     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeString::FIRST_OFFSET), first);
2015     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeString::SECOND_OFFSET), second);
2016     Jump(exit);
2017 }
2018 
FastNewThisObject(GateRef glue,GateRef ctor)2019 GateRef NewObjectStubBuilder::FastNewThisObject(GateRef glue, GateRef ctor)
2020 {
2021     auto env = GetEnvironment();
2022     Label entry(env);
2023     env->SubCfgEntry(&entry);
2024     Label exit(env);
2025     Label isHeapObject(env);
2026     Label callRuntime(env);
2027     Label checkJSObject(env);
2028     Label newObject(env);
2029     Label isJSObject(env);
2030 
2031     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
2032     auto protoOrHClass = Load(VariableType::JS_ANY(), glue, ctor,
2033         IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2034     BRANCH(TaggedIsHeapObject(protoOrHClass), &isHeapObject, &callRuntime);
2035     Bind(&isHeapObject);
2036     BRANCH(IsJSHClass(glue, protoOrHClass), &checkJSObject, &callRuntime);
2037     Bind(&checkJSObject);
2038     auto objectType = GetObjectType(protoOrHClass);
2039     BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))), &isJSObject, &callRuntime);
2040     Bind(&isJSObject);
2041     {
2042         auto funcProto = GetPrototypeFromHClass(glue, protoOrHClass);
2043         BRANCH(IsEcmaObject(glue, funcProto), &newObject, &callRuntime);
2044     }
2045     Bind(&newObject);
2046     {
2047         SetParameters(glue, 0);
2048         NewJSObject(&thisObj, &exit, protoOrHClass);
2049     }
2050     Bind(&callRuntime);
2051     {
2052         thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor, Undefined()});
2053         Jump(&exit);
2054     }
2055     Bind(&exit);
2056     auto ret = *thisObj;
2057     env->SubCfgExit();
2058     return ret;
2059 }
2060 
FastSuperAllocateThis(GateRef glue,GateRef superCtor,GateRef newTarget)2061 GateRef NewObjectStubBuilder::FastSuperAllocateThis(GateRef glue, GateRef superCtor, GateRef newTarget)
2062 {
2063     auto env = GetEnvironment();
2064     Label entry(env);
2065     env->SubCfgEntry(&entry);
2066     Label exit(env);
2067     Label isHeapObject(env);
2068     Label checkJSObject(env);
2069     Label callRuntime(env);
2070     Label newObject(env);
2071     Label isFunction(env);
2072 
2073     BRANCH(IsJSFunction(glue, newTarget), &isFunction, &callRuntime);
2074     Bind(&isFunction);
2075     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
2076     DEFVARIABLE(protoOrHClass, VariableType::JS_ANY(), Undefined());
2077     protoOrHClass = Load(VariableType::JS_ANY(), glue, newTarget,
2078         IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2079     BRANCH(TaggedIsHeapObject(*protoOrHClass), &isHeapObject, &callRuntime);
2080     Bind(&isHeapObject);
2081     BRANCH(IsJSHClass(glue, *protoOrHClass), &checkJSObject, &callRuntime);
2082     Bind(&checkJSObject);
2083     auto objectType = GetObjectType(*protoOrHClass);
2084     BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))),
2085         &newObject, &callRuntime);
2086     Bind(&newObject);
2087     {
2088         SetParameters(glue, 0);
2089         NewJSObject(&thisObj, &exit, *protoOrHClass);
2090     }
2091     Bind(&callRuntime);
2092     {
2093         thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {superCtor, newTarget});
2094         Jump(&exit);
2095     }
2096     Bind(&exit);
2097     auto ret = *thisObj;
2098     env->SubCfgExit();
2099     return ret;
2100 }
2101 
NewThisObjectChecked(GateRef glue,GateRef ctor)2102 GateRef NewObjectStubBuilder::NewThisObjectChecked(GateRef glue, GateRef ctor)
2103 {
2104     auto env = GetEnvironment();
2105     Label entry(env);
2106     env->SubCfgEntry(&entry);
2107     Label exit(env);
2108 
2109     Label ctorIsHeapObject(env);
2110     Label ctorIsJSFunction(env);
2111     Label fastPath(env);
2112     Label slowPath(env);
2113     Label ctorIsBase(env);
2114 
2115     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
2116 
2117     BRANCH(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath);
2118     Bind(&ctorIsHeapObject);
2119     BRANCH(IsJSFunction(glue, ctor), &ctorIsJSFunction, &slowPath);
2120     Bind(&ctorIsJSFunction);
2121     BRANCH(IsConstructor(glue, ctor), &fastPath, &slowPath);
2122     Bind(&fastPath);
2123     {
2124         BRANCH(IsBase(glue, ctor), &ctorIsBase, &exit);
2125         Bind(&ctorIsBase);
2126         {
2127             thisObj = FastNewThisObject(glue, ctor);
2128             Jump(&exit);
2129         }
2130     }
2131     Bind(&slowPath);
2132     {
2133         thisObj = Hole();
2134         Jump(&exit);
2135     }
2136     Bind(&exit);
2137     auto ret = *thisObj;
2138     env->SubCfgExit();
2139     return ret;
2140 }
2141 
2142 // 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)2143 GateRef NewObjectStubBuilder::LoadTrackInfo(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo,
2144     GateRef profileTypeInfo, GateRef slotId, GateRef slotValue, GateRef arrayLiteral, ProfileOperation callback)
2145 {
2146     auto env = GetEnvironment();
2147     Label entry(env);
2148     env->SubCfgEntry(&entry);
2149     Label exit(env);
2150     DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
2151 
2152     Label uninitialized(env);
2153     Label fastpath(env);
2154     BRANCH(TaggedIsHeapObject(slotValue), &fastpath, &uninitialized);
2155     Bind(&fastpath);
2156     {
2157         ret = slotValue;
2158         Jump(&exit);
2159     }
2160     Bind(&uninitialized);
2161     {
2162         auto hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, arrayLiteral, callback);
2163         // emptyarray
2164         if (arrayLiteral == Circuit::NullGate()) {
2165             ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, Int32(0));
2166         } else {
2167             GateRef arrayLength = GetArrayLength(arrayLiteral);
2168             ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, arrayLength);
2169         }
2170 
2171         SetValueToTaggedArray(VariableType::JS_POINTER(), glue, profileTypeInfo, slotId, *ret);
2172         callback.TryPreDump();
2173         Jump(&exit);
2174     }
2175     Bind(&exit);
2176     auto result = *ret;
2177     env->SubCfgExit();
2178     return result;
2179 }
2180 
LoadArrayHClassSlowPath(GateRef glue,GateRef jsFunc,TraceIdInfo traceIdInfo,GateRef arrayLiteral,ProfileOperation callback)2181 GateRef NewObjectStubBuilder::LoadArrayHClassSlowPath(
2182     GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo, GateRef arrayLiteral, ProfileOperation callback)
2183 {
2184     auto env = GetEnvironment();
2185     Label entry(env);
2186     env->SubCfgEntry(&entry);
2187     Label exit(env);
2188     Label originLoad(env);
2189 
2190     DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
2191 
2192     auto hcIndexInfos = LoadHCIndexInfosFromConstPool(glue, jsFunc);
2193     auto indexInfosLength = GetLengthOfTaggedArray(hcIndexInfos);
2194     Label aotLoad(env);
2195     BRANCH(Int32Equal(indexInfosLength, Int32(0)), &originLoad, &aotLoad);
2196     Bind(&aotLoad);
2197     {
2198         GateRef traceId = 0;
2199         if (traceIdInfo.isPc) {
2200             auto pfAddr = LoadPfHeaderFromConstPool(glue, jsFunc);
2201             traceId = TruncPtrToInt32(PtrSub(traceIdInfo.pc, pfAddr));
2202         } else {
2203             traceId = traceIdInfo.traceId;
2204         }
2205 
2206         GateRef hcIndex = LoadHCIndexFromConstPool(glue, hcIndexInfos, indexInfosLength, traceId, &originLoad);
2207         GateRef globalEnv = GetCurrentGlobalEnv();
2208         ret = GetGlobalEnvValue(VariableType::JS_POINTER(), glue, globalEnv, static_cast<size_t>(hcIndex));
2209         Jump(&exit);
2210     }
2211     Bind(&originLoad);
2212     {
2213         // emptyarray
2214         if (arrayLiteral == Circuit::NullGate()) {
2215             GateRef globalEnv = GetCurrentGlobalEnv();
2216             if (callback.IsEmpty()) {
2217                 auto arrayFunc =
2218                     GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2219                 ret = Load(VariableType::JS_POINTER(), glue, arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2220             } else {
2221                 ret = GetGlobalEnvValue(VariableType::JS_POINTER(), glue, globalEnv,
2222                     static_cast<size_t>(GlobalEnvField::ELEMENT_NONE_HCLASS_INDEX));
2223             }
2224         } else {
2225             ret = LoadHClass(glue, arrayLiteral);
2226         }
2227         Jump(&exit);
2228     }
2229     Bind(&exit);
2230     auto result = *ret;
2231     env->SubCfgExit();
2232     return result;
2233 }
2234 
CreateEmptyArrayCommon(GateRef glue,GateRef hclass,GateRef trackInfo)2235 GateRef NewObjectStubBuilder::CreateEmptyArrayCommon(GateRef glue, GateRef hclass, GateRef trackInfo)
2236 {
2237     auto env = GetEnvironment();
2238     Label entry(env);
2239     env->SubCfgEntry(&entry);
2240     Label exit(env);
2241 
2242     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2243 
2244     GateRef size = GetObjectSizeFromHClass(hclass);
2245     GateRef emptyArray = GetGlobalConstantValue(
2246         VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
2247     SetParameters(glue, size);
2248     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, emptyArray, hclass, trackInfo, true);
2249     Bind(&exit);
2250     GateRef ret = *result;
2251     env->SubCfgExit();
2252     return ret;
2253 }
2254 
CreateEmptyObject(GateRef glue)2255 GateRef NewObjectStubBuilder::CreateEmptyObject(GateRef glue)
2256 {
2257     GateRef globalEnv = GetCurrentGlobalEnv();
2258     GateRef objectFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX);
2259     GateRef hclass = Load(VariableType::JS_POINTER(), glue, objectFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2260     return NewJSObject(glue, hclass);
2261 }
2262 
CreateEmptyArray(GateRef glue)2263 GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue)
2264 {
2265     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
2266     GateRef globalEnv = GetCurrentGlobalEnv();
2267     GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2268     GateRef hclass = Load(VariableType::JS_POINTER(), glue, arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2269     return CreateEmptyArrayCommon(glue, hclass, *trackInfo);
2270 }
2271 
CreateEmptyArray(GateRef glue,GateRef jsFunc,TraceIdInfo traceIdInfo,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)2272 GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue, GateRef jsFunc, TraceIdInfo traceIdInfo,
2273     GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
2274 {
2275     auto env = GetEnvironment();
2276     Label entry(env);
2277     env->SubCfgEntry(&entry);
2278 
2279     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
2280     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
2281     Label slowpath(env);
2282     Label mayFastpath(env);
2283     Label createArray(env);
2284     Label profileNotUndefined(env);
2285     BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined);
2286     Bind(&profileNotUndefined);
2287     GateRef slotValue = GetValueFromTaggedArray(glue, profileTypeInfo, slotId);
2288     BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath);
2289     Bind(&mayFastpath);
2290     {
2291         trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo,
2292             slotId, slotValue, Circuit::NullGate(), callback);
2293         hclass = Load(VariableType::JS_ANY(), glue, *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
2294         trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
2295         Jump(&createArray);
2296     }
2297     Bind(&slowpath);
2298     {
2299         hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, Circuit::NullGate(), callback);
2300         Jump(&createArray);
2301     }
2302     Bind(&createArray);
2303     GateRef result = CreateEmptyArrayCommon(glue, *hclass, *trackInfo);
2304     env->SubCfgExit();
2305     return result;
2306 }
2307 
CreateArrayWithBuffer(GateRef glue,GateRef index,GateRef jsFunc,TraceIdInfo traceIdInfo,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)2308 GateRef NewObjectStubBuilder::CreateArrayWithBuffer(GateRef glue, GateRef index, GateRef jsFunc,
2309     TraceIdInfo traceIdInfo, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
2310 {
2311     auto env = GetEnvironment();
2312     Label entry(env);
2313     env->SubCfgEntry(&entry);
2314     Label exit(env);
2315 
2316     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2317     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
2318     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
2319 
2320     GateRef method = GetMethodFromFunction(glue, jsFunc);
2321     GateRef constPool = Load(VariableType::JS_ANY(), glue, method, IntPtr(Method::CONSTANT_POOL_OFFSET));
2322     GateRef module = GetModuleFromFunction(glue, jsFunc);
2323 
2324     auto obj = GetArrayLiteralFromConstPool(glue, constPool, index, module);
2325 
2326     Label slowpath(env);
2327     Label mayFastpath(env);
2328     Label createArray(env);
2329     Label profileNotUndefined(env);
2330     BRANCH(TaggedIsUndefined(profileTypeInfo), &slowpath, &profileNotUndefined);
2331     Bind(&profileNotUndefined);
2332     GateRef slotValue = GetValueFromTaggedArray(glue, profileTypeInfo, slotId);
2333     BRANCH(TaggedIsHole(slotValue), &slowpath, &mayFastpath);
2334     Bind(&mayFastpath);
2335     {
2336         trackInfo = LoadTrackInfo(glue, jsFunc, traceIdInfo, profileTypeInfo, slotId, slotValue, obj, callback);
2337         hclass = Load(VariableType::JS_ANY(), glue, *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
2338         trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
2339         Jump(&createArray);
2340     }
2341     Bind(&slowpath);
2342     {
2343         hclass = LoadArrayHClassSlowPath(glue, jsFunc, traceIdInfo, obj, callback);
2344         Jump(&createArray);
2345     }
2346     Bind(&createArray);
2347     GateRef size = GetObjectSizeFromHClass(*hclass);
2348 
2349     SetParameters(glue, size);
2350     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, obj, *hclass, *trackInfo, false);
2351 
2352     Bind(&exit);
2353     auto ret = *result;
2354     env->SubCfgExit();
2355     return ret;
2356 }
2357 
2358 template <typename IteratorType, typename CollectionType>
CreateJSCollectionIterator(Variable * result,Label * exit,GateRef thisValue,GateRef kind)2359 void NewObjectStubBuilder::CreateJSCollectionIterator(
2360     Variable *result, Label *exit, GateRef thisValue, GateRef kind)
2361 {
2362     ASSERT_PRINT((std::is_same_v<IteratorType, JSSetIterator> || std::is_same_v<IteratorType, JSMapIterator>),
2363         "IteratorType must be JSSetIterator or JSMapIterator type");
2364     auto env = GetEnvironment();
2365     ConstantIndex iterClassIdx = static_cast<ConstantIndex>(0);
2366     int32_t iterOffset = 0;       // ITERATED_SET_OFFSET
2367     size_t linkedOffset = 0;      // LINKED_MAP_OFFSET
2368     if constexpr (std::is_same_v<IteratorType, JSSetIterator>) {
2369         iterClassIdx = ConstantIndex::JS_SET_ITERATOR_CLASS_INDEX;
2370         iterOffset = IteratorType::ITERATED_SET_OFFSET;
2371         linkedOffset = CollectionType::LINKED_SET_OFFSET;
2372         size_ = IntPtr(JSSetIterator::SIZE);
2373     } else {
2374         iterClassIdx = ConstantIndex::JS_MAP_ITERATOR_CLASS_INDEX;
2375         iterOffset = IteratorType::ITERATED_MAP_OFFSET;
2376         linkedOffset = CollectionType::LINKED_MAP_OFFSET;
2377         size_ = IntPtr(JSMapIterator::SIZE);
2378     }
2379     GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx);
2380 
2381     Label noException(env);
2382     // Be careful. NO GC is allowed when initization is not complete.
2383     AllocateInYoung(result, exit, &noException, iteratorHClass);
2384     Bind(&noException);
2385     {
2386         StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass);
2387         InitializeObject(result);
2388 
2389         // GetLinked
2390         GateRef linked = Load(VariableType::JS_ANY(), glue_, thisValue, IntPtr(linkedOffset));
2391         // SetIterated
2392         GateRef iteratorOffset = IntPtr(iterOffset);
2393         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, linked,
2394               MemoryAttribute::UnknownBarrier());
2395 
2396         // SetIteratorNextIndex
2397         GateRef nextIndexOffset = IntPtr(IteratorType::NEXT_INDEX_OFFSET);
2398         Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0));
2399 
2400         // SetIterationKind
2401         GateRef kindBitfieldOffset = IntPtr(IteratorType::BIT_FIELD_OFFSET);
2402         Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind);
2403         Jump(exit);
2404     }
2405 }
2406 
2407 template void NewObjectStubBuilder::CreateJSCollectionIterator<JSSetIterator, JSSet>(
2408     Variable *result, Label *exit, GateRef set, GateRef kind);
2409 template void NewObjectStubBuilder::CreateJSCollectionIterator<JSMapIterator, JSMap>(
2410     Variable *result, Label *exit, GateRef set, GateRef kind);
2411 
CreateJSTypedArrayIterator(Variable * result,Label * exit,GateRef thisValue,GateRef kind)2412 void NewObjectStubBuilder::CreateJSTypedArrayIterator(Variable *result, Label *exit, GateRef thisValue, GateRef kind)
2413 {
2414     auto env = GetEnvironment();
2415     size_ = IntPtr(JSArrayIterator::SIZE);
2416 
2417     ConstantIndex iterClassIdx = ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX;
2418     GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx);
2419 
2420     Label thisExists(env);
2421     Label isEcmaObject(env);
2422     Label isTypedArray(env);
2423     Label throwTypeError(env);
2424 
2425     BRANCH(TaggedIsUndefinedOrNullOrHole(thisValue), &throwTypeError, &thisExists);
2426     Bind(&thisExists);
2427     BRANCH(IsEcmaObject(glue_, thisValue), &isEcmaObject, &throwTypeError);
2428     Bind(&isEcmaObject);
2429     BRANCH(IsTypedArray(glue_, thisValue), &isTypedArray, &throwTypeError);
2430     Bind(&isTypedArray);
2431 
2432     Label noException(env);
2433     // Be careful. NO GC is allowed when initization is not complete.
2434     AllocateInYoung(result, exit, &noException, iteratorHClass);
2435     Bind(&noException);
2436     {
2437         StoreBuiltinHClass(glue_, result->ReadVariable(), iteratorHClass);
2438         InitializeObject(result);
2439 
2440         GateRef iteratorOffset = IntPtr(JSArrayIterator::ITERATED_ARRAY_OFFSET);
2441         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, thisValue,
2442               MemoryAttribute::NeedBarrier());
2443 
2444         // SetIteratorNextIndex
2445         GateRef nextIndexOffset = IntPtr(JSArrayIterator::NEXT_INDEX_OFFSET);
2446         Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0));
2447 
2448         // SetIterationKind
2449         GateRef kindBitfieldOffset = IntPtr(JSArrayIterator::BIT_FIELD_OFFSET);
2450         Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind);
2451         Jump(exit);
2452     }
2453 
2454     Bind(&throwTypeError);
2455     {
2456         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotTypedArray));
2457         CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
2458         result->WriteVariable(Exception());
2459         Jump(exit);
2460     }
2461 }
2462 
NewTaggedSubArray(GateRef glue,GateRef srcTypedArray,GateRef elementSize,GateRef newLength,GateRef beginIndex,GateRef arrayCls,GateRef buffer)2463 GateRef NewObjectStubBuilder::NewTaggedSubArray(GateRef glue, GateRef srcTypedArray,
2464     GateRef elementSize, GateRef newLength, GateRef beginIndex, GateRef arrayCls, GateRef buffer)
2465 {
2466     auto env = GetEnvironment();
2467     Label entry(env);
2468     env->SubCfgEntry(&entry);
2469     GateRef constructorName = Load(VariableType::JS_POINTER(), glue, srcTypedArray,
2470         IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
2471     GateRef srcByteOffset =
2472         LoadPrimitive(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
2473     GateRef contentType =
2474         LoadPrimitive(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
2475     GateRef beginByteOffset = Int32Add(srcByteOffset, Int32Mul(beginIndex, elementSize));
2476 
2477     Label isOnHeap(env);
2478     Label isNotOnHeap(env);
2479     Label createNewArray(env);
2480     Label comparePrototype(env);
2481     Label protoChanged(env);
2482     Label exit(env);
2483     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2484     DEFVARIABLE(newArrayHClass, VariableType::JS_ANY(), Undefined());
2485     GateRef srcType = GetObjectType(arrayCls);
2486 
2487     BRANCH(env->GetBuilder()->IsOnHeap(arrayCls), &isOnHeap, &isNotOnHeap);
2488     Bind(&isOnHeap);
2489     {
2490         newArrayHClass = GetOnHeapHClassFromType(glue, srcType);
2491         Jump(&comparePrototype);
2492     }
2493     Bind(&isNotOnHeap);
2494     {
2495         newArrayHClass = GetNotOnHeapHClassFromType(glue, srcType);
2496         Jump(&comparePrototype);
2497     }
2498 
2499     Bind(&comparePrototype);
2500     {
2501         GateRef newPrototype = GetPrototypeFromHClass(glue, *newArrayHClass);
2502         GateRef srcPrototype = GetPrototypeFromHClass(glue, arrayCls);
2503         BRANCH_LIKELY(Equal(newPrototype, srcPrototype), &createNewArray, &protoChanged);
2504         Bind(&protoChanged);
2505         {
2506             newArrayHClass = CallRuntime(glue, RTSTUB_ID(CloneHclass), { *newArrayHClass });
2507             StorePrototype(glue, *newArrayHClass, srcPrototype);
2508             Jump(&createNewArray);
2509         }
2510     }
2511 
2512     Bind(&createNewArray);
2513     {
2514         result = NewJSObject(glue, *newArrayHClass);
2515         GateRef newByteLength = Int32Mul(elementSize, newLength);
2516         Store(VariableType::JS_POINTER(), glue, *result, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), buffer);
2517         Store(VariableType::JS_POINTER(), glue, *result, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET),
2518               constructorName);
2519         Store(VariableType::INT32(), glue, *result, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2520         Store(VariableType::INT32(), glue, *result, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), beginByteOffset);
2521         Store(VariableType::INT32(), glue, *result, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), newLength);
2522         Store(VariableType::INT32(), glue, *result, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
2523         Jump(&exit);
2524     }
2525 
2526     Bind(&exit);
2527     auto ret = *result;
2528     env->SubCfgExit();
2529     return ret;
2530 }
2531 
NewTypedArray(GateRef glue,GateRef srcTypedArray,GateRef srcType,GateRef length)2532 GateRef NewObjectStubBuilder::NewTypedArray(GateRef glue, GateRef srcTypedArray, GateRef srcType, GateRef length)
2533 {
2534     auto env = GetEnvironment();
2535     Label entry(env);
2536     env->SubCfgEntry(&entry);
2537 
2538     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2539     Label slowPath(env);
2540     Label defaultConstr(env);
2541     Label markerCellValid(env);
2542     Label isProtoChangeMarker(env);
2543     Label accessorNotChanged(env);
2544     Label exit(env);
2545     BRANCH(HasConstructor(glue, srcTypedArray), &slowPath, &defaultConstr);
2546     Bind(&defaultConstr);
2547     GateRef globalEnv = GetCurrentGlobalEnv();
2548     GateRef detector = GetTypedArraySpeciesProtectDetector(globalEnv);
2549     BRANCH(BoolNot(detector), &markerCellValid, &slowPath);
2550     Bind(&markerCellValid);
2551     GateRef marker = GetProtoChangeMarkerFromHClass(glue, LoadHClass(glue, srcTypedArray));
2552     BRANCH(TaggedIsProtoChangeMarker(glue, marker), &isProtoChangeMarker, &accessorNotChanged);
2553     Bind(&isProtoChangeMarker);
2554     BRANCH(GetAccessorHasChanged(marker), &slowPath, &accessorNotChanged);
2555 
2556     Bind(&accessorNotChanged);
2557     {
2558         DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2559         Label next(env);
2560         GateRef hclass = LoadHClass(glue, srcTypedArray);
2561         GateRef obj = NewJSObject(glue, hclass);
2562         result = obj;
2563         GateRef ctorName = Load(VariableType::JS_POINTER(), glue, srcTypedArray,
2564             IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
2565         GateRef elementSize = GetElementSizeFromType(glue, srcType);
2566         GateRef newByteLength = Int32Mul(elementSize, length);
2567         GateRef contentType =
2568             LoadPrimitive(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
2569         BRANCH(Int32LessThanOrEqual(newByteLength, Int32(RangeInfo::TYPED_ARRAY_ONHEAP_MAX)), &next, &slowPath);
2570         Bind(&next);
2571         {
2572             Label sameObjectSize(env);
2573             Label newByteArrayExit(env);
2574             GateRef onHeapHClass = GetOnHeapHClassFromType(glue, srcType);
2575             GateRef originalHClassObjectSize = GetObjectSizeFromHClass(hclass);
2576             GateRef onHeapHClassObjectSize = GetObjectSizeFromHClass(onHeapHClass);
2577             BRANCH(Equal(originalHClassObjectSize, onHeapHClassObjectSize), &sameObjectSize, &slowPath);
2578             Bind(&sameObjectSize);
2579             NewByteArray(&buffer, &newByteArrayExit, elementSize, length);
2580             Bind(&newByteArrayExit);
2581             StoreHClass(glue, obj, onHeapHClass);
2582             Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2583             Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), ctorName);
2584             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2585             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), Int32(0));
2586             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length);
2587             Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
2588             Jump(&exit);
2589         }
2590     }
2591 
2592     Bind(&slowPath);
2593     {
2594         result = CallRuntime(glue, RTSTUB_ID(TypedArraySpeciesCreate),
2595             { srcTypedArray, IntToTaggedInt(Int32(1)), IntToTaggedInt(length) });
2596         Jump(&exit);
2597     }
2598 
2599     Bind(&exit);
2600     auto ret = *result;
2601     env->SubCfgExit();
2602     return ret;
2603 }
2604 
NewTypedArraySameType(GateRef glue,GateRef srcTypedArray,GateRef srcType,GateRef length)2605 GateRef NewObjectStubBuilder::NewTypedArraySameType(GateRef glue, GateRef srcTypedArray, GateRef srcType,
2606                                                     GateRef length)
2607 {
2608     auto env = GetEnvironment();
2609     Label entry(env);
2610     env->SubCfgEntry(&entry);
2611 
2612     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2613     DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2614     Label slowPath(env);
2615     Label next(env);
2616     Label exit(env);
2617     GateRef hclass = LoadHClass(glue, srcTypedArray);
2618     GateRef obj = NewJSObject(glue, hclass);
2619     result = obj;
2620     GateRef ctorName = Load(VariableType::JS_POINTER(), glue, srcTypedArray,
2621         IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
2622     GateRef elementSize = GetElementSizeFromType(glue, srcType);
2623     GateRef newByteLength = Int32Mul(elementSize, length);
2624     GateRef contentType =
2625         LoadPrimitive(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
2626     BRANCH(Int32LessThanOrEqual(newByteLength, Int32(RangeInfo::TYPED_ARRAY_ONHEAP_MAX)), &next, &slowPath);
2627     Bind(&next);
2628     {
2629         Label passFastGuard(env);
2630         Label checkSize(env);
2631         Label newByteArrayExit(env);
2632         /* 1. HClass pointer equality guard
2633          *    - if the instance already uses the canonical on-heap HClass, we can skip size comparison */
2634         GateRef onHeapHClass = GetOnHeapHClassFromType(glue, srcType);
2635         BRANCH(Equal(hclass, onHeapHClass), &passFastGuard, &checkSize);
2636 
2637         /* 2. size guard
2638          *    - pointer differs (sub-class, etc).
2639          *      ensure object size still match before staying on fast-path; otherwise fall back to slowPath. */
2640         Bind(&checkSize);
2641         GateRef originalSize = GetObjectSizeFromHClass(hclass);
2642         GateRef onHeapSize = GetObjectSizeFromHClass(onHeapHClass);
2643         BRANCH(Equal(originalSize, onHeapSize), &passFastGuard, &slowPath);
2644 
2645         /* 3. all guards passed
2646          *    - safe to stay on fast-path */
2647         Bind(&passFastGuard);
2648         NewByteArray(&buffer, &newByteArrayExit, elementSize, length);
2649         Bind(&newByteArrayExit);
2650         StoreHClass(glue, obj, onHeapHClass);
2651         Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2652         Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), ctorName);
2653         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2654         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), Int32(0));
2655         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length);
2656         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
2657         Jump(&exit);
2658     }
2659 
2660     Bind(&slowPath);
2661     {
2662         result = CallRuntime(glue, RTSTUB_ID(TypedArrayCreateSameType),
2663             { srcTypedArray, IntToTaggedInt(Int32(1)), IntToTaggedInt(length) });
2664         Jump(&exit);
2665     }
2666 
2667     Bind(&exit);
2668     auto ret = *result;
2669     env->SubCfgExit();
2670     return ret;
2671 }
2672 
2673 // use NewJSObjectByConstructor need to InitializeJSObject by type
NewJSObjectByConstructor(GateRef glue,GateRef constructor,GateRef newTarget)2674 GateRef NewObjectStubBuilder::NewJSObjectByConstructor(GateRef glue, GateRef constructor, GateRef newTarget)
2675 {
2676     auto env = GetEnvironment();
2677     Label entry(env);
2678     env->SubCfgEntry(&entry);
2679     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2680     DEFVARIABLE(jshclass, VariableType::JS_ANY(), Undefined());
2681     Label exit(env);
2682     Label slowPath(env);
2683     Label newObj(env);
2684     Label isValid(env);
2685     Label checkIsJSShared(env);
2686     Label constructorIsShared(env);
2687     SetGlue(glue);
2688     BRANCH(IntPtrEqual(constructor, newTarget), &isValid, &checkIsJSShared);
2689     Bind(&checkIsJSShared);
2690     BRANCH(IsJSShared(glue, constructor), &constructorIsShared, &isValid);
2691     Bind(&constructorIsShared);
2692     {
2693         BRANCH(IsJSShared(glue, newTarget), &isValid, &slowPath);
2694     }
2695     Bind(&isValid);
2696     {
2697         Label hasFunctionPrototype(env);
2698         Label notHasFunctionPrototype(env);
2699         BRANCH(HasFunctionPrototype(glue, constructor), &hasFunctionPrototype, &notHasFunctionPrototype);
2700         Bind(&hasFunctionPrototype);
2701         {
2702             GateRef proto = GetCtorPrototype(glue, constructor);
2703             BRANCH(IsEcmaObject(glue, proto), &notHasFunctionPrototype, &slowPath);
2704         }
2705         Bind(&notHasFunctionPrototype);
2706         {
2707             Label isEqual(env);
2708             Label isHClass(env);
2709             BRANCH(IntPtrEqual(constructor, newTarget), &isEqual, &slowPath);
2710             Bind(&isEqual);
2711             GateRef protoOrHClass = GetProtoOrHClass(glue, constructor);
2712             BRANCH(IsJSHClass(glue, protoOrHClass), &isHClass, &slowPath);
2713             Bind(&isHClass);
2714             jshclass = protoOrHClass;
2715             Jump(&newObj);
2716         }
2717     }
2718     Bind(&newObj);
2719     {
2720         Label notShared(env);
2721         BRANCH(IsJSShared(glue, *jshclass), &slowPath, &notShared);
2722         Bind(&notShared);
2723         {
2724             result = NewJSObject(glue, *jshclass);
2725             Jump(&exit);
2726         }
2727     }
2728     Bind(&slowPath);
2729     {
2730         result = CallRuntime(glue, RTSTUB_ID(NewJSObjectByConstructor), { constructor, newTarget });
2731         Jump(&exit);
2732     }
2733 
2734     Bind(&exit);
2735     auto ret = *result;
2736     env->SubCfgExit();
2737     return ret;
2738 }
2739 
NewFloat32ArrayObj(GateRef glue)2740 GateRef NewObjectStubBuilder::NewFloat32ArrayObj(GateRef glue)
2741 {
2742     GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glue, GetCurrentGlobalEnv(),
2743                                           GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX);
2744     GateRef hclass = Load(VariableType::JS_POINTER(), glue, arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2745     GateRef obj = NewJSObject(glue, hclass);
2746     return obj;
2747 }
2748 
NewFloat32ArrayWithSize(GateRef glue,GateRef size)2749 GateRef NewObjectStubBuilder::NewFloat32ArrayWithSize(GateRef glue, GateRef size)
2750 {
2751     auto env = GetEnvironment();
2752     Label entry(env);
2753     env->SubCfgEntry(&entry);
2754     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2755     DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2756     Label exit(env);
2757     GateRef obj = NewFloat32ArrayObj(glue);
2758     result = obj;
2759     GateRef ctorName = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
2760                                               ConstantIndex::FLOAT32_ARRAY_STRING_INDEX);
2761     GateRef elementSize = Int32(4);  // 4: float32 primtype's byte length
2762     GateRef newByteLength = Int32Mul(size, elementSize);
2763     GateRef contentType = Int32(static_cast<int32_t>(ContentType::Number));
2764     {
2765         Label newByteArrayExit(env);
2766         NewByteArray(&buffer, &newByteArrayExit, elementSize, size);
2767         Bind(&newByteArrayExit);
2768         GateRef onHeapHClass = GetGlobalEnvValue(VariableType::JS_ANY(), glue,  GetCurrentGlobalEnv(),
2769                                                  GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
2770         StoreHClass(glue, obj, onHeapHClass);
2771         Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2772         Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET),
2773               ctorName, MemoryAttribute::NoBarrier());
2774         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET),
2775               newByteLength, MemoryAttribute::NoBarrier());
2776         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET),
2777               Int32(0), MemoryAttribute::NoBarrier());
2778         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET),
2779               size, MemoryAttribute::NoBarrier());
2780         Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET),
2781               contentType, MemoryAttribute::NoBarrier());
2782         Jump(&exit);
2783     }
2784     Bind(&exit);
2785     auto ret = *result;
2786     env->SubCfgExit();
2787     return ret;
2788 }
2789 
NewTypedArrayFromCtor(GateRef glue,GateRef ctor,GateRef length,Label * slowPath)2790 GateRef NewObjectStubBuilder::NewTypedArrayFromCtor(GateRef glue, GateRef ctor, GateRef length, Label *slowPath)
2791 {
2792     auto env = GetEnvironment();
2793     Label entry(env);
2794     env->SubCfgEntry(&entry);
2795 
2796     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2797     Label thisObjIsECmaObject(env);
2798     Label thisObjIsFastTypedArray(env);
2799     Label defaultConstr(env);
2800     Label exit(env);
2801 
2802     GateRef thisObj = FastNewThisObject(glue, ctor);
2803     result = thisObj;
2804     GateRef arrayType = GetObjectType(LoadHClass(glue, thisObj));
2805 
2806     BRANCH(IsEcmaObject(glue, thisObj), &thisObjIsECmaObject, slowPath);
2807     Bind(&thisObjIsECmaObject);
2808     BRANCH(IsFastTypeArray(arrayType), &thisObjIsFastTypedArray, slowPath);
2809     Bind(&thisObjIsFastTypedArray);
2810     BRANCH(HasConstructor(glue, thisObj), slowPath, &defaultConstr);
2811     Bind(&defaultConstr);
2812 
2813     DEFVARIABLE(buffer, VariableType::JS_ANY(), Undefined());
2814     GateRef elementSize = GetElementSizeFromType(glue, arrayType);
2815     GateRef newByteLength = Int32Mul(elementSize, length);
2816     Label newByteArrayExit(env);
2817     NewByteArray(&buffer, &newByteArrayExit, elementSize, length);
2818     Bind(&newByteArrayExit);
2819     Store(VariableType::JS_POINTER(), glue, thisObj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), *buffer);
2820     Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
2821     Store(VariableType::INT32(), glue, thisObj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), length);
2822     Jump(&exit);
2823 
2824     Bind(&exit);
2825     auto ret = *result;
2826     env->SubCfgExit();
2827     return ret;
2828 }
2829 
NewByteArray(Variable * result,Label * exit,GateRef elementSize,GateRef length)2830 void NewObjectStubBuilder::NewByteArray(Variable *result, Label *exit, GateRef elementSize, GateRef length)
2831 {
2832     auto env = GetEnvironment();
2833 
2834     Label noError(env);
2835     Label initializeExit(env);
2836     GateRef size = AlignUp(ComputeTaggedTypedArraySize(ZExtInt32ToPtr(elementSize), ZExtInt32ToPtr(length)),
2837         IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
2838     size_ = size;
2839     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::BYTE_ARRAY_CLASS_INDEX);
2840     AllocateInYoung(result, exit, &noError, hclass);
2841     Bind(&noError);
2842     {
2843         StoreBuiltinHClass(glue_, result->ReadVariable(), hclass);
2844         auto startOffset = Int32(ByteArray::DATA_OFFSET);
2845         static_assert(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT) == 8);
2846         InitializeWithSpeicalValue(&initializeExit, result->ReadVariable(), Int64(0), startOffset,
2847                                    TruncPtrToInt32(size), MemoryAttribute::NoBarrier());
2848         Bind(&initializeExit);
2849         Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::ARRAY_LENGTH_OFFSET), length);
2850         Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(ByteArray::BYTE_LENGTH_OFFSET), elementSize);
2851         Jump(exit);
2852     }
2853 }
2854 
NewProfileTypeInfoCell(GateRef glue,GateRef value)2855 GateRef NewObjectStubBuilder::NewProfileTypeInfoCell(GateRef glue, GateRef value)
2856 {
2857     auto env = GetEnvironment();
2858     Label entry(env);
2859     env->SubCfgEntry(&entry);
2860 
2861     Label initialize(env);
2862     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2863     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
2864                                          ConstantIndex::PROFILE_TYPE_INFO_CELL_0_CLASS_INDEX);
2865     GateRef size = GetObjectSizeFromHClass(hclass);
2866     SetParameters(glue, size);
2867     HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
2868     Bind(&initialize);
2869     StoreHClass(glue, *result, hclass, MemoryAttribute::NoBarrier());
2870     SetValueToProfileTypeInfoCell(glue, *result, value);
2871     GateRef machineCodeOffset = IntPtr(ProfileTypeInfoCell::MACHINE_CODE_OFFSET);
2872     Store(VariableType::JS_POINTER(), glue, *result, machineCodeOffset, Hole());
2873     GateRef handleOffset = IntPtr(ProfileTypeInfoCell::HANDLE_OFFSET);
2874     Store(VariableType::JS_POINTER(), glue, *result, handleOffset, Undefined());
2875 
2876     auto ret = *result;
2877     env->SubCfgExit();
2878     return ret;
2879 }
2880 
NewEnumCache(GateRef glue)2881 GateRef NewObjectStubBuilder::NewEnumCache(GateRef glue)
2882 {
2883     auto env = GetEnvironment();
2884     Label entry(env);
2885     env->SubCfgEntry(&entry);
2886 
2887     Label initialize(env);
2888     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
2889 
2890     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
2891         ConstantIndex::ENUM_CACHE_CLASS_INDEX);
2892     GateRef size = GetObjectSizeFromHClass(hclass);
2893     SetParameters(glue, size);
2894     HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
2895     Bind(&initialize);
2896     Store(VariableType::JS_POINTER(), glue, result.ReadVariable(), IntPtr(0), hclass);
2897     GateRef enumCacheKindOffset = IntPtr(EnumCache::ENUM_CACHE_KIND_OFFSET);
2898     Store(VariableType::INT32(), glue, *result, enumCacheKindOffset,
2899         Int32(static_cast<uint32_t>(EnumCacheKind::NONE)));
2900     GateRef enumCacheAllOffset = IntPtr(EnumCache::ENUM_CACHE_ALL_OFFSET);
2901     Store(VariableType::JS_POINTER(), glue, *result, enumCacheAllOffset, Null());
2902     GateRef enumCacheOwnOffset = IntPtr(EnumCache::ENUM_CACHE_OWN_OFFSET);
2903     Store(VariableType::JS_POINTER(), glue, *result, enumCacheOwnOffset, Null());
2904     GateRef enumCacheProtoChainOffset = IntPtr(EnumCache::PROTO_CHAIN_INFO_ENUM_CACHE_OFFSET);
2905     Store(VariableType::JS_POINTER(), glue, *result, enumCacheProtoChainOffset, Null());
2906 
2907     auto ret = *result;
2908     env->SubCfgExit();
2909     return ret;
2910 }
2911 
GetElementSizeFromType(GateRef glue,GateRef type)2912 GateRef NewObjectStubBuilder::GetElementSizeFromType(GateRef glue, GateRef type)
2913 {
2914     auto env = GetEnvironment();
2915     Label entry(env);
2916     env->SubCfgEntry(&entry);
2917 
2918     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
2919     Label defaultLabel(env);
2920     Label exit(env);
2921     Label labelBuffer[11] = {
2922         Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
2923         Label(env), Label(env), Label(env), Label(env), Label(env) };
2924     int64_t valueBuffer[11] = {
2925         static_cast<int64_t>(JSType::JS_INT8_ARRAY),
2926         static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
2927         static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY),
2928         static_cast<int64_t>(JSType::JS_INT16_ARRAY),
2929         static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
2930         static_cast<int64_t>(JSType::JS_INT32_ARRAY),
2931         static_cast<int64_t>(JSType::JS_UINT32_ARRAY),
2932         static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
2933         static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY),
2934         static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY),
2935         static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) };
2936 
2937     // 11 : this switch has 11 case
2938     Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11);
2939     // 0 : index of this buffer
2940     Bind(&labelBuffer[0]);
2941     {
2942         // 1 : the elementSize of this type is 1
2943         result = Int32(1);
2944         Jump(&exit);
2945     }
2946     // 1 : index of this buffer
2947     Bind(&labelBuffer[1]);
2948     {
2949         // 1 : the elementSize of this type is 1
2950         result = Int32(1);
2951         Jump(&exit);
2952     }
2953     // 2 : index of this buffer
2954     Bind(&labelBuffer[2]);
2955     {
2956         // 1 : the elementSize of this type is 1
2957         result = Int32(1);
2958         Jump(&exit);
2959     }
2960     // 3 : index of this buffer
2961     Bind(&labelBuffer[3]);
2962     {
2963         // 2 : the elementSize of this type is 2
2964         result = Int32(2);
2965         Jump(&exit);
2966     }
2967     // 4 : index of this buffer
2968     Bind(&labelBuffer[4]);
2969     {
2970         // 2 : the elementSize of this type is 2
2971         result = Int32(2);
2972         Jump(&exit);
2973     }
2974     // 5 : index of this buffer
2975     Bind(&labelBuffer[5]);
2976     {
2977         // 4 : the elementSize of this type is 4
2978         result = Int32(4);
2979         Jump(&exit);
2980     }
2981     // 6 : index of this buffer
2982     Bind(&labelBuffer[6]);
2983     {
2984         // 4 : the elementSize of this type is 4
2985         result = Int32(4);
2986         Jump(&exit);
2987     }
2988     // 7 : index of this buffer
2989     Bind(&labelBuffer[7]);
2990     {
2991         // 4 : the elementSize of this type is 4
2992         result = Int32(4);
2993         Jump(&exit);
2994     }
2995     // 8 : index of this buffer
2996     Bind(&labelBuffer[8]);
2997     {
2998         // 8 : the elementSize of this type is 8
2999         result = Int32(8);
3000         Jump(&exit);
3001     }
3002     // 9 : index of this buffer
3003     Bind(&labelBuffer[9]);
3004     {
3005         // 8 : the elementSize of this type is 8
3006         result = Int32(8);
3007         Jump(&exit);
3008     }
3009     // 10 : index of this buffer
3010     Bind(&labelBuffer[10]);
3011     {
3012         // 8 : the elementSize of this type is 8
3013         result = Int32(8);
3014         Jump(&exit);
3015     }
3016     Bind(&defaultLabel);
3017     {
3018         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
3019         Jump(&exit);
3020     }
3021 
3022     Bind(&exit);
3023     auto ret = *result;
3024     env->SubCfgExit();
3025     return ret;
3026 }
3027 
GetOnHeapHClassFromType(GateRef glue,GateRef type)3028 GateRef NewObjectStubBuilder::GetOnHeapHClassFromType(GateRef glue, GateRef type)
3029 {
3030     auto env = GetEnvironment();
3031     Label entry(env);
3032     env->SubCfgEntry(&entry);
3033 
3034     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3035     GateRef globalEnv = GetCurrentGlobalEnv();
3036     Label defaultLabel(env);
3037     Label exit(env);
3038     Label labelBuffer[11] = {
3039         Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
3040         Label(env), Label(env), Label(env), Label(env), Label(env) };
3041     int64_t valueBuffer[11] = {
3042         static_cast<int64_t>(JSType::JS_INT8_ARRAY),
3043         static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
3044         static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY),
3045         static_cast<int64_t>(JSType::JS_INT16_ARRAY),
3046         static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
3047         static_cast<int64_t>(JSType::JS_INT32_ARRAY),
3048         static_cast<int64_t>(JSType::JS_UINT32_ARRAY),
3049         static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
3050         static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY),
3051         static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY),
3052         static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) };
3053 
3054     // 11 : this switch has 11 case
3055     Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11);
3056     // 0 : index of this buffer
3057     Bind(&labelBuffer[0]);
3058     {
3059         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3060             GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3061         Jump(&exit);
3062     }
3063     // 1 : index of this buffer
3064     Bind(&labelBuffer[1]);
3065     {
3066         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3067             GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3068         Jump(&exit);
3069     }
3070     // 2 : index of this buffer
3071     Bind(&labelBuffer[2]);
3072     {
3073         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3074             GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3075         Jump(&exit);
3076     }
3077     // 3 : index of this buffer
3078     Bind(&labelBuffer[3]);
3079     {
3080         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3081             GlobalEnv::INT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3082         Jump(&exit);
3083     }
3084     // 4 : index of this buffer
3085     Bind(&labelBuffer[4]);
3086     {
3087         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3088             GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3089         Jump(&exit);
3090     }
3091     // 5 : index of this buffer
3092     Bind(&labelBuffer[5]);
3093     {
3094         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3095             GlobalEnv::INT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3096         Jump(&exit);
3097     }
3098     // 6 : index of this buffer
3099     Bind(&labelBuffer[6]);
3100     {
3101         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3102             GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3103         Jump(&exit);
3104     }
3105     // 7 : index of this buffer
3106     Bind(&labelBuffer[7]);
3107     {
3108         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3109             GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3110         Jump(&exit);
3111     }
3112     // 8 : index of this buffer
3113     Bind(&labelBuffer[8]);
3114     {
3115         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3116             GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3117         Jump(&exit);
3118     }
3119     // 9 : index of this buffer
3120     Bind(&labelBuffer[9]);
3121     {
3122         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3123             GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3124         Jump(&exit);
3125     }
3126     // 10 : index of this buffer
3127     Bind(&labelBuffer[10]);
3128     {
3129         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3130             GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX);
3131         Jump(&exit);
3132     }
3133     Bind(&defaultLabel);
3134     {
3135         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
3136         Jump(&exit);
3137     }
3138 
3139     Bind(&exit);
3140     auto ret = *result;
3141     env->SubCfgExit();
3142     return ret;
3143 }
3144 
GetNotOnHeapHClassFromType(GateRef glue,GateRef type)3145 GateRef NewObjectStubBuilder::GetNotOnHeapHClassFromType(GateRef glue, GateRef type)
3146 {
3147     auto env = GetEnvironment();
3148     Label entry(env);
3149     env->SubCfgEntry(&entry);
3150 
3151     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
3152     GateRef globalEnv = GetCurrentGlobalEnv();
3153     Label defaultLabel(env);
3154     Label exit(env);
3155     Label labelBuffer[11] = {
3156         Label(env), Label(env), Label(env), Label(env), Label(env), Label(env),
3157         Label(env), Label(env), Label(env), Label(env), Label(env) };
3158     int64_t valueBuffer[11] = {
3159         static_cast<int64_t>(JSType::JS_INT8_ARRAY),
3160         static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
3161         static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY),
3162         static_cast<int64_t>(JSType::JS_INT16_ARRAY),
3163         static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
3164         static_cast<int64_t>(JSType::JS_INT32_ARRAY),
3165         static_cast<int64_t>(JSType::JS_UINT32_ARRAY),
3166         static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
3167         static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY),
3168         static_cast<int64_t>(JSType::JS_BIGINT64_ARRAY),
3169         static_cast<int64_t>(JSType::JS_BIGUINT64_ARRAY) };
3170 
3171     // 11 : this switch has 11 case
3172     Switch(type, &defaultLabel, valueBuffer, labelBuffer, 11);
3173     // 0 : index of this buffer
3174     Bind(&labelBuffer[0]);
3175     {
3176         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3177                                    GlobalEnv::INT8_ARRAY_ROOT_HCLASS_INDEX);
3178         Jump(&exit);
3179     }
3180     // 1 : index of this buffer
3181     Bind(&labelBuffer[1]);
3182     {
3183         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3184                                    GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_INDEX);
3185         Jump(&exit);
3186     }
3187     // 2 : index of this buffer
3188     Bind(&labelBuffer[2]);
3189     {
3190         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3191                                    GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_INDEX);
3192         Jump(&exit);
3193     }
3194     // 3 : index of this buffer
3195     Bind(&labelBuffer[3]);
3196     {
3197         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3198                                    GlobalEnv::INT16_ARRAY_ROOT_HCLASS_INDEX);
3199         Jump(&exit);
3200     }
3201     // 4 : index of this buffer
3202     Bind(&labelBuffer[4]);
3203     {
3204         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3205                                    GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_INDEX);
3206         Jump(&exit);
3207     }
3208     // 5 : index of this buffer
3209     Bind(&labelBuffer[5]);
3210     {
3211         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3212                                    GlobalEnv::INT32_ARRAY_ROOT_HCLASS_INDEX);
3213         Jump(&exit);
3214     }
3215     // 6 : index of this buffer
3216     Bind(&labelBuffer[6]);
3217     {
3218         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3219                                    GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_INDEX);
3220         Jump(&exit);
3221     }
3222     // 7 : index of this buffer
3223     Bind(&labelBuffer[7]);
3224     {
3225         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3226                                    GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_INDEX);
3227         Jump(&exit);
3228     }
3229     // 8 : index of this buffer
3230     Bind(&labelBuffer[8]);
3231     {
3232         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3233                                    GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_INDEX);
3234         Jump(&exit);
3235     }
3236     // 9 : index of this buffer
3237     Bind(&labelBuffer[9]);
3238     {
3239         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3240                                    GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_INDEX);
3241         Jump(&exit);
3242     }
3243     // 10 : index of this buffer
3244     Bind(&labelBuffer[10]);
3245     {
3246         result = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3247                                    GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_INDEX);
3248         Jump(&exit);
3249     }
3250     Bind(&defaultLabel);
3251     {
3252         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
3253         Jump(&exit);
3254     }
3255 
3256     Bind(&exit);
3257     auto ret = *result;
3258     env->SubCfgExit();
3259     return ret;
3260 }
3261 
CreateArrayFromList(GateRef glue,GateRef elements,GateRef kind)3262 GateRef NewObjectStubBuilder::CreateArrayFromList(GateRef glue, GateRef elements, GateRef kind)
3263 {
3264     auto env = GetEnvironment();
3265     Label entry(env);
3266     env->SubCfgEntry(&entry);
3267     GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
3268     GateRef intialHClass = GetElementsKindHClass(glue, kind);
3269     GateRef len = GetLengthOfTaggedArray(elements);
3270     GateRef result = NewJSObject(glue, intialHClass);
3271     SetPropertyInlinedProps(glue, result, intialHClass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
3272     SetArrayLength(glue, result, len);
3273     SetExtensibleToBitfield(glue, result, true);
3274     SetElementsArray(VariableType::JS_POINTER(), glue, result, elements);
3275     auto ret = result;
3276     env->SubCfgExit();
3277     return ret;
3278 }
CreateListFromArrayLike(GateRef glue,GateRef arrayObj)3279 GateRef NewObjectStubBuilder::CreateListFromArrayLike(GateRef glue, GateRef arrayObj)
3280 {
3281     auto env = GetEnvironment();
3282     Label entry(env);
3283     env->SubCfgEntry(&entry);
3284     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
3285     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
3286     Label exit(env);
3287 
3288     // 3. If Type(obj) is Object, throw a TypeError exception.
3289     Label targetIsHeapObject(env);
3290     Label targetIsEcmaObject(env);
3291     Label targetNotEcmaObject(env);
3292     BRANCH(TaggedIsHeapObject(arrayObj), &targetIsHeapObject, &targetNotEcmaObject);
3293     Bind(&targetIsHeapObject);
3294     BRANCH(TaggedObjectIsEcmaObject(glue, arrayObj), &targetIsEcmaObject, &targetNotEcmaObject);
3295     Bind(&targetNotEcmaObject);
3296     {
3297         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
3298         CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
3299         Jump(&exit);
3300     }
3301     Bind(&targetIsEcmaObject);
3302     {
3303         Label targetIsTypeArray(env);
3304         Label targetNotTypeArray(env);
3305         BRANCH(IsTypedArray(glue, arrayObj), &targetIsTypeArray, &targetNotTypeArray);
3306         Bind(&targetIsTypeArray);
3307         {
3308             GateRef int32Len = GetLengthOfJSTypedArray(arrayObj);
3309             GateRef array = NewTaggedArray(glue, int32Len);
3310             BuiltinsTypedArrayStubBuilder arrayStubBuilder(this, GetCurrentGlobalEnv());
3311             arrayStubBuilder.FastCopyElementToArray(glue, arrayObj, array);
3312             // c. ReturnIfAbrupt(next).
3313             Label noPendingException1(env);
3314             BRANCH(HasPendingException(glue), &exit, &noPendingException1);
3315             Bind(&noPendingException1);
3316             {
3317                 res = array;
3318                 Jump(&exit);
3319             }
3320         }
3321         Bind(&targetNotTypeArray);
3322         // 4. Let len be ToLength(Get(obj, "length")).
3323         GateRef lengthString =
3324             GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::LENGTH_STRING_INDEX);
3325         GateRef value = FastGetPropertyByName(glue, arrayObj, lengthString, ProfileOperation());
3326         GateRef number = ToLength(glue, value);
3327         // 5. ReturnIfAbrupt(len).
3328         Label noPendingException2(env);
3329         BRANCH(HasPendingException(glue), &exit, &noPendingException2);
3330         Bind(&noPendingException2);
3331         {
3332             Label indexInRange(env);
3333             Label indexOutRange(env);
3334 
3335             GateRef doubleLen = GetDoubleOfTNumber(number);
3336             BRANCH(DoubleGreaterThan(doubleLen, Double(JSObject::MAX_ELEMENT_INDEX)), &indexOutRange, &indexInRange);
3337             Bind(&indexOutRange);
3338             {
3339                 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax));
3340                 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), {IntToTaggedInt(taggedId)});
3341                 Jump(&exit);
3342             }
3343             Bind(&indexInRange);
3344             {
3345                 // 8. Repeat while index < len
3346                 GateRef int32Length = DoubleToInt(glue, doubleLen);
3347                 GateRef array = NewTaggedArray(glue, int32Length);
3348                 Label loopHead(env);
3349                 Label loopEnd(env);
3350                 Label afterLoop(env);
3351                 Label noPendingException3(env);
3352                 Label storeValue(env);
3353                 Jump(&loopHead);
3354                 LoopBegin(&loopHead);
3355                 {
3356                     BRANCH(Int32UnsignedLessThan(*index, int32Length), &storeValue, &afterLoop);
3357                     Bind(&storeValue);
3358                     {
3359                         GateRef next = FastGetPropertyByIndex(glue, arrayObj, *index, ProfileOperation());
3360                         // c. ReturnIfAbrupt(next).
3361                         BRANCH(HasPendingException(glue), &exit, &noPendingException3);
3362                         Bind(&noPendingException3);
3363                         SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, next);
3364                         index = Int32Add(*index, Int32(1));
3365                         Jump(&loopEnd);
3366                     }
3367                 }
3368                 Bind(&loopEnd);
3369                 LoopEndWithCheckSafePoint(&loopHead, env, glue);
3370                 Bind(&afterLoop);
3371                 {
3372                     res = array;
3373                     Jump(&exit);
3374                 }
3375             }
3376         }
3377     }
3378     Bind(&exit);
3379     GateRef ret = *res;
3380     env->SubCfgExit();
3381     return ret;
3382 }
3383 
CreateJSIteratorResult(GateRef glue,Variable * res,GateRef value,GateRef done,Label * exit)3384 void NewObjectStubBuilder::CreateJSIteratorResult(GateRef glue, Variable *res, GateRef value, GateRef done, Label *exit)
3385 {
3386     auto env = GetEnvironment();
3387     GateRef globalEnv = GetCurrentGlobalEnv();
3388     GateRef iterResultClass = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
3389                                                 GlobalEnv::ITERATOR_RESULT_CLASS_INDEX);
3390     Label afterNew(env);
3391     SetParameters(glue, 0);
3392     NewJSObject(res, &afterNew, iterResultClass);
3393     Bind(&afterNew);
3394     Store(VariableType::JS_POINTER(), glue, res->ReadVariable(),
3395           IntPtr(JSIterator::GetInlinedPropertyOffset(JSIterator::VALUE_INLINE_PROPERTY_INDEX)), value);
3396     Store(VariableType::JS_POINTER(), glue, res->ReadVariable(),
3397           IntPtr(JSIterator::GetInlinedPropertyOffset(JSIterator::DONE_INLINE_PROPERTY_INDEX)), done);
3398 
3399     Jump(exit);
3400 }
3401 }  // namespace panda::ecmascript::kungfu
3402