• 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/compiler/stub_builder.h"
20 #include "ecmascript/ecma_string.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/global_env_constants.h"
23 #include "ecmascript/js_arguments.h"
24 #include "ecmascript/js_object.h"
25 #include "ecmascript/js_thread.h"
26 #include "ecmascript/lexical_env.h"
27 #include "ecmascript/mem/mem.h"
28 #include "ecmascript/js_map_iterator.h"
29 #include "ecmascript/js_set_iterator.h"
30 #include "ecmascript/js_set.h"
31 #include "ecmascript/js_map.h"
32 
33 namespace panda::ecmascript::kungfu {
NewLexicalEnv(Variable * result,Label * exit,GateRef numSlots,GateRef parent)34 void NewObjectStubBuilder::NewLexicalEnv(Variable *result, Label *exit, GateRef numSlots, GateRef parent)
35 {
36     auto env = GetEnvironment();
37 
38     auto length = Int32Add(numSlots, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
39     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(length));
40     Label afterAllocate(env);
41     // Be careful. NO GC is allowed when initization is not complete.
42     AllocateInYoung(result, &afterAllocate);
43     Bind(&afterAllocate);
44     Label hasPendingException(env);
45     Label noException(env);
46     Branch(TaggedIsException(result->ReadVariable()), &hasPendingException, &noException);
47     Bind(&noException);
48     {
49         auto hclass = GetGlobalConstantValue(
50             VariableType::JS_POINTER(), glue_, ConstantIndex::ENV_CLASS_INDEX);
51         StoreHClass(glue_, result->ReadVariable(), hclass);
52         Label afterInitialize(env);
53         InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
54             result->ReadVariable(), Hole(), Int32(LexicalEnv::RESERVED_ENV_LENGTH), length);
55         Bind(&afterInitialize);
56         SetValueToTaggedArray(VariableType::INT64(),
57             glue_, result->ReadVariable(), Int32(LexicalEnv::SCOPE_INFO_INDEX), Hole());
58         SetValueToTaggedArray(VariableType::JS_POINTER(),
59             glue_, result->ReadVariable(), Int32(LexicalEnv::PARENT_ENV_INDEX), parent);
60         Jump(exit);
61     }
62     Bind(&hasPendingException);
63     {
64         Jump(exit);
65     }
66 }
67 
NewJSArrayWithSize(GateRef hclass,GateRef size)68 GateRef NewObjectStubBuilder::NewJSArrayWithSize(GateRef hclass, GateRef size)
69 {
70     auto env = GetEnvironment();
71     Label entry(env);
72     Label exit(env);
73     env->SubCfgEntry(&entry);
74 
75     GateRef result = NewJSObject(glue_, hclass);
76     DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
77     NewTaggedArrayChecked(&array, TruncInt64ToInt32(size), &exit);
78     Bind(&exit);
79     auto arrayRet = *array;
80     env->SubCfgExit();
81     SetElementsArray(VariableType::JS_POINTER(), glue_, result, arrayRet);
82     return result;
83 }
84 
NewJSObject(Variable * result,Label * exit,GateRef hclass)85 void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hclass)
86 {
87     auto env = GetEnvironment();
88 
89     size_ = GetObjectSizeFromHClass(hclass);
90     Label afterAllocate(env);
91     // Be careful. NO GC is allowed when initization is not complete.
92     AllocateInYoung(result, &afterAllocate);
93     Bind(&afterAllocate);
94     Label hasPendingException(env);
95     Label noException(env);
96     Branch(TaggedIsException(result->ReadVariable()), &hasPendingException, &noException);
97     Bind(&noException);
98     {
99         StoreHClass(glue_, result->ReadVariable(), hclass);
100         DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
101         Label isTS(env);
102         Label initialize(env);
103         Branch(IsTSHClass(hclass), &isTS, &initialize);
104         Bind(&isTS);
105         {
106             // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist,
107             // to follow ECMA spec.
108             initValue = Hole();
109             Jump(&initialize);
110         }
111         Bind(&initialize);
112         Label afterInitialize(env);
113         InitializeWithSpeicalValue(&afterInitialize,
114             result->ReadVariable(), *initValue, Int32(JSObject::SIZE), ChangeIntPtrToInt32(size_));
115         Bind(&afterInitialize);
116         auto emptyArray = GetGlobalConstantValue(
117             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
118         SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
119         SetPropertiesArray(VariableType::INT64(),
120             glue_, result->ReadVariable(), emptyArray);
121         SetElementsArray(VariableType::INT64(),
122             glue_, result->ReadVariable(), emptyArray);
123         Jump(exit);
124     }
125     Bind(&hasPendingException);
126     {
127         Jump(exit);
128     }
129 }
130 
NewJSObject(GateRef glue,GateRef hclass)131 GateRef NewObjectStubBuilder::NewJSObject(GateRef glue, GateRef hclass)
132 {
133     auto env = GetEnvironment();
134     Label entry(env);
135     env->SubCfgEntry(&entry);
136     Label exit(env);
137 
138     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
139     SetGlue(glue);
140     NewJSObject(&result, &exit, hclass);
141 
142     Bind(&exit);
143     auto ret = *result;
144     env->SubCfgExit();
145     return ret;
146 }
147 
NewTaggedArrayChecked(Variable * result,GateRef len,Label * exit)148 void NewObjectStubBuilder::NewTaggedArrayChecked(Variable *result, GateRef len, Label *exit)
149 {
150     auto env = GetEnvironment();
151     Label overflow(env);
152     Label notOverflow(env);
153     Branch(Int32UnsignedGreaterThan(len, Int32(INT32_MAX)), &overflow, &notOverflow);
154     Bind(&overflow);
155     {
156         GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(LenGreaterThanMax));
157         CallRuntime(glue_, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
158         result->WriteVariable(Exception());
159         Jump(exit);
160     }
161     Bind(&notOverflow);
162     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(len));
163     Label afterAllocate(env);
164     // Be careful. NO GC is allowed when initization is not complete.
165     AllocateInYoung(result, &afterAllocate);
166     Bind(&afterAllocate);
167     Label noException(env);
168     Branch(TaggedIsException(result->ReadVariable()), exit, &noException);
169     Bind(&noException);
170     {
171         auto hclass = GetGlobalConstantValue(
172             VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_CLASS_INDEX);
173         StoreHClass(glue_, result->ReadVariable(), hclass);
174         Label afterInitialize(env);
175         InitializeTaggedArrayWithSpeicalValue(&afterInitialize,
176             result->ReadVariable(), Hole(), Int32(0), len);
177         Bind(&afterInitialize);
178         Jump(exit);
179     }
180 }
181 
NewTaggedArray(GateRef glue,GateRef len)182 GateRef NewObjectStubBuilder::NewTaggedArray(GateRef glue, GateRef len)
183 {
184     auto env = GetEnvironment();
185     Label entry(env);
186     env->SubCfgEntry(&entry);
187     Label exit(env);
188     Label isEmpty(env);
189     Label notEmpty(env);
190 
191     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
192     SetGlue(glue);
193     Branch(Int32Equal(len, Int32(0)), &isEmpty, &notEmpty);
194     Bind(&isEmpty);
195     {
196         result = GetGlobalConstantValue(
197             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
198         Jump(&exit);
199     }
200     Bind(&notEmpty);
201     {
202         Label next(env);
203         Label slowPath(env);
204         Branch(Int32LessThan(len, Int32(MAX_TAGGED_ARRAY_LENGTH)), &next, &slowPath);
205         Bind(&next);
206         {
207             NewTaggedArrayChecked(&result, len, &exit);
208         }
209         Bind(&slowPath);
210         {
211             result = CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(len) });
212             Jump(&exit);
213         }
214     }
215 
216     Bind(&exit);
217     auto ret = *result;
218     env->SubCfgExit();
219     return ret;
220 }
221 
ExtendArray(GateRef glue,GateRef elements,GateRef newLen)222 GateRef NewObjectStubBuilder::ExtendArray(GateRef glue, GateRef elements, GateRef newLen)
223 {
224     auto env = GetEnvironment();
225     Label subEntry(env);
226     env->SubCfgEntry(&subEntry);
227     Label newMutantArray(env);
228     Label newNormalArray(env);
229     Label afterNew(env);
230     Label exit(env);
231     NewObjectStubBuilder newBuilder(this);
232     SetGlue(glue);
233     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
234     DEFVARIABLE(res, VariableType::JS_ANY(), Hole());
235     DEFVARIABLE(array, VariableType::JS_ANY(), Undefined());
236     Branch(IsMutantTaggedArray(elements),
237            &newMutantArray, &newNormalArray);
238     Bind(&newNormalArray);
239     {
240         array = newBuilder.NewTaggedArray(glue, newLen);
241         Jump(&afterNew);
242     }
243     Bind(&newMutantArray);
244     {
245         array = CallRuntime(glue_, RTSTUB_ID(NewMutantTaggedArray), { IntToTaggedInt(newLen) });
246         Jump(&afterNew);
247     }
248     Bind(&afterNew);
249     Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen);
250     GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements);
251     Store(VariableType::INT32(), glue, *array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
252     GateRef oldL = GetLengthOfTaggedArray(elements);
253     Label loopHead(env);
254     Label loopEnd(env);
255     Label afterLoop(env);
256     Label storeValue(env);
257     Label storeToNormalArray(env);
258     Label storeToMutantArray(env);
259     Label finishStore(env);
260     Jump(&loopHead);
261     LoopBegin(&loopHead);
262     {
263         Branch(Int32UnsignedLessThan(*index, oldL), &storeValue, &afterLoop);
264         Bind(&storeValue);
265         {
266             Branch(IsMutantTaggedArray(elements),
267                    &storeToMutantArray, &storeToNormalArray);
268             Bind(&storeToNormalArray);
269             {
270                 GateRef value = GetValueFromTaggedArray(elements, *index);
271                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, *index, value);
272                 Jump(&finishStore);
273             }
274             Bind(&storeToMutantArray);
275             {
276                 GateRef value = GetValueFromMutantTaggedArray(elements, *index);
277                 SetValueToTaggedArray(VariableType::INT64(), glue, *array, *index, value);
278                 Jump(&finishStore);
279             }
280             Bind(&finishStore);
281             {
282                 index = Int32Add(*index, Int32(1));
283                 Jump(&loopEnd);
284             }
285         }
286     }
287     Bind(&loopEnd);
288     LoopEnd(&loopHead);
289     Bind(&afterLoop);
290     {
291         Label loopHead1(env);
292         Label loopEnd1(env);
293         Label afterLoop1(env);
294         Label storeValue1(env);
295         Jump(&loopHead1);
296         Label storeNormalHole(env);
297         Label storeMutantHole(env);
298         Label finishStoreHole(env);
299         LoopBegin(&loopHead1);
300         {
301             Branch(Int32UnsignedLessThan(*index, newLen), &storeValue1, &afterLoop1);
302             Bind(&storeValue1);
303             {
304                 Branch(IsMutantTaggedArray(elements),
305                        &storeMutantHole, &storeNormalHole);
306                 Bind(&storeNormalHole);
307                 {
308                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, *index, Hole());
309                     Jump(&finishStoreHole);
310                 }
311                 Bind(&storeMutantHole);
312                 {
313                     SetValueToTaggedArray(VariableType::INT64(), glue, *array, *index, SpecialHole());
314                     Jump(&finishStoreHole);
315                 }
316                 Bind(&finishStoreHole);
317                 {
318                     index = Int32Add(*index, Int32(1));
319                     Jump(&loopEnd1);
320                 }
321             }
322         }
323         Bind(&loopEnd1);
324         LoopEnd(&loopHead1);
325         Bind(&afterLoop1);
326         {
327             res = *array;
328             Jump(&exit);
329         }
330     }
331     Bind(&exit);
332     auto ret = *res;
333     env->SubCfgExit();
334     return ret;
335 }
336 
CopyArray(GateRef glue,GateRef elements,GateRef oldLen,GateRef newLen)337 GateRef NewObjectStubBuilder::CopyArray(GateRef glue, GateRef elements, GateRef oldLen, GateRef newLen)
338 {
339     auto env = GetEnvironment();
340     Label subEntry(env);
341     env->SubCfgEntry(&subEntry);
342     Label exit(env);
343     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
344     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
345     NewObjectStubBuilder newBuilder(this);
346     Label emptyArray(env);
347     Label notEmptyArray(env);
348     Branch(Int32Equal(newLen, Int32(0)), &emptyArray, &notEmptyArray);
349     Bind(&emptyArray);
350     result = GetEmptyArray(glue);
351     Jump(&exit);
352     Bind(&notEmptyArray);
353     {
354         Label extendArray(env);
355         Label notExtendArray(env);
356         Branch(Int32GreaterThan(newLen, oldLen), &extendArray, &notExtendArray);
357         Bind(&extendArray);
358         {
359             result = ExtendArray(glue, elements, newLen);
360             Jump(&exit);
361         }
362         Bind(&notExtendArray);
363         {
364             GateRef array = newBuilder.NewTaggedArray(glue, newLen);
365             Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::LENGTH_OFFSET), newLen);
366             GateRef oldExtractLen = GetExtractLengthOfTaggedArray(elements);
367             Store(VariableType::INT32(), glue, array, IntPtr(TaggedArray::EXTRA_LENGTH_OFFSET), oldExtractLen);
368             Label loopHead(env);
369             Label loopEnd(env);
370             Label afterLoop(env);
371             Label storeValue(env);
372             Jump(&loopHead);
373             LoopBegin(&loopHead);
374             {
375                 Branch(Int32UnsignedLessThan(*index, newLen), &storeValue, &afterLoop);
376                 Bind(&storeValue);
377                 {
378                     GateRef value = GetValueFromTaggedArray(elements, *index);
379                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *index, value);
380                     index = Int32Add(*index, Int32(1));
381                     Jump(&loopEnd);
382                 }
383             }
384             Bind(&loopEnd);
385             LoopEnd(&loopHead);
386             Bind(&afterLoop);
387             {
388                 result = array;
389                 Jump(&exit);
390             }
391         }
392     }
393     Bind(&exit);
394     auto ret = *result;
395     env->SubCfgExit();
396     return ret;
397 }
398 
NewJSForinIterator(GateRef glue,GateRef receiver,GateRef keys,GateRef cachedHclass)399 GateRef NewObjectStubBuilder::NewJSForinIterator(GateRef glue, GateRef receiver, GateRef keys, GateRef cachedHclass)
400 {
401     auto env = GetEnvironment();
402     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
403     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
404     GateRef hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FOR_IN_ITERATOR_CLASS_INDEX);
405     GateRef iter = NewJSObject(glue, hclass);
406     // init JSForinIterator
407     SetObjectOfForInIterator(glue, iter, receiver);
408     SetCachedHclassOfForInIterator(glue, iter, cachedHclass);
409     SetKeysOfForInIterator(glue, iter, keys);
410     SetIndexOfForInIterator(glue, iter, Int32(EnumCache::ENUM_CACHE_HEADER_SIZE));
411     GateRef length = GetLengthOfTaggedArray(keys);
412     SetLengthOfForInIterator(glue, iter, length);
413     return iter;
414 }
415 
LoadHClassFromMethod(GateRef glue,GateRef method)416 GateRef NewObjectStubBuilder::LoadHClassFromMethod(GateRef glue, GateRef method)
417 {
418     auto env = GetEnvironment();
419     Label entry(env);
420     env->SubCfgEntry(&entry);
421     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
422     GateRef kind = GetFuncKind(method);
423     Label exit(env);
424     Label defaultLabel(env);
425     Label isNormal(env);
426     Label notNormal(env);
427     Label isAsync(env);
428     Label notAsync(env);
429 
430     Label labelBuffer[2] = { Label(env), Label(env) };
431     Label labelBuffer1[3] = { Label(env), Label(env), Label(env) };
432     int64_t valueBuffer[2] = {
433         static_cast<int64_t>(FunctionKind::NORMAL_FUNCTION), static_cast<int64_t>(FunctionKind::ARROW_FUNCTION) };
434     int64_t valueBuffer1[3] = {
435         static_cast<int64_t>(FunctionKind::BASE_CONSTRUCTOR), static_cast<int64_t>(FunctionKind::GENERATOR_FUNCTION),
436         static_cast<int64_t>(FunctionKind::ASYNC_GENERATOR_FUNCTION) };
437     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
438     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
439     Branch(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ARROW_FUNCTION))),
440         &isNormal, &notNormal);
441     Bind(&isNormal);
442     {
443         // 2 : this switch has 2 case
444         Switch(kind, &defaultLabel, valueBuffer, labelBuffer, 2);
445         Bind(&labelBuffer[0]);
446         {
447             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITH_PROTO);
448             Jump(&exit);
449         }
450         Bind(&labelBuffer[1]);
451         {
452             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITHOUT_PROTO);
453             Jump(&exit);
454         }
455     }
456     Bind(&notNormal);
457     {
458         Branch(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ASYNC_FUNCTION))),
459             &isAsync, &notAsync);
460         Bind(&isAsync);
461         {
462             hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ASYNC_FUNCTION_CLASS);
463             Jump(&exit);
464         }
465         Bind(&notAsync);
466         {
467             // 3 : this switch has 3 case
468             Switch(kind, &defaultLabel, valueBuffer1, labelBuffer1, 3);
469             Bind(&labelBuffer1[0]);
470             {
471                 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::FUNCTION_CLASS_WITH_PROTO);
472                 Jump(&exit);
473             }
474             Bind(&labelBuffer1[1]);
475             {
476                 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::GENERATOR_FUNCTION_CLASS);
477                 Jump(&exit);
478             }
479             // 2 : index of kind
480             Bind(&labelBuffer1[2]);
481             {
482                 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
483                                            GlobalEnv::ASYNC_GENERATOR_FUNCTION_CLASS);
484                 Jump(&exit);
485             }
486         }
487     }
488     Bind(&defaultLabel);
489     {
490         FatalPrint(glue, { Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable)) });
491         Jump(&exit);
492     }
493     Bind(&exit);
494     auto ret = *hclass;
495     env->SubCfgExit();
496     return ret;
497 }
498 
NewJSFunction(GateRef glue,GateRef constpool,GateRef module,GateRef index)499 GateRef NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef constpool, GateRef module, GateRef index)
500 {
501     auto env = GetEnvironment();
502     Label subentry(env);
503     env->SubCfgEntry(&subentry);
504     Label exit(env);
505     DEFVARIABLE(ihc, VariableType::JS_ANY(), Undefined());
506     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
507     auto val = GetValueFromTaggedArray(constpool, index);
508     Label isHeapObject(env);
509     Label afterAOTLiteral(env);
510     Branch(TaggedIsHeapObject(val), &isHeapObject, &afterAOTLiteral);
511     {
512         Bind(&isHeapObject);
513         Label isAOTLiteral(env);
514         Branch(IsAOTLiteralInfo(val), &isAOTLiteral, &afterAOTLiteral);
515         {
516             Bind(&isAOTLiteral);
517             ihc = GetIhcFromAOTLiteralInfo(val);
518             Jump(&afterAOTLiteral);
519         }
520     }
521     Bind(&afterAOTLiteral);
522     GateRef method = GetMethodFromConstPool(glue, constpool, module, index);
523     GateRef hclass = LoadHClassFromMethod(glue, method);
524     result = NewJSObject(glue, hclass);
525     SetExtensibleToBitfield(glue, hclass, true);
526     SetCallableToBitfield(glue, hclass, true);
527     GateRef kind = GetFuncKind(method);
528     InitializeJSFunction(glue, *result, kind);
529     SetMethodToFunction(glue, *result, method);
530 
531     Label ihcNotUndefined(env);
532     Branch(TaggedIsUndefined(*ihc), &exit, &ihcNotUndefined);
533     Bind(&ihcNotUndefined);
534     {
535         CallRuntime(glue, RTSTUB_ID(AOTEnableProtoChangeMarker), { *result, *ihc});
536         Jump(&exit);
537     }
538     Bind(&exit);
539     auto ret = *result;
540     env->SubCfgExit();
541     return ret;
542 }
543 
NewJSFunction(GateRef glue,GateRef jsFunc,GateRef index,GateRef length,GateRef lexEnv,Variable * result,Label * success,Label * failed)544 void NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef jsFunc, GateRef index, GateRef length, GateRef lexEnv,
545                                          Variable *result, Label *success, Label *failed)
546 {
547     auto env = GetEnvironment();
548     Label hasException(env);
549     Label notException(env);
550     GateRef constPool = GetConstPoolFromFunction(jsFunc);
551     GateRef module = GetModuleFromFunction(jsFunc);
552     result->WriteVariable(NewJSFunction(glue, constPool, module, index));
553     Branch(HasPendingException(glue), &hasException, &notException);
554     Bind(&hasException);
555     {
556         Jump(failed);
557     }
558     Bind(&notException);
559     {
560         SetLengthToFunction(glue_, result->ReadVariable(), length);
561         SetLexicalEnvToFunction(glue_, result->ReadVariable(), lexEnv);
562         SetHomeObjectToFunction(glue_, result->ReadVariable(), GetHomeObjectFromFunction(jsFunc));
563         Jump(success);
564     }
565 }
566 
InitializeJSFunction(GateRef glue,GateRef func,GateRef kind)567 void NewObjectStubBuilder::InitializeJSFunction(GateRef glue, GateRef func, GateRef kind)
568 {
569     auto env = GetEnvironment();
570     Label entry(env);
571     env->SubCfgEntry(&entry);
572     Label exit(env);
573     Label hasProto(env);
574     Label notProto(env);
575     Label hasAccess(env);
576     Label isBase(env);
577     Label notBase(env);
578     Label isGenerator(env);
579     Label notClassConstructor(env);
580 
581     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
582     GateRef hclass = LoadHClass(func);
583 
584     SetLexicalEnvToFunction(glue, func, Undefined());
585     SetHomeObjectToFunction(glue, func, Undefined());
586     SetProtoOrHClassToFunction(glue, func, Hole());
587     SetWorkNodePointerToFunction(glue, func, NullPtr());
588     SetMethodToFunction(glue, func, Undefined());
589 
590     Branch(HasPrototype(kind), &hasProto, &notProto);
591     Bind(&hasProto);
592     {
593         auto funcprotoAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
594                                                         ConstantIndex::FUNCTION_PROTOTYPE_ACCESSOR);
595         Branch(IsBaseKind(kind), &isBase, &notBase);
596         Bind(&isBase);
597         {
598             SetPropertyInlinedProps(glue, func, hclass, funcprotoAccessor,
599                                     Int32(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX));
600             auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
601                                                        ConstantIndex::FUNCTION_NAME_ACCESSOR);
602             SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
603                                     Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX));
604             funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
605                                                   ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
606             SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
607                                     Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX));
608             Branch(IsGeneratorKind(kind), &isGenerator, &exit);
609             Bind(&isGenerator);
610             {
611                 thisObj = CallRuntime(glue, RTSTUB_ID(InitializeGeneratorFunction), {kind});
612                 SetProtoOrHClassToFunction(glue, func, *thisObj);
613                 Jump(&exit);
614             }
615         }
616         Bind(&notBase);
617         {
618             Branch(IsClassConstructorKind(kind), &exit, &notClassConstructor);
619             Bind(&notClassConstructor);
620             {
621                 CallRuntime(glue, RTSTUB_ID(FunctionDefineOwnProperty), {func, funcprotoAccessor, kind});
622                 Jump(&exit);
623             }
624         }
625     }
626     Bind(&notProto);
627     {
628         Branch(HasAccessor(kind), &hasAccess, &exit);
629         Bind(&hasAccess);
630         {
631             auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
632                                                        ConstantIndex::FUNCTION_NAME_ACCESSOR);
633             SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX));
634             funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
635                                                   ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
636             SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX));
637             Jump(&exit);
638         }
639     }
640     Bind(&exit);
641     env->SubCfgExit();
642     return;
643 }
644 
EnumerateObjectProperties(GateRef glue,GateRef obj)645 GateRef NewObjectStubBuilder::EnumerateObjectProperties(GateRef glue, GateRef obj)
646 {
647     auto env = GetEnvironment();
648     Label entry(env);
649     env->SubCfgEntry(&entry);
650     Label exit(env);
651     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
652     DEFVARIABLE(object, VariableType::JS_ANY(), Undefined());
653 
654     Label isString(env);
655     Label isNotString(env);
656     Label afterObjectTransform(env);
657     Label slowpath(env);
658     Label empty(env);
659     Label tryGetEnumCache(env);
660     Label cacheHit(env);
661     Branch(TaggedIsString(obj), &isString, &isNotString);
662     Bind(&isString);
663     {
664         object = CallRuntime(glue, RTSTUB_ID(PrimitiveStringCreate), { obj });;
665         Jump(&afterObjectTransform);
666     }
667     Bind(&isNotString);
668     {
669         object = ToPrototypeOrObj(glue, obj);
670         Jump(&afterObjectTransform);
671     }
672     Bind(&afterObjectTransform);
673     Branch(TaggedIsUndefinedOrNull(*object), &empty, &tryGetEnumCache);
674     Bind(&tryGetEnumCache);
675     GateRef enumCache = TryGetEnumCache(glue, *object);
676     Branch(TaggedIsUndefined(enumCache), &slowpath, &cacheHit);
677     Bind(&cacheHit);
678     {
679         GateRef hclass = LoadHClass(*object);
680         result = NewJSForinIterator(glue, *object, enumCache, hclass);
681         Jump(&exit);
682     }
683     Bind(&empty);
684     {
685         GateRef emptyArray = GetEmptyArray(glue);
686         result = NewJSForinIterator(glue, Undefined(), emptyArray, Undefined());
687         Jump(&exit);
688     }
689 
690     Bind(&slowpath);
691     {
692         result = CallRuntime(glue, RTSTUB_ID(GetPropIteratorSlowpath), { *object });
693         Jump(&exit);
694     }
695     Bind(&exit);
696     auto ret = *result;
697     env->SubCfgExit();
698     return ret;
699 }
700 
NewArgumentsList(Variable * result,Label * exit,GateRef sp,GateRef startIdx,GateRef numArgs)701 void NewObjectStubBuilder::NewArgumentsList(Variable *result, Label *exit,
702     GateRef sp, GateRef startIdx, GateRef numArgs)
703 {
704     auto env = GetEnvironment();
705     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
706     Label setHClass(env);
707     size_ = ComputeTaggedArraySize(ZExtInt32ToPtr(numArgs));
708     Label afterAllocate(env);
709     AllocateInYoung(result, &afterAllocate);
710     Bind(&afterAllocate);
711     Branch(TaggedIsException(result->ReadVariable()), exit, &setHClass);
712     Bind(&setHClass);
713     GateRef arrayClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
714                                                 ConstantIndex::ARRAY_CLASS_INDEX);
715     StoreHClass(glue_, result->ReadVariable(), arrayClass);
716     Store(VariableType::INT32(), glue_, result->ReadVariable(), IntPtr(TaggedArray::LENGTH_OFFSET), numArgs);
717     // skip InitializeTaggedArrayWithSpeicalValue due to immediate setting arguments
718     Label setArgumentsBegin(env);
719     Label setArgumentsAgain(env);
720     Label setArgumentsEnd(env);
721     Branch(Int32UnsignedLessThan(*i, numArgs), &setArgumentsBegin, &setArgumentsEnd);
722     LoopBegin(&setArgumentsBegin);
723     GateRef idx = ZExtInt32ToPtr(Int32Add(startIdx, *i));
724     GateRef argument = Load(VariableType::JS_ANY(), sp, PtrMul(IntPtr(sizeof(JSTaggedType)), idx));
725     SetValueToTaggedArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), *i, argument);
726     i = Int32Add(*i, Int32(1));
727     Branch(Int32UnsignedLessThan(*i, numArgs), &setArgumentsAgain, &setArgumentsEnd);
728     Bind(&setArgumentsAgain);
729     LoopEnd(&setArgumentsBegin);
730     Bind(&setArgumentsEnd);
731     Jump(exit);
732 }
733 
NewArgumentsObj(Variable * result,Label * exit,GateRef argumentsList,GateRef numArgs)734 void NewObjectStubBuilder::NewArgumentsObj(Variable *result, Label *exit,
735     GateRef argumentsList, GateRef numArgs)
736 {
737     auto env = GetEnvironment();
738 
739     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
740     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue_, glueGlobalEnvOffset);
741     GateRef argumentsClass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
742                                                GlobalEnv::ARGUMENTS_CLASS);
743     Label afterNewObject(env);
744     NewJSObject(result, &afterNewObject, argumentsClass);
745     Bind(&afterNewObject);
746     Label setArgumentsObjProperties(env);
747     Branch(TaggedIsException(result->ReadVariable()), exit, &setArgumentsObjProperties);
748     Bind(&setArgumentsObjProperties);
749     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, IntToTaggedInt(numArgs),
750                             Int32(JSArguments::LENGTH_INLINE_PROPERTY_INDEX));
751     SetElementsArray(VariableType::JS_ANY(), glue_, result->ReadVariable(), argumentsList);
752     GateRef arrayProtoValuesFunction = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
753                                                          GlobalEnv::ARRAY_PROTO_VALUES_FUNCTION_INDEX);
754     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, arrayProtoValuesFunction,
755                             Int32(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX));
756     GateRef accessorCaller = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
757                                                GlobalEnv::ARGUMENTS_CALLER_ACCESSOR);
758     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCaller,
759                             Int32(JSArguments::CALLER_INLINE_PROPERTY_INDEX));
760     GateRef accessorCallee = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
761                                                GlobalEnv::ARGUMENTS_CALLEE_ACCESSOR);
762     SetPropertyInlinedProps(glue_, result->ReadVariable(), argumentsClass, accessorCallee,
763                             Int32(JSArguments::CALLEE_INLINE_PROPERTY_INDEX));
764     Jump(exit);
765 }
766 
NewJSArrayLiteral(Variable * result,Label * exit,RegionSpaceFlag spaceType,GateRef obj,GateRef hclass,GateRef trackInfo,bool isEmptyArray)767 void NewObjectStubBuilder::NewJSArrayLiteral(Variable *result, Label *exit, RegionSpaceFlag spaceType, GateRef obj,
768                                              GateRef hclass, GateRef trackInfo, bool isEmptyArray)
769 {
770     auto env = GetEnvironment();
771     Label initializeArray(env);
772     Label afterInitialize(env);
773     HeapAlloc(result, &initializeArray, spaceType);
774     Bind(&initializeArray);
775     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(0), hclass);
776     InitializeWithSpeicalValue(&afterInitialize, result->ReadVariable(), Undefined(), Int32(JSArray::SIZE),
777                                TruncInt64ToInt32(size_));
778     Bind(&afterInitialize);
779     GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET);
780     Store(VariableType::INT64(), glue_, result->ReadVariable(), hashOffset, Int64(JSTaggedValue(0).GetRawData()));
781 
782     GateRef propertiesOffset = IntPtr(JSObject::PROPERTIES_OFFSET);
783     GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
784     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
785     GateRef trackInfoOffset = IntPtr(JSArray::TRACK_INFO_OFFSET);
786     if (isEmptyArray) {
787         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, obj);
788         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, obj);
789         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, Int32(0));
790     } else {
791         auto newProperties = Load(VariableType::JS_POINTER(), obj, propertiesOffset);
792         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), propertiesOffset, newProperties);
793 
794         auto newElements = Load(VariableType::JS_POINTER(), obj, elementsOffset);
795         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), elementsOffset, newElements);
796 
797         GateRef arrayLength = Load(VariableType::INT32(), obj, lengthOffset);
798         Store(VariableType::INT32(), glue_, result->ReadVariable(), lengthOffset, arrayLength);
799     }
800     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), trackInfoOffset, trackInfo);
801 
802     auto accessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
803     SetPropertyInlinedProps(glue_, result->ReadVariable(), hclass, accessor,
804         Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_POINTER());
805     Jump(exit);
806 }
807 
HeapAlloc(Variable * result,Label * exit,RegionSpaceFlag spaceType)808 void NewObjectStubBuilder::HeapAlloc(Variable *result, Label *exit, RegionSpaceFlag spaceType)
809 {
810     switch (spaceType) {
811         case RegionSpaceFlag::IN_YOUNG_SPACE:
812             AllocateInYoung(result, exit);
813             break;
814         default:
815             break;
816     }
817 }
818 
AllocateInYoung(Variable * result,Label * exit)819 void NewObjectStubBuilder::AllocateInYoung(Variable *result, Label *exit)
820 {
821     auto env = GetEnvironment();
822     Label success(env);
823     Label callRuntime(env);
824     Label next(env);
825 
826 #ifdef ARK_ASAN_ON
827     DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
828     Jump(&callRuntime);
829 #else
830 #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
831     auto isStartHeapSamplingOffset = JSThread::GlueData::GetIsStartHeapSamplingOffset(env->Is32Bit());
832     auto isStartHeapSampling = Load(VariableType::JS_ANY(), glue_, IntPtr(isStartHeapSamplingOffset));
833     Branch(TaggedIsTrue(isStartHeapSampling), &callRuntime, &next);
834     Bind(&next);
835 #endif
836     auto topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(env->Is32Bit());
837     auto endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(env->Is32Bit());
838     auto topAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(topOffset));
839     auto endAddress = Load(VariableType::NATIVE_POINTER(), glue_, IntPtr(endOffset));
840     auto top = Load(VariableType::JS_POINTER(), topAddress, IntPtr(0));
841     auto end = Load(VariableType::JS_POINTER(), endAddress, IntPtr(0));
842     DEFVARIABLE(ret, VariableType::JS_ANY(), Undefined());
843     auto newTop = PtrAdd(top, size_);
844     Branch(IntPtrGreaterThan(newTop, end), &callRuntime, &success);
845     Bind(&success);
846     {
847         Store(VariableType::NATIVE_POINTER(), glue_, topAddress, IntPtr(0), newTop);
848         if (env->Is32Bit()) {
849             top = ZExtInt32ToInt64(top);
850         }
851         ret = top;
852         result->WriteVariable(*ret);
853         Jump(exit);
854     }
855 #endif
856     Bind(&callRuntime);
857     {
858         ret = CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), {
859             IntToTaggedInt(size_) });
860         result->WriteVariable(*ret);
861         Jump(exit);
862     }
863 }
864 
NewTrackInfo(GateRef glue,GateRef cachedHClass,GateRef cachedFunc,RegionSpaceFlag spaceFlag,GateRef arraySize)865 GateRef NewObjectStubBuilder::NewTrackInfo(GateRef glue, GateRef cachedHClass, GateRef cachedFunc,
866                                            RegionSpaceFlag spaceFlag, GateRef arraySize)
867 {
868     auto env = GetEnvironment();
869     Label entry(env);
870     env->SubCfgEntry(&entry);
871 
872     Label initialize(env);
873     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
874     auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::TRACK_INFO_CLASS_INDEX);
875     GateRef size = GetObjectSizeFromHClass(hclass);
876     SetParameters(glue, size);
877     HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE);
878     Bind(&initialize);
879     Store(VariableType::JS_POINTER(), glue_, *result, IntPtr(0), hclass);
880     GateRef cachedHClassOffset = IntPtr(TrackInfo::CACHED_HCLASS_OFFSET);
881     Store(VariableType::JS_POINTER(), glue, *result, cachedHClassOffset, cachedHClass);
882     GateRef cachedFuncOffset = IntPtr(TrackInfo::CACHED_FUNC_OFFSET);
883     GateRef weakCachedFunc = env->GetBuilder()->CreateWeakRef(cachedFunc);
884     Store(VariableType::JS_POINTER(), glue, *result, cachedFuncOffset, weakCachedFunc);
885     GateRef arrayLengthOffset = IntPtr(TrackInfo::ARRAY_LENGTH_OFFSET);
886     Store(VariableType::INT32(), glue, *result, arrayLengthOffset, arraySize);
887     SetSpaceFlagToTrackInfo(glue, *result, Int32(spaceFlag));
888     auto elementsKind = GetElementsKindFromHClass(cachedHClass);
889     SetElementsKindToTrackInfo(glue, *result, elementsKind);
890     auto ret = *result;
891     env->SubCfgExit();
892     return ret;
893 }
894 
InitializeWithSpeicalValue(Label * exit,GateRef object,GateRef value,GateRef start,GateRef end)895 void NewObjectStubBuilder::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef value, GateRef start,
896                                                       GateRef end)
897 {
898     auto env = GetEnvironment();
899     Label begin(env);
900     Label storeValue(env);
901     Label endLoop(env);
902 
903     DEFVARIABLE(startOffset, VariableType::INT32(), start);
904     Jump(&begin);
905     LoopBegin(&begin);
906     {
907         Branch(Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
908         Bind(&storeValue);
909         {
910             Store(VariableType::INT64(), glue_, object, ZExtInt32ToPtr(*startOffset), value);
911             startOffset = Int32Add(*startOffset, Int32(JSTaggedValue::TaggedTypeSize()));
912             Jump(&endLoop);
913         }
914         Bind(&endLoop);
915         LoopEnd(&begin);
916     }
917 }
918 
InitializeTaggedArrayWithSpeicalValue(Label * exit,GateRef array,GateRef value,GateRef start,GateRef length)919 void NewObjectStubBuilder::InitializeTaggedArrayWithSpeicalValue(Label *exit,
920     GateRef array, GateRef value, GateRef start, GateRef length)
921 {
922     Store(VariableType::INT32(), glue_, array, IntPtr(TaggedArray::LENGTH_OFFSET), length);
923     auto offset = Int32Mul(start, Int32(JSTaggedValue::TaggedTypeSize()));
924     auto dataOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
925     offset = Int32Mul(length, Int32(JSTaggedValue::TaggedTypeSize()));
926     auto endOffset = Int32Add(offset, Int32(TaggedArray::DATA_OFFSET));
927     InitializeWithSpeicalValue(exit, array, value, dataOffset, endOffset);
928 }
929 
AllocLineStringObject(Variable * result,Label * exit,GateRef length,bool compressed)930 void NewObjectStubBuilder::AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed)
931 {
932     auto env = GetEnvironment();
933     if (compressed) {
934         size_ = AlignUp(ComputeSizeUtf8(ZExtInt32ToPtr(length)),
935             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
936     } else {
937         size_ = AlignUp(ComputeSizeUtf16(ZExtInt32ToPtr(length)),
938             IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
939     }
940     Label afterAllocate(env);
941     AllocateInYoung(result, &afterAllocate);
942 
943     Bind(&afterAllocate);
944     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
945                                                  ConstantIndex::LINE_STRING_CLASS_INDEX);
946     StoreHClass(glue_, result->ReadVariable(), stringClass);
947     SetLength(glue_, result->ReadVariable(), length, compressed);
948     SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
949     Jump(exit);
950 }
951 
AllocSlicedStringObject(Variable * result,Label * exit,GateRef from,GateRef length,FlatStringStubBuilder * flatString)952 void NewObjectStubBuilder::AllocSlicedStringObject(Variable *result, Label *exit, GateRef from, GateRef length,
953     FlatStringStubBuilder *flatString)
954 {
955     auto env = GetEnvironment();
956 
957     size_ = AlignUp(IntPtr(SlicedString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
958     Label afterAllocate(env);
959     AllocateInYoung(result, &afterAllocate);
960 
961     Bind(&afterAllocate);
962     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
963                                                  ConstantIndex::SLICED_STRING_CLASS_INDEX);
964     StoreHClass(glue_, result->ReadVariable(), stringClass);
965     GateRef mixLength = Load(VariableType::INT32(), flatString->GetFlatString(), IntPtr(EcmaString::MIX_LENGTH_OFFSET));
966     GateRef isCompressed = Int32And(Int32(EcmaString::STRING_COMPRESSED_BIT), mixLength);
967     SetLength(glue_, result->ReadVariable(), length, isCompressed);
968     SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
969     BuiltinsStringStubBuilder builtinsStringStubBuilder(this);
970     builtinsStringStubBuilder.StoreParent(glue_, result->ReadVariable(), flatString->GetFlatString());
971     builtinsStringStubBuilder.StoreStartIndex(glue_, result->ReadVariable(),
972         Int32Add(from, flatString->GetStartIndex()));
973     builtinsStringStubBuilder.StoreHasBackingStore(glue_, result->ReadVariable(), Int32(0));
974     Jump(exit);
975 }
976 
AllocTreeStringObject(Variable * result,Label * exit,GateRef first,GateRef second,GateRef length,bool compressed)977 void NewObjectStubBuilder::AllocTreeStringObject(Variable *result, Label *exit, GateRef first, GateRef second,
978     GateRef length, bool compressed)
979 {
980     auto env = GetEnvironment();
981 
982     size_ = AlignUp(IntPtr(TreeEcmaString::SIZE), IntPtr(static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)));
983     Label afterAllocate(env);
984     AllocateInYoung(result, &afterAllocate);
985 
986     Bind(&afterAllocate);
987     GateRef stringClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_,
988                                                  ConstantIndex::TREE_STRING_CLASS_INDEX);
989     StoreHClass(glue_, result->ReadVariable(), stringClass);
990     SetLength(glue_, result->ReadVariable(), length, compressed);
991     SetRawHashcode(glue_, result->ReadVariable(), Int32(0), False());
992     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::FIRST_OFFSET), first);
993     Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeEcmaString::SECOND_OFFSET), second);
994     Jump(exit);
995 }
996 
FastNewThisObject(GateRef glue,GateRef ctor)997 GateRef NewObjectStubBuilder::FastNewThisObject(GateRef glue, GateRef ctor)
998 {
999     auto env = GetEnvironment();
1000     Label entry(env);
1001     env->SubCfgEntry(&entry);
1002     Label exit(env);
1003     Label isHeapObject(env);
1004     Label callRuntime(env);
1005     Label checkJSObject(env);
1006     Label newObject(env);
1007 
1008     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1009     auto protoOrHclass = Load(VariableType::JS_ANY(), ctor,
1010         IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1011     Branch(TaggedIsHeapObject(protoOrHclass), &isHeapObject, &callRuntime);
1012     Bind(&isHeapObject);
1013     Branch(IsJSHClass(protoOrHclass), &checkJSObject, &callRuntime);
1014     Bind(&checkJSObject);
1015     auto objectType = GetObjectType(protoOrHclass);
1016     Branch(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))),
1017         &newObject, &callRuntime);
1018     Bind(&newObject);
1019     {
1020         SetParameters(glue, 0);
1021         NewJSObject(&thisObj, &exit, protoOrHclass);
1022     }
1023     Bind(&callRuntime);
1024     {
1025         thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor, Undefined()});
1026         Jump(&exit);
1027     }
1028     Bind(&exit);
1029     auto ret = *thisObj;
1030     env->SubCfgExit();
1031     return ret;
1032 }
1033 
FastSuperAllocateThis(GateRef glue,GateRef superCtor,GateRef newTarget)1034 GateRef NewObjectStubBuilder::FastSuperAllocateThis(GateRef glue, GateRef superCtor, GateRef newTarget)
1035 {
1036     auto env = GetEnvironment();
1037     Label entry(env);
1038     env->SubCfgEntry(&entry);
1039     Label exit(env);
1040     Label newTargetIsBase(env);
1041     Label newTargetNotBase(env);
1042     Label checkHeapObject(env);
1043     Label isHeapObject(env);
1044     Label checkJSObject(env);
1045     Label callRuntime(env);
1046     Label newObject(env);
1047 
1048     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1049     DEFVARIABLE(protoOrHclass, VariableType::JS_ANY(), Undefined());
1050     Branch(IsBase(newTarget), &newTargetIsBase, &newTargetNotBase);
1051     Bind(&newTargetIsBase);
1052     {
1053         protoOrHclass = Load(VariableType::JS_ANY(), superCtor,
1054             IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1055         Jump(&checkHeapObject);
1056     }
1057     Bind(&newTargetNotBase);
1058     {
1059         protoOrHclass = Load(VariableType::JS_ANY(), newTarget,
1060             IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1061         Jump(&checkHeapObject);
1062     }
1063     Bind(&checkHeapObject);
1064     Branch(TaggedIsHeapObject(*protoOrHclass), &isHeapObject, &callRuntime);
1065     Bind(&isHeapObject);
1066     Branch(IsJSHClass(*protoOrHclass), &checkJSObject, &callRuntime);
1067     Bind(&checkJSObject);
1068     auto objectType = GetObjectType(*protoOrHclass);
1069     Branch(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT))),
1070         &newObject, &callRuntime);
1071     Bind(&newObject);
1072     {
1073         SetParameters(glue, 0);
1074         NewJSObject(&thisObj, &exit, *protoOrHclass);
1075     }
1076     Bind(&callRuntime);
1077     {
1078         thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {superCtor, newTarget});
1079         Jump(&exit);
1080     }
1081     Bind(&exit);
1082     auto ret = *thisObj;
1083     env->SubCfgExit();
1084     return ret;
1085 }
1086 
NewThisObjectChecked(GateRef glue,GateRef ctor)1087 GateRef NewObjectStubBuilder::NewThisObjectChecked(GateRef glue, GateRef ctor)
1088 {
1089     auto env = GetEnvironment();
1090     Label entry(env);
1091     env->SubCfgEntry(&entry);
1092     Label exit(env);
1093 
1094     Label ctorIsHeapObject(env);
1095     Label ctorIsJSFunction(env);
1096     Label fastPath(env);
1097     Label slowPath(env);
1098     Label ctorIsBase(env);
1099 
1100     DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
1101 
1102     Branch(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath);
1103     Bind(&ctorIsHeapObject);
1104     Branch(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath);
1105     Bind(&ctorIsJSFunction);
1106     Branch(IsConstructor(ctor), &fastPath, &slowPath);
1107     Bind(&fastPath);
1108     {
1109         Branch(IsBase(ctor), &ctorIsBase, &exit);
1110         Bind(&ctorIsBase);
1111         {
1112             thisObj = FastNewThisObject(glue, ctor);
1113             Jump(&exit);
1114         }
1115     }
1116     Bind(&slowPath);
1117     {
1118         thisObj = Hole();
1119         Jump(&exit);
1120     }
1121     Bind(&exit);
1122     auto ret = *thisObj;
1123     env->SubCfgExit();
1124     return ret;
1125 }
1126 
LoadTrackInfo(GateRef glue,GateRef jsFunc,GateRef pc,GateRef profileTypeInfo,GateRef slotId,GateRef arrayLiteral,ProfileOperation callback)1127 GateRef NewObjectStubBuilder::LoadTrackInfo(GateRef glue, GateRef jsFunc, GateRef pc, GateRef profileTypeInfo,
1128     GateRef slotId, GateRef arrayLiteral, ProfileOperation callback)
1129 {
1130     auto env = GetEnvironment();
1131     Label entry(env);
1132     env->SubCfgEntry(&entry);
1133     Label exit(env);
1134     DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
1135 
1136     Label uninitialized(env);
1137     Label fastpath(env);
1138     GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
1139     Branch(TaggedIsHeapObject(slotValue), &fastpath, &uninitialized);
1140     Bind(&fastpath);
1141     {
1142         ret = slotValue;
1143         Jump(&exit);
1144     }
1145     Bind(&uninitialized);
1146     {
1147         auto hclass = LoadArrayHClassSlowPath(glue, jsFunc, pc, arrayLiteral, callback);
1148         // emptyarray
1149         if (arrayLiteral == Circuit::NullGate()) {
1150             ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, Int32(0));
1151         } else {
1152             GateRef arrayLength = GetArrayLength(arrayLiteral);
1153             ret = NewTrackInfo(glue, hclass, jsFunc, RegionSpaceFlag::IN_YOUNG_SPACE, arrayLength);
1154         }
1155 
1156         SetValueToTaggedArray(VariableType::JS_POINTER(), glue, profileTypeInfo, slotId, *ret);
1157         callback.TryPreDump();
1158         Jump(&exit);
1159     }
1160     Bind(&exit);
1161     auto result = *ret;
1162     env->SubCfgExit();
1163     return result;
1164 }
1165 
LoadArrayHClassSlowPath(GateRef glue,GateRef jsFunc,GateRef pc,GateRef arrayLiteral,ProfileOperation callback)1166 GateRef NewObjectStubBuilder::LoadArrayHClassSlowPath(
1167     GateRef glue, GateRef jsFunc, GateRef pc, GateRef arrayLiteral, ProfileOperation callback)
1168 {
1169     auto env = GetEnvironment();
1170     Label entry(env);
1171     env->SubCfgEntry(&entry);
1172     Label exit(env);
1173     Label originLoad(env);
1174 
1175     DEFVARIABLE(ret, VariableType::JS_POINTER(), Undefined());
1176 
1177     auto hcIndexInfos = LoadHCIndexInfosFromConstPool(jsFunc);
1178     auto indexInfosLength = GetLengthOfTaggedArray(hcIndexInfos);
1179     Label aotLoad(env);
1180     Branch(Int32Equal(indexInfosLength, Int32(0)), &originLoad, &aotLoad);
1181     Bind(&aotLoad);
1182     {
1183         auto pfAddr = LoadPfHeaderFromConstPool(jsFunc);
1184         GateRef traceId = TruncPtrToInt32(PtrSub(pc, pfAddr));
1185         GateRef hcIndex = LoadHCIndexFromConstPool(hcIndexInfos, indexInfosLength, traceId, &originLoad);
1186         GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
1187             IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit())));
1188         GateRef offset = Int32Mul(Int32(sizeof(JSTaggedValue)), hcIndex);
1189         ret = Load(VariableType::JS_POINTER(), gConstAddr, offset);
1190         Jump(&exit);
1191     }
1192     Bind(&originLoad);
1193     {
1194         // emptyarray
1195         if (arrayLiteral == Circuit::NullGate()) {
1196             if (callback.IsEmpty()) {
1197                 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1198                 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1199                 auto arrayFunc =
1200                     GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
1201                 ret = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1202             } else {
1203                 ret =
1204                     GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::ELEMENT_NONE_HCLASS_INDEX);
1205             }
1206         } else {
1207             ret = LoadHClass(arrayLiteral);
1208         }
1209         Jump(&exit);
1210     }
1211     Bind(&exit);
1212     auto result = *ret;
1213     env->SubCfgExit();
1214     return result;
1215 }
1216 
CreateEmptyArrayCommon(GateRef glue,GateRef hclass,GateRef trackInfo)1217 GateRef NewObjectStubBuilder::CreateEmptyArrayCommon(GateRef glue, GateRef hclass, GateRef trackInfo)
1218 {
1219     auto env = GetEnvironment();
1220     Label entry(env);
1221     env->SubCfgEntry(&entry);
1222     Label exit(env);
1223 
1224     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1225 
1226     GateRef size = GetObjectSizeFromHClass(hclass);
1227     GateRef emptyArray = GetGlobalConstantValue(
1228         VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
1229     SetParameters(glue, size);
1230     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, emptyArray, hclass, trackInfo, true);
1231     Bind(&exit);
1232     GateRef ret = *result;
1233     env->SubCfgExit();
1234     return ret;
1235 }
1236 
CreateEmptyObject(GateRef glue)1237 GateRef NewObjectStubBuilder::CreateEmptyObject(GateRef glue)
1238 {
1239     auto env = GetEnvironment();
1240     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1241     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1242     GateRef objectFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX);
1243     GateRef hclass = Load(VariableType::JS_POINTER(), objectFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1244     return NewJSObject(glue, hclass);
1245 }
1246 
CreateEmptyArray(GateRef glue)1247 GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue)
1248 {
1249     auto env = GetEnvironment();
1250     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
1251     GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1252     GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1253     GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
1254     GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1255     return CreateEmptyArrayCommon(glue, hclass, *trackInfo);
1256 }
1257 
CreateEmptyArray(GateRef glue,GateRef jsFunc,GateRef pc,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)1258 GateRef NewObjectStubBuilder::CreateEmptyArray(
1259     GateRef glue, GateRef jsFunc, GateRef pc, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
1260 {
1261     auto env = GetEnvironment();
1262     Label entry(env);
1263     env->SubCfgEntry(&entry);
1264 
1265     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
1266     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
1267     Label slowpath(env);
1268     Label mayFastpath(env);
1269     Label createArray(env);
1270     Branch(TaggedIsUndefined(profileTypeInfo), &slowpath, &mayFastpath);
1271     Bind(&mayFastpath);
1272     {
1273         trackInfo = LoadTrackInfo(glue, jsFunc, pc, profileTypeInfo, slotId, Circuit::NullGate(), callback);
1274         hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
1275         trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
1276         Jump(&createArray);
1277     }
1278     Bind(&slowpath);
1279     {
1280         hclass = LoadArrayHClassSlowPath(glue, jsFunc, pc, Circuit::NullGate(), callback);
1281         Jump(&createArray);
1282     }
1283     Bind(&createArray);
1284     GateRef result = CreateEmptyArrayCommon(glue, *hclass, *trackInfo);
1285     env->SubCfgExit();
1286     return result;
1287 }
1288 
CreateArrayWithBuffer(GateRef glue,GateRef index,GateRef jsFunc,GateRef pc,GateRef profileTypeInfo,GateRef slotId,ProfileOperation callback)1289 GateRef NewObjectStubBuilder::CreateArrayWithBuffer(GateRef glue,
1290     GateRef index, GateRef jsFunc, GateRef pc, GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
1291 {
1292     auto env = GetEnvironment();
1293     Label entry(env);
1294     env->SubCfgEntry(&entry);
1295     Label exit(env);
1296 
1297     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1298     DEFVARIABLE(trackInfo, VariableType::JS_ANY(), Undefined());
1299     DEFVARIABLE(hclass, VariableType::JS_ANY(), Undefined());
1300 
1301     GateRef method = GetMethodFromFunction(jsFunc);
1302     GateRef constPool = Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
1303     GateRef module = GetModuleFromFunction(jsFunc);
1304 
1305     auto obj = GetArrayLiteralFromConstPool(glue, constPool, index, module);
1306 
1307     Label slowpath(env);
1308     Label mayFastpath(env);
1309     Label createArray(env);
1310     Branch(TaggedIsUndefined(profileTypeInfo), &slowpath, &mayFastpath);
1311     Bind(&mayFastpath);
1312     {
1313         trackInfo = LoadTrackInfo(glue, jsFunc, pc, profileTypeInfo, slotId, obj, callback);
1314         hclass = Load(VariableType::JS_ANY(), *trackInfo, IntPtr(TrackInfo::CACHED_HCLASS_OFFSET));
1315         trackInfo = env->GetBuilder()->CreateWeakRef(*trackInfo);
1316         Jump(&createArray);
1317     }
1318     Bind(&slowpath);
1319     {
1320         hclass = LoadArrayHClassSlowPath(glue, jsFunc, pc, obj, callback);
1321         Jump(&createArray);
1322     }
1323     Bind(&createArray);
1324     GateRef size = GetObjectSizeFromHClass(*hclass);
1325 
1326     SetParameters(glue, size);
1327     NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, obj, *hclass, *trackInfo, false);
1328 
1329     Bind(&exit);
1330     auto ret = *result;
1331     env->SubCfgExit();
1332     return ret;
1333 }
1334 
1335 template <typename IteratorType, typename CollectionType>
CreateJSCollectionIterator(Variable * result,Label * exit,GateRef thisValue,GateRef kind)1336 void NewObjectStubBuilder::CreateJSCollectionIterator(
1337     Variable *result, Label *exit, GateRef thisValue, GateRef kind)
1338 {
1339     ASSERT_PRINT((std::is_same_v<IteratorType, JSSetIterator> || std::is_same_v<IteratorType, JSMapIterator>),
1340         "IteratorType must be JSSetIterator or JSMapIterator type");
1341     auto env = GetEnvironment();
1342     ConstantIndex iterClassIdx = static_cast<ConstantIndex>(0);
1343     int32_t iterOffset = 0;       // ITERATED_SET_OFFSET
1344     size_t linkedOffset = 0;      // LINKED_MAP_OFFSET
1345     if constexpr (std::is_same_v<IteratorType, JSSetIterator>) {
1346         iterClassIdx = ConstantIndex::JS_SET_ITERATOR_CLASS_INDEX;
1347         iterOffset = IteratorType::ITERATED_SET_OFFSET;
1348         linkedOffset = CollectionType::LINKED_SET_OFFSET;
1349         size_ = IntPtr(JSSetIterator::SIZE);
1350     } else {
1351         iterClassIdx = ConstantIndex::JS_MAP_ITERATOR_CLASS_INDEX;
1352         iterOffset = IteratorType::ITERATED_MAP_OFFSET;
1353         linkedOffset = CollectionType::LINKED_MAP_OFFSET;
1354         size_ = IntPtr(JSMapIterator::SIZE);
1355     }
1356     GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, iterClassIdx);
1357 
1358     Label afterAllocate(env);
1359     // Be careful. NO GC is allowed when initization is not complete.
1360     AllocateInYoung(result, &afterAllocate);
1361     Bind(&afterAllocate);
1362     Label noException(env);
1363     Branch(TaggedIsException(result->ReadVariable()), exit, &noException);
1364     Bind(&noException);
1365     {
1366         StoreHClass(glue_, result->ReadVariable(), iteratorHClass);
1367         SetHash(glue_, result->ReadVariable(), Int64(JSTaggedValue(0).GetRawData()));
1368         auto emptyArray = GetGlobalConstantValue(
1369             VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
1370         SetPropertiesArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
1371         SetElementsArray(VariableType::INT64(), glue_, result->ReadVariable(), emptyArray);
1372 
1373         // GetLinked
1374         GateRef linked = Load(VariableType::JS_ANY(), thisValue, IntPtr(linkedOffset));
1375         // SetIterated
1376         GateRef iteratorOffset = IntPtr(iterOffset);
1377         Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), iteratorOffset, linked);
1378 
1379         // SetIteratorNextIndex
1380         GateRef nextIndexOffset = IntPtr(IteratorType::NEXT_INDEX_OFFSET);
1381         Store(VariableType::INT32(), glue_, result->ReadVariable(), nextIndexOffset, Int32(0));
1382 
1383         // SetIterationKind
1384         GateRef kindBitfieldOffset = IntPtr(IteratorType::BIT_FIELD_OFFSET);
1385         Store(VariableType::INT32(), glue_, result->ReadVariable(), kindBitfieldOffset, kind);
1386         Jump(exit);
1387     }
1388 }
1389 
1390 template void NewObjectStubBuilder::CreateJSCollectionIterator<JSSetIterator, JSSet>(
1391     Variable *result, Label *exit, GateRef set, GateRef kind);
1392 template void NewObjectStubBuilder::CreateJSCollectionIterator<JSMapIterator, JSMap>(
1393     Variable *result, Label *exit, GateRef set, GateRef kind);
1394 
NewTaggedSubArray(GateRef glue,GateRef srcTypedArray,GateRef elementSize,GateRef newLength,GateRef beginIndex,GateRef arrayCls,GateRef buffer)1395 GateRef NewObjectStubBuilder::NewTaggedSubArray(GateRef glue, GateRef srcTypedArray,
1396     GateRef elementSize, GateRef newLength, GateRef beginIndex, GateRef arrayCls, GateRef buffer)
1397 {
1398     auto env = GetEnvironment();
1399     Label entry(env);
1400     env->SubCfgEntry(&entry);
1401     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
1402     GateRef constructorName = Load(VariableType::JS_POINTER(), srcTypedArray,
1403         IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET));
1404     GateRef srcByteOffset = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1405     GateRef contentType = Load(VariableType::INT32(), srcTypedArray, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET));
1406     GateRef beginByteOffset = Int32Add(srcByteOffset, Int32Mul(beginIndex, elementSize));
1407 
1408     GateRef obj = NewJSObject(glue, arrayCls);
1409     result = obj;
1410     GateRef newByteLength = Int32Mul(elementSize, newLength);
1411     Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET), buffer);
1412     Store(VariableType::JS_POINTER(), glue, obj, IntPtr(JSTypedArray::TYPED_ARRAY_NAME_OFFSET), constructorName);
1413     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET), newByteLength);
1414     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET), beginByteOffset);
1415     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET), newLength);
1416     Store(VariableType::INT32(), glue, obj, IntPtr(JSTypedArray::CONTENT_TYPE_OFFSET), contentType);
1417     auto ret = *result;
1418     env->SubCfgExit();
1419     return ret;
1420 }
1421 }  // namespace panda::ecmascript::kungfu
1422