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