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