• 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/stub_builder-inl.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/global_env_constants.h"
21 #include "ecmascript/js_arguments.h"
22 #include "ecmascript/js_object.h"
23 #include "ecmascript/js_thread.h"
24 #include "ecmascript/lexical_env.h"
25 #include "ecmascript/mem/mem.h"
26 
27 namespace panda::ecmascript::kungfu {
NewLexicalEnv(Variable * result,Label * exit,GateRef numSlots,GateRef parent)28 void NewObjectStubBuilder::NewLexicalEnv(Variable *result, Label *exit, GateRef numSlots, GateRef parent)
29 {
30     auto env = GetEnvironment();
31 
32     auto length = Int32Add(numSlots, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
33     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length));
34     Label afterAllocate(env);
35     // Be careful. NO GC is allowed when initization is not complete.
36     AllocateInYoung(result, &afterAllocate);
37     Bind(&afterAllocate);
38     Label hasPendingException(env);
39     Label noException(env);
40     Branch(TaggedIsException(result->ReadVariable()), &hasPendingException, &noException);
41     Bind(&noException);
42     {
43         auto hclass = GetGlobalConstantValue(
44             VariableType::JS_POINTER(), glue_, ConstantIndex::ENV_CLASS_INDEX);
45         StoreHClass(glue_, result->ReadVariable(), hclass);
46         Label afterInitialize(env);
47         InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
48             result->ReadVariable(), Hole(), Int32(LexicalEnv::RESERVED_ENV_LENGTH), length);
49         Bind(&afterInitialize);
50         SetValueToTaggedArray(VariableType::INT64(),
51             glue_, result->ReadVariable(), Int32(LexicalEnv::SCOPE_INFO_INDEX), Hole());
52         SetValueToTaggedArray(VariableType::JS_POINTER(),
53             glue_, result->ReadVariable(), Int32(LexicalEnv::PARENT_ENV_INDEX), parent);
54         Jump(exit);
55     }
56     Bind(&hasPendingException);
57     {
58         Jump(exit);
59     }
60 }
61 
NewJSArrayWithSize(GateRef hclass,GateRef size)62 GateRef NewObjectStubBuilder::NewJSArrayWithSize(GateRef hclass, GateRef size)
63 {
64     auto env = GetEnvironment();
65     Label entry(env);
66     Label exit(env);
67     env->SubCfgEntry(&entry);
68 
69     GateRef result = NewJSObject(glue_, hclass);
70     DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
71     NewTaggedArrayChecked(&array, TruncInt64ToInt32(size), &exit);
72     Bind(&exit);
73     auto arrayRet = *array;
74     env->SubCfgExit();
75     SetElementsArray(VariableType::JS_POINTER(), glue_, result, arrayRet);
76     return result;
77 }
78 
NewJSObject(Variable * result,Label * exit,GateRef hclass)79 void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass)
80 {
81     auto env = GetEnvironment();
82 
83     size_ = GetObjectSizeFromHClass(hclass);
84     Label afterAllocate(env);
85     // Be careful. NO GC is allowed when initization is not complete.
86     AllocateInYoung(result, &afterAllocate);
87     Bind(&afterAllocate);
88     Label hasPendingException(env);
89     Label noException(env);
90     Branch(TaggedIsException(result->ReadVariable()), &hasPendingException, &noException);
91     Bind(&noException);
92     {
93         StoreHClass(glue_, result->ReadVariable(), hclass);
94         DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
95         Label isTS(env);
96         Label initialize(env);
97         Branch(IsTSHClass(hclass), &isTS, &initialize);
98         Bind(&isTS);
99         {
100             // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist,
101             // to follow ECMA spec.
102             initValue = Hole();
103             Jump(&initialize);
104         }
105         Bind(&initialize);
106         Label afterInitialize(env);
107         InitializeWithSpeicalValue(&afterInitialize,
108             result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_));
109         Bind(&afterInitialize);
110         auto emptyArray = GetGlobalConstantValue(
111             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
112         SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
113         SetPropertiesArray(VariableType::INT64(),
114             glue_, result->ReadVariable(), emptyArray);
115         SetElementsArray(VariableType::INT64(),
116             glue_, result->ReadVariable(), emptyArray);
117         Jump(exit);
118     }
119     Bind(&hasPendingException);
120     {
121         Jump(exit);
122     }
123 }
124 
NewJSObject(GateRef glue,GateRef hclass)125 GateRef NewObjectStubBuilder::NewJSObject(GateRef glue, GateRef hclass)
126 {
127     auto env = GetEnvironment();
128     Label entry(env);
129     env->SubCfgEntry(&entry);
130     Label exit(env);
131 
132     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
133     SetGlue(glue);
134     NewJSObject(&result, &exit, hclass);
135 
136     Bind(&exit);
137     auto ret = *result;
138     env->SubCfgExit();
139     return ret;
140 }
141 
NewTaggedArrayChecked(Variable * result,GateRef len,Label * exit)142 void NewObjectStubBuilder::NewTaggedArrayChecked(Variable *result, GateRef len, Label *exit)
143 {
144     auto env = GetEnvironment();
145     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len));
146     Label afterAllocate(env);
147     // Be careful. NO GC is allowed when initization is not complete.
148     AllocateInYoung(result, &afterAllocate);
149     Bind(&afterAllocate);
150     Label noException(env);
151     Branch(TaggedIsException(result->ReadVariable()), exit, &noException);
152     Bind(&noException);
153     {
154         auto hclass = GetGlobalConstantValue(
155             VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_CLASS_INDEX);
156         StoreHClass(glue_, result->ReadVariable(), hclass);
157         Label afterInitialize(env);
158         InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
159             result->ReadVariable(), Hole(), Int32(0), len);
160         Bind(&afterInitialize);
161         Jump(exit);
162     }
163 }
164 
NewTaggedArray(GateRef glue,GateRef len)165 GateRef NewObjectStubBuilder::NewTaggedArray(GateRef glue, GateRef len)
166 {
167     auto env = GetEnvironment();
168     Label entry(env);
169     env->SubCfgEntry(&entry);
170     Label exit(env);
171     Label isEmpty(env);
172     Label notEmpty(env);
173 
174     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
175     SetGlue(glue);
176     Branch(Int32Equal(len, Int32(0)), &isEmpty, &notEmpty);
177     Bind(&isEmpty);
178     {
179         result = GetGlobalConstantValue(
180             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
181         Jump(&exit);
182     }
183     Bind(&notEmpty);
184     {
185         Label next(env);
186         Label slowPath(env);
187         Branch(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath);
188         Bind(&next);
189         {
190             NewTaggedArrayChecked(&result, len, &exit);
191         }
192         Bind(&slowPath);
193         {
194             result = CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(len) });
195             Jump(&exit);
196         }
197     }
198 
199     Bind(&exit);
200     auto ret = *result;
201     env->SubCfgExit();
202     return ret;
203 }
204 
NewArgumentsList(Variable * result,Label * exit,GateRef sp,GateRef startIdx,GateRef numArgs)205 void NewObjectStubBuilder::NewArgumentsList(Variable *result, Label *exit,
206     GateRef sp, GateRef startIdx, GateRef numArgs)
207 {
208     auto env = GetEnvironment();
209     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
210     Label setHClass(env);
211     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(numArgs));
212     Label afterAllocate(env);
213     AllocateInYoung(result, &afterAllocate);
214     Bind(&afterAllocate);
215     Branch(TaggedIsException(result->ReadVariable()), exit, &setHClass);
216     Bind(&setHClass);
217     GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
218                                                 ConstantIndex::ARRAY_CLASS_INDEX);
219     StoreHClass(glue_, result->ReadVariable(), arrayClass);
220     Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(TaggedArray::LENGTH_OFFSET), numArgs);
221     // skip InitializeTaggedArrayWithSpeicalValue due to immediate setting arguments
222     Label setArgumentsBegin(env);
223     Label setArgumentsAgain(env);
224     Label setArgumentsEnd(env);
225     Branch(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
226     LoopBegin(&setArgumentsBegin);
227     GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
228     GateRef argument = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx));
229     SetValueToTaggedArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), *i, argument);
230     i = Int32Add(*i, Int32(1));
231     Branch(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
232     Bind(&setArgumentsAgain);
233     LoopEnd(&setArgumentsBegin);
234     Bind(&setArgumentsEnd);
235     Jump(exit);
236 }
237 
NewArgumentsObj(Variable * result,Label * exit,GateRef argumentsList,GateRef numArgs)238 void NewObjectStubBuilder::NewArgumentsObj(Variable *result, Label *exit,
239     GateRef argumentsList, GateRef numArgs)
240 {
241     auto env = GetEnvironment();
242 
243     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
244     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset);
245     GateRef argumentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
246                                                GlobalEnv::ARGUMENTS_CLASS);
247     Label afterNewObject(env);
248     NewJSObject(result, &afterNewObject, argumentsClass);
249     Bind(&afterNewObject);
250     Label setArgumentsObjProperties(env);
251     Branch(TaggedIsException(result->ReadVariable()), exit, &setArgumentsObjProperties);
252     Bind(&setArgumentsObjProperties);
253     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, IntToTaggedInt(numArgs),
254                             Int32(JSArguments::LENGTH_INLINE_PROPERTY_INDEX));
255     SetElementsArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), argumentsList);
256     GateRef arrayProtoValuesFunction = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
257                                                          GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
258     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, arrayProtoValuesFunction,
259                             Int32(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX));
260     GateRef accessorCaller = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
261                                                GlobalEnv::ARGUMENTS_CALLER_ACCESSOR);
262     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCaller,
263                             Int32(JSArguments::CALLER_INLINE_PROPERTY_INDEX));
264     GateRef accessorCallee = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
265                                                GlobalEnv::ARGUMENTS_CALLEE_ACCESSOR);
266     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCallee,
267                             Int32(JSArguments::CALLEE_INLINE_PROPERTY_INDEX));
268     Jump(exit);
269 }
270 
NewJSArrayLiteral(Variable * result,Label * exit,RegionSpaceFlag spaceType,GateRef obj,GateRef hclass,bool isEmptyArray)271 void NewObjectStubBuilder::NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj,
272                                              GateRef hclass, bool isEmptyArray)
273 {
274     auto env = GetEnvironment();
275     Label initializeArray(env);
276     Label afterInitialize(env);
277     HeapAlloc(result, &initializeArray, spaceType);
278     Bind(&initializeArray);
279     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(0), hclass);
280     InitializeWithSpeicalValue(&afterInitialize, result->ReadVariable(), Undefined(), Int32(JSArray::SIZE),
281                                TruncInt64ToInt32(size_));
282     Bind(&afterInitialize);
283     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
284     Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()));
285 
286     GateRef propertiesOffset = IntPtr(JSObject::PROPERTIES_OFFSET);
287     GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
288     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
289     if (isEmptyArray) {
290         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, obj);
291         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, obj);
292         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, Int32(0));
293     } else {
294         auto newProperties = Load(VariableType::JS_POINTER(), obj, propertiesOffset);
295         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, newProperties);
296 
297         auto newElements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
298         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, newElements);
299 
300         GateRef arrayLength = Load(VariableType::INT32(), obj, lengthOffset);
301         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, arrayLength);
302     }
303 
304     auto accessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
305     SetPropertyInlinedProps(glue_, result->ReadVariable(), hclass, accessor,
306         Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_POINTER());
307     Jump(exit);
308 }
309 
HeapAlloc(Variable * result,Label * exit,RegionSpaceFlag spaceType)310 void NewObjectStubBuilder::HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType)
311 {
312     switch (spaceType) {
313         case RegionSpaceFlag::IN_YOUNG_SPACE:
314             AllocateInYoung(result, exit);
315             break;
316         default:
317             break;
318     }
319 }
320 
AllocateInYoung(Variable * result,Label * exit)321 void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *exit)
322 {
323     auto env = GetEnvironment();
324     Label success(env);
325     Label callRuntime(env);
326     Label next(env);
327 
328 #ifdef ARK_ASAN_ON
329     DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
330     Jump(&callRuntime);
331 #else
332 #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
333     auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
334     auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
335     Branch(TaggedIsTrue(isStartHeapSampling), &callRuntime, &next);
336     Bind(&next);
337 #endif
338     auto topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(env->Is32Bit());
339     auto endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(env->Is32Bit());
340     auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
341     auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
342     auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0));
343     auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0));
344     DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
345     auto newTop = PtrAdd(top, size_);
346     Branch(IntPtrGreaterThan(newTop, end), &callRuntime, &success);
347     Bind(&success);
348     {
349         Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop);
350         if (env->Is32Bit()) {
351             top = ZExtInt32ToInt64(top);
352         }
353         ret = top;
354         result->WriteVariable(*ret);
355         Jump(exit);
356     }
357 #endif
358     Bind(&callRuntime);
359     {
360         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
361             IntToTaggedInt(size_) });
362         result->WriteVariable(*ret);
363         Jump(exit);
364     }
365 }
366 
InitializeWithSpeicalValue(Label * exit,GateRef object,GateRef value,GateRef start,GateRef end)367 void NewObjectStubBuilder::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef value, GateRef start,
368                                                       GateRef end)
369 {
370     auto env = GetEnvironment();
371     Label begin(env);
372     Label storeValue(env);
373     Label endLoop(env);
374 
375     DEFVARIABLE(startOffset, VariableType::INT32(), start);
376     Jump(&begin);
377     LoopBegin(&begin);
378     {
379         Branch(Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
380         Bind(&storeValue);
381         {
382             Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(*startOffset), value);
383             startOffset = Int32Add(*startOffset, Int32(JSTaggedValue::TaggedTypeSize()));
384             Jump(&endLoop);
385         }
386         Bind(&endLoop);
387         LoopEnd(&begin);
388     }
389 }
390 
InitializeTaggedArrayWithSpeicalValue(Label * exit,GateRef array,GateRef value,GateRef start,GateRef length)391 void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit,
392     GateRef array, GateRef value, GateRef start, GateRef length)
393 {
394     Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::LENGTH_OFFSET), length);
395     auto offset = Int32Mul(start, Int32(JSTaggedValue::TaggedTypeSize()));
396     auto dataOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
397     offset = Int32Mul(length, Int32(JSTaggedValue::TaggedTypeSize()));
398     auto endOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
399     InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset);
400 }
401 
AllocLineStringObject(Variable * result,Label * exit,GateRef length,bool compressed)402 void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
403 {
404     auto env = GetEnvironment();
405     if (compressed) {
406         size_ = AlignUp(ComputeSizeUtf8(ZExtInt32ToPtr(length)),
407             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
408     } else {
409         size_ = AlignUp(ComputeSizeUtf16(ZExtInt32ToPtr(length)),
410             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
411     }
412     Label afterAllocate(env);
413     AllocateInYoung(result, &afterAllocate);
414 
415     Bind(&afterAllocate);
416     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
417                                                  ConstantIndex::LINE_STRING_CLASS_INDEX);
418     StoreHClass(glue_, result->ReadVariable(), stringClass);
419     SetLength(glue_, result->ReadVariable(), length, compressed);
420     SetRawHashcode(glue_, result->ReadVariable(), Int32(0));
421     Jump(exit);
422 }
423 
424 
FastNewThisObject(GateRef glue,GateRef ctor)425 GateRef NewObjectStubBuilder::FastNewThisObject(GateRef glue, GateRef ctor)
426 {
427     auto env = GetEnvironment();
428     Label entry(env);
429     env->SubCfgEntry(&entry);
430     Label exit(env);
431     Label isHeapObject(env);
432     Label callRuntime(env);
433     Label checkJSObject(env);
434     Label newObject(env);
435 
436     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
437     auto protoOrHclass = Load(VariableType::JS_ANY(), ctor,
438         IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
439     Branch(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &callRuntime);
440     Bind(&isHeapObject);
441     Branch(IsJSHClass(protoOrHclass), &checkJSObject, &callRuntime);
442     Bind(&checkJSObject);
443     auto objectType = GetObjectType(protoOrHclass);
444     Branch(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))),
445         &newObject, &callRuntime);
446     Bind(&newObject);
447     {
448         SetParameters(glue, 0);
449         NewJSObject(&thisObj, &exit, protoOrHclass);
450     }
451     Bind(&callRuntime);
452     {
453         thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor});
454         Jump(&exit);
455     }
456     Bind(&exit);
457     auto ret = *thisObj;
458     env->SubCfgExit();
459     return ret;
460 }
461 
NewThisObjectChecked(GateRef glue,GateRef ctor)462 GateRef NewObjectStubBuilder::NewThisObjectChecked(GateRef glue, GateRef ctor)
463 {
464     auto env = GetEnvironment();
465     Label entry(env);
466     env->SubCfgEntry(&entry);
467     Label exit(env);
468 
469     Label ctorIsHeapObject(env);
470     Label ctorIsJSFunction(env);
471     Label fastPath(env);
472     Label slowPath(env);
473     Label ctorIsBase(env);
474 
475     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
476 
477     Branch(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath);
478     Bind(&ctorIsHeapObject);
479     Branch(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath);
480     Bind(&ctorIsJSFunction);
481     Branch(IsConstructor(ctor), &fastPath, &slowPath);
482     Bind(&fastPath);
483     {
484         Branch(IsBase(ctor), &ctorIsBase, &exit);
485         Bind(&ctorIsBase);
486         {
487             thisObj = FastNewThisObject(glue, ctor);
488             Jump(&exit);
489         }
490     }
491     Bind(&slowPath);
492     {
493         thisObj = Hole();
494         Jump(&exit);
495     }
496     Bind(&exit);
497     auto ret = *thisObj;
498     env->SubCfgExit();
499     return ret;
500 }
501 
CreateEmptyArray(GateRef glue,ProfileOperation callback)502 GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue, ProfileOperation callback)
503 {
504     auto env = GetEnvironment();
505     Label entry(env);
506     env->SubCfgEntry(&entry);
507     Label exit(env);
508 
509     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
510 
511     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
512     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
513     auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
514     auto hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
515     GateRef size = GetObjectSizeFromHClass(hclass);
516     auto emptyArray = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
517 
518     SetParameters(glue, size);
519     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, emptyArray, hclass, true);
520     Bind(&exit);
521     auto ret = *result;
522     if (!callback.IsEmpty()) {
523         auto noneHClass =
524             GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
525         StoreHClass(glue, ret, noneHClass);
526         callback.ProfileCreateObject(ret);
527     }
528     env->SubCfgExit();
529     return ret;
530 }
531 
CreateArrayWithBuffer(GateRef glue,GateRef index,GateRef jsFunc,ProfileOperation callback)532 GateRef NewObjectStubBuilder::CreateArrayWithBuffer(
533     GateRef glue, GateRef index, GateRef jsFunc, ProfileOperation callback)
534 {
535     auto env = GetEnvironment();
536     Label entry(env);
537     env->SubCfgEntry(&entry);
538     Label exit(env);
539 
540     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
541     GateRef method = GetMethodFromFunction(jsFunc);
542     GateRef constPool = Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
543     GateRef module = GetModuleFromFunction(jsFunc);
544 
545     auto obj = GetArrayLiteralFromConstPool(glue, constPool, index, module);
546     auto hclass = LoadHClass(obj);
547     GateRef size = GetObjectSizeFromHClass(hclass);
548 
549     SetParameters(glue, size);
550     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, obj, hclass, false);
551 
552     Bind(&exit);
553     auto ret = *result;
554     callback.ProfileCreateObject(ret);
555     env->SubCfgExit();
556     return ret;
557 }
558 }  // namespace panda::ecmascript::kungfu
559