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