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