1 /*
2 * Copyright (c) 2023 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/builtins/builtins_array_stub_builder.h"
17
18 #include "ecmascript/builtins/builtins_string.h"
19 #include "ecmascript/compiler/builtins/builtins_stubs.h"
20 #include "ecmascript/compiler/call_stub_builder.h"
21 #include "ecmascript/compiler/new_object_stub_builder.h"
22 #include "ecmascript/compiler/profiler_operation.h"
23 #include "ecmascript/compiler/rt_call_signature.h"
24 #include "ecmascript/runtime_call_id.h"
25 #include "ecmascript/js_iterator.h"
26 #include "ecmascript/compiler/access_object_stub_builder.h"
27 #include "ecmascript/base/array_helper.h"
28
29 namespace panda::ecmascript::kungfu {
30
ElementsKindHclassCompare(GateRef glue,GateRef arrayCls,Label * matchCls,Label * slowPath)31 void BuiltinsArrayStubBuilder::ElementsKindHclassCompare(GateRef glue, GateRef arrayCls,
32 Label *matchCls, Label *slowPath)
33 {
34 auto env = GetEnvironment();
35 Label isGeneric(env);
36 GateRef elementsKind = GetElementsKindFromHClass(arrayCls);
37 GateRef notGeneric = NotEqual(elementsKind, Int32(static_cast<uint32_t>(ElementsKind::GENERIC)));
38 BRANCH(notGeneric, matchCls, &isGeneric);
39 Bind(&isGeneric);
40 {
41 GateRef intialHClass = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
42 ConstantIndex::ELEMENT_HOLE_TAGGED_HCLASS_INDEX);
43 BRANCH(Equal(intialHClass, arrayCls), matchCls, slowPath);
44 }
45 }
46
With(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)47 void BuiltinsArrayStubBuilder::With(GateRef glue, GateRef thisValue, GateRef numArgs,
48 Variable *result, Label *exit, Label *slowPath)
49 {
50 auto env = GetEnvironment();
51 DEFVARIABLE(relativeIndex, VariableType::INT64(), Int64(0));
52 DEFVARIABLE(actualIndex, VariableType::INT64(), Int64(0));
53 Label isHeapObject(env);
54 Label isJsArray(env);
55 Label isStableArray(env);
56 Label defaultConstr(env);
57 Label notCOWArray(env);
58 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
59 Bind(&isHeapObject);
60 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
61 Bind(&isJsArray);
62 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
63 Bind(&defaultConstr);
64 BRANCH(IsStableJSArray(glue, thisValue), &isStableArray, slowPath);
65 Bind(&isStableArray);
66 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
67 Bind(¬COWArray);
68
69 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
70 GateRef index = GetCallArg0(numArgs);
71 Label taggedIsInt(env);
72 BRANCH(TaggedIsInt(index), &taggedIsInt, slowPath);
73 Bind(&taggedIsInt);
74 {
75 relativeIndex = GetInt64OfTInt(index);
76 DEFVARIABLE(value, VariableType::JS_ANY(), Hole());
77 Label twoArg(env);
78 Label ifOneArg(env);
79 Label getIndex(env);
80 // 2 : means there are two args
81 BRANCH(Int64Equal(numArgs, IntPtr(2)), &twoArg, &ifOneArg);
82 Bind(&twoArg);
83 {
84 value = GetCallArg1(numArgs);
85 Jump(&getIndex);
86 }
87 Bind(&ifOneArg);
88 {
89 // 1 : means there are only one arg
90 BRANCH(Int64Equal(numArgs, IntPtr(1)), &getIndex, slowPath);
91 }
92 Bind(&getIndex);
93 {
94 Label indexGreaterOrEqualZero(env);
95 Label indexLessZero(env);
96 Label next(env);
97 Label notOutOfRange(env);
98 BRANCH(Int64GreaterThanOrEqual(*relativeIndex, Int64(0)), &indexGreaterOrEqualZero, &indexLessZero);
99 Bind(&indexGreaterOrEqualZero);
100 {
101 actualIndex = *relativeIndex;
102 Jump(&next);
103 }
104 Bind(&indexLessZero);
105 {
106 actualIndex = Int64Add(thisLen, *relativeIndex);
107 Jump(&next);
108 }
109 Bind(&next);
110 {
111 BRANCH(BitOr(Int64GreaterThanOrEqual(*actualIndex, thisLen), Int64LessThan(*actualIndex, Int64(0))),
112 slowPath, ¬OutOfRange);
113 Bind(¬OutOfRange);
114 {
115 GateRef newArray = NewArray(glue, Int32(0));
116 GrowElementsCapacity(glue, newArray, TruncInt64ToInt32(thisLen));
117 DEFVARIABLE(k, VariableType::INT64(), Int64(0));
118 Label loopHead(env);
119 Label loopEnd(env);
120 Label loopExit(env);
121 Label loopNext(env);
122 Label replaceIndex(env);
123 Label notReplaceIndex(env);
124 Jump(&loopHead);
125 LoopBegin(&loopHead);
126 {
127 BRANCH(Int64LessThan(*k, thisLen), &loopNext, &loopExit);
128 Bind(&loopNext);
129 BRANCH(Int64Equal(*k, *actualIndex), &replaceIndex, ¬ReplaceIndex);
130 Bind(&replaceIndex);
131 {
132 SetValueWithElementsKind(glue, newArray, *value, *k, Boolean(true),
133 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
134 Jump(&loopEnd);
135 }
136 Bind(¬ReplaceIndex);
137 {
138 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *k);
139 Label eleIsHole(env);
140 Label eleNotHole(env);
141 BRANCH(TaggedIsHole(ele), &eleIsHole, &eleNotHole);
142 Bind(&eleIsHole);
143 {
144 SetValueWithElementsKind(glue, newArray, Undefined(), *k, Boolean(true),
145 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
146 Jump(&loopEnd);
147 }
148 Bind(&eleNotHole);
149 {
150 SetValueWithElementsKind(glue, newArray, ele, *k, Boolean(true),
151 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
152 Jump(&loopEnd);
153 }
154 }
155 }
156 Bind(&loopEnd);
157 k = Int64Add(*k, Int64(1));
158 LoopEnd(&loopHead);
159 Bind(&loopExit);
160 SetArrayLength(glue, newArray, thisLen);
161 result->WriteVariable(newArray);
162 Jump(exit);
163 }
164 }
165 }
166 }
167 }
168
Unshift(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)169 void BuiltinsArrayStubBuilder::Unshift(GateRef glue, GateRef thisValue, GateRef numArgs,
170 Variable *result, Label *exit, Label *slowPath)
171 {
172 auto env = GetEnvironment();
173 Label isHeapObject(env);
174 Label isJsArray(env);
175 Label isStableJsArray(env);
176 Label isGeneric(env);
177 Label notOverRange(env);
178 Label numNotEqualZero(env);
179 Label numLessThanOrEqualThree(env);
180 Label loopHead(env);
181 Label next(env);
182 Label loopEnd(env);
183 Label loopExit(env);
184 Label grow(env);
185 Label setValue(env);
186 Label matchCls(env);
187 Label numEqual2(env);
188 Label numEqual3(env);
189 Label threeArgs(env);
190 Label final(env);
191 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
192 Bind(&isHeapObject);
193 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
194 Bind(&isJsArray);
195 BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath);
196 Bind(&isStableJsArray);
197 GateRef arrayCls = LoadHClass(thisValue);
198 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
199 Bind(&matchCls);
200 BRANCH(Int64GreaterThan(numArgs, IntPtr(0)), &numNotEqualZero, slowPath);
201 Bind(&numNotEqualZero);
202 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
203 GateRef argLen = ZExtInt32ToInt64(ChangeIntPtrToInt32(numArgs));
204 GateRef newLen = Int64Add(thisLen, argLen);
205 BRANCH(Int64GreaterThan(newLen, Int64(base::MAX_SAFE_INTEGER)), slowPath, ¬OverRange);
206 Bind(¬OverRange);
207 // 3 : max param num
208 BRANCH(Int64LessThanOrEqual(numArgs, IntPtr(3)), &numLessThanOrEqualThree, slowPath);
209 Bind(&numLessThanOrEqualThree);
210 {
211 DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue));
212 GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(*elements));
213 BRANCH(Int64GreaterThan(newLen, capacity), &grow, &setValue);
214 Bind(&grow);
215 {
216 elements = CallRuntime(glue, RTSTUB_ID(JSObjectGrowElementsCapacity), {thisValue, IntToTaggedInt(newLen)});
217 Jump(&setValue);
218 }
219 Bind(&setValue);
220 {
221 DEFVARIABLE(fromKey, VariableType::INT64(), Int64Sub(thisLen, Int64(1)));
222 DEFVARIABLE(toKey, VariableType::INT64(), Int64Sub(newLen, Int64(1)));
223 DEFVARIABLE(ele, VariableType::JS_ANY(), Hole());
224 Label eleIsHole(env);
225 Label hasProperty(env);
226 Label notHasProperty(env);
227 Label hasException0(env);
228 Label notHasException0(env);
229 Jump(&loopHead);
230 LoopBegin(&loopHead);
231 {
232 BRANCH(Int64GreaterThanOrEqual(*fromKey, Int64(0)), &next, &loopExit);
233 Bind(&next);
234 {
235 ele = GetTaggedValueWithElementsKind(thisValue, *fromKey);
236 BRANCH(TaggedIsHole(*ele), &eleIsHole, ¬HasException0);
237 Bind(&eleIsHole);
238 {
239 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty),
240 { thisValue, IntToTaggedInt(*fromKey) });
241 BRANCH(TaggedIsTrue(hasProp), &hasProperty, ¬HasProperty);
242 Bind(&hasProperty);
243 {
244 ele = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*fromKey),
245 ProfileOperation());
246 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
247 Bind(&hasException0);
248 {
249 result->WriteVariable(Exception());
250 Jump(exit);
251 }
252 }
253 Bind(¬HasProperty);
254 {
255 SetValueWithElementsKind(glue, thisValue, Hole(), *toKey, Boolean(false),
256 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
257 Jump(&loopEnd);
258 }
259 }
260 Bind(¬HasException0);
261 {
262 SetValueWithElementsKind(glue, thisValue, *ele, *toKey, Boolean(false),
263 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
264 Jump(&loopEnd);
265 }
266 }
267 }
268 Bind(&loopEnd);
269 fromKey = Int64Sub(*fromKey, Int64(1));
270 toKey = Int64Sub(*toKey, Int64(1));
271 LoopEnd(&loopHead);
272 Bind(&loopExit);
273 {
274 GateRef value0 = GetCallArg0(numArgs);
275 // 0 : the first Element position
276 SetValueWithElementsKind(glue, thisValue, value0, Int64(0), Boolean(false),
277 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
278 // 2 : the second param
279 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(2)), &numEqual2, &numEqual3);
280 Bind(&numEqual2);
281 {
282 GateRef value1 = GetCallArg1(numArgs);
283 // 1 : the second Element position
284 SetValueWithElementsKind(glue, thisValue, value1, Int64(1), Boolean(false),
285 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
286 Jump(&numEqual3);
287 }
288 Bind(&numEqual3);
289 {
290 // 3 : the third param
291 BRANCH(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &final);
292 Bind(&threeArgs);
293 GateRef value2 = GetCallArg2(numArgs);
294 // 2 : the third Element position
295 SetValueWithElementsKind(glue, thisValue, value2, Int64(2), Boolean(false),
296 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
297 Jump(&final);
298 }
299 Bind(&final);
300 {
301 SetArrayLength(glue, thisValue, newLen);
302 result->WriteVariable(IntToTaggedPtr(newLen));
303 Jump(exit);
304 }
305 }
306 }
307 }
308 }
309
Shift(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)310 void BuiltinsArrayStubBuilder::Shift(GateRef glue, GateRef thisValue,
311 [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
312 {
313 auto env = GetEnvironment();
314 Label isHeapObject(env);
315 Label stableJSArray(env);
316 Label isDefaultConstructor(env);
317 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
318 Bind(&isHeapObject);
319 BRANCH(HasConstructor(thisValue), slowPath, &isDefaultConstructor);
320 Bind(&isDefaultConstructor);
321 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
322 Bind(&stableJSArray);
323 {
324 Label isLengthWritable(env);
325 BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath);
326 Bind(&isLengthWritable);
327 {
328 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
329 Label lengthNotZero(env);
330 BRANCH(Int64Equal(thisLen, Int64(0)), exit, &lengthNotZero);
331 Bind(&lengthNotZero);
332 {
333 Label isJsCOWArray(env);
334 Label getElements(env);
335 BRANCH(IsJsCOWArray(thisValue), &isJsCOWArray, &getElements);
336 Bind(&isJsCOWArray);
337 {
338 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), { thisValue });
339 Jump(&getElements);
340 }
341 Bind(&getElements);
342 {
343 GateRef elements = GetElementsArray(thisValue);
344 GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(elements));
345 GateRef index = Int64Sub(thisLen, Int64(1));
346 DEFVARIABLE(element, VariableType::JS_ANY(), Hole());
347 element = GetTaggedValueWithElementsKind(thisValue, Int64(0));
348 Label hasException0(env);
349 Label taggedHole(env);
350 Label copyArray(env);
351 BRANCH(TaggedIsHole(*element), &taggedHole, ©Array);
352 Bind(&taggedHole);
353 {
354 element = FastGetPropertyByIndex(glue, thisValue, Int32(0), ProfileOperation());
355 BRANCH(HasPendingException(glue), &hasException0, ©Array);
356 Bind(&hasException0);
357 {
358 result->WriteVariable(Exception());
359 Jump(exit);
360 }
361 }
362 Bind(©Array);
363 {
364 DEFVARIABLE(fromKey, VariableType::INT64(), Int64(1));
365 DEFVARIABLE(toKey, VariableType::INT64(), Int64Sub(*fromKey, Int64(1)));
366 Label loopHead(env);
367 Label loopNext(env);
368 Label loopEnd(env);
369 Label loopExit(env);
370 Jump(&loopHead);
371 LoopBegin(&loopHead);
372 {
373 BRANCH(Int64LessThan(*fromKey, thisLen), &loopNext, &loopExit);
374 Bind(&loopNext);
375 {
376 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *fromKey);
377 SetValueWithElementsKind(glue, thisValue, ele, *toKey, Boolean(false),
378 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
379 Jump(&loopEnd);
380 }
381 }
382 Bind(&loopEnd);
383 fromKey = Int64Add(*fromKey, Int64(1));
384 toKey = Int64Add(*toKey, Int64(1));
385 LoopEnd(&loopHead);
386 Bind(&loopExit);
387 {
388 Label noTrim(env);
389 Label needTrim(env);
390 Label setNewLen(env);
391 GateRef unused = Int64Sub(capacity, index);
392 BRANCH(Int64GreaterThan(unused, Int64(TaggedArray::MAX_END_UNUSED)), &needTrim, &noTrim);
393 Bind(&needTrim);
394 {
395 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, elements, index});
396 Jump(&setNewLen);
397 }
398 Bind(&noTrim);
399 {
400 SetValueWithElementsKind(glue, thisValue, Hole(), index, Boolean(false),
401 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
402 Jump(&setNewLen);
403 }
404 Bind(&setNewLen);
405 {
406 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
407 Store(VariableType::INT32(), glue, thisValue, lengthOffset, index);
408
409 Label isNotHole(env);
410 BRANCH(TaggedIsHole(*element), exit, &isNotHole);
411 Bind(&isNotHole);
412 {
413 result->WriteVariable(*element);
414 Jump(exit);
415 }
416 }
417 }
418 }
419 }
420 }
421 }
422 }
423 }
424
Concat(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)425 void BuiltinsArrayStubBuilder::Concat(GateRef glue, GateRef thisValue, GateRef numArgs,
426 Variable *result, Label *exit, Label *slowPath)
427 {
428 auto env = GetEnvironment();
429 Label isHeapObject(env);
430 Label isJsArray(env);
431 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
432 Bind(&isHeapObject);
433 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
434 Bind(&isJsArray);
435 {
436 Label isExtensible(env);
437 BRANCH(HasConstructor(thisValue), slowPath, &isExtensible);
438 Bind(&isExtensible);
439 {
440 Label numArgsOne(env);
441 BRANCH(Int64Equal(numArgs, IntPtr(1)), &numArgsOne, slowPath);
442 Bind(&numArgsOne);
443 {
444 GateRef arg0 = GetCallArg0(numArgs);
445 Label allStableJsArray(env);
446 GateRef isAllStableJsArray = LogicAndBuilder(env).And(IsStableJSArray(glue, thisValue))
447 .And(IsStableJSArray(glue, arg0)).Done();
448 BRANCH(isAllStableJsArray, &allStableJsArray, slowPath);
449 Bind(&allStableJsArray);
450 {
451 GateRef maxArrayIndex = Int64(TaggedArray::MAX_ARRAY_INDEX);
452 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
453 GateRef argLen = ZExtInt32ToInt64(GetArrayLength(arg0));
454 GateRef sumArrayLen = Int64Add(argLen, thisLen);
455 Label isEmptyArray(env);
456 Label notEmptyArray(env);
457 BRANCH(Int64Equal(sumArrayLen, Int64(0)), &isEmptyArray, ¬EmptyArray);
458 Bind(&isEmptyArray);
459 {
460 NewObjectStubBuilder newBuilder(this);
461 result->WriteVariable(newBuilder.CreateEmptyArray(glue));
462 Jump(exit);
463 }
464 Bind(¬EmptyArray);
465 Label notOverFlow(env);
466 BRANCH(Int64GreaterThan(sumArrayLen, maxArrayIndex), slowPath, ¬OverFlow);
467 Bind(¬OverFlow);
468 {
469 Label spreadable(env);
470 GateRef isAllConcatSpreadable = LogicAndBuilder(env).And(IsConcatSpreadable(glue, thisValue))
471 .And(IsConcatSpreadable(glue, arg0)).Done();
472 BRANCH(isAllConcatSpreadable, &spreadable, slowPath);
473 Bind(&spreadable);
474 {
475 Label setProperties(env);
476 GateRef glueGlobalEnvOffset =
477 IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
478 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
479 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
480 GlobalEnv::ARRAY_FUNCTION_INDEX);
481 GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc,
482 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
483 NewObjectStubBuilder newBuilder(this);
484 newBuilder.SetParameters(glue, 0);
485 GateRef newArray = newBuilder.NewJSArrayWithSize(intialHClass, sumArrayLen);
486 BRANCH(TaggedIsException(newArray), exit, &setProperties);
487 Bind(&setProperties);
488 {
489 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
490 Store(VariableType::INT32(), glue, newArray, lengthOffset,
491 TruncInt64ToInt32(sumArrayLen));
492 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
493 ConstantIndex::ARRAY_LENGTH_ACCESSOR);
494 SetPropertyInlinedProps(glue, newArray, intialHClass, accessor,
495 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
496 SetExtensibleToBitfield(glue, newArray, true);
497 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
498 DEFVARIABLE(j, VariableType::INT64(), Int64(0));
499 DEFVARIABLE(k, VariableType::INT64(), Int64(0));
500 Label loopHead(env);
501 Label loopEnd(env);
502 Label next(env);
503 Label loopExit(env);
504 Jump(&loopHead);
505 LoopBegin(&loopHead);
506 {
507 BRANCH(Int64LessThan(*i, thisLen), &next, &loopExit);
508 Bind(&next);
509 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *i);
510 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
511 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
512 Int32(static_cast<uint32_t>(ElementsKind::GENERIC)));
513 #else
514 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
515 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
516 #endif
517 Jump(&loopEnd);
518 }
519 Bind(&loopEnd);
520 i = Int64Add(*i, Int64(1));
521 j = Int64Add(*j, Int64(1));
522 LoopEnd(&loopHead, env, glue);
523 Bind(&loopExit);
524 Label loopHead1(env);
525 Label loopEnd1(env);
526 Label next1(env);
527 Label loopExit1(env);
528 Jump(&loopHead1);
529 LoopBegin(&loopHead1);
530 {
531 BRANCH(Int64LessThan(*k, argLen), &next1, &loopExit1);
532 Bind(&next1);
533 GateRef ele = GetTaggedValueWithElementsKind(arg0, *k);
534 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
535 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
536 Int32(static_cast<uint32_t>(ElementsKind::GENERIC)));
537 #else
538 SetValueWithElementsKind(glue, newArray, ele, *j, Boolean(true),
539 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
540 #endif
541 Jump(&loopEnd1);
542 }
543 Bind(&loopEnd1);
544 k = Int64Add(*k, Int64(1));
545 j = Int64Add(*j, Int64(1));
546 LoopEnd(&loopHead1);
547 Bind(&loopExit1);
548 result->WriteVariable(newArray);
549 Jump(exit);
550 }
551 }
552 }
553 }
554 }
555 }
556 }
557 }
558
Filter(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)559 void BuiltinsArrayStubBuilder::Filter(GateRef glue, GateRef thisValue, GateRef numArgs,
560 Variable *result, Label *exit, Label *slowPath)
561 {
562 auto env = GetEnvironment();
563 Label isHeapObject(env);
564 Label isJsArray(env);
565 Label defaultConstr(env);
566 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
567 Bind(&isHeapObject);
568 GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue))
569 .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done();
570 BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath);
571 Bind(&isJsArray);
572 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
573 Bind(&defaultConstr);
574
575 GateRef callbackFnHandle = GetCallArg0(numArgs);
576 Label argOHeapObject(env);
577 Label callable(env);
578 Label notOverFlow(env);
579 BRANCH(TaggedIsHeapObject(callbackFnHandle), &argOHeapObject, slowPath);
580 Bind(&argOHeapObject);
581 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
582 Bind(&callable);
583 GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue));
584 Label isEmptyArray(env);
585 Label notEmptyArray(env);
586 BRANCH(Int64Equal(len, Int64(0)), &isEmptyArray, ¬EmptyArray);
587 Bind(&isEmptyArray);
588 {
589 NewObjectStubBuilder newBuilder(this);
590 result->WriteVariable(newBuilder.CreateEmptyArray(glue));
591 Jump(exit);
592 }
593 Bind(¬EmptyArray);
594 BRANCH(Int64GreaterThan(len, Int64(JSObject::MAX_GAP)), slowPath, ¬OverFlow);
595 Bind(¬OverFlow);
596
597 GateRef argHandle = GetCallArg1(numArgs);
598 GateRef newArray = NewArray(glue, len);
599 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
600 GateRef newArrayEles = GetElementsArray(newArray);
601 Label stableJSArray(env);
602 Label notStableJSArray(env);
603 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
604 DEFVARIABLE(toIndex, VariableType::INT64(), Int64(0));
605 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
606 Bind(&stableJSArray);
607 {
608 DEFVARIABLE(thisArrLenVar, VariableType::INT64(), len);
609 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
610 Label loopHead(env);
611 Label loopEnd(env);
612 Label next(env);
613 Label loopExit(env);
614 Jump(&loopHead);
615 LoopBegin(&loopHead);
616 {
617 BRANCH(Int64LessThan(*i, *thisArrLenVar), &next, &loopExit);
618 Bind(&next);
619 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
620 Label kValueIsHole(env);
621 Label kValueNotHole(env);
622 Label arrayValueIsHole(env);
623 Label arrayValueNotHole(env);
624 Label hasProperty(env);
625 BRANCH(TaggedIsHole(*kValue), &arrayValueIsHole, &arrayValueNotHole);
626 Bind(&arrayValueIsHole);
627 {
628 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
629 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &arrayValueNotHole);
630 Bind(&hasProperty);
631 Label hasException0(env);
632 Label notHasException0(env);
633 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
634 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
635 Bind(&hasException0);
636 {
637 result->WriteVariable(Exception());
638 Jump(exit);
639 }
640 Bind(¬HasException0);
641 {
642 Jump(&arrayValueNotHole);
643 }
644 }
645 Bind(&arrayValueNotHole);
646 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &kValueNotHole);
647 Bind(&kValueNotHole);
648 {
649 GateRef key = Int64ToTaggedInt(*i);
650 Label checkArray(env);
651 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
652 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
653 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
654 Circuit::NullGate(), callArgs);
655 GateRef retValue = callBuilder.JSCallDispatch();
656 Label find(env);
657 Label hasException1(env);
658 Label notHasException1(env);
659 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
660 Bind(&hasException1);
661 {
662 result->WriteVariable(Exception());
663 Jump(exit);
664 }
665 Bind(¬HasException1);
666 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &checkArray);
667 Bind(&find);
668 {
669 SetValueWithElementsKind(glue, newArray, *kValue, *toIndex, Boolean(true),
670 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
671 toIndex = Int64Add(*toIndex, Int64(1));
672 Jump(&checkArray);
673 }
674 Bind(&checkArray);
675 {
676 Label lenChange(env);
677 GateRef tmpArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
678 BRANCH(Int64LessThan(tmpArrLen, *thisArrLenVar), &lenChange, &kValueIsHole);
679 Bind(&lenChange);
680 {
681 thisArrLenVar = tmpArrLen;
682 Jump(&kValueIsHole);
683 }
684 }
685 }
686 Bind(&kValueIsHole);
687 i = Int64Add(*i, Int64(1));
688 BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, ¬StableJSArray);
689 }
690 Bind(&loopEnd);
691 LoopEnd(&loopHead, env, glue);
692 Bind(&loopExit);
693 Jump(¬StableJSArray);
694 }
695 Bind(¬StableJSArray);
696 {
697 Label finish(env);
698 Label callRT(env);
699 BRANCH(Int32LessThan(*i, len), &callRT, &finish);
700 Bind(&callRT);
701 {
702 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, newArrayEles, *toIndex});
703 Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(*toIndex));
704 GateRef ret = CallRuntime(glue, RTSTUB_ID(JSArrayFilterUnStable), { argHandle, thisValue,
705 IntToTaggedInt(*i), IntToTaggedInt(len), IntToTaggedInt(*toIndex), newArray, callbackFnHandle });
706 result->WriteVariable(ret);
707 Jump(exit);
708 }
709 Bind(&finish);
710 {
711 result->WriteVariable(newArray);
712 Label needTrim(env);
713 BRANCH(Int64LessThan(*toIndex, len), &needTrim, exit);
714 Bind(&needTrim);
715 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, newArrayEles, *toIndex});
716 Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(*toIndex));
717 Jump(exit);
718 }
719 }
720 }
721
Map(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)722 void BuiltinsArrayStubBuilder::Map(GateRef glue, GateRef thisValue, GateRef numArgs,
723 Variable *result, Label *exit, Label *slowPath)
724 {
725 auto env = GetEnvironment();
726 Label isHeapObject(env);
727 Label isJsArray(env);
728 Label defaultConstr(env);
729 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
730 Bind(&isHeapObject);
731 GateRef thisValueAndProtoIsJSArray = LogicAndBuilder(env).And(IsJsArray(thisValue))
732 .And(IsJsArray(StubBuilder::GetPrototype(glue, thisValue))).Done();
733 BRANCH(thisValueAndProtoIsJSArray, &isJsArray, slowPath);
734 Bind(&isJsArray);
735 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
736 Bind(&defaultConstr);
737
738 GateRef callbackFnHandle = GetCallArg0(numArgs);
739 Label argOHeapObject(env);
740 Label callable(env);
741 Label notOverFlow(env);
742 BRANCH(TaggedIsHeapObject(callbackFnHandle), &argOHeapObject, slowPath);
743 Bind(&argOHeapObject);
744 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
745 Bind(&callable);
746 GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue));
747 Label isEmptyArray(env);
748 Label notEmptyArray(env);
749 BRANCH(Int64Equal(len, Int64(0)), &isEmptyArray, ¬EmptyArray);
750 Bind(&isEmptyArray);
751 {
752 NewObjectStubBuilder newBuilder(this);
753 result->WriteVariable(newBuilder.CreateEmptyArray(glue));
754 Jump(exit);
755 }
756 Bind(¬EmptyArray);
757 BRANCH(Int64GreaterThan(len, Int64(JSObject::MAX_GAP)), slowPath, ¬OverFlow);
758 Bind(¬OverFlow);
759
760 GateRef argHandle = GetCallArg1(numArgs);
761 GateRef newArray = NewArray(glue, len);
762 Label stableJSArray(env);
763 Label notStableJSArray(env);
764 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
765 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
766 Bind(&stableJSArray);
767 {
768 DEFVARIABLE(thisArrLenVar, VariableType::INT64(), len);
769 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
770 Label loopHead(env);
771 Label loopEnd(env);
772 Label next(env);
773 Label loopExit(env);
774 Jump(&loopHead);
775 LoopBegin(&loopHead);
776 {
777 BRANCH(Int64LessThan(*i, *thisArrLenVar), &next, &loopExit);
778 Bind(&next);
779 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
780 Label kValueIsHole(env);
781 Label kValueNotHole(env);
782 Label arrayValueIsHole(env);
783 Label arrayValueNotHole(env);
784 Label hasProperty(env);
785 BRANCH(TaggedIsHole(*kValue), &arrayValueIsHole, &arrayValueNotHole);
786 Bind(&arrayValueIsHole);
787 {
788 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
789 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &arrayValueNotHole);
790 Bind(&hasProperty);
791 Label hasException0(env);
792 Label notHasException0(env);
793 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
794 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
795 Bind(&hasException0);
796 {
797 result->WriteVariable(Exception());
798 Jump(exit);
799 }
800 Bind(¬HasException0);
801 {
802 Jump(&arrayValueNotHole);
803 }
804 }
805 Bind(&arrayValueNotHole);
806 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &kValueNotHole);
807 Bind(&kValueNotHole);
808 {
809 GateRef key = Int64ToTaggedInt(*i);
810 Label checkArray(env);
811 JSCallArgs callArgs = (JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
812 callArgs.callThisArg3WithReturnArgs = {argHandle, *kValue, key, thisValue};
813 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
814 Circuit::NullGate(), callArgs);
815 GateRef retValue = callBuilder.JSCallDispatch();
816 Label hasException1(env);
817 Label notHasException1(env);
818 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
819 Bind(&hasException1);
820 {
821 result->WriteVariable(Exception());
822 Jump(exit);
823 }
824 Bind(¬HasException1);
825 SetValueWithElementsKind(glue, newArray, retValue, *i, Boolean(true),
826 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
827 Label lenChange(env);
828 GateRef tmpArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
829 BRANCH(Int64LessThan(tmpArrLen, *thisArrLenVar), &lenChange, &kValueIsHole);
830 Bind(&lenChange);
831 {
832 thisArrLenVar = tmpArrLen;
833 Jump(&kValueIsHole);
834 }
835 }
836 Bind(&kValueIsHole);
837 i = Int64Add(*i, Int64(1));
838 BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, ¬StableJSArray);
839 }
840 Bind(&loopEnd);
841 LoopEnd(&loopHead);
842 Bind(&loopExit);
843 Jump(¬StableJSArray);
844 }
845 Bind(¬StableJSArray);
846 {
847 GateRef ret = CallRuntime(glue, RTSTUB_ID(JSArrayMapUnStable), { argHandle, thisValue,
848 IntToTaggedInt(*i), IntToTaggedInt(len), newArray, callbackFnHandle });
849 result->WriteVariable(ret);
850 Jump(exit);
851 }
852 }
853
854 // Note: unused arguments are reserved for further development
ForEach(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)855 void BuiltinsArrayStubBuilder::ForEach([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs,
856 [[maybe_unused]] Variable *result, Label *exit, Label *slowPath)
857 {
858 auto env = GetEnvironment();
859 Label thisExists(env);
860 Label matchCls(env);
861 Label isHeapObject(env);
862 Label isGeneric(env);
863 Label isJsArray(env);
864 Label defaultConstr(env);
865 Label isStability(env);
866 Label notCOWArray(env);
867 Label equalCls(env);
868 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
869 Bind(&thisExists);
870 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
871 Bind(&isHeapObject);
872 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
873 Bind(&isJsArray);
874 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
875 Bind(&defaultConstr);
876 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
877 Bind(&isStability);
878 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
879 Bind(¬COWArray);
880 GateRef arrayCls = LoadHClass(thisValue);
881 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
882 Bind(&matchCls);
883 Label arg0HeapObject(env);
884 Label callable(env);
885 Label thisIsStable(env);
886 Label thisNotStable(env);
887 GateRef callbackFnHandle = GetCallArg0(numArgs);
888 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
889 Bind(&arg0HeapObject);
890 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
891 Bind(&callable);
892 GateRef argHandle = GetCallArg1(numArgs);
893
894 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
895 DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0));
896 thisLen = GetArrayLength(thisValue);
897 Jump(&thisIsStable);
898
899 Bind(&thisIsStable);
900 {
901 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
902 Label loopHead(env);
903 Label loopEnd(env);
904 Label next(env);
905 Label loopExit(env);
906 Jump(&loopHead);
907 LoopBegin(&loopHead);
908 {
909 Label nextStep(env);
910 Label kValueIsHole(env);
911 Label callDispatch(env);
912 Label hasProperty(env);
913 Label hasException0(env);
914 Label hasException1(env);
915 GateRef newLen = GetArrayLength(thisValue);
916 BRANCH(BitAnd(IsStableJSArray(glue, thisValue), Int32Equal(*thisLen, newLen)),
917 &nextStep, &thisNotStable);
918 Bind(&nextStep);
919 BRANCH(Int64GreaterThanOrEqual(*i, ZExtInt32ToInt64(*thisLen)), &loopExit, &next);
920 Bind(&next);
921 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
922 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
923 Bind(&kValueIsHole);
924 {
925 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
926 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
927 Bind(&hasProperty);
928 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
929 BRANCH(HasPendingException(glue), &hasException0, &callDispatch);
930 Bind(&hasException0);
931 {
932 result->WriteVariable(Exception());
933 Jump(exit);
934 }
935 }
936 Bind(&callDispatch);
937 {
938 GateRef key = Int64ToTaggedInt(*i);
939 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
940 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
941 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
942 Circuit::NullGate(), callArgs);
943 callBuilder.JSCallDispatch();
944 BRANCH(HasPendingException(glue), &hasException1, &loopEnd);
945 Bind(&hasException1);
946 {
947 result->WriteVariable(Exception());
948 Jump(exit);
949 }
950 }
951 }
952 Bind(&loopEnd);
953 i = Int64Add(*i, Int64(1));
954 LoopEnd(&loopHead);
955 Bind(&loopExit);
956 Jump(exit);
957 }
958
959 Bind(&thisNotStable);
960 {
961 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
962 Label loopHead(env);
963 Label loopEnd(env);
964 Label next(env);
965 Label loopExit(env);
966 Jump(&loopHead);
967 LoopBegin(&loopHead);
968 {
969 Label hasProperty(env);
970 Label hasException0(env);
971 Label notHasException0(env);
972 Label hasException1(env);
973 BRANCH(Int64GreaterThanOrEqual(*i, ZExtInt32ToInt64(*thisLen)), &loopExit, &next);
974 Bind(&next);
975 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
976 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
977 Bind(&hasProperty);
978 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
979 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
980 Bind(&hasException0);
981 {
982 result->WriteVariable(Exception());
983 Jump(exit);
984 }
985 Bind(¬HasException0);
986 {
987 GateRef key = Int64ToTaggedInt(*i);
988 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
989 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
990 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
991 Circuit::NullGate(), callArgs);
992 callBuilder.JSCallDispatch();
993 BRANCH(HasPendingException(glue), &hasException1, &loopEnd);
994 Bind(&hasException1);
995 {
996 result->WriteVariable(Exception());
997 Jump(exit);
998 }
999 }
1000 }
1001 Bind(&loopEnd);
1002 i = Int64Add(*i, Int64(1));
1003 LoopEnd(&loopHead);
1004 Bind(&loopExit);
1005 Jump(exit);
1006 }
1007 }
1008
1009 // Note: unused arguments are reserved for further development
IndexOf(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1010 void BuiltinsArrayStubBuilder::IndexOf([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs,
1011 Variable *result, Label *exit, Label *slowPath)
1012 {
1013 auto env = GetEnvironment();
1014 Label thisIsEmpty(env);
1015 // Fast path if: (1) this is an empty array; (2) fromIndex is missing
1016 JsArrayRequirements req;
1017 BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, slowPath);
1018 Bind(&thisIsEmpty);
1019 {
1020 Label atMostOneArg(env);
1021 BRANCH(Int32LessThanOrEqual(TruncPtrToInt32(numArgs), Int32(1)), &atMostOneArg, slowPath);
1022 // Returns -1 on fast path
1023 Bind(&atMostOneArg);
1024 result->WriteVariable(IntToTaggedPtr(Int32(-1)));
1025 Jump(exit);
1026 }
1027 }
1028
1029 // Note: unused arguments are reserved for further development
LastIndexOf(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1030 void BuiltinsArrayStubBuilder::LastIndexOf([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs,
1031 Variable *result, Label *exit, Label *slowPath)
1032 {
1033 auto env = GetEnvironment();
1034 Label thisIsEmpty(env);
1035 // Fast path if: (1) this is an empty array; (2) fromIndex is missing
1036 JsArrayRequirements req;
1037 BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, slowPath);
1038 Bind(&thisIsEmpty);
1039 {
1040 Label atMostOneArg(env);
1041 BRANCH(Int32LessThanOrEqual(TruncPtrToInt32(numArgs), Int32(1)), &atMostOneArg, slowPath);
1042 // Returns -1 on fast path
1043 Bind(&atMostOneArg);
1044 result->WriteVariable(IntToTaggedPtr(Int32(-1)));
1045 Jump(exit);
1046 }
1047 }
1048
Pop(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1049 void BuiltinsArrayStubBuilder::Pop(GateRef glue, GateRef thisValue,
1050 [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
1051 {
1052 auto env = GetEnvironment();
1053 Label isHeapObject(env);
1054 Label stableJSArray(env);
1055 Label isDeufaltConstructor(env);
1056 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1057 Bind(&isHeapObject);
1058 BRANCH(HasConstructor(thisValue), slowPath, &isDeufaltConstructor);
1059 Bind(&isDeufaltConstructor);
1060 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, slowPath);
1061 Bind(&stableJSArray);
1062
1063 Label isLengthWritable(env);
1064 BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath);
1065 Bind(&isLengthWritable);
1066 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1067
1068 Label notZeroLen(env);
1069 BRANCH(Int64Equal(thisLen, Int64(0)), exit, ¬ZeroLen);
1070 Bind(¬ZeroLen);
1071 Label isJsCOWArray(env);
1072 Label getElements(env);
1073 BRANCH(IsJsCOWArray(thisValue), &isJsCOWArray, &getElements);
1074 Bind(&isJsCOWArray);
1075 {
1076 CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), { thisValue });
1077 Jump(&getElements);
1078 }
1079 Bind(&getElements);
1080 GateRef elements = GetElementsArray(thisValue);
1081 GateRef capacity = ZExtInt32ToInt64(GetLengthOfTaggedArray(elements));
1082 GateRef index = Int64Sub(thisLen, Int64(1));
1083
1084 Label inRange(env);
1085 Label trimCheck(env);
1086 Label noTrimCheck(env);
1087 Label setNewLen(env);
1088 Label isHole(env);
1089 DEFVARIABLE(element, VariableType::JS_ANY(), Hole());
1090 BRANCH(Int64LessThan(index, capacity), &inRange, &trimCheck);
1091 Bind(&inRange);
1092 {
1093 element = GetTaggedValueWithElementsKind(thisValue, index);
1094 Jump(&isHole);
1095 }
1096 Bind(&isHole);
1097 BRANCH(TaggedIsHole(*element), &noTrimCheck, &trimCheck);
1098 Bind(&noTrimCheck);
1099 {
1100 Label hasException0(env);
1101 Label notHasException0(env);
1102 element = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(index), ProfileOperation());
1103 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
1104 Bind(&hasException0);
1105 {
1106 result->WriteVariable(Exception());
1107 Jump(exit);
1108 }
1109 Bind(¬HasException0);
1110 {
1111 Jump(&setNewLen);
1112 }
1113 }
1114 Bind(&trimCheck);
1115 // ShouldTrim check
1116 // (oldLength - newLength > MAX_END_UNUSED)
1117 Label noTrim(env);
1118 Label needTrim(env);
1119 GateRef unused = Int64Sub(capacity, index);
1120 BRANCH(Int64GreaterThan(unused, Int64(TaggedArray::MAX_END_UNUSED)), &needTrim, &noTrim);
1121 Bind(&needTrim);
1122 {
1123 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, elements, index});
1124 Jump(&setNewLen);
1125 }
1126 Bind(&noTrim);
1127 {
1128 SetValueWithElementsKind(glue, thisValue, Hole(), index, Boolean(false),
1129 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1130 Jump(&setNewLen);
1131 }
1132 Bind(&setNewLen);
1133 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1134 Store(VariableType::INT32(), glue, thisValue, lengthOffset, TruncInt64ToInt32(index));
1135
1136 Label isNotHole(env);
1137 BRANCH(TaggedIsHole(*element), exit, &isNotHole);
1138 Bind(&isNotHole);
1139 {
1140 result->WriteVariable(*element);
1141 Jump(exit);
1142 }
1143 }
1144
Slice(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1145 void BuiltinsArrayStubBuilder::Slice(GateRef glue, GateRef thisValue, GateRef numArgs,
1146 Variable *result, Label *exit, Label *slowPath)
1147 {
1148 auto env = GetEnvironment();
1149 Label isHeapObject(env);
1150 Label isJsArray(env);
1151 Label noConstructor(env);
1152 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1153 Bind(&isHeapObject);
1154 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1155 Bind(&isJsArray);
1156 BRANCH(HasConstructor(thisValue), slowPath, &noConstructor);
1157 Bind(&noConstructor);
1158
1159 Label thisIsEmpty(env);
1160 Label thisNotEmpty(env);
1161 // Fast path if:
1162 // (1) this is an empty array with constructor not reset (see ArraySpeciesCreate for details);
1163 // (2) no arguments exist
1164 JsArrayRequirements req;
1165 req.defaultConstructor = true;
1166 BRANCH(IsJsArrayWithLengthLimit(glue, thisValue, MAX_LENGTH_ZERO, req), &thisIsEmpty, &thisNotEmpty);
1167 Bind(&thisIsEmpty);
1168 {
1169 Label noArgs(env);
1170 GateRef numArgsAsInt32 = TruncPtrToInt32(numArgs);
1171 BRANCH(Int32Equal(numArgsAsInt32, Int32(0)), &noArgs, slowPath);
1172 // Creates a new empty array on fast path
1173 Bind(&noArgs);
1174 NewObjectStubBuilder newBuilder(this);
1175 result->WriteVariable(newBuilder.CreateEmptyArray(glue));
1176 Jump(exit);
1177 }
1178 Bind(&thisNotEmpty);
1179 {
1180 Label stableJSArray(env);
1181 Label arrayLenNotZero(env);
1182
1183 GateRef isThisStableJSArray = IsStableJSArray(glue, thisValue);
1184 BRANCH(isThisStableJSArray, &stableJSArray, slowPath);
1185 Bind(&stableJSArray);
1186
1187 GateRef msg0 = GetCallArg0(numArgs);
1188 GateRef msg1 = GetCallArg1(numArgs);
1189 GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1190 Label msg0Int(env);
1191 BRANCH(TaggedIsInt(msg0), &msg0Int, slowPath);
1192 Bind(&msg0Int);
1193 DEFVARIABLE(start, VariableType::INT64(), Int64(0));
1194 DEFVARIABLE(end, VariableType::INT64(), thisArrLen);
1195
1196 GateRef argStart = SExtInt32ToInt64(TaggedGetInt(msg0));
1197 Label arg0LessZero(env);
1198 Label arg0NotLessZero(env);
1199 Label startDone(env);
1200 BRANCH(Int64LessThan(argStart, Int64(0)), &arg0LessZero, &arg0NotLessZero);
1201 Bind(&arg0LessZero);
1202 {
1203 Label tempGreaterZero(env);
1204 Label tempNotGreaterZero(env);
1205 GateRef tempStart = Int64Add(argStart, thisArrLen);
1206 BRANCH(Int64GreaterThan(tempStart, Int64(0)), &tempGreaterZero, &tempNotGreaterZero);
1207 Bind(&tempGreaterZero);
1208 {
1209 start = tempStart;
1210 Jump(&startDone);
1211 }
1212 Bind(&tempNotGreaterZero);
1213 {
1214 Jump(&startDone);
1215 }
1216 }
1217 Bind(&arg0NotLessZero);
1218 {
1219 Label argLessLen(env);
1220 Label argNotLessLen(env);
1221 BRANCH(Int64LessThan(argStart, thisArrLen), &argLessLen, &argNotLessLen);
1222 Bind(&argLessLen);
1223 {
1224 start = argStart;
1225 Jump(&startDone);
1226 }
1227 Bind(&argNotLessLen);
1228 {
1229 start = thisArrLen;
1230 Jump(&startDone);
1231 }
1232 }
1233 Bind(&startDone);
1234 {
1235 Label endDone(env);
1236 Label msg1Def(env);
1237 BRANCH(TaggedIsUndefined(msg1), &endDone, &msg1Def);
1238 Bind(&msg1Def);
1239 {
1240 Label msg1Int(env);
1241 BRANCH(TaggedIsInt(msg1), &msg1Int, slowPath);
1242 Bind(&msg1Int);
1243 {
1244 GateRef argEnd = SExtInt32ToInt64(TaggedGetInt(msg1));
1245 Label arg1LessZero(env);
1246 Label arg1NotLessZero(env);
1247 BRANCH(Int64LessThan(argEnd, Int64(0)), &arg1LessZero, &arg1NotLessZero);
1248 Bind(&arg1LessZero);
1249 {
1250 Label tempGreaterZero(env);
1251 Label tempNotGreaterZero(env);
1252 GateRef tempEnd = Int64Add(argEnd, thisArrLen);
1253 BRANCH(Int64GreaterThan(tempEnd, Int64(0)), &tempGreaterZero, &tempNotGreaterZero);
1254 Bind(&tempGreaterZero);
1255 {
1256 end = tempEnd;
1257 Jump(&endDone);
1258 }
1259 Bind(&tempNotGreaterZero);
1260 {
1261 end = Int64(0);
1262 Jump(&endDone);
1263 }
1264 }
1265 Bind(&arg1NotLessZero);
1266 {
1267 Label argLessLen(env);
1268 Label argNotLessLen(env);
1269 BRANCH(Int64LessThan(argEnd, thisArrLen), &argLessLen, &argNotLessLen);
1270 Bind(&argLessLen);
1271 {
1272 end = argEnd;
1273 Jump(&endDone);
1274 }
1275 Bind(&argNotLessLen);
1276 {
1277 end = thisArrLen;
1278 Jump(&endDone);
1279 }
1280 }
1281 }
1282 }
1283 Bind(&endDone);
1284 {
1285 DEFVARIABLE(count, VariableType::INT64(), Int64(0));
1286 GateRef tempCnt = Int64Sub(*end, *start);
1287 Label tempCntGreaterOrEqualZero(env);
1288 Label tempCntDone(env);
1289 BRANCH(Int64LessThan(tempCnt, Int64(0)), &tempCntDone, &tempCntGreaterOrEqualZero);
1290 Bind(&tempCntGreaterOrEqualZero);
1291 {
1292 count = tempCnt;
1293 Jump(&tempCntDone);
1294 }
1295 Bind(&tempCntDone);
1296 {
1297 Label notOverFlow(env);
1298 BRANCH(Int64GreaterThan(*count, Int64(JSObject::MAX_GAP)), slowPath, ¬OverFlow);
1299 Bind(¬OverFlow);
1300 {
1301 GateRef newArray = NewArray(glue, *count);
1302 GateRef thisEles = GetElementsArray(thisValue);
1303 GateRef thisElesLen = ZExtInt32ToInt64(GetLengthOfTaggedArray(thisEles));
1304
1305 Label inThisEles(env);
1306 Label outThisEles(env);
1307 BRANCH(Int64GreaterThan(thisElesLen, Int64Add(*start, *count)), &inThisEles, &outThisEles);
1308 Bind(&inThisEles);
1309 {
1310 DEFVARIABLE(idx, VariableType::INT64(), Int64(0));
1311 Label loopHead(env);
1312 Label loopEnd(env);
1313 Label next(env);
1314 Label loopExit(env);
1315 Jump(&loopHead);
1316 LoopBegin(&loopHead);
1317 {
1318 BRANCH(Int64LessThan(*idx, *count), &next, &loopExit);
1319 Bind(&next);
1320
1321 GateRef ele = GetTaggedValueWithElementsKind(thisValue, Int64Add(*idx, *start));
1322 SetValueWithElementsKind(glue, newArray, ele, *idx, Boolean(true),
1323 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1324 Jump(&loopEnd);
1325 }
1326 Bind(&loopEnd);
1327 idx = Int64Add(*idx, Int64(1));
1328 LoopEnd(&loopHead, env, glue);
1329 Bind(&loopExit);
1330 result->WriteVariable(newArray);
1331 Jump(exit);
1332 }
1333 Bind(&outThisEles);
1334 {
1335 DEFVARIABLE(idx, VariableType::INT64(), Int64(0));
1336 Label loopHead(env);
1337 Label loopEnd(env);
1338 Label next(env);
1339 Label loopExit(env);
1340 Jump(&loopHead);
1341 LoopBegin(&loopHead);
1342 {
1343 BRANCH(Int64LessThan(*idx, *count), &next, &loopExit);
1344 Bind(&next);
1345 GateRef index = Int64Add(*idx, *start);
1346 DEFVARIABLE(ele, VariableType::JS_ANY(), Hole());
1347
1348 Label indexOutRange(env);
1349 Label indexInRange(env);
1350 Label setEle(env);
1351 BRANCH(Int64GreaterThan(thisElesLen, index), &indexInRange, &indexOutRange);
1352 Bind(&indexInRange);
1353 {
1354 ele = GetTaggedValueWithElementsKind(thisValue, index);
1355 Jump(&setEle);
1356 }
1357 Bind(&indexOutRange);
1358 {
1359 ele = Hole();
1360 Jump(&setEle);
1361 }
1362 Bind(&setEle);
1363 SetValueWithElementsKind(glue, newArray, *ele, *idx, Boolean(true),
1364 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1365 Jump(&loopEnd);
1366 }
1367 Bind(&loopEnd);
1368 idx = Int64Add(*idx, Int64(1));
1369 LoopEnd(&loopHead, env, glue);
1370 Bind(&loopExit);
1371 result->WriteVariable(newArray);
1372 Jump(exit);
1373 }
1374 }
1375 }
1376 }
1377 }
1378 }
1379 }
1380
Sort(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1381 void BuiltinsArrayStubBuilder::Sort(GateRef glue, GateRef thisValue,
1382 GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
1383 {
1384 GateRef callbackFnHandle = GetCallArg0(numArgs);
1385 SortAfterArgs(glue, thisValue, callbackFnHandle, result, exit, slowPath);
1386 }
1387
SortAfterArgs(GateRef glue,GateRef thisValue,GateRef callbackFnHandle,Variable * result,Label * exit,Label * slowPath,GateRef hir)1388 void BuiltinsArrayStubBuilder::SortAfterArgs(GateRef glue, GateRef thisValue,
1389 GateRef callbackFnHandle, Variable *result, Label *exit, Label *slowPath, GateRef hir)
1390 {
1391 auto env = GetEnvironment();
1392 Label isHeapObject(env);
1393 Label isJsArray(env);
1394 Label defaultConstr(env);
1395 Label isStability(env);
1396 Label notCOWArray(env);
1397 Label argUndefined(env);
1398 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1399 Bind(&isHeapObject);
1400 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1401 Bind(&isJsArray);
1402 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1403 Bind(&defaultConstr);
1404 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1405 Bind(&isStability);
1406 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
1407 Bind(¬COWArray);
1408 BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath);
1409 Bind(&argUndefined);
1410 result->WriteVariable(DoSort(glue, thisValue, Boolean(false), result, exit, slowPath, hir));
1411 Jump(exit);
1412 }
1413
ToSorted(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1414 void BuiltinsArrayStubBuilder::ToSorted(GateRef glue, GateRef thisValue,
1415 GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
1416 {
1417 auto env = GetEnvironment();
1418 Label isHeapObject(env);
1419 Label isJsArray(env);
1420 Label defaultConstr(env);
1421 Label isStability(env);
1422 Label notCOWArray(env);
1423 Label argUndefined(env);
1424 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1425 Bind(&isHeapObject);
1426 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1427 Bind(&isJsArray);
1428 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1429 Bind(&defaultConstr);
1430 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1431 Bind(&isStability);
1432 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
1433 Bind(¬COWArray);
1434 GateRef callbackFnHandle = GetCallArg0(numArgs);
1435 BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath);
1436 Bind(&argUndefined);
1437
1438 GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1439 GateRef receiver = NewArray(glue, thisArrLen);
1440 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1441 Label loopHead(env);
1442 Label loopEnd(env);
1443 Label next(env);
1444 Label loopExit(env);
1445 Jump(&loopHead);
1446 LoopBegin(&loopHead);
1447 {
1448 BRANCH(Int64LessThan(*i, thisArrLen), &next, &loopExit);
1449 Bind(&next);
1450 {
1451 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *i);
1452 SetValueWithElementsKind(glue, receiver, ele, *i, Boolean(true),
1453 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1454 Jump(&loopEnd);
1455 }
1456 }
1457 Bind(&loopEnd);
1458 i = Int64Add(*i, Int64(1));
1459 LoopEnd(&loopHead);
1460 Bind(&loopExit);
1461 result->WriteVariable(DoSort(glue, receiver, Boolean(true), result, exit, slowPath));
1462 Jump(exit);
1463 }
1464
DoSort(GateRef glue,GateRef receiver,GateRef receiverState,Variable * result,Label * exit,Label * slowPath,GateRef hir)1465 GateRef BuiltinsArrayStubBuilder::DoSort(GateRef glue, GateRef receiver, GateRef receiverState,
1466 Variable *result, Label *exit, Label *slowPath, GateRef hir)
1467 {
1468 auto env = GetEnvironment();
1469 Label entry(env);
1470 env->SubCfgEntry(&entry);
1471 GateRef len = ZExtInt32ToInt64(GetArrayLength(receiver));
1472 DEFVARIABLE(i, VariableType::INT64(), Int64(1));
1473 DEFVARIABLE(presentValue, VariableType::JS_ANY(), Undefined());
1474 DEFVARIABLE(middleValue, VariableType::JS_ANY(), Undefined());
1475 DEFVARIABLE(previousValue, VariableType::JS_ANY(), Undefined());
1476 Label loopHead(env);
1477 Label loopEnd(env);
1478 Label next(env);
1479 Label loopExit(env);
1480 Jump(&loopHead);
1481 LoopBegin(&loopHead);
1482 {
1483 BRANCH(Int64LessThan(*i, len), &next, &loopExit);
1484 Bind(&next);
1485 DEFVARIABLE(beginIndex, VariableType::INT64(), Int64(0));
1486 DEFVARIABLE(endIndex, VariableType::INT64(), *i);
1487 Label presentValueIsHole(env);
1488 Label afterGettingpresentValue(env);
1489 Label presentValueHasProperty(env);
1490 Label presentValueHasException0(env);
1491 presentValue = GetTaggedValueWithElementsKind(receiver, *i);
1492 BRANCH(TaggedIsHole(*presentValue), &presentValueIsHole, &afterGettingpresentValue);
1493 Bind(&presentValueIsHole);
1494 {
1495 GateRef presentValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { receiver, IntToTaggedInt(*i) });
1496 BRANCH(TaggedIsTrue(presentValueHasProp), &presentValueHasProperty, &afterGettingpresentValue);
1497 Bind(&presentValueHasProperty);
1498 {
1499 presentValue = FastGetPropertyByIndex(glue, receiver, TruncInt64ToInt32(*i), ProfileOperation(), hir);
1500 BRANCH(HasPendingException(glue), &presentValueHasException0, &afterGettingpresentValue);
1501 Bind(&presentValueHasException0);
1502 {
1503 result->WriteVariable(Exception());
1504 Jump(exit);
1505 }
1506 }
1507 }
1508 Bind(&afterGettingpresentValue);
1509 {
1510 Label loopHead1(env);
1511 Label loopEnd1(env);
1512 Label next1(env);
1513 Label loopExit1(env);
1514 Jump(&loopHead1);
1515 LoopBegin(&loopHead1);
1516 {
1517 Label middleValueIsHole(env);
1518 Label afterGettingmiddleValue(env);
1519 Label middleValueHasProperty(env);
1520 Label middleValueHasException0(env);
1521 BRANCH(Int64LessThan(*beginIndex, *endIndex), &next1, &loopExit1);
1522 Bind(&next1);
1523 GateRef sum = Int64Add(*beginIndex, *endIndex);
1524 GateRef middleIndex = Int64Div(sum, Int64(2)); // 2 : half
1525 middleValue = GetTaggedValueWithElementsKind(receiver, middleIndex);
1526 BRANCH(TaggedIsHole(*middleValue), &middleValueIsHole, &afterGettingmiddleValue);
1527 Bind(&middleValueIsHole);
1528 {
1529 GateRef middleValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty),
1530 { receiver, IntToTaggedInt(middleIndex) });
1531 BRANCH(TaggedIsTrue(middleValueHasProp), &middleValueHasProperty, &afterGettingmiddleValue);
1532 Bind(&middleValueHasProperty);
1533 {
1534 middleValue = FastGetPropertyByIndex(glue, receiver,
1535 TruncInt64ToInt32(middleIndex), ProfileOperation(), hir);
1536 BRANCH(HasPendingException(glue), &middleValueHasException0, &afterGettingmiddleValue);
1537 Bind(&middleValueHasException0);
1538 {
1539 result->WriteVariable(Exception());
1540 Jump(exit);
1541 }
1542 }
1543 }
1544 Bind(&afterGettingmiddleValue);
1545 {
1546 Label isInt(env);
1547 GateRef middleVal = *middleValue;
1548 GateRef presentVal = *presentValue;
1549 BRANCH(LogicAndBuilder(env).And(TaggedIsInt(middleVal)).And(TaggedIsInt(presentVal)).Done(),
1550 &isInt, slowPath);
1551 Bind(&isInt);
1552 {
1553 GateRef compareResult =
1554 CallNGCRuntime(glue, RTSTUB_ID(FastArraySort), {*middleValue, *presentValue});
1555 Label less0(env);
1556 Label greater0(env);
1557 BRANCH(Int32LessThanOrEqual(compareResult, Int32(0)), &less0, &greater0);
1558 Bind(&greater0);
1559 {
1560 endIndex = middleIndex;
1561 Jump(&loopEnd1);
1562 }
1563 Bind(&less0);
1564 {
1565 beginIndex = middleIndex;
1566 beginIndex = Int64Add(*beginIndex, Int64(1));
1567 Jump(&loopEnd1);
1568 }
1569 }
1570 }
1571 }
1572 Bind(&loopEnd1);
1573 LoopEnd(&loopHead1);
1574 Bind(&loopExit1);
1575
1576 Label shouldCopy(env);
1577 GateRef isGreater0 = Int64GreaterThanOrEqual(*endIndex, Int64(0));
1578 GateRef lessI = Int64LessThan(*endIndex, *i);
1579 BRANCH(BitAnd(isGreater0, lessI), &shouldCopy, &loopEnd);
1580 Bind(&shouldCopy);
1581 {
1582 DEFVARIABLE(j, VariableType::INT64(), *i);
1583 Label loopHead2(env);
1584 Label loopEnd2(env);
1585 Label next2(env);
1586 Label loopExit2(env);
1587 Label receiverIsNew(env);
1588 Label receiverIsOrigin(env);
1589 Label receiverIsNew2(env);
1590 Label receiverIsOrigin2(env);
1591 Jump(&loopHead2);
1592 LoopBegin(&loopHead2);
1593 {
1594 Label previousValueIsHole(env);
1595 Label afterGettingpreviousValue(env);
1596 Label previousValueHasProperty(env);
1597 Label previousValueHasException0(env);
1598 BRANCH(Int64GreaterThan(*j, *endIndex), &next2, &loopExit2);
1599 Bind(&next2);
1600 previousValue = GetTaggedValueWithElementsKind(receiver, Int64Sub(*j, Int64(1)));
1601 BRANCH(TaggedIsHole(*previousValue), &previousValueIsHole, &afterGettingpreviousValue);
1602 Bind(&previousValueIsHole);
1603 {
1604 GateRef previousValueHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty),
1605 { receiver, IntToTaggedInt(Int64Sub(*j, Int64(1))) });
1606 BRANCH(TaggedIsTrue(previousValueHasProp),
1607 &previousValueHasProperty, &afterGettingpreviousValue);
1608 Bind(&previousValueHasProperty);
1609 {
1610 previousValue = FastGetPropertyByIndex(glue, receiver,
1611 TruncInt64ToInt32(Int64Sub(*j, Int64(1))), ProfileOperation(), hir);
1612 BRANCH(HasPendingException(glue), &previousValueHasException0, &afterGettingpreviousValue);
1613 Bind(&previousValueHasException0);
1614 {
1615 result->WriteVariable(Exception());
1616 Jump(exit);
1617 }
1618 }
1619 }
1620 Bind(&afterGettingpreviousValue);
1621 {
1622 BRANCH(receiverState, &receiverIsNew, &receiverIsOrigin);
1623 Bind(&receiverIsNew);
1624 SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(true),
1625 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1626 Jump(&loopEnd2);
1627 Bind(&receiverIsOrigin);
1628 SetValueWithElementsKind(glue, receiver, *previousValue, *j, Boolean(false),
1629 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1630 Jump(&loopEnd2);
1631 }
1632 }
1633 Bind(&loopEnd2);
1634 j = Int64Sub(*j, Int64(1));
1635 LoopEnd(&loopHead2);
1636 Bind(&loopExit2);
1637 BRANCH(receiverState, &receiverIsNew2, &receiverIsOrigin2);
1638 Bind(&receiverIsNew2);
1639 {
1640 SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(true),
1641 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1642 Jump(&loopEnd);
1643 }
1644 Bind(&receiverIsOrigin2);
1645 {
1646 SetValueWithElementsKind(glue, receiver, *presentValue, *endIndex, Boolean(false),
1647 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1648 Jump(&loopEnd);
1649 }
1650 }
1651 }
1652 }
1653 Bind(&loopEnd);
1654 i = Int64Add(*i, Int64(1));
1655 LoopEnd(&loopHead);
1656 Bind(&loopExit);
1657 env->SubCfgExit();
1658 return receiver;
1659 }
1660
Reduce(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1661 void BuiltinsArrayStubBuilder::Reduce(GateRef glue, GateRef thisValue, GateRef numArgs,
1662 Variable *result, Label *exit, Label *slowPath)
1663 {
1664 auto env = GetEnvironment();
1665 DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0));
1666 Label isHeapObject(env);
1667 Label isJsArray(env);
1668 Label defaultConstr(env);
1669 Label atLeastOneArg(env);
1670 Label callbackFnHandleHeapObject(env);
1671 Label callbackFnHandleCallable(env);
1672 Label noTypeError(env);
1673
1674 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1675 Bind(&isHeapObject);
1676 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1677 Bind(&isJsArray);
1678 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1679 Bind(&defaultConstr);
1680 thisLen = GetArrayLength(thisValue);
1681 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
1682 Bind(&atLeastOneArg);
1683 GateRef callbackFnHandle = GetCallArg0(numArgs);
1684 BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath);
1685 Bind(&callbackFnHandleHeapObject);
1686 BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath);
1687 Bind(&callbackFnHandleCallable);
1688 GateRef thisLenIsZero = Int32Equal(*thisLen, Int32(0));
1689 GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2));
1690 BRANCH(BitAnd(thisLenIsZero, numArgsLessThanTwo), slowPath, &noTypeError);
1691 Bind(&noTypeError);
1692 {
1693 DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined());
1694 DEFVARIABLE(k, VariableType::INT32(), Int32(0));
1695
1696 Label updateAccumulator(env);
1697 Label checkForStableJSArray(env);
1698
1699 BRANCH(Int64Equal(numArgs, IntPtr(2)), &updateAccumulator, slowPath); // 2: provide initialValue param
1700 Bind(&updateAccumulator);
1701 {
1702 accumulator = GetCallArg1(numArgs);
1703 Jump(&checkForStableJSArray);
1704 }
1705 Bind(&checkForStableJSArray);
1706 {
1707 Label isStableJSArray(env);
1708 Label notStableJSArray(env);
1709 BRANCH(IsStableJSArray(glue, thisValue), &isStableJSArray, ¬StableJSArray);
1710 Bind(&isStableJSArray);
1711 {
1712 GateRef argsLength = Int32(4); // 4: «accumulator, kValue, k, thisValue»
1713 NewObjectStubBuilder newBuilder(this);
1714 GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
1715 Label loopHead(env);
1716 Label next(env);
1717 Label loopEnd(env);
1718 Label loopExit(env);
1719 Jump(&loopHead);
1720 LoopBegin(&loopHead);
1721 {
1722 BRANCH(Int32LessThan(*k, *thisLen), &next, &loopExit);
1723 Bind(&next);
1724 {
1725 Label updateK(env);
1726 Label notHole(env);
1727 Label changeThisLen(env);
1728 Label updateCallResult(env);
1729 GateRef elements = GetElementsArray(thisValue);
1730 GateRef kValue = GetTaggedValueWithElementsKind(thisValue, *k);
1731 BRANCH(TaggedIsHole(kValue), &loopEnd, ¬Hole);
1732 Bind(¬Hole);
1733 {
1734 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
1735 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), kValue);
1736 // 2 : parameter location
1737 SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
1738 // 3 : parameter location
1739 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
1740 GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
1741 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
1742 callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
1743 CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr,
1744 Circuit::NullGate(), callArgs);
1745 GateRef callResult = callBuilder.JSCallDispatch();
1746 Label hasException1(env);
1747 Label notHasException1(env);
1748 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
1749 Bind(&hasException1);
1750 {
1751 result->WriteVariable(Exception());
1752 Jump(exit);
1753 }
1754 Bind(¬HasException1);
1755 GateRef newLen = GetLengthOfTaggedArray(elements);
1756 BRANCH(Int32LessThan(newLen, *thisLen), &changeThisLen, &updateCallResult);
1757 Bind(&changeThisLen);
1758 {
1759 thisLen = newLen;
1760 Jump(&updateCallResult);
1761 }
1762 Bind(&updateCallResult);
1763 {
1764 accumulator = callResult;
1765 Jump(&loopEnd);
1766 }
1767 }
1768 }
1769 }
1770 Bind(&loopEnd);
1771 {
1772 k = Int32Add(*k, Int32(1));
1773
1774 Label isStableJSArray1(env);
1775 Label notStableJSArray1(env);
1776 BRANCH(IsStableJSArray(glue, thisValue), &isStableJSArray1, ¬StableJSArray1);
1777 Bind(¬StableJSArray1);
1778 {
1779 Jump(&loopExit);
1780 }
1781 Bind(&isStableJSArray1);
1782 LoopEnd(&loopHead, env, glue);
1783 }
1784 Bind(&loopExit);
1785 Jump(¬StableJSArray);
1786 }
1787 Bind(¬StableJSArray);
1788 {
1789 Label finish(env);
1790 Label callRT(env);
1791 BRANCH(Int32LessThan(*k, *thisLen), &callRT, &finish);
1792 Bind(&callRT);
1793 {
1794 accumulator = CallRuntime(glue, RTSTUB_ID(JSArrayReduceUnStable), { thisValue, thisValue,
1795 IntToTaggedInt(*k), IntToTaggedInt(*thisLen), *accumulator, callbackFnHandle });
1796 Jump(&finish);
1797 }
1798 Bind(&finish);
1799 {
1800 result->WriteVariable(*accumulator);
1801 Jump(exit);
1802 }
1803 }
1804 }
1805 }
1806 }
1807
Reverse(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1808 void BuiltinsArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs,
1809 Variable *result, Label *exit, Label *slowPath)
1810 {
1811 auto env = GetEnvironment();
1812 Label isHeapObject(env);
1813 Label isJsArray(env);
1814 Label isStability(env);
1815 Label defaultConstr(env);
1816 Label notCOWArray(env);
1817 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1818 Bind(&isHeapObject);
1819 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1820 Bind(&isJsArray);
1821 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1822 Bind(&defaultConstr);
1823 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1824 Bind(&isStability);
1825 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
1826 Bind(¬COWArray);
1827
1828 GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1829 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1830 DEFVARIABLE(j, VariableType::INT64(), Int64Sub(thisArrLen, Int64(1)));
1831
1832 GateRef hclass = LoadHClass(thisValue);
1833 GateRef kind = GetElementsKindFromHClass(hclass);
1834 Label isInt(env);
1835 Label isNotInt(env);
1836 Label notFastKind(env);
1837 GateRef isElementsKindEnabled = IsEnableElementsKind(glue);
1838 GateRef checkIntKind = LogicAndBuilder(env)
1839 .And(isElementsKindEnabled)
1840 .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::INT))))
1841 .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_INT))))
1842 .Done();
1843 BRANCH(checkIntKind, &isInt, &isNotInt);
1844 Bind(&isInt);
1845 {
1846 FastReverse(glue, thisValue, thisArrLen, ElementsKind::INT, result, exit);
1847 }
1848 Bind(&isNotInt);
1849 {
1850 Label isNumber(env);
1851 Label isNotNumber(env);
1852 GateRef checkNumberKind = LogicAndBuilder(env)
1853 .And(isElementsKindEnabled)
1854 .And(Int32GreaterThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::NUMBER))))
1855 .And(Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(ElementsKind::HOLE_NUMBER))))
1856 .Done();
1857 BRANCH(checkNumberKind, &isNumber, &isNotNumber);
1858 Bind(&isNumber);
1859 {
1860 FastReverse(glue, thisValue, thisArrLen, ElementsKind::NUMBER, result, exit);
1861 }
1862 Bind(&isNotNumber);
1863 {
1864 FastReverse(glue, thisValue, thisArrLen, ElementsKind::TAGGED, result, exit);
1865 }
1866 }
1867 }
1868
FastReverse(GateRef glue,GateRef thisValue,GateRef len,ElementsKind kind,Variable * result,Label * exit)1869 void BuiltinsArrayStubBuilder::FastReverse(GateRef glue, GateRef thisValue, GateRef len,
1870 ElementsKind kind, Variable *result, Label *exit)
1871 {
1872 auto env = GetEnvironment();
1873 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1874 DEFVARIABLE(j, VariableType::INT64(), Int64Sub(len, Int64(1)));
1875 GateRef elements = GetElementsArray(thisValue);
1876 Label loopHead(env);
1877 Label loopEnd(env);
1878 Label next(env);
1879 Label loopExit(env);
1880 Jump(&loopHead);
1881 LoopBegin(&loopHead);
1882 {
1883 Label arrayValue(env);
1884 Label valueEqual(env);
1885 BRANCH(Int64LessThan(*i, *j), &next, &loopExit);
1886 Bind(&next);
1887 {
1888 if (kind == ElementsKind::INT || kind == ElementsKind::NUMBER) {
1889 GateRef lower = GetValueFromMutantTaggedArray(elements, *i);
1890 GateRef upper = GetValueFromMutantTaggedArray(elements, *j);
1891 FastSetValueWithElementsKind(glue, elements, upper, *i, kind);
1892 FastSetValueWithElementsKind(glue, elements, lower, *j, kind);
1893 Jump(&loopEnd);
1894 } else {
1895 GateRef lower = GetValueFromTaggedArray(elements, *i);
1896 GateRef upper = GetValueFromTaggedArray(elements, *j);
1897 FastSetValueWithElementsKind(glue, elements, upper, *i, kind);
1898 FastSetValueWithElementsKind(glue, elements, lower, *j, kind);
1899 Jump(&loopEnd);
1900 }
1901 }
1902 }
1903 Bind(&loopEnd);
1904 i = Int64Add(*i, Int64(1));
1905 j = Int64Sub(*j, Int64(1));
1906 LoopEnd(&loopHead, env, glue);
1907 Bind(&loopExit);
1908 result->WriteVariable(thisValue);
1909 Jump(exit);
1910 }
1911
ToReversed(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1912 void BuiltinsArrayStubBuilder::ToReversed(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs,
1913 Variable *result, Label *exit, Label *slowPath)
1914 {
1915 auto env = GetEnvironment();
1916 Label isHeapObject(env);
1917 Label isJsArray(env);
1918 Label defaultConstr(env);
1919 Label isStability(env);
1920 Label notCOWArray(env);
1921 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1922 Bind(&isHeapObject);
1923 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
1924 Bind(&isJsArray);
1925 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1926 Bind(&defaultConstr);
1927 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
1928 Bind(&isStability);
1929 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
1930 Bind(¬COWArray);
1931
1932 GateRef thisArrLen = GetArrayLength(thisValue);
1933 GateRef receiver = NewArray(glue, Int32(0));
1934 GrowElementsCapacity(glue, receiver, thisArrLen);
1935 SetArrayLength(glue, receiver, thisArrLen);
1936 result->WriteVariable(DoReverse(glue, thisValue, receiver, Boolean(true), result, exit));
1937 Jump(exit);
1938 }
1939
DoReverse(GateRef glue,GateRef thisValue,GateRef receiver,GateRef receiverState,Variable * result,Label * exit)1940 GateRef BuiltinsArrayStubBuilder::DoReverse(GateRef glue, GateRef thisValue, GateRef receiver,
1941 GateRef receiverState, Variable *result, Label *exit)
1942 {
1943 auto env = GetEnvironment();
1944 Label entry(env);
1945 env->SubCfgEntry(&entry);
1946 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1947 DEFVARIABLE(j, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1)));
1948 Label loopHead(env);
1949 Label loopEnd(env);
1950 Label next(env);
1951 Label loopExit(env);
1952
1953 Jump(&loopHead);
1954 LoopBegin(&loopHead);
1955 {
1956 DEFVARIABLE(lower, VariableType::JS_ANY(), Hole());
1957 DEFVARIABLE(upper, VariableType::JS_ANY(), Hole());
1958 Label lowerValueIsHole(env);
1959 Label afterGettingLower(env);
1960 Label lowerHasProperty(env);
1961 Label lowerHasException0(env);
1962 Label upperValueIsHole(env);
1963 Label afterGettingUpper(env);
1964 Label upperHasProperty(env);
1965 Label upperHasException0(env);
1966 Label receiverIsNew(env);
1967 Label receiverIsOrigin(env);
1968 Label lowerIsHole(env);
1969 Label lowerIsNotHole(env);
1970 Label dealWithUpper(env);
1971 Label upperIsHole(env);
1972 Label upperIsNotHole(env);
1973 BRANCH(Int64LessThanOrEqual(*i, *j), &next, &loopExit);
1974 Bind(&next);
1975 {
1976 lower = GetTaggedValueWithElementsKind(thisValue, *i);
1977 BRANCH(TaggedIsHole(*lower), &lowerValueIsHole, &afterGettingLower);
1978 Bind(&lowerValueIsHole);
1979 {
1980 GateRef lowerHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
1981 BRANCH(TaggedIsTrue(lowerHasProp), &lowerHasProperty, &afterGettingLower);
1982 Bind(&lowerHasProperty);
1983 {
1984 lower = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
1985 BRANCH(HasPendingException(glue), &lowerHasException0, &afterGettingLower);
1986 Bind(&lowerHasException0);
1987 {
1988 result->WriteVariable(Exception());
1989 Jump(exit);
1990 }
1991 }
1992 }
1993 Bind(&afterGettingLower);
1994 {
1995 upper = GetTaggedValueWithElementsKind(thisValue, *j);
1996 BRANCH(TaggedIsHole(*upper), &upperValueIsHole, &afterGettingUpper);
1997 Bind(&upperValueIsHole);
1998 {
1999 GateRef upperHasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*j) });
2000 BRANCH(TaggedIsTrue(upperHasProp), &upperHasProperty, &afterGettingUpper);
2001 Bind(&upperHasProperty);
2002 {
2003 upper = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*j), ProfileOperation());
2004 BRANCH(HasPendingException(glue), &upperHasException0, &afterGettingUpper);
2005 }
2006 Bind(&upperHasException0);
2007 {
2008 result->WriteVariable(Exception());
2009 Jump(exit);
2010 }
2011 }
2012 Bind(&afterGettingUpper);
2013 {
2014 BRANCH(receiverState, &receiverIsNew, &receiverIsOrigin);
2015 Bind(&receiverIsNew);
2016 {
2017 BRANCH(TaggedIsHole(*lower), &lowerIsHole, &lowerIsNotHole);
2018 Bind(&lowerIsHole);
2019 {
2020 SetValueWithElementsKind(glue, receiver, Undefined(), *j, Boolean(true),
2021 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2022 Jump(&dealWithUpper);
2023 }
2024 Bind(&lowerIsNotHole);
2025 {
2026 SetValueWithElementsKind(glue, receiver, *lower, *j, Boolean(true),
2027 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2028 Jump(&dealWithUpper);
2029 }
2030 Bind(&dealWithUpper);
2031 {
2032 BRANCH(TaggedIsHole(*upper), &upperIsHole, &upperIsNotHole);
2033 Bind(&upperIsHole);
2034 {
2035 SetValueWithElementsKind(glue, receiver, Undefined(), *i, Boolean(true),
2036 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2037 Jump(&loopEnd);
2038 }
2039 Bind(&upperIsNotHole);
2040 {
2041 SetValueWithElementsKind(glue, receiver, *upper, *i, Boolean(true),
2042 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2043 Jump(&loopEnd);
2044 }
2045 }
2046 }
2047 Bind(&receiverIsOrigin);
2048 {
2049 SetValueWithElementsKind(glue, receiver, *upper, *i, Boolean(false),
2050 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2051 SetValueWithElementsKind(glue, receiver, *lower, *j, Boolean(false),
2052 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2053 Jump(&loopEnd);
2054 }
2055 }
2056 }
2057 }
2058 }
2059 Bind(&loopEnd);
2060 i = Int64Add(*i, Int64(1));
2061 j = Int64Sub(*j, Int64(1));
2062 LoopEnd(&loopHead);
2063 Bind(&loopExit);
2064 env->SubCfgExit();
2065 return receiver;
2066 }
2067
IsJsArrayWithLengthLimit(GateRef glue,GateRef object,uint32_t maxLength,JsArrayRequirements requirements)2068 GateRef BuiltinsArrayStubBuilder::IsJsArrayWithLengthLimit(GateRef glue, GateRef object,
2069 uint32_t maxLength, JsArrayRequirements requirements)
2070 {
2071 auto env = GetEnvironment();
2072 Label entry(env);
2073 env->SubCfgEntry(&entry);
2074 Label isHeapObject(env);
2075 Label isJsArray(env);
2076 Label stabilityCheckPassed(env);
2077 Label defaultConstructorCheckPassed(env);
2078 Label exit(env);
2079 DEFVARIABLE(result, VariableType::BOOL(), False());
2080
2081 BRANCH(TaggedIsHeapObject(object), &isHeapObject, &exit);
2082 Bind(&isHeapObject);
2083 BRANCH(IsJsArray(object), &isJsArray, &exit);
2084 Bind(&isJsArray);
2085 if (requirements.stable) {
2086 BRANCH(IsStableJSArray(glue, object), &stabilityCheckPassed, &exit);
2087 } else {
2088 Jump(&stabilityCheckPassed);
2089 }
2090 Bind(&stabilityCheckPassed);
2091 if (requirements.defaultConstructor) {
2092 // If HasConstructor bit is set to 1, then the constructor has been modified.
2093 BRANCH(HasConstructor(object), &exit, &defaultConstructorCheckPassed);
2094 } else {
2095 Jump(&defaultConstructorCheckPassed);
2096 }
2097 Bind(&defaultConstructorCheckPassed);
2098 result.WriteVariable(Int32UnsignedLessThanOrEqual(GetArrayLength(object), Int32(maxLength)));
2099 Jump(&exit);
2100 Bind(&exit);
2101 GateRef ret = *result;
2102 env->SubCfgExit();
2103 return ret;
2104 }
2105
Values(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2106 void BuiltinsArrayStubBuilder::Values(GateRef glue, GateRef thisValue,
2107 [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
2108 {
2109 auto env = GetEnvironment();
2110 Label isHeapObject(env);
2111 Label isJsArray(env);
2112 Label defaultConstr(env);
2113 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2114 Bind(&isHeapObject);
2115 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2116 Bind(&isJsArray);
2117 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2118 Bind(&defaultConstr);
2119 ConstantIndex iterClassIdx = ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX;
2120 GateRef iteratorHClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, iterClassIdx);
2121 NewObjectStubBuilder newBuilder(this);
2122 newBuilder.SetParameters(glue, 0);
2123 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2124 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2125 GateRef prototype = GetGlobalEnvValue(VariableType::JS_POINTER(), glueGlobalEnv,
2126 GlobalEnv::ARRAY_ITERATOR_PROTOTYPE_INDEX);
2127 SetPrototypeToHClass(VariableType::JS_POINTER(), glue, iteratorHClass, prototype);
2128 GateRef iter = newBuilder.NewJSObject(glue, iteratorHClass);
2129 SetIteratedArrayOfArrayIterator(glue, iter, thisValue);
2130 SetNextIndexOfArrayIterator(glue, iter, Int32(0));
2131 GateRef kind = Int32(static_cast<int32_t>(IterationKind::VALUE));
2132 SetBitFieldOfArrayIterator(glue, iter, kind);
2133 result->WriteVariable(iter);
2134 Jump(exit);
2135 }
2136
Find(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2137 void BuiltinsArrayStubBuilder::Find(GateRef glue, GateRef thisValue, GateRef numArgs,
2138 Variable *result, Label *exit, Label *slowPath)
2139 {
2140 auto env = GetEnvironment();
2141 Label isHeapObject(env);
2142 Label isJsArray(env);
2143 Label isStability(env);
2144 Label defaultConstr(env);
2145 Label notCOWArray(env);
2146 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2147 Bind(&isHeapObject);
2148 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2149 Bind(&isJsArray);
2150 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2151 Bind(&defaultConstr);
2152 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
2153 Bind(&isStability);
2154 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
2155 Bind(¬COWArray);
2156
2157 GateRef callbackFnHandle = GetCallArg0(numArgs);
2158 Label arg0HeapObject(env);
2159 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
2160 Bind(&arg0HeapObject);
2161 Label callable(env);
2162 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
2163 Bind(&callable);
2164 GateRef argHandle = GetCallArg1(numArgs);
2165 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
2166 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
2167 Label loopHead(env);
2168 Label loopEnd(env);
2169 Label next(env);
2170 Label loopExit(env);
2171 Jump(&loopHead);
2172 LoopBegin(&loopHead);
2173 {
2174 Label hasException0(env);
2175 Label notHasException0(env);
2176 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
2177 Bind(&next);
2178 GateRef kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
2179 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
2180 Bind(&hasException0);
2181 {
2182 result->WriteVariable(Exception());
2183 Jump(exit);
2184 }
2185 Bind(¬HasException0);
2186 {
2187 GateRef key = Int64ToTaggedInt(*i);
2188 Label hasException(env);
2189 Label notHasException(env);
2190 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2191 callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue };
2192 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
2193 Circuit::NullGate(), callArgs);
2194 GateRef retValue = callBuilder.JSCallDispatch();
2195 BRANCH(HasPendingException(glue), &hasException, ¬HasException);
2196 Bind(&hasException);
2197 {
2198 result->WriteVariable(retValue);
2199 Jump(exit);
2200 }
2201 Bind(¬HasException);
2202 {
2203 Label find(env);
2204 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
2205 Bind(&find);
2206 {
2207 result->WriteVariable(kValue);
2208 Jump(exit);
2209 }
2210 }
2211 }
2212 }
2213 Bind(&loopEnd);
2214 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2215 i = Int64Add(*i, Int64(1));
2216 LoopEnd(&loopHead, env, glue);
2217 Bind(&loopExit);
2218 Jump(exit);
2219 }
2220
FindIndex(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2221 void BuiltinsArrayStubBuilder::FindIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
2222 Variable *result, Label *exit, Label *slowPath)
2223 {
2224 auto env = GetEnvironment();
2225 Label isHeapObject(env);
2226 Label isJsArray(env);
2227 Label defaultConstr(env);
2228 Label notCOWArray(env);
2229 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2230 Bind(&isHeapObject);
2231 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2232 Bind(&isJsArray);
2233 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2234 Bind(&defaultConstr);
2235 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
2236 Bind(¬COWArray);
2237
2238 Label arg0HeapObject(env);
2239 Label callable(env);
2240 Label stableJSArray(env);
2241 Label notStableJSArray(env);
2242 GateRef callbackFnHandle = GetCallArg0(numArgs);
2243 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
2244 Bind(&arg0HeapObject);
2245 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
2246 Bind(&callable);
2247 result->WriteVariable(IntToTaggedPtr(Int32(-1)));
2248 GateRef argHandle = GetCallArg1(numArgs);
2249 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
2250 BRANCH(IsStableJSArray(glue, thisValue), &stableJSArray, ¬StableJSArray);
2251 Bind(&stableJSArray);
2252 {
2253 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
2254 DEFVARIABLE(kValue, VariableType::JS_ANY(), Undefined());
2255 Label loopHead(env);
2256 Label loopEnd(env);
2257 Label next(env);
2258 Label loopExit(env);
2259 Jump(&loopHead);
2260 LoopBegin(&loopHead);
2261 {
2262 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
2263 Bind(&next);
2264 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
2265 Label isHole(env);
2266 Label notHole(env);
2267 BRANCH(TaggedIsHole(*kValue), &isHole, ¬Hole);
2268 Bind(&isHole);
2269 {
2270 Label hasException0(env);
2271 Label notHasException0(env);
2272 GateRef res = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
2273 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
2274 Bind(&hasException0);
2275 {
2276 result->WriteVariable(Exception());
2277 Jump(exit);
2278 }
2279 Bind(¬HasException0);
2280 {
2281 Label resIsHole(env);
2282 Label resNotHole(env);
2283 BRANCH(TaggedIsHole(res), &resIsHole, &resNotHole);
2284 Bind(&resIsHole);
2285 {
2286 kValue = Undefined();
2287 Jump(¬Hole);
2288 }
2289 Bind(&resNotHole);{
2290 kValue = res;
2291 Jump(¬Hole);
2292 }
2293 }
2294 }
2295 Bind(¬Hole);
2296 {
2297 GateRef key = IntToTaggedPtr(*i);
2298 Label hasException(env);
2299 Label notHasException(env);
2300 Label checkStable(env);
2301 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2302 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
2303 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
2304 Circuit::NullGate(), callArgs);
2305 GateRef retValue = callBuilder.JSCallDispatch();
2306 BRANCH(HasPendingException(glue), &hasException, ¬HasException);
2307 Bind(&hasException);
2308 {
2309 result->WriteVariable(retValue);
2310 Jump(exit);
2311 }
2312 Bind(¬HasException);
2313 {
2314 Label find(env);
2315 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &checkStable);
2316 Bind(&find);
2317 {
2318 result->WriteVariable(key);
2319 Jump(exit);
2320 }
2321 }
2322 Bind(&checkStable);
2323 i = Int64Add(*i, Int64(1));
2324 BRANCH(IsStableJSArray(glue, thisValue), &loopEnd, ¬StableJSArray);
2325 }
2326 }
2327 Bind(&loopEnd);
2328 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2329 LoopEnd(&loopHead, env, glue);
2330 Bind(&loopExit);
2331 Jump(exit);
2332 }
2333 Bind(¬StableJSArray);
2334 {
2335 DEFVARIABLE(j, VariableType::INT64(), Int64(0));
2336 Label loopHead(env);
2337 Label loopEnd(env);
2338 Label next(env);
2339 Label loopExit(env);
2340 Jump(&loopHead);
2341 LoopBegin(&loopHead);
2342 {
2343 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2344 BRANCH(Int64LessThan(*j, *thisArrLen), &next, &loopExit);
2345 Bind(&next);
2346 {
2347 Label hasException0(env);
2348 Label notHasException0(env);
2349 GateRef kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*j), ProfileOperation());
2350 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
2351 Bind(&hasException0);
2352 {
2353 result->WriteVariable(Exception());
2354 Jump(exit);
2355 }
2356 Bind(¬HasException0);
2357 {
2358 GateRef key = IntToTaggedPtr(*j);
2359 Label hasException(env);
2360 Label notHasException(env);
2361 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2362 callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue };
2363 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
2364 nullptr, Circuit::NullGate(), callArgs);
2365 GateRef retValue = callBuilder.JSCallDispatch();
2366 BRANCH(TaggedIsException(retValue), &hasException, ¬HasException);
2367 Bind(&hasException);
2368 {
2369 result->WriteVariable(retValue);
2370 Jump(exit);
2371 }
2372 Bind(¬HasException);
2373 {
2374 Label find(env);
2375 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
2376 Bind(&find);
2377 {
2378 result->WriteVariable(key);
2379 Jump(exit);
2380 }
2381 }
2382 }
2383 }
2384 }
2385 Bind(&loopEnd);
2386 thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2387 j = Int64Add(*j, Int64(1));
2388 LoopEnd(&loopHead, env, glue);
2389 Bind(&loopExit);
2390 Jump(exit);
2391 }
2392 }
2393
Push(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2394 void BuiltinsArrayStubBuilder::Push(GateRef glue, GateRef thisValue,
2395 GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
2396 {
2397 auto env = GetEnvironment();
2398 Label isHeapObject(env);
2399 Label isJsArray(env);
2400 Label isStability(env);
2401 Label setLength(env);
2402 Label smallArgs(env);
2403 Label checkSmallArgs(env);
2404
2405 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2406 Bind(&isHeapObject);
2407 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2408 Bind(&isJsArray);
2409 Label isLengthWritable(env);
2410 BRANCH(IsArrayLengthWritable(glue, thisValue), &isLengthWritable, slowPath);
2411 Bind(&isLengthWritable);
2412
2413 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
2414 Bind(&isStability);
2415
2416 GateRef oldLength = GetArrayLength(thisValue);
2417 *result = IntToTaggedPtr(oldLength);
2418
2419 BRANCH(Int32Equal(ChangeIntPtrToInt32(numArgs), Int32(0)), exit, &checkSmallArgs);
2420 Bind(&checkSmallArgs);
2421 // now unsupport more than 2 args
2422 BRANCH(Int32LessThanOrEqual(ChangeIntPtrToInt32(numArgs), Int32(2)), &smallArgs, slowPath);
2423 Bind(&smallArgs);
2424 GateRef newLength = Int32Add(oldLength, ChangeIntPtrToInt32(numArgs));
2425
2426 DEFVARIABLE(elements, VariableType::JS_ANY(), GetElementsArray(thisValue));
2427 GateRef capacity = GetLengthOfTaggedArray(*elements);
2428 Label grow(env);
2429 Label setValue(env);
2430 BRANCH(Int32GreaterThan(newLength, capacity), &grow, &setValue);
2431 Bind(&grow);
2432 {
2433 elements = GrowElementsCapacity(glue, thisValue, newLength);
2434 Jump(&setValue);
2435 }
2436 Bind(&setValue);
2437 {
2438 Label oneArg(env);
2439 Label twoArg(env);
2440 DEFVARIABLE(index, VariableType::INT32(), Int32(0));
2441 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
2442 BRANCH(Int64Equal(numArgs, IntPtr(1)), &oneArg, &twoArg); // 1 one arg
2443 Bind(&oneArg);
2444 {
2445 value = GetCallArg0(numArgs);
2446 index = Int32Add(oldLength, Int32(0)); // 0 slot index
2447 SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true),
2448 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2449 Jump(&setLength);
2450 }
2451 Bind(&twoArg);
2452 {
2453 value = GetCallArg0(numArgs);
2454 index = Int32Add(oldLength, Int32(0)); // 0 slot index
2455 SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true),
2456 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2457 value = GetCallArg1(numArgs);
2458 index = Int32Add(oldLength, Int32(1)); // 1 slot index
2459 SetValueWithElementsKind(glue, thisValue, *value, *index, Boolean(true),
2460 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2461 Jump(&setLength);
2462 }
2463 }
2464 Bind(&setLength);
2465 SetArrayLength(glue, thisValue, newLength);
2466 result->WriteVariable(IntToTaggedPtr(newLength));
2467 Jump(exit);
2468 }
2469
IsConcatSpreadable(GateRef glue,GateRef obj)2470 GateRef BuiltinsArrayStubBuilder::IsConcatSpreadable(GateRef glue, GateRef obj)
2471 {
2472 auto env = GetEnvironment();
2473 Label entry(env);
2474 env->SubCfgEntry(&entry);
2475 DEFVARIABLE(result, VariableType::BOOL(), False());
2476 Label exit(env);
2477 Label isEcmaObj(env);
2478 BRANCH(IsEcmaObject(obj), &isEcmaObj, &exit);
2479 Bind(&isEcmaObj);
2480 {
2481 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2482 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2483 GateRef isConcatsprKey =
2484 GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ISCONCAT_SYMBOL_INDEX);
2485 AccessObjectStubBuilder builder(this);
2486 GateRef spreadable =
2487 builder.LoadObjByValue(glue, obj, isConcatsprKey, Undefined(), Int32(0), ProfileOperation());
2488 Label isDefined(env);
2489 Label isUnDefined(env);
2490 BRANCH(TaggedIsUndefined(spreadable), &isUnDefined, &isDefined);
2491 Bind(&isUnDefined);
2492 {
2493 Label IsArray(env);
2494 BRANCH(IsJsArray(obj), &IsArray, &exit);
2495 Bind(&IsArray);
2496 result = True();
2497 Jump(&exit);
2498 }
2499 Bind(&isDefined);
2500 {
2501 result = TaggedIsTrue(spreadable);
2502 Jump(&exit);
2503 }
2504 }
2505 Bind(&exit);
2506 auto res = *result;
2507 env->SubCfgExit();
2508 return res;
2509 }
2510
NewArray(GateRef glue,GateRef count)2511 GateRef BuiltinsArrayStubBuilder::NewArray(GateRef glue, GateRef count)
2512 {
2513 auto env = GetEnvironment();
2514 Label entry(env);
2515 env->SubCfgEntry(&entry);
2516 DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined());
2517 Label exit(env);
2518 Label setProperties(env);
2519 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2520 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2521 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2522 GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2523 NewObjectStubBuilder newBuilder(this);
2524 newBuilder.SetParameters(glue, 0);
2525 result = newBuilder.NewJSArrayWithSize(intialHClass, count);
2526 BRANCH(TaggedIsException(*result), &exit, &setProperties);
2527 Bind(&setProperties);
2528 {
2529 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
2530 Store(VariableType::INT32(), glue, *result, lengthOffset, TruncInt64ToInt32(count));
2531 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2532 SetPropertyInlinedProps(glue, *result, intialHClass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
2533 SetExtensibleToBitfield(glue, *result, true);
2534 Jump(&exit);
2535 }
2536 Bind(&exit);
2537 auto res = *result;
2538 env->SubCfgExit();
2539 return res;
2540 }
2541
Includes(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2542 void BuiltinsArrayStubBuilder::Includes(GateRef glue, GateRef thisValue, GateRef numArgs,
2543 Variable *result, Label *exit, Label *slowPath)
2544 {
2545 auto env = GetEnvironment();
2546 Label isDictMode(env);
2547 Label isHeapObject(env);
2548 Label isJsArray(env);
2549 Label isStableJsArray(env);
2550 Label notFound(env);
2551 Label thisLenNotZero(env);
2552 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2553 Bind(&isHeapObject);
2554 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2555 Bind(&isJsArray);
2556 BRANCH(IsStableJSArray(glue, thisValue), &isStableJsArray, slowPath);
2557 Bind(&isStableJsArray);
2558 GateRef thisLen = GetArrayLength(thisValue);
2559 BRANCH(Int32Equal(thisLen, Int32(0)), ¬Found, &thisLenNotZero);
2560 Bind(&thisLenNotZero);
2561 {
2562 DEFVARIABLE(fromIndex, VariableType::INT32(), Int32(0));
2563 Label getArgTwo(env);
2564 Label nextProcess(env);
2565 BRANCH(Int64Equal(numArgs, IntPtr(2)), &getArgTwo, &nextProcess); // 2: 2 parameters
2566 Bind(&getArgTwo);
2567 {
2568 Label secondArgIsInt(env);
2569 GateRef fromIndexTemp = GetCallArg1(numArgs);
2570 BRANCH(TaggedIsInt(fromIndexTemp), &secondArgIsInt, slowPath);
2571 Bind(&secondArgIsInt);
2572 fromIndex = GetInt32OfTInt(fromIndexTemp);
2573 Jump(&nextProcess);
2574 }
2575 Bind(&nextProcess);
2576 {
2577 Label atLeastOneArg(env);
2578 Label setBackZero(env);
2579 Label calculateFrom(env);
2580 Label nextCheck(env);
2581 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
2582 Bind(&atLeastOneArg);
2583 BRANCH(Int32GreaterThanOrEqual(*fromIndex, thisLen), ¬Found, &nextCheck);
2584 Bind(&nextCheck);
2585 {
2586 GateRef negThisLen = Int32Sub(Int32(0), thisLen);
2587 BRANCH(Int32LessThan(*fromIndex, negThisLen), &setBackZero, &calculateFrom);
2588 Bind(&setBackZero);
2589 {
2590 fromIndex = Int32(0);
2591 Jump(&calculateFrom);
2592 }
2593 Bind(&calculateFrom);
2594 {
2595 DEFVARIABLE(from, VariableType::INT32(), Int32(0));
2596 Label fromIndexGreaterOrEqualZero(env);
2597 Label fromIndexLessThanZero(env);
2598 Label startLoop(env);
2599 BRANCH(Int32GreaterThanOrEqual(*fromIndex, Int32(0)),
2600 &fromIndexGreaterOrEqualZero, &fromIndexLessThanZero);
2601 Bind(&fromIndexGreaterOrEqualZero);
2602 {
2603 from = *fromIndex;
2604 Jump(&startLoop);
2605 }
2606 Bind(&fromIndexLessThanZero);
2607 {
2608 Label isLenFromIndex(env);
2609 GateRef lenFromIndexSum = Int32Add(thisLen, *fromIndex);
2610 BRANCH(Int32GreaterThanOrEqual(lenFromIndexSum, Int32(0)), &isLenFromIndex, &startLoop);
2611 Bind(&isLenFromIndex);
2612 {
2613 from = lenFromIndexSum;
2614 Jump(&startLoop);
2615 }
2616 }
2617 Bind(&startLoop);
2618 {
2619 GateRef searchElement = GetCallArg0(numArgs);
2620 Label loopHead(env);
2621 Label loopEnd(env);
2622 Label next(env);
2623 Label loopExit(env);
2624 Jump(&loopHead);
2625 LoopBegin(&loopHead);
2626 {
2627 BRANCH(Int32LessThan(*from, thisLen), &next, &loopExit);
2628 Bind(&next);
2629 {
2630 Label notHoleOrUndefValue(env);
2631 Label valueFound(env);
2632 GateRef value = GetTaggedValueWithElementsKind(thisValue, *from);
2633 GateRef isHole = TaggedIsHole(value);
2634 GateRef isUndef = TaggedIsUndefined(value);
2635 BRANCH(BitOr(isHole, isUndef), slowPath, ¬HoleOrUndefValue);
2636 Bind(¬HoleOrUndefValue);
2637 GateRef valueEqual = StubBuilder::SameValueZero(glue, searchElement, value);
2638 BRANCH(valueEqual, &valueFound, &loopEnd);
2639 Bind(&valueFound);
2640 {
2641 result->WriteVariable(TaggedTrue());
2642 Jump(exit);
2643 }
2644 }
2645 }
2646 Bind(&loopEnd);
2647 from = Int32Add(*from, Int32(1));
2648 LoopEnd(&loopHead, env, glue);
2649 Bind(&loopExit);
2650 Jump(¬Found);
2651 }
2652 }
2653 }
2654 }
2655 }
2656 Bind(¬Found);
2657 {
2658 result->WriteVariable(TaggedFalse());
2659 Jump(exit);
2660 }
2661 }
2662
From(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2663 void BuiltinsArrayStubBuilder::From(GateRef glue, [[maybe_unused]] GateRef thisValue, GateRef numArgs,
2664 Variable *result, Label *exit, Label *slowPath)
2665 {
2666 auto env = GetEnvironment();
2667 GateRef item = GetCallArg0(numArgs);
2668 Label stringItem(env);
2669 BRANCH(TaggedIsString(item), &stringItem, slowPath);
2670 Bind(&stringItem);
2671 Label undefFn(env);
2672 GateRef fn = GetCallArg1(numArgs);
2673 BRANCH(TaggedIsUndefined(fn), &undefFn, slowPath);
2674 Bind(&undefFn);
2675 GateRef strLen = GetLengthFromString(item);
2676 Label lessStrLen(env);
2677 BRANCH(Int32LessThan(strLen, Int32(builtins::StringToListResultCache::MAX_STRING_LENGTH)), &lessStrLen, slowPath);
2678 Bind(&lessStrLen);
2679 GateRef cacheArray = CallNGCRuntime(glue, RTSTUB_ID(GetStringToListCacheArray), { glue });
2680
2681 Label cacheDef(env);
2682 BRANCH(TaggedIsUndefined(cacheArray), slowPath, &cacheDef);
2683 Bind(&cacheDef);
2684 {
2685 GateRef hash = GetHashcodeFromString(glue, item);
2686 GateRef entry = Int32And(hash, Int32Sub(Int32(builtins::StringToListResultCache::CACHE_SIZE), Int32(1)));
2687 GateRef index = Int32Mul(entry, Int32(builtins::StringToListResultCache::ENTRY_SIZE));
2688 GateRef cacheStr = GetValueFromTaggedArray(cacheArray,
2689 Int32Add(index, Int32(builtins::StringToListResultCache::STRING_INDEX)));
2690 Label cacheStrDef(env);
2691 BRANCH(TaggedIsUndefined(cacheStr), slowPath, &cacheStrDef);
2692 Bind(&cacheStrDef);
2693 Label strEqual(env);
2694 Label strSlowEqual(env);
2695 // cache str is intern
2696 BRANCH(Equal(cacheStr, item), &strEqual, &strSlowEqual);
2697 Bind(&strSlowEqual);
2698 BRANCH(FastStringEqual(glue, cacheStr, item), &strEqual, slowPath);
2699 Bind(&strEqual);
2700
2701 GateRef cacheResArray = GetValueFromTaggedArray(cacheArray,
2702 Int32Add(index, Int32(builtins::StringToListResultCache::ARRAY_INDEX)));
2703 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
2704 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2705 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2706 GateRef intialHClass = Load(VariableType::JS_ANY(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2707 NewObjectStubBuilder newBuilder(this);
2708 newBuilder.SetParameters(glue, 0);
2709 GateRef newArray = newBuilder.NewJSObject(glue, intialHClass);
2710 Store(VariableType::INT32(), glue, newArray, IntPtr(JSArray::LENGTH_OFFSET), strLen);
2711 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2712 SetPropertyInlinedProps(glue, newArray, intialHClass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
2713 SetExtensibleToBitfield(glue, newArray, true);
2714
2715 SetElementsArray(VariableType::JS_ANY(), glue, newArray, cacheResArray);
2716 *result = newArray;
2717 Jump(exit);
2718 }
2719 }
2720
CreateSpliceDeletedArray(GateRef glue,GateRef thisValue,GateRef actualDeleteCount,GateRef arrayCls,GateRef start)2721 GateRef BuiltinsArrayStubBuilder::CreateSpliceDeletedArray(GateRef glue, GateRef thisValue, GateRef actualDeleteCount,
2722 GateRef arrayCls, GateRef start)
2723 {
2724 auto env = GetEnvironment();
2725 Label subentry(env);
2726 Label exit(env);
2727 env->SubCfgEntry(&subentry);
2728 DEFVARIABLE(result, VariableType::BOOL(), False());
2729
2730 // new delete array
2731 DEFVARIABLE(srcElements, VariableType::JS_ANY(), GetElementsArray(thisValue));
2732 NewObjectStubBuilder newBuilder(this);
2733 newBuilder.SetParameters(glue, 0);
2734 GateRef newArray = newBuilder.NewJSArrayWithSize(arrayCls, actualDeleteCount);
2735 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
2736 Store(VariableType::INT32(), glue, newArray, lengthOffset, TruncInt64ToInt32(actualDeleteCount));
2737 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2738 SetPropertyInlinedProps(glue, newArray, arrayCls, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
2739 SetExtensibleToBitfield(glue, newArray, true);
2740 result = newArray;
2741
2742 DEFVARIABLE(i, VariableType::INT32(), Int32(0));
2743 Label loopHead(env);
2744 Label loopEnd(env);
2745 Label next(env);
2746 Label loopExit(env);
2747 Jump(&loopHead);
2748 LoopBegin(&loopHead);
2749 {
2750 BRANCH(Int32LessThan(*i, actualDeleteCount), &next, &loopExit);
2751 Bind(&next);
2752 Label setHole(env);
2753 Label setSrc(env);
2754 BRANCH(Int32GreaterThanOrEqual(Int32Add(*i, start),
2755 GetLengthOfTaggedArray(*srcElements)), &setHole, &setSrc);
2756 Bind(&setHole);
2757 {
2758 SetValueWithElementsKind(glue, newArray, Hole(), *i, Boolean(true),
2759 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2760 Jump(&loopEnd);
2761 }
2762 Bind(&setSrc);
2763 {
2764 GateRef val = GetTaggedValueWithElementsKind(thisValue, Int32Add(start, *i));
2765 SetValueWithElementsKind(glue, newArray, val, *i, Boolean(true),
2766 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2767 Jump(&loopEnd);
2768 }
2769 }
2770 Bind(&loopEnd);
2771 i = Int32Add(*i, Int32(1));
2772 LoopEnd(&loopHead, env, glue);
2773 Bind(&loopExit);
2774 Jump(&exit);
2775
2776 Bind(&exit);
2777 auto res = *result;
2778 env->SubCfgExit();
2779 return res;
2780 }
2781
Splice(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2782 void BuiltinsArrayStubBuilder::Splice(GateRef glue, GateRef thisValue, GateRef numArgs,
2783 Variable *result, Label *exit, Label *slowPath)
2784 {
2785 auto env = GetEnvironment();
2786 Label isHeapObject(env);
2787 Label isJsArray(env);
2788 Label isStability(env);
2789 Label defaultConstr(env);
2790 Label matchCls(env);
2791 Label isGeneric(env);
2792 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2793 Bind(&isHeapObject);
2794 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
2795 Bind(&isJsArray);
2796 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2797 Bind(&defaultConstr);
2798 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
2799 Bind(&isStability);
2800 Label notCOWArray(env);
2801 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
2802 Bind(¬COWArray);
2803 GateRef arrayCls = LoadHClass(thisValue);
2804 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
2805 Bind(&matchCls);
2806 GateRef arrayLen = GetArrayLength(thisValue);
2807 Label lessThreeArg(env);
2808
2809 DEFVARIABLE(start, VariableType::INT32(), Int32(0));
2810 DEFVARIABLE(insertCount, VariableType::INT32(), Int32(0));
2811 DEFVARIABLE(actualDeleteCount, VariableType::INT32(), Int32(0));
2812 GateRef argc = ChangeIntPtrToInt32(numArgs);
2813 BRANCH(Int32LessThanOrEqual(argc, Int32(3)), &lessThreeArg, slowPath); // 3 : three arg
2814 Bind(&lessThreeArg);
2815 {
2816 Label checkOverflow(env);
2817 Label greaterZero(env);
2818 Label greaterOne(env);
2819 Label checkGreaterOne(env);
2820 Label notOverflow(env);
2821 BRANCH(Int32GreaterThan(argc, Int32(0)), &greaterZero, &checkGreaterOne);
2822 Bind(&greaterZero);
2823 GateRef taggedStart = GetCallArg0(numArgs);
2824 Label taggedStartInt(env);
2825 BRANCH(TaggedIsInt(taggedStart), &taggedStartInt, slowPath);
2826 Bind(&taggedStartInt);
2827 {
2828 GateRef intStart = GetInt32OfTInt(taggedStart);
2829 start = CalArrayRelativePos(intStart, arrayLen);
2830 }
2831 actualDeleteCount = Int32Sub(arrayLen, *start);
2832 Jump(&checkGreaterOne);
2833 Bind(&checkGreaterOne);
2834 BRANCH(Int32GreaterThan(argc, Int32(1)), &greaterOne, &checkOverflow);
2835 Bind(&greaterOne);
2836 insertCount = Int32Sub(argc, Int32(2)); // 2 : two args
2837 GateRef argDeleteCount = GetCallArg1(numArgs);
2838 Label argDeleteCountInt(env);
2839 BRANCH(TaggedIsInt(argDeleteCount), &argDeleteCountInt, slowPath);
2840 Bind(&argDeleteCountInt);
2841 DEFVARIABLE(deleteCount, VariableType::INT32(), TaggedGetInt(argDeleteCount));
2842 Label deleteCountLessZero(env);
2843 Label calActualDeleteCount(env);
2844 BRANCH(Int32LessThan(*deleteCount, Int32(0)), &deleteCountLessZero, &calActualDeleteCount);
2845 Bind(&deleteCountLessZero);
2846 deleteCount = Int32(0);
2847 Jump(&calActualDeleteCount);
2848 Bind(&calActualDeleteCount);
2849 actualDeleteCount = *deleteCount;
2850 Label lessArrayLen(env);
2851 BRANCH(Int32LessThan(Int32Sub(arrayLen, *start), *deleteCount), &lessArrayLen, &checkOverflow);
2852 Bind(&lessArrayLen);
2853 actualDeleteCount = Int32Sub(arrayLen, *start);
2854 Jump(&checkOverflow);
2855 Bind(&checkOverflow);
2856 BRANCH(Int64GreaterThan(Int64Sub(Int64Add(ZExtInt32ToInt64(arrayLen), ZExtInt32ToInt64(*insertCount)),
2857 ZExtInt32ToInt64(*actualDeleteCount)), Int64(base::MAX_SAFE_INTEGER)), slowPath, ¬Overflow);
2858 Bind(¬Overflow);
2859 *result = CreateSpliceDeletedArray(glue, thisValue, *actualDeleteCount, arrayCls, *start);
2860 // insert Val
2861 DEFVARIABLE(srcElements, VariableType::JS_ANY(), GetElementsArray(thisValue));
2862 GateRef oldCapacity = GetLengthOfTaggedArray(*srcElements);
2863 GateRef newCapacity = Int32Add(Int32Sub(arrayLen, *actualDeleteCount), *insertCount);
2864 Label grow(env);
2865 Label copy(env);
2866 BRANCH(Int32GreaterThan(newCapacity, oldCapacity), &grow, ©);
2867 Bind(&grow);
2868 {
2869 srcElements = GrowElementsCapacity(glue, thisValue, newCapacity);
2870 Jump(©);
2871 }
2872 Bind(©);
2873 GateRef srcElementsLen = GetLengthOfTaggedArray(*srcElements);
2874 Label insertLessDelete(env);
2875 Label insertGreaterDelete(env);
2876 Label insertCountVal(env);
2877 Label setArrayLen(env);
2878 Label trimCheck(env);
2879 BRANCH(Int32LessThan(*insertCount, *actualDeleteCount), &insertLessDelete, &insertGreaterDelete);
2880 Bind(&insertLessDelete);
2881 {
2882 {
2883 DEFVARIABLE(i, VariableType::INT32(), *start);
2884 DEFVARIABLE(ele, VariableType::JS_ANY(), Hole());
2885
2886 Label loopHead(env);
2887 Label loopEnd(env);
2888 Label next(env);
2889 Label loopExit(env);
2890 Jump(&loopHead);
2891 LoopBegin(&loopHead);
2892 {
2893 BRANCH(Int32LessThan(*i, Int32Sub(arrayLen, *actualDeleteCount)), &next, &loopExit);
2894 Bind(&next);
2895 ele = Hole();
2896 Label getSrcEle(env);
2897 Label setEle(env);
2898 BRANCH(Int32LessThan(Int32Add(*i, *actualDeleteCount), srcElementsLen), &getSrcEle, &setEle);
2899 Bind(&getSrcEle);
2900 {
2901 ele = GetTaggedValueWithElementsKind(thisValue, Int32Add(*i, *actualDeleteCount));
2902 Jump(&setEle);
2903 }
2904 Bind(&setEle);
2905 {
2906 Label setIndexLessLen(env);
2907 BRANCH(Int32LessThan(Int32Add(*i, *insertCount), srcElementsLen), &setIndexLessLen, &loopEnd);
2908 Bind(&setIndexLessLen);
2909 {
2910 SetValueWithElementsKind(glue, thisValue, *ele, Int32Add(*i, *insertCount), Boolean(true),
2911 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2912 Jump(&loopEnd);
2913 }
2914 }
2915 }
2916 Bind(&loopEnd);
2917 i = Int32Add(*i, Int32(1));
2918 LoopEnd(&loopHead, env, glue);
2919 Bind(&loopExit);
2920 Jump(&trimCheck);
2921 }
2922
2923 Label trim(env);
2924 Label noTrim(env);
2925 Bind(&trimCheck);
2926 GateRef needTrim = LogicAndBuilder(env)
2927 .And(Int32GreaterThan(oldCapacity, newCapacity))
2928 .And(Int32GreaterThan(Int32Sub(newCapacity, oldCapacity), Int32(TaggedArray::MAX_END_UNUSED)))
2929 .Done();
2930 BRANCH(needTrim, &trim, &noTrim);
2931 Bind(&trim);
2932 {
2933 CallNGCRuntime(glue, RTSTUB_ID(ArrayTrim), {glue, *srcElements, ZExtInt32ToInt64(newCapacity)});
2934 Jump(&insertCountVal);
2935 }
2936 Bind(&noTrim);
2937 {
2938 DEFVARIABLE(idx, VariableType::INT32(), newCapacity);
2939 Label loopHead1(env);
2940 Label loopEnd1(env);
2941 Label next1(env);
2942 Label loopExit1(env);
2943 Jump(&loopHead1);
2944 LoopBegin(&loopHead1);
2945 {
2946 BRANCH(Int32LessThan(*idx, arrayLen), &next1, &loopExit1);
2947 Bind(&next1);
2948
2949 Label setHole(env);
2950 BRANCH(Int32LessThan(*idx, srcElementsLen), &setHole, &loopEnd1);
2951 Bind(&setHole);
2952 {
2953 SetValueWithElementsKind(glue, thisValue, Hole(), *idx, Boolean(true),
2954 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2955 Jump(&loopEnd1);
2956 }
2957 }
2958 Bind(&loopEnd1);
2959 idx = Int32Add(*idx, Int32(1));
2960 LoopEnd(&loopHead1);
2961 Bind(&loopExit1);
2962 Jump(&insertCountVal);
2963 }
2964 Bind(&insertGreaterDelete);
2965 {
2966 DEFVARIABLE(j, VariableType::INT32(), Int32Sub(arrayLen, *actualDeleteCount));
2967 DEFVARIABLE(ele, VariableType::JS_ANY(), Hole());
2968 Label loopHead(env);
2969 Label loopEnd(env);
2970 Label next(env);
2971 Label loopExit(env);
2972 Jump(&loopHead);
2973 LoopBegin(&loopHead);
2974 {
2975 BRANCH(Int32GreaterThan(*j, *start), &next, &loopExit);
2976 Bind(&next);
2977 ele = GetTaggedValueWithElementsKind(thisValue, Int32Sub(Int32Add(*j, *actualDeleteCount),
2978 Int32(1)));
2979 SetValueWithElementsKind(glue, thisValue, *ele, Int32Sub(Int32Add(*j, *insertCount), Int32(1)),
2980 Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2981 Jump(&loopEnd);
2982 }
2983 Bind(&loopEnd);
2984 j = Int32Sub(*j, Int32(1));
2985 LoopEnd(&loopHead, env, glue);
2986 Bind(&loopExit);
2987 Jump(&insertCountVal);
2988 }
2989 Bind(&insertCountVal);
2990 {
2991 Label threeArgs(env);
2992 BRANCH(Int32Equal(ChangeIntPtrToInt32(numArgs), Int32(3)), &threeArgs, &setArrayLen); // 3 : three arg
2993 Bind(&threeArgs);
2994 {
2995 GateRef e = GetCallArg2(numArgs);
2996 SetValueWithElementsKind(glue, thisValue, e, *start, Boolean(true),
2997 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
2998 Jump(&setArrayLen);
2999 }
3000 }
3001 Bind(&setArrayLen);
3002 SetArrayLength(glue, thisValue, newCapacity);
3003 Jump(exit);
3004 }
3005 }
3006 }
3007
ToSpliced(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)3008 void BuiltinsArrayStubBuilder::ToSpliced(GateRef glue, GateRef thisValue, GateRef numArgs,
3009 Variable *result, Label *exit, Label *slowPath)
3010 {
3011 auto env = GetEnvironment();
3012 Label isHeapObject(env);
3013 Label isJsArray(env);
3014 Label isStability(env);
3015 Label defaultConstr(env);
3016 Label matchCls(env);
3017 Label isGeneric(env);
3018 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3019 Bind(&isHeapObject);
3020 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3021 Bind(&isJsArray);
3022 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3023 Bind(&defaultConstr);
3024 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3025 Bind(&isStability);
3026 Label notCOWArray(env);
3027 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
3028 Bind(¬COWArray);
3029 GateRef arrayCls = LoadHClass(thisValue);
3030 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3031 Bind(&matchCls);
3032 GateRef thisLen = GetArrayLength(thisValue);
3033 Label lessThreeArg(env);
3034 DEFVARIABLE(actualStart, VariableType::INT32(), Int32(0));
3035 DEFVARIABLE(actualDeleteCount, VariableType::INT32(), Int32(0));
3036 DEFVARIABLE(newLen, VariableType::INT32(), Int32(0));
3037 DEFVARIABLE(insertCount, VariableType::INT32(), Int32(0));
3038 GateRef argc = ChangeIntPtrToInt32(numArgs);
3039 // 3: max arg count
3040 BRANCH(Int32LessThanOrEqual(argc, Int32(3)), &lessThreeArg, slowPath);
3041 Bind(&lessThreeArg);
3042 {
3043 Label checkOverFlow(env);
3044 Label greaterZero(env);
3045 Label greaterOne(env);
3046 Label checkGreaterOne(env);
3047 Label notOverFlow(env);
3048 Label copyAfter(env);
3049 // 0: judge the first arg exists
3050 BRANCH(Int32GreaterThan(argc, Int32(0)), &greaterZero, &checkGreaterOne);
3051 Bind(&greaterZero);
3052 {
3053 GateRef taggedStart = GetCallArg0(numArgs);
3054 Label taggedStartInt(env);
3055 BRANCH(TaggedIsInt(taggedStart), &taggedStartInt, slowPath);
3056 Bind(&taggedStartInt);
3057 {
3058 GateRef intStart = GetInt32OfTInt(taggedStart);
3059 actualStart = CalArrayRelativePos(intStart, thisLen);
3060 actualDeleteCount = Int32Sub(thisLen, *actualStart);
3061 Jump(&checkGreaterOne);
3062 }
3063 }
3064 Bind(&checkGreaterOne);
3065 {
3066 // 1: judge the second arg exists
3067 BRANCH(Int32GreaterThan(argc, Int32(1)), &greaterOne, &checkOverFlow);
3068 Bind(&greaterOne);
3069 {
3070 // 2: arg count which is not an item
3071 insertCount = Int32Sub(argc, Int32(2));
3072 GateRef argDeleteCount = GetCallArg1(numArgs);
3073 Label argDeleteCountInt(env);
3074 BRANCH(TaggedIsInt(argDeleteCount), &argDeleteCountInt, slowPath);
3075 Bind(&argDeleteCountInt);
3076 {
3077 DEFVARIABLE(deleteCount, VariableType::INT32(), TaggedGetInt(argDeleteCount));
3078 Label deleteCountLessZero(env);
3079 Label calActualDeleteCount(env);
3080 BRANCH(Int32LessThan(*deleteCount, Int32(0)), &deleteCountLessZero, &calActualDeleteCount);
3081 Bind(&deleteCountLessZero);
3082 {
3083 deleteCount = Int32(0);
3084 Jump(&calActualDeleteCount);
3085 }
3086 Bind(&calActualDeleteCount);
3087 {
3088 actualDeleteCount = *deleteCount;
3089 Label lessArrayLen(env);
3090 BRANCH(Int32LessThan(Int32Sub(thisLen, *actualStart), *deleteCount),
3091 &lessArrayLen, &checkOverFlow);
3092 Bind(&lessArrayLen);
3093 {
3094 actualDeleteCount = Int32Sub(thisLen, *actualStart);
3095 Jump(&checkOverFlow);
3096 }
3097 }
3098 }
3099 }
3100 Bind(&checkOverFlow);
3101 {
3102 newLen = Int32Add(Int32Sub(thisLen, *actualDeleteCount), *insertCount);
3103 BRANCH(Int64GreaterThan(ZExtInt32ToInt64(*newLen), Int64(base::MAX_SAFE_INTEGER)),
3104 slowPath, ¬OverFlow);
3105 Bind(¬OverFlow);
3106 Label newLenEmpty(env);
3107 Label newLenNotEmpty(env);
3108 BRANCH(Int32Equal(*newLen, Int32(0)), &newLenEmpty, &newLenNotEmpty);
3109 Bind(&newLenEmpty);
3110 {
3111 NewObjectStubBuilder newBuilder(this);
3112 result->WriteVariable(newBuilder.CreateEmptyArray(glue));
3113 Jump(exit);
3114 }
3115 Bind(&newLenNotEmpty);
3116 {
3117 Label copyBefore(env);
3118 Label insertArg(env);
3119 GateRef newArray = NewArray(glue, Int32(0));
3120 GrowElementsCapacity(glue, newArray, *newLen);
3121 DEFVARIABLE(oldIndex, VariableType::INT32(), Int32(0));
3122 DEFVARIABLE(newIndex, VariableType::INT32(), Int32(0));
3123 BRANCH(Int32GreaterThan(*actualStart, Int32(0)), ©Before, &insertArg);
3124 Bind(©Before);
3125 {
3126 Label loopHead(env);
3127 Label loopEnd(env);
3128 Label loopNext(env);
3129 Label loopExit(env);
3130 Label eleIsHole(env);
3131 Label eleNotHole(env);
3132 Jump(&loopHead);
3133 LoopBegin(&loopHead);
3134 {
3135 BRANCH(Int32LessThan(*oldIndex, *actualStart), &loopNext, &loopExit);
3136 Bind(&loopNext);
3137 GateRef ele = GetTaggedValueWithElementsKind(thisValue, *oldIndex);
3138 BRANCH(TaggedIsHole(ele), &eleIsHole, &eleNotHole);
3139 Bind(&eleIsHole);
3140 {
3141 SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true),
3142 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3143 Jump(&loopEnd);
3144 }
3145 Bind(&eleNotHole);
3146 {
3147 SetValueWithElementsKind(glue, newArray, ele, *newIndex, Boolean(true),
3148 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3149 Jump(&loopEnd);
3150 }
3151 }
3152 Bind(&loopEnd);
3153 oldIndex = Int32Add(*oldIndex, Int32(1));
3154 newIndex = Int32Add(*newIndex, Int32(1));
3155 LoopEnd(&loopHead);
3156 Bind(&loopExit);
3157 Jump(&insertArg);
3158 }
3159 Bind(&insertArg);
3160 {
3161 Label insert(env);
3162 BRANCH(Int32GreaterThan(*insertCount, Int32(0)), &insert, ©After);
3163 Bind(&insert);
3164 {
3165 GateRef insertNum = GetCallArg2(numArgs);
3166 SetValueWithElementsKind(glue, newArray, insertNum, *newIndex, Boolean(true),
3167 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3168 newIndex = Int32Add(*newIndex, Int32(1));
3169 Jump(©After);
3170 }
3171 }
3172 Bind(©After);
3173 {
3174 Label canCopyAfter(env);
3175 Label setLength(env);
3176 oldIndex = Int32Add(*actualStart, *actualDeleteCount);
3177 BRANCH(Int32LessThan(*oldIndex, thisLen), &canCopyAfter, &setLength);
3178 Bind(&canCopyAfter);
3179 {
3180 Label loopHead1(env);
3181 Label loopNext1(env);
3182 Label loopEnd1(env);
3183 Label loopExit1(env);
3184 Label ele1IsHole(env);
3185 Label ele1NotHole(env);
3186 Jump(&loopHead1);
3187 LoopBegin(&loopHead1);
3188 {
3189 BRANCH(Int32LessThan(*oldIndex, thisLen), &loopNext1, &loopExit1);
3190 Bind(&loopNext1);
3191 GateRef ele1 = GetTaggedValueWithElementsKind(thisValue, *oldIndex);
3192 BRANCH(TaggedIsHole(ele1), &ele1IsHole, &ele1NotHole);
3193 Bind(&ele1IsHole);
3194 {
3195 SetValueWithElementsKind(glue, newArray, Undefined(), *newIndex, Boolean(true),
3196 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3197 Jump(&loopEnd1);
3198 }
3199 Bind(&ele1NotHole);
3200 {
3201 SetValueWithElementsKind(glue, newArray, ele1, *newIndex, Boolean(true),
3202 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3203 Jump(&loopEnd1);
3204 }
3205 }
3206 Bind(&loopEnd1);
3207 oldIndex = Int32Add(*oldIndex, Int32(1));
3208 newIndex = Int32Add(*newIndex, Int32(1));
3209 LoopEnd(&loopHead1);
3210 Bind(&loopExit1);
3211 Jump(&setLength);
3212 }
3213 Bind(&setLength);
3214 {
3215 SetArrayLength(glue, newArray, *newLen);
3216 result->WriteVariable(newArray);
3217 Jump(exit);
3218 }
3219 }
3220 }
3221 }
3222 }
3223 }
3224 }
3225
CopyWithin(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)3226 void BuiltinsArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateRef numArgs,
3227 Variable *result, Label *exit, Label *slowPath)
3228 {
3229 auto env = GetEnvironment();
3230 Label thisExists(env);
3231 Label isHeapObject(env);
3232 Label isJsArray(env);
3233 Label defaultConstr(env);
3234 Label isStability(env);
3235 Label isGeneric(env);
3236 Label notCOWArray(env);
3237 Label matchCls(env);
3238 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
3239 Bind(&thisExists);
3240 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3241 Bind(&isHeapObject);
3242 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3243 Bind(&isJsArray);
3244 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3245 Bind(&defaultConstr);
3246 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3247 Bind(&isStability);
3248 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
3249 Bind(¬COWArray);
3250 GateRef arrayCls = LoadHClass(thisValue);
3251 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3252 Bind(&matchCls);
3253 DEFVARIABLE(startPos, VariableType::INT64(), Int64(0));
3254 DEFVARIABLE(endPos, VariableType::INT64(), Int64(0));
3255 Label targetTagExists(env);
3256 Label targetTagIsInt(env);
3257 Label startTagExists(env);
3258 Label startTagIsInt(env);
3259 Label afterCallArg1(env);
3260 Label endTagExists(env);
3261 Label endTagIsInt(env);
3262 Label afterCallArg2(env);
3263 GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
3264 BRANCH(Int64GreaterThanOrEqual(IntPtr(0), numArgs), slowPath, &targetTagExists);
3265 Bind(&targetTagExists);
3266 GateRef targetTag = GetCallArg0(numArgs);
3267 BRANCH(TaggedIsInt(targetTag), &targetTagIsInt, slowPath);
3268 Bind(&targetTagIsInt);
3269 GateRef argTarget = SExtInt32ToInt64(TaggedGetInt(targetTag));
3270 BRANCH(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &afterCallArg1, &startTagExists);
3271 Bind(&startTagExists);
3272 {
3273 GateRef startTag = GetCallArg1(numArgs);
3274 BRANCH(TaggedIsInt(startTag), &startTagIsInt, slowPath);
3275 Bind(&startTagIsInt);
3276 startPos = SExtInt32ToInt64(TaggedGetInt(startTag));
3277 Jump(&afterCallArg1);
3278 }
3279 Bind(&afterCallArg1);
3280 {
3281 endPos = thisLen;
3282 BRANCH(Int64GreaterThanOrEqual(IntPtr(2), numArgs), &afterCallArg2, &endTagExists); //2: 2 parameters
3283 Bind(&endTagExists);
3284 {
3285 GateRef endTag = GetCallArg2(numArgs);
3286 BRANCH(TaggedIsInt(endTag), &endTagIsInt, slowPath);
3287 Bind(&endTagIsInt);
3288 {
3289 endPos = SExtInt32ToInt64(TaggedGetInt(endTag));
3290 Jump(&afterCallArg2);
3291 }
3292 }
3293 }
3294 Bind(&afterCallArg2);
3295 {
3296 DEFVARIABLE(copyTo, VariableType::INT64(), Int64(0));
3297 DEFVARIABLE(copyFrom, VariableType::INT64(), Int64(0));
3298 DEFVARIABLE(copyEnd, VariableType::INT64(), Int64(0));
3299 DEFVARIABLE(count, VariableType::INT64(), Int64(0));
3300 DEFVARIABLE(direction, VariableType::INT64(), Int64(0));
3301 Label calculateCountBranch1(env);
3302 Label calculateCountBranch2(env);
3303 Label afterCalculateCount(env);
3304 Label needToAdjustParam(env);
3305 Label afterAdjustParam(env);
3306 copyTo = CalculatePositionWithLength(argTarget, thisLen);
3307 copyFrom = CalculatePositionWithLength(*startPos, thisLen);
3308 copyEnd = CalculatePositionWithLength(*endPos, thisLen);
3309 BRANCH(Int64LessThan(Int64Sub(*copyEnd, *copyFrom), Int64Sub(thisLen, *copyTo)),
3310 &calculateCountBranch1, &calculateCountBranch2);
3311 Bind(&calculateCountBranch1);
3312 {
3313 count = Int64Sub(*copyEnd, *copyFrom);
3314 Jump(&afterCalculateCount);
3315 }
3316 Bind(&calculateCountBranch2);
3317 {
3318 count = Int64Sub(thisLen, *copyTo);
3319 Jump(&afterCalculateCount);
3320 }
3321
3322 Bind(&afterCalculateCount);
3323 {
3324 direction = Int64(1);
3325 GateRef copyFromVal = *copyFrom;
3326 GateRef copyToVal = *copyTo;
3327 GateRef countVal = *count;
3328 BRANCH(LogicAndBuilder(env).And(Int64LessThan(copyFromVal, copyToVal))
3329 .And(Int64LessThan(copyToVal, Int64Add(copyFromVal, countVal))).Done(),
3330 &needToAdjustParam, &afterAdjustParam);
3331 Bind(&needToAdjustParam);
3332 {
3333 direction = Int64(-1);
3334 copyFrom = Int64Sub(Int64Add(*copyFrom, *count), Int64(1));
3335 copyTo = Int64Sub(Int64Add(*copyTo, *count), Int64(1));
3336 Jump(&afterAdjustParam);
3337 }
3338
3339 Bind(&afterAdjustParam);
3340 {
3341 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3342 Label loopHead(env);
3343 Label loopEnd(env);
3344 Label next(env);
3345 Label loopExit(env);
3346 Jump(&loopHead);
3347 LoopBegin(&loopHead);
3348 {
3349 Label kValueIsHole(env);
3350 Label setValue(env);
3351 Label hasProperty(env);
3352 Label setHole(env);
3353 Label hasException0(env);
3354 Label notHasException0(env);
3355 BRANCH(Int64GreaterThan(*count, Int64(0)), &next, &loopExit);
3356 Bind(&next);
3357 kValue = GetTaggedValueWithElementsKind(thisValue, *copyFrom);
3358 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &setValue);
3359 Bind(&kValueIsHole);
3360 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty),
3361 { thisValue, IntToTaggedInt(*copyFrom) });
3362 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &setHole);
3363
3364 Bind(&hasProperty);
3365 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*copyFrom), ProfileOperation());
3366 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
3367 Bind(&hasException0);
3368 {
3369 result->WriteVariable(Exception());
3370 Jump(exit);
3371 }
3372 Bind(¬HasException0);
3373 BRANCH(TaggedIsHole(*kValue), &setHole, &setValue);
3374 Bind(&setHole);
3375 {
3376 SetValueWithElementsKind(glue, thisValue, Hole(), *copyTo,
3377 Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::DICTIONARY)));
3378 Jump(&loopEnd);
3379 }
3380 Bind(&setValue);
3381 {
3382 SetValueWithElementsKind(glue, thisValue, *kValue, *copyTo,
3383 Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::NONE)));
3384 Jump(&loopEnd);
3385 }
3386 }
3387 Bind(&loopEnd);
3388 copyFrom = Int64Add(*copyFrom, *direction);
3389 copyTo = Int64Add(*copyTo, *direction);
3390 count = Int64Sub(*count, Int64(1));
3391 LoopEnd(&loopHead);
3392 Bind(&loopExit);
3393 result->WriteVariable(thisValue);
3394 Jump(exit);
3395 }
3396 }
3397 }
3398 }
3399
CalculatePositionWithLength(GateRef position,GateRef length)3400 GateRef BuiltinsArrayStubBuilder::CalculatePositionWithLength(GateRef position, GateRef length)
3401 {
3402 auto env = GetEnvironment();
3403 Label entry(env);
3404 env->SubCfgEntry(&entry);
3405 DEFVARIABLE(result, VariableType::INT64(), Int64(0));
3406 Label positionLessThanZero(env);
3407 Label positionNotLessThanZero(env);
3408 Label resultNotGreaterThanZero(env);
3409 Label positionLessThanLength(env);
3410 Label positionNotLessThanLength(env);
3411 Label afterCalculatePosition(env);
3412
3413 BRANCH(Int64LessThan(position, Int64(0)), &positionLessThanZero, &positionNotLessThanZero);
3414 Bind(&positionLessThanZero);
3415 {
3416 result = Int64Add(position, length);
3417 BRANCH(Int64GreaterThan(*result, Int64(0)), &afterCalculatePosition, &resultNotGreaterThanZero);
3418 Bind(&resultNotGreaterThanZero);
3419 result = Int64(0);
3420 Jump(&afterCalculatePosition);
3421 }
3422 Bind(&positionNotLessThanZero);
3423 {
3424 BRANCH(Int64LessThan(position, length), &positionLessThanLength, &positionNotLessThanLength);
3425 Bind(&positionLessThanLength);
3426 {
3427 result = position;
3428 Jump(&afterCalculatePosition);
3429 }
3430 Bind(&positionNotLessThanLength);
3431 {
3432 result = length;
3433 Jump(&afterCalculatePosition);
3434 }
3435 }
3436 Bind(&afterCalculatePosition);
3437 auto ret = *result;
3438 env->SubCfgExit();
3439 return ret;
3440 }
3441
Some(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)3442 void BuiltinsArrayStubBuilder::Some(GateRef glue, GateRef thisValue, GateRef numArgs,
3443 Variable *result, Label *exit, Label *slowPath)
3444 {
3445 auto env = GetEnvironment();
3446 Label thisExists(env);
3447 Label isHeapObject(env);
3448 Label isJsArray(env);
3449 Label defaultConstr(env);
3450 Label isStability(env);
3451 Label notCOWArray(env);
3452 Label equalCls(env);
3453 Label matchCls(env);
3454 Label isGeneric(env);
3455 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
3456 Bind(&thisExists);
3457 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3458 Bind(&isHeapObject);
3459 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3460 Bind(&isJsArray);
3461 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3462 Bind(&defaultConstr);
3463 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3464 Bind(&isStability);
3465 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
3466 Bind(¬COWArray);
3467 GateRef arrayCls = LoadHClass(thisValue);
3468 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3469 Bind(&matchCls);
3470 Label arg0HeapObject(env);
3471 Label callable(env);
3472 Label thisIsStable(env);
3473 Label thisNotStable(env);
3474 GateRef callbackFnHandle = GetCallArg0(numArgs);
3475 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
3476 Bind(&arg0HeapObject);
3477 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
3478 Bind(&callable);
3479 GateRef argHandle = GetCallArg1(numArgs);
3480
3481 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
3482 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
3483 Jump(&thisIsStable);
3484
3485 Bind(&thisIsStable);
3486 {
3487 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3488 Label loopHead(env);
3489 Label loopEnd(env);
3490 Label next(env);
3491 Label loopExit(env);
3492 Jump(&loopHead);
3493 LoopBegin(&loopHead);
3494 {
3495 Label nextStep(env);
3496 Label kValueIsHole(env);
3497 Label callDispatch(env);
3498 Label hasProperty(env);
3499 Label hasException0(env);
3500 Label notHasException0(env);
3501 Label hasException1(env);
3502 Label notHasException1(env);
3503 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
3504 Bind(&nextStep);
3505 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
3506 Bind(&next);
3507 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
3508 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
3509 Bind(&kValueIsHole);
3510 {
3511 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
3512 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3513 Bind(&hasProperty);
3514 {
3515 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
3516 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
3517 Bind(&hasException0);
3518 {
3519 result->WriteVariable(Exception());
3520 Jump(exit);
3521 }
3522 Bind(¬HasException0);
3523 {
3524 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3525 }
3526 }
3527 }
3528 Bind(&callDispatch);
3529 {
3530 GateRef key = Int64ToTaggedInt(*i);
3531 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
3532 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
3533 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
3534 Circuit::NullGate(), callArgs);
3535 GateRef retValue = callBuilder.JSCallDispatch();
3536 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
3537 Bind(&hasException1);
3538 {
3539 result->WriteVariable(Exception());
3540 Jump(exit);
3541 }
3542 Bind(¬HasException1);
3543 {
3544 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
3545 Label changeThisLen(env);
3546 Label afterChangeLen(env);
3547 Label retValueIsTrue(env);
3548 BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen);
3549 Bind(&changeThisLen);
3550 {
3551 thisArrLen = *newLen;
3552 Jump(&afterChangeLen);
3553 }
3554 Bind(&afterChangeLen);
3555 {
3556 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd);
3557 Bind(&retValueIsTrue);
3558 {
3559 result->WriteVariable(TaggedTrue());
3560 Jump(exit);
3561 }
3562 }
3563 }
3564 }
3565 }
3566 Bind(&loopEnd);
3567 i = Int64Add(*i, Int64(1));
3568 LoopEnd(&loopHead);
3569 Bind(&loopExit);
3570 result->WriteVariable(TaggedFalse());
3571 Jump(exit);
3572 }
3573
3574 Bind(&thisNotStable);
3575 {
3576 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3577 Label loopHead(env);
3578 Label loopEnd(env);
3579 Label next(env);
3580 Label loopExit(env);
3581 Jump(&loopHead);
3582 LoopBegin(&loopHead);
3583 {
3584 Label hasProperty(env);
3585 Label hasException0(env);
3586 Label notHasException0(env);
3587 Label callDispatch(env);
3588 Label hasException1(env);
3589 Label notHasException1(env);
3590 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
3591 Bind(&next);
3592 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
3593 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3594 Bind(&hasProperty);
3595 {
3596 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
3597 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
3598 Bind(&hasException0);
3599 {
3600 result->WriteVariable(Exception());
3601 Jump(exit);
3602 }
3603 Bind(¬HasException0);
3604 {
3605 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3606 Bind(&callDispatch);
3607 {
3608 GateRef key = Int64ToTaggedInt(*i);
3609 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
3610 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
3611 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
3612 nullptr, Circuit::NullGate(), callArgs);
3613 GateRef retValue = callBuilder.JSCallDispatch();
3614 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
3615 Bind(&hasException1);
3616 {
3617 result->WriteVariable(Exception());
3618 Jump(exit);
3619 }
3620 Bind(¬HasException1);
3621 {
3622 Label retValueIsTrue(env);
3623 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd);
3624 Bind(&retValueIsTrue);
3625 {
3626 result->WriteVariable(TaggedTrue());
3627 Jump(exit);
3628 }
3629 }
3630 }
3631 }
3632 }
3633 }
3634 Bind(&loopEnd);
3635 i = Int64Add(*i, Int64(1));
3636 LoopEnd(&loopHead);
3637 Bind(&loopExit);
3638 result->WriteVariable(TaggedFalse());
3639 Jump(exit);
3640 }
3641 }
3642
Every(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)3643 void BuiltinsArrayStubBuilder::Every(GateRef glue, GateRef thisValue, GateRef numArgs,
3644 Variable *result, Label *exit, Label *slowPath)
3645 {
3646 auto env = GetEnvironment();
3647 Label thisExists(env);
3648 Label isHeapObject(env);
3649 Label isJsArray(env);
3650 Label defaultConstr(env);
3651 Label isStability(env);
3652 Label notCOWArray(env);
3653 Label equalCls(env);
3654 Label arg0HeapObject(env);
3655 Label callable(env);
3656 Label matchCls(env);
3657 Label isGeneric(env);
3658 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
3659 Bind(&thisExists);
3660 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3661 Bind(&isHeapObject);
3662 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3663 Bind(&isJsArray);
3664 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3665 Bind(&defaultConstr);
3666 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3667 Bind(&isStability);
3668 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
3669 Bind(¬COWArray);
3670 GateRef arrayCls = LoadHClass(thisValue);
3671 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3672 Bind(&matchCls);
3673 GateRef callbackFnHandle = GetCallArg0(numArgs);
3674 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
3675 Bind(&arg0HeapObject);
3676 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
3677 Bind(&callable);
3678
3679 Label thisIsStable(env);
3680 Label thisNotStable(env);
3681 GateRef argHandle = GetCallArg1(numArgs);
3682 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
3683 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
3684 Jump(&thisIsStable);
3685
3686 Bind(&thisIsStable);
3687 {
3688 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3689 Label loopHead(env);
3690 Label loopEnd(env);
3691 Label next(env);
3692 Label loopExit(env);
3693 Jump(&loopHead);
3694 LoopBegin(&loopHead);
3695 {
3696 Label nextStep(env);
3697 Label kValueIsHole(env);
3698 Label callDispatch(env);
3699 Label hasProperty(env);
3700 Label hasException0(env);
3701 Label notHasException0(env);
3702 Label hasException1(env);
3703 Label notHasException1(env);
3704 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
3705 Bind(&nextStep);
3706 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
3707 Bind(&next);
3708 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
3709 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
3710 Bind(&kValueIsHole);
3711 {
3712 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
3713 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3714 Bind(&hasProperty);
3715 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
3716 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
3717 Bind(&hasException0);
3718 {
3719 result->WriteVariable(Exception());
3720 Jump(exit);
3721 }
3722 Bind(¬HasException0);
3723 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3724 }
3725 Bind(&callDispatch);
3726 {
3727 GateRef key = Int64ToTaggedInt(*i);
3728 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
3729 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
3730 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
3731 Circuit::NullGate(), callArgs);
3732 GateRef retValue = callBuilder.JSCallDispatch();
3733 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
3734 Bind(&hasException1);
3735 {
3736 result->WriteVariable(Exception());
3737 Jump(exit);
3738 }
3739 Bind(¬HasException1);
3740 {
3741 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
3742 Label changeThisLen(env);
3743 Label afterChangeLen(env);
3744 Label retValueIsFalse(env);
3745 BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen);
3746 Bind(&changeThisLen);
3747 {
3748 thisArrLen = *newLen;
3749 Jump(&afterChangeLen);
3750 }
3751 Bind(&afterChangeLen);
3752 {
3753 BRANCH(TaggedIsFalse(FastToBoolean(retValue)), &retValueIsFalse, &loopEnd);
3754 Bind(&retValueIsFalse);
3755 result->WriteVariable(TaggedFalse());
3756 Jump(exit);
3757 }
3758 }
3759 }
3760 }
3761 Bind(&loopEnd);
3762 i = Int64Add(*i, Int64(1));
3763 LoopEnd(&loopHead);
3764 Bind(&loopExit);
3765 result->WriteVariable(TaggedTrue());
3766 Jump(exit);
3767 }
3768
3769 Bind(&thisNotStable);
3770 {
3771 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3772 Label loopHead(env);
3773 Label loopEnd(env);
3774 Label next(env);
3775 Label loopExit(env);
3776 Jump(&loopHead);
3777 LoopBegin(&loopHead);
3778 {
3779 Label hasProperty(env);
3780 Label hasException0(env);
3781 Label notHasException0(env);
3782 Label callDispatch(env);
3783 Label hasException1(env);
3784 Label notHasException1(env);
3785 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
3786 Bind(&next);
3787 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
3788 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3789 Bind(&hasProperty);
3790 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
3791 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
3792 Bind(&hasException0);
3793 {
3794 result->WriteVariable(Exception());
3795 Jump(exit);
3796 }
3797 Bind(¬HasException0);
3798 {
3799 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3800 Bind(&callDispatch);
3801 GateRef key = Int64ToTaggedInt(*i);
3802 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
3803 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
3804 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
3805 Circuit::NullGate(), callArgs);
3806 GateRef retValue = callBuilder.JSCallDispatch();
3807 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
3808 Bind(&hasException1);
3809 {
3810 result->WriteVariable(Exception());
3811 Jump(exit);
3812 }
3813 Bind(¬HasException1);
3814 {
3815 Label retValueIsFalse(env);
3816 BRANCH(TaggedIsFalse(FastToBoolean(retValue)), &retValueIsFalse, &loopEnd);
3817 Bind(&retValueIsFalse);
3818 result->WriteVariable(TaggedFalse());
3819 Jump(exit);
3820 }
3821 }
3822 }
3823 Bind(&loopEnd);
3824 i = Int64Add(*i, Int64(1));
3825 LoopEnd(&loopHead);
3826 Bind(&loopExit);
3827 result->WriteVariable(TaggedTrue());
3828 Jump(exit);
3829 }
3830 }
3831
ReduceRight(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)3832 void BuiltinsArrayStubBuilder::ReduceRight(GateRef glue, GateRef thisValue, GateRef numArgs,
3833 Variable *result, Label *exit, Label *slowPath)
3834 {
3835 auto env = GetEnvironment();
3836 Label thisExists(env);
3837 Label isHeapObject(env);
3838 Label isJsArray(env);
3839 Label defaultConstr(env);
3840 Label isStability(env);
3841 Label notCOWArray(env);
3842 Label equalCls(env);
3843 Label matchCls(env);
3844 Label isGeneric(env);
3845 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
3846 Bind(&thisExists);
3847 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
3848 Bind(&isHeapObject);
3849 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
3850 Bind(&isJsArray);
3851 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
3852 Bind(&defaultConstr);
3853 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
3854 Bind(&isStability);
3855 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
3856 Bind(¬COWArray);
3857 GateRef arrayCls = LoadHClass(thisValue);
3858 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
3859 Bind(&matchCls);
3860 DEFVARIABLE(thisLen, VariableType::INT32(), Int32(0));
3861 DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined());
3862 DEFVARIABLE(k, VariableType::INT32(), Int32(0));
3863 Label atLeastOneArg(env);
3864 Label callbackFnHandleHeapObject(env);
3865 Label callbackFnHandleCallable(env);
3866 Label updateAccumulator(env);
3867 Label thisIsStable(env);
3868 Label thisNotStable(env);
3869 thisLen = GetArrayLength(thisValue);
3870 BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
3871 Bind(&atLeastOneArg);
3872 GateRef callbackFnHandle = GetCallArg0(numArgs);
3873 BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath);
3874 Bind(&callbackFnHandleHeapObject);
3875 BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath);
3876 Bind(&callbackFnHandleCallable);
3877 GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2)); // 2: callbackFn initialValue
3878 k = Int32Sub(*thisLen, Int32(1));
3879 BRANCH(numArgsLessThanTwo, slowPath, &updateAccumulator); // 2: callbackFn initialValue
3880 Bind(&updateAccumulator);
3881 accumulator = GetCallArg1(numArgs);
3882 Jump(&thisIsStable);
3883
3884 Bind(&thisIsStable);
3885 {
3886 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3887 GateRef argsLength = Int32(4);
3888 NewObjectStubBuilder newBuilder(this);
3889 GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
3890 Label loopHead(env);
3891 Label next(env);
3892 Label loopEnd(env);
3893 Label loopExit(env);
3894 Jump(&loopHead);
3895 LoopBegin(&loopHead);
3896 {
3897 Label nextStep(env);
3898 Label kValueIsHole(env);
3899 Label callDispatch(env);
3900 Label hasProperty(env);
3901 Label hasException0(env);
3902 Label notHasException0(env);
3903 Label hasException1(env);
3904 Label notHasException1(env);
3905 GateRef thisLenVal = *thisLen;
3906 BRANCH(LogicAndBuilder(env).And(IsStableJSArray(glue, thisValue))
3907 .And(Int32Equal(thisLenVal, GetArrayLength(thisValue))).Done(),
3908 &nextStep, &thisNotStable);
3909 Bind(&nextStep);
3910 BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit);
3911 Bind(&next);
3912 kValue = GetTaggedValueWithElementsKind(thisValue, *k);
3913 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
3914 Bind(&kValueIsHole);
3915 {
3916 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) });
3917 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3918 Bind(&hasProperty);
3919 kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation());
3920 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
3921 Bind(&hasException0);
3922 result->WriteVariable(Exception());
3923 Jump(exit);
3924 Bind(¬HasException0);
3925 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3926 }
3927 Bind(&callDispatch);
3928 {
3929 // callback param 0: accumulator
3930 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
3931 // callback param 1: currentValue
3932 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue);
3933 // callback param 2: index
3934 SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
3935 // callback param 3: array
3936 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
3937 GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
3938 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
3939 callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
3940 CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr, Circuit::NullGate(),
3941 callArgs);
3942 GateRef callResult = callBuilder.JSCallDispatch();
3943 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
3944 Bind(&hasException1);
3945 {
3946 result->WriteVariable(Exception());
3947 Jump(exit);
3948 }
3949
3950 Bind(¬HasException1);
3951 {
3952 accumulator = callResult;
3953 Jump(&loopEnd);
3954 }
3955 }
3956 }
3957 Bind(&loopEnd);
3958 k = Int32Sub(*k, Int32(1));
3959 LoopEnd(&loopHead);
3960 Bind(&loopExit);
3961 result->WriteVariable(*accumulator);
3962 Jump(exit);
3963 }
3964
3965 Bind(&thisNotStable);
3966 {
3967 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
3968 GateRef argsLength = Int32(4);
3969 NewObjectStubBuilder newBuilder(this);
3970 GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
3971 Label loopHead(env);
3972 Label next(env);
3973 Label loopEnd(env);
3974 Label loopExit(env);
3975 Jump(&loopHead);
3976 LoopBegin(&loopHead);
3977 {
3978 Label hasProperty(env);
3979 Label hasException0(env);
3980 Label notHasException0(env);
3981 Label callDispatch(env);
3982 Label hasException1(env);
3983 Label notHasException1(env);
3984 BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit);
3985 Bind(&next);
3986 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*k) });
3987 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &loopEnd);
3988 Bind(&hasProperty);
3989 kValue = FastGetPropertyByIndex(glue, thisValue, *k, ProfileOperation());
3990 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
3991 Bind(&hasException0);
3992 result->WriteVariable(Exception());
3993 Jump(exit);
3994 Bind(¬HasException0);
3995 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
3996 Bind(&callDispatch);
3997 {
3998 // callback param 0: accumulator
3999 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
4000 // callback param 1: currentValue
4001 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), *kValue);
4002 // callback param 2: index
4003 SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
4004 // callback param 3: array
4005 SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
4006 GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
4007 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
4008 callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
4009 CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr, Circuit::NullGate(),
4010 callArgs);
4011 GateRef callResult = callBuilder.JSCallDispatch();
4012 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
4013 Bind(&hasException1);
4014 {
4015 result->WriteVariable(Exception());
4016 Jump(exit);
4017 }
4018
4019 Bind(¬HasException1);
4020 {
4021 accumulator = callResult;
4022 Jump(&loopEnd);
4023 }
4024 }
4025 }
4026 Bind(&loopEnd);
4027 k = Int32Sub(*k, Int32(1));
4028 LoopEnd(&loopHead);
4029 Bind(&loopExit);
4030 result->WriteVariable(*accumulator);
4031 Jump(exit);
4032 }
4033 }
4034
FindLastIndex(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)4035 void BuiltinsArrayStubBuilder::FindLastIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
4036 Variable *result, Label *exit, Label *slowPath)
4037 {
4038 auto env = GetEnvironment();
4039 Label thisExists(env);
4040 Label isHeapObject(env);
4041 Label isJsArray(env);
4042 Label defaultConstr(env);
4043 Label isStability(env);
4044 Label notCOWArray(env);
4045 Label equalCls(env);
4046 Label isGeneric(env);
4047 Label matchCls(env);
4048 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
4049 Bind(&thisExists);
4050 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
4051 Bind(&isHeapObject);
4052 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
4053 Bind(&isJsArray);
4054 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
4055 Bind(&defaultConstr);
4056 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
4057 Bind(&isStability);
4058 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
4059 Bind(¬COWArray);
4060 GateRef arrayCls = LoadHClass(thisValue);
4061 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
4062 Bind(&matchCls);
4063 Label arg0HeapObject(env);
4064 Label callable(env);
4065 Label thisIsStable(env);
4066 Label thisNotStable(env);
4067 GateRef callbackFnHandle = GetCallArg0(numArgs);
4068 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
4069 Bind(&arg0HeapObject);
4070 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
4071 Bind(&callable);
4072 GateRef argHandle = GetCallArg1(numArgs);
4073
4074 DEFVARIABLE(i, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1)));
4075 Jump(&thisIsStable);
4076
4077 Bind(&thisIsStable);
4078 {
4079 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4080 Label loopHead(env);
4081 Label loopEnd(env);
4082 Label next(env);
4083 Label loopExit(env);
4084 Jump(&loopHead);
4085 LoopBegin(&loopHead);
4086 {
4087 Label nextStep(env);
4088 Label kValueIsHole(env);
4089 Label callDispatch(env);
4090 Label hasProperty(env);
4091 Label hasException0(env);
4092 Label notHasException0(env);
4093 Label useUndefined(env);
4094 Label hasException1(env);
4095 Label notHasException1(env);
4096 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
4097 Bind(&nextStep);
4098 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4099 Bind(&next);
4100 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
4101 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
4102 Bind(&kValueIsHole);
4103 {
4104 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4105 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4106 Bind(&hasProperty);
4107 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4108 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
4109 Bind(&hasException0);
4110 {
4111 result->WriteVariable(Exception());
4112 Jump(exit);
4113 }
4114 Bind(¬HasException0);
4115 {
4116 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4117 Bind(&useUndefined);
4118 kValue = Undefined();
4119 Jump(&callDispatch);
4120 }
4121 }
4122 Bind(&callDispatch);
4123 {
4124 GateRef key = Int64ToTaggedInt(*i);
4125 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4126 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4127 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4128 Circuit::NullGate(), callArgs);
4129 GateRef retValue = callBuilder.JSCallDispatch();
4130 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
4131 Bind(&hasException1);
4132 {
4133 result->WriteVariable(Exception());
4134 Jump(exit);
4135 }
4136
4137 Bind(¬HasException1);
4138 {
4139 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4140 Label checkRetValue(env);
4141 Label find(env);
4142 BRANCH(Int64LessThan(*newLen, Int64Add(*i, Int64(1))), &thisNotStable, &checkRetValue);
4143 Bind(&checkRetValue);
4144 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4145 Bind(&find);
4146 result->WriteVariable(IntToTaggedPtr(*i));
4147 Jump(exit);
4148 }
4149 }
4150 }
4151 Bind(&loopEnd);
4152 i = Int64Sub(*i, Int64(1));
4153 LoopEnd(&loopHead);
4154 Bind(&loopExit);
4155 result->WriteVariable(IntToTaggedPtr(Int32(-1)));
4156 Jump(exit);
4157 }
4158
4159 Bind(&thisNotStable);
4160 {
4161 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4162 Label loopHead(env);
4163 Label loopEnd(env);
4164 Label next(env);
4165 Label loopExit(env);
4166 Jump(&loopHead);
4167 LoopBegin(&loopHead);
4168 {
4169 Label hasProperty(env);
4170 Label hasException0(env);
4171 Label notHasException0(env);
4172 Label useUndefined(env);
4173 Label callDispatch(env);
4174 Label hasException1(env);
4175 Label notHasException1(env);
4176 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4177 Bind(&next);
4178 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4179 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4180 Bind(&hasProperty);
4181 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4182 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
4183 Bind(&hasException0);
4184 {
4185 result->WriteVariable(Exception());
4186 Jump(exit);
4187 }
4188 Bind(¬HasException0);
4189 {
4190 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4191 Bind(&useUndefined);
4192 kValue = Undefined();
4193 Jump(&callDispatch);
4194 Bind(&callDispatch);
4195 GateRef key = Int64ToTaggedInt(*i);
4196 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4197 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4198 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4199 Circuit::NullGate(), callArgs);
4200 GateRef retValue = callBuilder.JSCallDispatch();
4201 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
4202 Bind(&hasException1);
4203 {
4204 result->WriteVariable(Exception());
4205 Jump(exit);
4206 }
4207
4208 Bind(¬HasException1);
4209 {
4210 Label find(env);
4211 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4212 Bind(&find);
4213 result->WriteVariable(IntToTaggedPtr(*i));
4214 Jump(exit);
4215 }
4216 }
4217 }
4218 Bind(&loopEnd);
4219 i = Int64Sub(*i, Int64(1));
4220 LoopEnd(&loopHead);
4221 Bind(&loopExit);
4222 result->WriteVariable(IntToTaggedPtr(Int32(-1)));
4223 Jump(exit);
4224 }
4225 }
4226
FindLast(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)4227 void BuiltinsArrayStubBuilder::FindLast(GateRef glue, GateRef thisValue, GateRef numArgs,
4228 Variable *result, Label *exit, Label *slowPath)
4229 {
4230 auto env = GetEnvironment();
4231 Label thisExists(env);
4232 Label isHeapObject(env);
4233 Label isJsArray(env);
4234 Label defaultConstr(env);
4235 Label isStability(env);
4236 Label notCOWArray(env);
4237 Label equalCls(env);
4238 Label matchCls(env);
4239 Label isGeneric(env);
4240 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
4241 Bind(&thisExists);
4242 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
4243 Bind(&isHeapObject);
4244 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
4245 Bind(&isJsArray);
4246 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
4247 Bind(&defaultConstr);
4248 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
4249 Bind(&isStability);
4250 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
4251 Bind(¬COWArray);
4252 GateRef arrayCls = LoadHClass(thisValue);
4253 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
4254 Bind(&matchCls);
4255 Label arg0HeapObject(env);
4256 Label callable(env);
4257 Label thisIsStable(env);
4258 Label thisNotStable(env);
4259 GateRef callbackFnHandle = GetCallArg0(numArgs);
4260 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
4261 Bind(&arg0HeapObject);
4262 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
4263 Bind(&callable);
4264 GateRef argHandle = GetCallArg1(numArgs);
4265
4266 DEFVARIABLE(i, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1)));
4267 Jump(&thisIsStable);
4268
4269 Bind(&thisIsStable);
4270 {
4271 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4272 Label loopHead(env);
4273 Label loopEnd(env);
4274 Label next(env);
4275 Label loopExit(env);
4276 Jump(&loopHead);
4277 LoopBegin(&loopHead);
4278 {
4279 Label nextStep(env);
4280 Label kValueIsHole(env);
4281 Label callDispatch(env);
4282 Label hasProperty(env);
4283 Label hasException0(env);
4284 Label notHasException0(env);
4285 Label useUndefined(env);
4286 Label hasException1(env);
4287 Label notHasException1(env);
4288 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
4289 Bind(&nextStep);
4290 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4291 Bind(&next);
4292 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
4293 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
4294 Bind(&kValueIsHole);
4295 {
4296 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4297 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4298 Bind(&hasProperty);
4299 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4300 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
4301 Bind(&hasException0);
4302 {
4303 result->WriteVariable(Exception());
4304 Jump(exit);
4305 }
4306 Bind(¬HasException0);
4307 {
4308 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4309 Bind(&useUndefined);
4310 kValue = Undefined();
4311 Jump(&callDispatch);
4312 }
4313 }
4314 Bind(&callDispatch);
4315 {
4316 GateRef key = Int64ToTaggedInt(*i);
4317 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4318 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4319 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4320 Circuit::NullGate(), callArgs);
4321 GateRef retValue = callBuilder.JSCallDispatch();
4322 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
4323 Bind(&hasException1);
4324 {
4325 result->WriteVariable(Exception());
4326 Jump(exit);
4327 }
4328
4329 Bind(¬HasException1);
4330 {
4331 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4332 Label checkRetValue(env);
4333 Label find(env);
4334 BRANCH(Int64LessThan(*newLen, Int64Add(*i, Int64(1))), &thisNotStable, &checkRetValue);
4335 Bind(&checkRetValue);
4336 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4337 Bind(&find);
4338 result->WriteVariable(*kValue);
4339 Jump(exit);
4340 }
4341 }
4342 }
4343 Bind(&loopEnd);
4344 i = Int64Sub(*i, Int64(1));
4345 LoopEnd(&loopHead);
4346 Bind(&loopExit);
4347 Jump(exit);
4348 }
4349
4350 Bind(&thisNotStable);
4351 {
4352 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4353 Label loopHead(env);
4354 Label loopEnd(env);
4355 Label next(env);
4356 Label loopExit(env);
4357 Jump(&loopHead);
4358 LoopBegin(&loopHead);
4359 {
4360 Label hasProperty(env);
4361 Label hasException0(env);
4362 Label notHasException0(env);
4363 Label useUndefined(env);
4364 Label callDispatch(env);
4365 Label hasException1(env);
4366 Label notHasException1(env);
4367 BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &next);
4368 Bind(&next);
4369 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4370 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &useUndefined);
4371 Bind(&hasProperty);
4372 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4373 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
4374 Bind(&hasException0);
4375 {
4376 result->WriteVariable(Exception());
4377 Jump(exit);
4378 }
4379 Bind(¬HasException0);
4380 {
4381 BRANCH(TaggedIsHole(*kValue), &useUndefined, &callDispatch);
4382 Bind(&useUndefined);
4383 {
4384 kValue = Undefined();
4385 Jump(&callDispatch);
4386 }
4387 Bind(&callDispatch);
4388 {
4389 GateRef key = Int64ToTaggedInt(*i);
4390 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4391 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4392 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
4393 nullptr, Circuit::NullGate(), callArgs);
4394 GateRef retValue = callBuilder.JSCallDispatch();
4395 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
4396 Bind(&hasException1);
4397 {
4398 result->WriteVariable(Exception());
4399 Jump(exit);
4400 }
4401
4402 Bind(¬HasException1);
4403 {
4404 Label find(env);
4405 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
4406 Bind(&find);
4407 result->WriteVariable(*kValue);
4408 Jump(exit);
4409 }
4410 }
4411 }
4412 }
4413 Bind(&loopEnd);
4414 i = Int64Sub(*i, Int64(1));
4415 LoopEnd(&loopHead);
4416 Bind(&loopExit);
4417 Jump(exit);
4418 }
4419 }
4420
FastCreateArrayWithArgv(GateRef glue,Variable * res,GateRef argc,GateRef hclass,Label * exit)4421 void BuiltinsArrayStubBuilder::FastCreateArrayWithArgv(GateRef glue, Variable *res, GateRef argc,
4422 GateRef hclass, Label *exit)
4423 {
4424 auto env = GetEnvironment();
4425 NewObjectStubBuilder newBuilder(this);
4426 newBuilder.SetParameters(glue, 0);
4427
4428 // create elements from argv
4429 GateRef len = TruncInt64ToInt32(argc);
4430 GateRef elements = newBuilder.NewTaggedArray(glue, len);
4431
4432 // set value
4433 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
4434 DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
4435 #if ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC
4436 DEFVARIABLE(elementKind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::GENERIC)));
4437 #else
4438 DEFVARIABLE(elementKind, VariableType::INT32(), Int32(static_cast<int32_t>(ElementsKind::HOLE)));
4439 #endif
4440 Label loopHead(env);
4441 Label loopEnd(env);
4442 Label setValue(env);
4443 Label loopExit(env);
4444 Jump(&loopHead);
4445 LoopBegin(&loopHead);
4446 {
4447 BRANCH(Int64LessThan(*i, argc), &setValue, &loopExit);
4448 Bind(&setValue);
4449 Label isHole(env);
4450 Label notHole(env);
4451 value = GetArgFromArgv(*i);
4452 elementKind = Int32Or(TaggedToElementKind(*value), *elementKind);
4453 BRANCH(TaggedIsHole(*value), &isHole, ¬Hole);
4454 Bind(&isHole);
4455 value = TaggedUndefined();
4456 Jump(¬Hole);
4457 Bind(¬Hole);
4458 SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, *i, *value);
4459 i = Int64Add(*i, Int64(1));
4460 Jump(&loopEnd);
4461 }
4462 Bind(&loopEnd);
4463 LoopEnd(&loopHead);
4464 Bind(&loopExit);
4465
4466 // create array object
4467 GateRef arr = newBuilder.NewJSObject(glue, hclass);
4468 res->WriteVariable(arr);
4469 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
4470 Store(VariableType::INT32(), glue, arr, lengthOffset, len);
4471 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
4472 SetPropertyInlinedProps(glue, arr, hclass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4473 SetExtensibleToBitfield(glue, arr, true);
4474 SetElementsArray(VariableType::JS_POINTER(), glue, arr, elements);
4475
4476 // set elementkind if needed
4477 Label enabledElementsKind(env);
4478 BRANCH(IsEnableElementsKind(glue), &enabledElementsKind, exit);
4479 Bind(&enabledElementsKind);
4480 CallRuntime(glue, RTSTUB_ID(UpdateHClassForElementsKind), { arr, *elementKind });
4481 Jump(exit);
4482 }
4483
GenArrayConstructor(GateRef glue,GateRef nativeCode,GateRef func,GateRef newTarget,GateRef thisValue,GateRef numArgs)4484 void BuiltinsArrayStubBuilder::GenArrayConstructor(GateRef glue, GateRef nativeCode,
4485 GateRef func, GateRef newTarget, GateRef thisValue, GateRef numArgs)
4486 {
4487 auto env = GetEnvironment();
4488 DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
4489
4490 Label newTargetIsHeapObject(env);
4491 Label newTargetIsJSFunction(env);
4492 Label slowPath(env);
4493 Label slowPath1(env);
4494 Label exit(env);
4495
4496 BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
4497 Bind(&newTargetIsHeapObject);
4498 BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
4499 Bind(&newTargetIsJSFunction);
4500 {
4501 Label fastGetHclass(env);
4502 Label intialHClassIsHClass(env);
4503 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
4504 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
4505 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
4506 BRANCH(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath1);
4507 Bind(&fastGetHclass);
4508 GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
4509 DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0));
4510 BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1);
4511 Bind(&intialHClassIsHClass);
4512 {
4513 Label noArg(env);
4514 Label hasArg(env);
4515 Label arrayCreate(env);
4516 BRANCH(Int64Equal(numArgs, IntPtr(0)), &noArg, &hasArg);
4517 Bind(&noArg);
4518 {
4519 Jump(&arrayCreate);
4520 }
4521 Bind(&hasArg);
4522 {
4523 Label hasOneArg(env);
4524 Label multiArg(env);
4525 BRANCH(Int64Equal(numArgs, IntPtr(1)), &hasOneArg, &multiArg);
4526 Bind(&hasOneArg);
4527 {
4528 Label argIsNumber(env);
4529 GateRef arg0 = GetArgFromArgv(IntPtr(0), numArgs, true);
4530 BRANCH(TaggedIsNumber(arg0), &argIsNumber, &slowPath);
4531 Bind(&argIsNumber);
4532 {
4533 Label argIsInt(env);
4534 Label argIsDouble(env);
4535 BRANCH(TaggedIsInt(arg0), &argIsInt, &argIsDouble);
4536 Bind(&argIsInt);
4537 {
4538 Label validIntLength(env);
4539 GateRef intLen = GetInt64OfTInt(arg0);
4540 GateRef isGEZero = Int64GreaterThanOrEqual(intLen, Int64(0));
4541 GateRef isLEMaxLen = Int64LessThanOrEqual(intLen, Int64(JSArray::MAX_ARRAY_INDEX));
4542 BRANCH(BitAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath);
4543 Bind(&validIntLength);
4544 {
4545 arrayLength = intLen;
4546 Jump(&arrayCreate);
4547 }
4548 }
4549 Bind(&argIsDouble);
4550 {
4551 Label validDoubleLength(env);
4552 GateRef doubleLength = GetDoubleOfTDouble(arg0);
4553 GateRef doubleToInt = DoubleToInt(glue, doubleLength);
4554 GateRef intToDouble = CastInt64ToFloat64(SExtInt32ToInt64(doubleToInt));
4555 GateRef doubleEqual = DoubleEqual(doubleLength, intToDouble);
4556 GateRef doubleLEMaxLen =
4557 DoubleLessThanOrEqual(doubleLength, Double(JSArray::MAX_ARRAY_INDEX));
4558 BRANCH(BitAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath);
4559 Bind(&validDoubleLength);
4560 {
4561 arrayLength = SExtInt32ToInt64(doubleToInt);
4562 Jump(&arrayCreate);
4563 }
4564 }
4565 }
4566 }
4567 Bind(&multiArg);
4568 {
4569 Label lengthValid(env);
4570 BRANCH(Int64LessThan(numArgs, IntPtr(JSObject::MAX_GAP)), &lengthValid, &slowPath);
4571 Bind(&lengthValid);
4572 {
4573 FastCreateArrayWithArgv(glue, &res, numArgs, intialHClass, &exit);
4574 }
4575 }
4576 }
4577 Bind(&arrayCreate);
4578 {
4579 Label lengthValid(env);
4580 BRANCH(Int64GreaterThan(*arrayLength, Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid);
4581 Bind(&lengthValid);
4582 {
4583 NewObjectStubBuilder newBuilder(this);
4584 newBuilder.SetParameters(glue, 0);
4585 res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength);
4586 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
4587 Store(VariableType::INT32(), glue, *res, lengthOffset, TruncInt64ToInt32(*arrayLength));
4588 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
4589 ConstantIndex::ARRAY_LENGTH_ACCESSOR);
4590 SetPropertyInlinedProps(glue, *res, intialHClass, accessor,
4591 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
4592 SetExtensibleToBitfield(glue, *res, true);
4593 Jump(&exit);
4594 }
4595 }
4596 }
4597 Bind(&slowPath1);
4598 {
4599 GateRef argv = GetArgv();
4600 res = CallBuiltinRuntimeWithNewTarget(glue,
4601 { glue, nativeCode, func, thisValue, numArgs, argv, newTarget });
4602 Jump(&exit);
4603 }
4604 }
4605 Bind(&slowPath);
4606 {
4607 GateRef argv = GetArgv();
4608 res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true);
4609 Jump(&exit);
4610 }
4611
4612 Bind(&exit);
4613 Return(*res);
4614 }
4615
FlatMap(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)4616 void BuiltinsArrayStubBuilder::FlatMap(GateRef glue, GateRef thisValue, GateRef numArgs,
4617 Variable *result, Label *exit, Label *slowPath)
4618 {
4619 auto env = GetEnvironment();
4620 Label thisExists(env);
4621 Label isHeapObject(env);
4622 Label isJsArray(env);
4623 Label defaultConstr(env);
4624 Label isStability(env);
4625 Label notCOWArray(env);
4626 Label equalCls(env);
4627 Label matchCls(env);
4628 Label isGeneric(env);
4629 BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
4630 Bind(&thisExists);
4631 BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
4632 Bind(&isHeapObject);
4633 BRANCH(IsJsArray(thisValue), &isJsArray, slowPath);
4634 Bind(&isJsArray);
4635 BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
4636 Bind(&defaultConstr);
4637 BRANCH(IsStableJSArray(glue, thisValue), &isStability, slowPath);
4638 Bind(&isStability);
4639 BRANCH(IsJsCOWArray(thisValue), slowPath, ¬COWArray);
4640 Bind(¬COWArray);
4641 GateRef arrayCls = LoadHClass(thisValue);
4642 ElementsKindHclassCompare(glue, arrayCls, &matchCls, slowPath);
4643 Bind(&matchCls);
4644 Label arg0HeapObject(env);
4645 Label callable(env);
4646 Label thisIsStable(env);
4647 Label thisNotStable(env);
4648 Label doFlat(env);
4649 GateRef callbackFnHandle = GetCallArg0(numArgs);
4650 BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
4651 Bind(&arg0HeapObject);
4652 BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
4653 Bind(&callable);
4654 GateRef argHandle = GetCallArg1(numArgs);
4655
4656 DEFVARIABLE(i, VariableType::INT64(), Int64(0));
4657 DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4658 DEFVARIABLE(newArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4659 GateRef mappedArray = NewArray(glue, *thisArrLen);
4660 BRANCH(IsStableJSArray(glue, thisValue), &thisIsStable, &thisNotStable);
4661
4662 Bind(&thisIsStable);
4663 {
4664 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4665 Label loopHead(env);
4666 Label loopEnd(env);
4667 Label next(env);
4668 Label loopExit(env);
4669 Jump(&loopHead);
4670 LoopBegin(&loopHead);
4671 {
4672 Label nextStep(env);
4673 Label kValueIsHole(env);
4674 Label callDispatch(env);
4675 Label hasProperty(env);
4676 Label changeNewArrLen(env);
4677 Label hasException0(env);
4678 Label notHasException0(env);
4679 Label hasException1(env);
4680 Label notHasException1(env);
4681 BRANCH(IsStableJSArray(glue, thisValue), &nextStep, &thisNotStable);
4682 Bind(&nextStep);
4683 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
4684 Bind(&next);
4685 kValue = GetTaggedValueWithElementsKind(thisValue, *i);
4686 BRANCH(TaggedIsHole(*kValue), &kValueIsHole, &callDispatch);
4687 Bind(&kValueIsHole);
4688 {
4689 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4690 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &changeNewArrLen);
4691 Bind(&hasProperty);
4692 {
4693 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4694 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
4695 Bind(&hasException0);
4696 {
4697 result->WriteVariable(Exception());
4698 Jump(exit);
4699 }
4700 Bind(¬HasException0);
4701 {
4702 BRANCH(TaggedIsHole(*kValue), &changeNewArrLen, &callDispatch);
4703 }
4704 }
4705 Bind(&changeNewArrLen);
4706 {
4707 newArrLen = Int64Sub(*newArrLen, Int64(1));
4708 Jump(&loopEnd);
4709 }
4710 }
4711 Bind(&callDispatch);
4712 {
4713 GateRef key = Int64ToTaggedInt(*i);
4714 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4715 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4716 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4717 Circuit::NullGate(), callArgs);
4718 GateRef retValue = callBuilder.JSCallDispatch();
4719 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
4720 Bind(&hasException1);
4721 {
4722 result->WriteVariable(Exception());
4723 Jump(exit);
4724 }
4725 Bind(¬HasException1);
4726 {
4727 DEFVARIABLE(newLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
4728 Label changeThisLen(env);
4729 Label afterChangeLen(env);
4730 Label retValueIsHeapObject(env);
4731 Label retValueIsJsArray(env);
4732 BRANCH(Int64LessThan(*newLen, *thisArrLen), &changeThisLen, &afterChangeLen);
4733 Bind(&changeThisLen);
4734 {
4735 newArrLen = Int64Sub(*newArrLen, Int64Sub(*thisArrLen, *newLen));
4736 thisArrLen = *newLen;
4737 Jump(&afterChangeLen);
4738 }
4739 Bind(&afterChangeLen);
4740 {
4741 SetValueWithElementsKind(glue, mappedArray, retValue, *i, Boolean(true),
4742 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4743 BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &loopEnd);
4744 Bind(&retValueIsHeapObject);
4745 {
4746 BRANCH(IsJsArray(retValue), &retValueIsJsArray, &loopEnd);
4747 }
4748 Bind(&retValueIsJsArray);
4749 {
4750 GateRef elementsNum =
4751 ZExtInt32ToInt64(GetNumberOfElements(retValue)); // newArray only contains non-hole elements
4752 newArrLen = Int64Sub(Int64Add(*newArrLen, elementsNum), Int64(1));
4753 Jump(&loopEnd);
4754 }
4755 }
4756 }
4757 }
4758 }
4759 Bind(&loopEnd);
4760 i = Int64Add(*i, Int64(1));
4761 LoopEnd(&loopHead);
4762 Bind(&loopExit);
4763 Jump(&doFlat);
4764 }
4765
4766 Bind(&thisNotStable);
4767 {
4768 DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
4769 Label loopHead(env);
4770 Label loopEnd(env);
4771 Label next(env);
4772 Label loopExit(env);
4773 Jump(&loopHead);
4774 LoopBegin(&loopHead);
4775 {
4776 Label hasProperty(env);
4777 Label changeNewArrLen(env);
4778 Label hasException0(env);
4779 Label notHasException0(env);
4780 Label callDispatch(env);
4781 Label hasException1(env);
4782 Label notHasException1(env);
4783 BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
4784 Bind(&next);
4785 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { thisValue, IntToTaggedInt(*i) });
4786 BRANCH(TaggedIsTrue(hasProp), &hasProperty, &changeNewArrLen);
4787 Bind(&hasProperty);
4788 {
4789 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), ProfileOperation());
4790 BRANCH(HasPendingException(glue), &hasException0, ¬HasException0);
4791 Bind(&hasException0);
4792 {
4793 result->WriteVariable(Exception());
4794 Jump(exit);
4795 }
4796 Bind(¬HasException0);
4797 {
4798 BRANCH(TaggedIsHole(*kValue), &changeNewArrLen, &callDispatch);
4799 }
4800 }
4801 Bind(&changeNewArrLen);
4802 {
4803 newArrLen = Int64Sub(*newArrLen, Int64(1));
4804 Jump(&loopEnd);
4805 }
4806 Bind(&callDispatch);
4807 {
4808 GateRef key = Int64ToTaggedInt(*i);
4809 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
4810 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
4811 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
4812 Circuit::NullGate(), callArgs);
4813 GateRef retValue = callBuilder.JSCallDispatch();
4814 BRANCH(HasPendingException(glue), &hasException1, ¬HasException1);
4815 Bind(&hasException1);
4816 {
4817 result->WriteVariable(Exception());
4818 Jump(exit);
4819 }
4820 Bind(¬HasException1);
4821 {
4822 Label retValueIsHeapObject(env);
4823 Label retValueIsJsArray(env);
4824 SetValueWithElementsKind(glue, mappedArray, retValue, *i, Boolean(true),
4825 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4826 BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &loopEnd);
4827 Bind(&retValueIsHeapObject);
4828 {
4829 BRANCH(IsJsArray(retValue), &retValueIsJsArray, &loopEnd);
4830 }
4831 Bind(&retValueIsJsArray);
4832 {
4833 GateRef elementsNum =
4834 ZExtInt32ToInt64(GetNumberOfElements(retValue)); // newArray only contains non-hole elements
4835 newArrLen = Int64Sub(Int64Add(*newArrLen, elementsNum), Int64(1));
4836 Jump(&loopEnd);
4837 }
4838 }
4839 }
4840 }
4841 Bind(&loopEnd);
4842 i = Int64Add(*i, Int64(1));
4843 LoopEnd(&loopHead);
4844 Bind(&loopExit);
4845 Jump(&doFlat);
4846 }
4847
4848 Bind(&doFlat);
4849 {
4850 i = Int64(0);
4851 DEFVARIABLE(j, VariableType::INT64(), Int64(0));
4852 DEFVARIABLE(retValueItem, VariableType::JS_ANY(), Hole());
4853 GateRef newArray = NewArray(glue, *newArrLen);
4854 Label loopHead2(env);
4855 Label loopEnd2(env);
4856 Label next2(env);
4857 Label loopExit2(env);
4858 Jump(&loopHead2);
4859 LoopBegin(&loopHead2);
4860 {
4861 Label nextStep(env);
4862 Label retValueIsHeapObject(env);
4863 Label retValueIsJsArray(env);
4864 Label retValueIsNotJsArray(env);
4865 BRANCH(Int64LessThan(*i, *thisArrLen), &next2, &loopExit2);
4866 Bind(&next2);
4867 GateRef retValue = GetTaggedValueWithElementsKind(mappedArray, *i);
4868 BRANCH(TaggedIsHole(retValue), &loopEnd2, &nextStep);
4869 Bind(&nextStep);
4870 BRANCH(TaggedIsHeapObject(retValue), &retValueIsHeapObject, &retValueIsNotJsArray);
4871 Bind(&retValueIsHeapObject);
4872 {
4873 BRANCH(IsJsArray(retValue), &retValueIsJsArray, &retValueIsNotJsArray);
4874 Bind(&retValueIsJsArray);
4875 {
4876 Label retValueIsStableArray(env);
4877 Label retValueNotStableArray(env);
4878 GateRef retValueIsStable = IsStableJSArray(glue, retValue);
4879 GateRef arrLen = ZExtInt32ToInt64(GetArrayLength(retValue));
4880 DEFVARIABLE(k, VariableType::INT64(), Int64(0));
4881 Label loopHead3(env);
4882 Label loopEnd3(env);
4883 Label next3(env);
4884 Label loopExit3(env);
4885 Label setValue(env);
4886 Label itemExist(env);
4887 Jump(&loopHead3);
4888 LoopBegin(&loopHead3);
4889 {
4890 BRANCH(Int64LessThan(*k, arrLen), &next3, &loopExit3);
4891 Bind(&next3);
4892 BRANCH(retValueIsStable, &retValueIsStableArray, &retValueNotStableArray);
4893 Bind(&retValueIsStableArray);
4894 retValueItem = GetTaggedValueWithElementsKind(retValue, *k);
4895 BRANCH(TaggedIsHole(*retValueItem), &loopEnd3, &setValue);
4896 Bind(&retValueNotStableArray);
4897 GateRef hasProp = CallRuntime(glue, RTSTUB_ID(HasProperty), { retValue, IntToTaggedInt(*k) });
4898 BRANCH(TaggedIsTrue(hasProp), &itemExist, &loopEnd3);
4899 Bind(&itemExist);
4900 retValueItem =
4901 FastGetPropertyByIndex(glue, retValue, TruncInt64ToInt32(*k), ProfileOperation());
4902 Jump(&setValue);
4903 Bind(&setValue);
4904 SetValueWithElementsKind(glue, newArray, *retValueItem, *j, Boolean(true),
4905 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4906 j = Int64Add(*j, Int64(1));
4907 Jump(&loopEnd3);
4908 }
4909 Bind(&loopEnd3);
4910 k = Int64Add(*k, Int64(1));
4911 LoopEnd(&loopHead3);
4912 Bind(&loopExit3);
4913 Jump(&loopEnd2);
4914 }
4915 }
4916 Bind(&retValueIsNotJsArray);
4917 {
4918 SetValueWithElementsKind(glue, newArray, retValue, *j, Boolean(true),
4919 Int32(static_cast<uint32_t>(ElementsKind::NONE)));
4920 j = Int64Add(*j, Int64(1));
4921 Jump(&loopEnd2);
4922 }
4923 }
4924 Bind(&loopEnd2);
4925 i = Int64Add(*i, Int64(1));
4926 LoopEnd(&loopHead2);
4927 Bind(&loopExit2);
4928 result->WriteVariable(newArray);
4929 Jump(exit);
4930 }
4931 }
4932
IsArray(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)4933 void BuiltinsArrayStubBuilder::IsArray([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef thisValue,
4934 GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
4935 {
4936 auto env = GetEnvironment();
4937 GateRef obj = GetCallArg0(numArgs);
4938 Label isHeapObj(env);
4939 Label notHeapObj(env);
4940 BRANCH(TaggedIsHeapObject(obj), &isHeapObj, ¬HeapObj);
4941 Bind(&isHeapObj);
4942 {
4943 Label isJSArray(env);
4944 Label notJSArray(env);
4945 GateRef objectType = GetObjectType(LoadHClass(obj));
4946 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY))), &isJSArray, ¬JSArray);
4947 Bind(&isJSArray);
4948 {
4949 result->WriteVariable(TaggedTrue());
4950 Jump(exit);
4951 }
4952 Bind(¬JSArray);
4953 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_PROXY))), slowPath, ¬HeapObj);
4954 }
4955 Bind(¬HeapObj);
4956 {
4957 result->WriteVariable(TaggedFalse());
4958 Jump(exit);
4959 }
4960 }
4961 } // namespace panda::ecmascript::kungfu
4962