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