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