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, ¬Overflow);
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(¬Overflow);
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, ¬Empty);
194 Bind(&isEmpty);
195 {
196 result = GetGlobalConstantValue(
197 VariableType::JS_POINTER(), glue_, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
198 Jump(&exit);
199 }
200 Bind(¬Empty);
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, ¬EmptyArray);
349 Bind(&emptyArray);
350 result = GetEmptyArray(glue);
351 Jump(&exit);
352 Bind(¬EmptyArray);
353 {
354 Label extendArray(env);
355 Label notExtendArray(env);
356 Branch(Int32GreaterThan(newLen, oldLen), &extendArray, ¬ExtendArray);
357 Bind(&extendArray);
358 {
359 result = ExtendArray(glue, elements, newLen);
360 Jump(&exit);
361 }
362 Bind(¬ExtendArray);
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, ¬Normal);
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(¬Normal);
457 {
458 Branch(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::ASYNC_FUNCTION))),
459 &isAsync, ¬Async);
460 Bind(&isAsync);
461 {
462 hclass = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ASYNC_FUNCTION_CLASS);
463 Jump(&exit);
464 }
465 Bind(¬Async);
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, ¬Exception);
554 Bind(&hasException);
555 {
556 Jump(failed);
557 }
558 Bind(¬Exception);
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, ¬Proto);
591 Bind(&hasProto);
592 {
593 auto funcprotoAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
594 ConstantIndex::FUNCTION_PROTOTYPE_ACCESSOR);
595 Branch(IsBaseKind(kind), &isBase, ¬Base);
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(¬Base);
617 {
618 Branch(IsClassConstructorKind(kind), &exit, ¬ClassConstructor);
619 Bind(¬ClassConstructor);
620 {
621 CallRuntime(glue, RTSTUB_ID(FunctionDefineOwnProperty), {func, funcprotoAccessor, kind});
622 Jump(&exit);
623 }
624 }
625 }
626 Bind(¬Proto);
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