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