• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_typedarray_stub_builder.h"
17 
18 #include "ecmascript/base/typed_array_helper.h"
19 #include "ecmascript/byte_array.h"
20 #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h"
21 #include "ecmascript/compiler/call_stub_builder.h"
22 #include "ecmascript/compiler/new_object_stub_builder.h"
23 #include "ecmascript/js_iterator.h"
24 
25 namespace panda::ecmascript::kungfu {
GetDataPointFromBuffer(GateRef arrBuf)26 GateRef BuiltinsTypedArrayStubBuilder::GetDataPointFromBuffer(GateRef arrBuf)
27 {
28     auto env = GetEnvironment();
29     Label entryPass(env);
30     env->SubCfgEntry(&entryPass);
31     Label isNull(env);
32     Label exit(env);
33     Label isByteArray(env);
34     Label notByteArray(env);
35     DEFVARIABLE(result, VariableType::NATIVE_POINTER(), IntPtr(0));
36     BRANCH(IsByteArray(arrBuf), &isByteArray, &notByteArray);
37     Bind(&isByteArray);
38     {
39         result = ChangeByteArrayTaggedPointerToInt64(PtrAdd(arrBuf, IntPtr(ByteArray::DATA_OFFSET)));
40         Jump(&exit);
41     }
42     Bind(&notByteArray);
43     {
44         GateRef data = GetArrayBufferData(arrBuf);
45         result = GetExternalPointer(data);
46         Jump(&exit);
47     }
48     Bind(&exit);
49     auto ret = *result;
50     env->SubCfgExit();
51     return ret;
52 }
53 
CheckTypedArrayIndexInRange(GateRef array,GateRef index)54 GateRef BuiltinsTypedArrayStubBuilder::CheckTypedArrayIndexInRange(GateRef array, GateRef index)
55 {
56     auto env = GetEnvironment();
57     Label entryPass(env);
58     env->SubCfgEntry(&entryPass);
59     DEFVARIABLE(result, VariableType::BOOL(), False());
60     Label exit(env);
61     Label indexIsvalid(env);
62     Label indexNotLessZero(env);
63     BRANCH(Int64LessThan(index, Int64(0)), &exit, &indexNotLessZero);
64     Bind(&indexNotLessZero);
65     {
66         GateRef arrLen = GetArrayLength(array);
67         BRANCH(Int64GreaterThanOrEqual(index, ZExtInt32ToInt64(arrLen)), &exit, &indexIsvalid);
68         Bind(&indexIsvalid);
69         {
70             result = True();
71             Jump(&exit);
72         }
73     }
74     Bind(&exit);
75     auto ret = *result;
76     env->SubCfgExit();
77     return ret;
78 }
79 
LoadTypedArrayElement(GateRef glue,GateRef array,GateRef key,GateRef jsType)80 GateRef BuiltinsTypedArrayStubBuilder::LoadTypedArrayElement(GateRef glue, GateRef array, GateRef key, GateRef jsType)
81 {
82     auto env = GetEnvironment();
83     Label entryPass(env);
84     env->SubCfgEntry(&entryPass);
85     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
86     Label exit(env);
87     Label notDetached(env);
88     Label indexIsvalid(env);
89     Label slowPath(env);
90     GateRef buffer = GetViewedArrayBuffer(array);
91     BRANCH(IsDetachedBuffer(buffer), &exit, &notDetached);
92     Bind(&notDetached);
93     {
94         GateRef index = TryToElementsIndex(glue, key);
95         BRANCH(CheckTypedArrayIndexInRange(array, index), &indexIsvalid, &exit);
96         Bind(&indexIsvalid);
97         {
98             GateRef offset = GetByteOffset(array);
99             result = GetValueFromBuffer(buffer, TruncInt64ToInt32(index), offset, jsType);
100             BRANCH(TaggedIsNumber(*result), &exit, &slowPath);
101         }
102         Bind(&slowPath);
103         {
104             result = CallRuntime(glue, RTSTUB_ID(GetTypeArrayPropertyByIndex),
105                 { array, IntToTaggedInt(index), IntToTaggedInt(jsType) });
106             Jump(&exit);
107         }
108     }
109     Bind(&exit);
110     auto ret = *result;
111     env->SubCfgExit();
112     return ret;
113 }
114 
StoreTypedArrayElement(GateRef glue,GateRef array,GateRef index,GateRef value,GateRef jsType)115 GateRef BuiltinsTypedArrayStubBuilder::StoreTypedArrayElement(GateRef glue, GateRef array, GateRef index, GateRef value,
116                                                               GateRef jsType)
117 {
118     auto env = GetEnvironment();
119     Label entryPass(env);
120     env->SubCfgEntry(&entryPass);
121     DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
122     Label exit(env);
123     Label notDetached(env);
124     Label indexIsvalid(env);
125     GateRef buffer = GetViewedArrayBuffer(array);
126     BRANCH(IsDetachedBuffer(buffer), &exit, &notDetached);
127     Bind(&notDetached);
128     {
129         BRANCH(CheckTypedArrayIndexInRange(array, index), &indexIsvalid, &exit);
130         Bind(&indexIsvalid);
131         {
132             result = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
133                 { array, IntToTaggedInt(index), value, IntToTaggedInt(jsType) });
134             Jump(&exit);
135         }
136     }
137     Bind(&exit);
138     auto ret = *result;
139     env->SubCfgExit();
140     return ret;
141 }
142 
FastGetPropertyByIndex(GateRef glue,GateRef array,GateRef index,GateRef jsType)143 GateRef BuiltinsTypedArrayStubBuilder::FastGetPropertyByIndex(GateRef glue, GateRef array,
144                                                               GateRef index, GateRef jsType)
145 {
146     auto env = GetEnvironment();
147     Label entryPass(env);
148     env->SubCfgEntry(&entryPass);
149     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
150     Label exit(env);
151     Label isDetached(env);
152     Label notDetached(env);
153     Label slowPath(env);
154     Label indexIsvalid(env);
155 
156     GateRef buffer = GetViewedArrayBuffer(array);
157     BRANCH(IsDetachedBuffer(buffer), &isDetached, &notDetached);
158     Bind(&isDetached);
159     {
160         Jump(&slowPath);
161     }
162     Bind(&notDetached);
163     {
164         GateRef arrLen = GetArrayLength(array);
165         BRANCH(Int32GreaterThanOrEqual(index, arrLen), &exit, &indexIsvalid);
166         Bind(&indexIsvalid);
167         {
168             GateRef offset = GetByteOffset(array);
169             result = GetValueFromBuffer(buffer, index, offset, jsType);
170             BRANCH(TaggedIsNumber(*result), &exit, &slowPath);
171         }
172     }
173     Bind(&slowPath);
174     {
175         result = CallRuntime(glue, RTSTUB_ID(GetTypeArrayPropertyByIndex),
176             { array, IntToTaggedInt(index), IntToTaggedInt(jsType)});
177         Jump(&exit);
178     }
179     Bind(&exit);
180     auto ret = *result;
181     env->SubCfgExit();
182     return ret;
183 }
184 
FastCopyElementToArray(GateRef glue,GateRef typedArray,GateRef array)185 GateRef BuiltinsTypedArrayStubBuilder::FastCopyElementToArray(GateRef glue, GateRef typedArray, GateRef array)
186 {
187     auto env = GetEnvironment();
188     Label entryPass(env);
189     env->SubCfgEntry(&entryPass);
190     DEFVARIABLE(result, VariableType::BOOL(), True());
191     DEFVARIABLE(start, VariableType::INT32(), Int32(0));
192     Label exit(env);
193     Label isDetached(env);
194     Label notDetached(env);
195     Label slowPath(env);
196     Label begin(env);
197     Label storeValue(env);
198     Label endLoop(env);
199 
200     GateRef buffer = GetViewedArrayBuffer(typedArray);
201     BRANCH(IsDetachedBuffer(buffer), &isDetached, &notDetached);
202     Bind(&isDetached);
203     {
204         result = False();
205         Jump(&slowPath);
206     }
207     Bind(&notDetached);
208     {
209         GateRef arrLen = GetArrayLength(typedArray);
210         GateRef offset = GetByteOffset(typedArray);
211         GateRef hclass = LoadHClass(typedArray);
212         GateRef jsType = GetObjectType(hclass);
213 
214         Jump(&begin);
215         LoopBegin(&begin);
216         {
217             BRANCH(Int32UnsignedLessThan(*start, arrLen), &storeValue, &exit);
218             Bind(&storeValue);
219             {
220                 GateRef value = GetValueFromBuffer(buffer, *start, offset, jsType);
221                 SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, *start, value);
222                 start = Int32Add(*start, Int32(1));
223                 Jump(&endLoop);
224             }
225             Bind(&endLoop);
226             LoopEnd(&begin);
227         }
228     }
229     Bind(&slowPath);
230     {
231         CallRuntime(glue, RTSTUB_ID(FastCopyElementToArray), { typedArray, array});
232         Jump(&exit);
233     }
234     Bind(&exit);
235     auto ret = *result;
236     env->SubCfgExit();
237     return ret;
238 }
239 
GetValueFromBuffer(GateRef buffer,GateRef index,GateRef offset,GateRef jsType)240 GateRef BuiltinsTypedArrayStubBuilder::GetValueFromBuffer(GateRef buffer, GateRef index, GateRef offset, GateRef jsType)
241 {
242     auto env = GetEnvironment();
243     Label entryPass(env);
244     env->SubCfgEntry(&entryPass);
245     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
246     Label exit(env);
247     Label defaultLabel(env);
248     Label isInt8(env);
249     Label notInt8(env);
250     Label isInt16(env);
251     Label notInt16(env);
252 
253     Label labelBuffer[3] = { Label(env), Label(env), Label(env) };
254     Label labelBuffer1[3] = { Label(env), Label(env), Label(env) };
255     Label labelBuffer2[3] = { Label(env), Label(env), Label(env) };
256     int64_t valueBuffer[3] = {
257         static_cast<int64_t>(JSType::JS_INT8_ARRAY), static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
258         static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY) };
259     int64_t valueBuffer1[3] = {
260         static_cast<int64_t>(JSType::JS_INT16_ARRAY), static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
261         static_cast<int64_t>(JSType::JS_INT32_ARRAY) };
262     int64_t valueBuffer2[3] = {
263         static_cast<int64_t>(JSType::JS_UINT32_ARRAY), static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
264         static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY) };
265 
266     BRANCH(Int32LessThanOrEqual(jsType, Int32(static_cast<int32_t>(JSType::JS_UINT8_CLAMPED_ARRAY))),
267         &isInt8, &notInt8);
268     Bind(&isInt8);
269     {
270         // 3 : this switch has 3 case
271         Switch(jsType, &defaultLabel, valueBuffer, labelBuffer, 3);
272         Bind(&labelBuffer[0]);
273         {
274             GateRef byteIndex = Int32Add(index, offset);
275             GateRef block = GetDataPointFromBuffer(buffer);
276             GateRef re = Load(VariableType::INT8(), block, byteIndex);
277             result = IntToTaggedPtr(SExtInt8ToInt32(re));
278             Jump(&exit);
279         }
280 
281         Bind(&labelBuffer[1]);
282         {
283             GateRef byteIndex = Int32Add(index, offset);
284             GateRef block = GetDataPointFromBuffer(buffer);
285             GateRef re = Load(VariableType::INT8(), block, byteIndex);
286             result = IntToTaggedPtr(ZExtInt8ToInt32(re));
287             Jump(&exit);
288         }
289         // 2 : index of this buffer
290         Bind(&labelBuffer[2]);
291         {
292             GateRef byteIndex = Int32Add(index, offset);
293             GateRef block = GetDataPointFromBuffer(buffer);
294             GateRef re = Load(VariableType::INT8(), block, byteIndex);
295             result = IntToTaggedPtr(ZExtInt8ToInt32(re));
296             Jump(&exit);
297         }
298     }
299 
300     Bind(&notInt8);
301     {
302         BRANCH(Int32LessThanOrEqual(jsType, Int32(static_cast<int32_t>(JSType::JS_INT32_ARRAY))),
303             &isInt16, &notInt16);
304         Bind(&isInt16);
305         {
306             // 3 : this switch has 3 case
307             Switch(jsType, &defaultLabel, valueBuffer1, labelBuffer1, 3);
308             Bind(&labelBuffer1[0]);
309             {
310                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::TWO)), offset);
311                 GateRef block = GetDataPointFromBuffer(buffer);
312                 GateRef re = Load(VariableType::INT16(), block, byteIndex);
313                 result = IntToTaggedPtr(SExtInt16ToInt32(re));
314                 Jump(&exit);
315             }
316 
317             Bind(&labelBuffer1[1]);
318             {
319                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::TWO)), offset);
320                 GateRef block = GetDataPointFromBuffer(buffer);
321                 GateRef re = Load(VariableType::INT16(), block, byteIndex);
322                 result = IntToTaggedPtr(ZExtInt16ToInt32(re));
323                 Jump(&exit);
324             }
325             // 2 : index of this buffer
326             Bind(&labelBuffer1[2]);
327             {
328                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::FOUR)), offset);
329                 GateRef block = GetDataPointFromBuffer(buffer);
330                 GateRef re = Load(VariableType::INT32(), block, byteIndex);
331                 result = IntToTaggedPtr(re);
332                 Jump(&exit);
333             }
334         }
335         Bind(&notInt16);
336         {
337             // 3 : this switch has 3 case
338             Switch(jsType, &defaultLabel, valueBuffer2, labelBuffer2, 3);
339             Bind(&labelBuffer2[0]);
340             {
341                 Label overflow(env);
342                 Label notOverflow(env);
343                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::FOUR)), offset);
344                 GateRef block = GetDataPointFromBuffer(buffer);
345                 GateRef re = Load(VariableType::INT32(), block, byteIndex);
346 
347                 auto condition = Int32UnsignedGreaterThan(re, Int32(INT32_MAX));
348                 BRANCH(condition, &overflow, &notOverflow);
349                 Bind(&overflow);
350                 {
351                     result = DoubleToTaggedDoublePtr(ChangeUInt32ToFloat64(re));
352                     Jump(&exit);
353                 }
354                 Bind(&notOverflow);
355                 {
356                     result = IntToTaggedPtr(re);
357                     Jump(&exit);
358                 }
359             }
360             Bind(&labelBuffer2[1]);
361             {
362                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::FOUR)), offset);
363                 GateRef block = GetDataPointFromBuffer(buffer);
364                 GateRef re = Load(VariableType::INT32(), block, byteIndex);
365                 result = DoubleToTaggedDoublePtr(ExtFloat32ToDouble(CastInt32ToFloat32(re)));
366                 Jump(&exit);
367             }
368             // 2 : index of this buffer
369             Bind(&labelBuffer2[2]);
370             {
371                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::EIGHT)), offset);
372                 GateRef block = GetDataPointFromBuffer(buffer);
373                 GateRef re = Load(VariableType::INT64(), block, byteIndex);
374                 result = DoubleToTaggedDoublePtr(CastInt64ToFloat64(re));
375                 Jump(&exit);
376             }
377         }
378     }
379 
380     Bind(&defaultLabel);
381     {
382         Jump(&exit);
383     }
384     Bind(&exit);
385     auto ret = *result;
386     env->SubCfgExit();
387     return ret;
388 }
389 
CalculatePositionWithLength(GateRef position,GateRef length)390 GateRef BuiltinsTypedArrayStubBuilder::CalculatePositionWithLength(GateRef position, GateRef length)
391 {
392     auto env = GetEnvironment();
393     Label entry(env);
394     env->SubCfgEntry(&entry);
395     DEFVARIABLE(result, VariableType::INT64(), Int64(0));
396     Label positionLessThanZero(env);
397     Label positionNotLessThanZero(env);
398     Label resultNotGreaterThanZero(env);
399     Label positionLessThanLength(env);
400     Label positionNotLessThanLength(env);
401     Label afterCalculatePosition(env);
402 
403     BRANCH(Int64LessThan(position, Int64(0)), &positionLessThanZero, &positionNotLessThanZero);
404     Bind(&positionLessThanZero);
405     {
406         result = Int64Add(position, length);
407         BRANCH(Int64GreaterThan(*result, Int64(0)), &afterCalculatePosition, &resultNotGreaterThanZero);
408         Bind(&resultNotGreaterThanZero);
409         {
410             result = Int64(0);
411             Jump(&afterCalculatePosition);
412         }
413     }
414     Bind(&positionNotLessThanZero);
415     {
416         BRANCH(Int64LessThan(position, length), &positionLessThanLength, &positionNotLessThanLength);
417         Bind(&positionLessThanLength);
418         {
419             result = position;
420             Jump(&afterCalculatePosition);
421         }
422         Bind(&positionNotLessThanLength);
423         {
424             result = length;
425             Jump(&afterCalculatePosition);
426         }
427     }
428     Bind(&afterCalculatePosition);
429     auto ret = *result;
430     env->SubCfgExit();
431     return ret;
432 }
433 
Reverse(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)434 void BuiltinsTypedArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs,
435     Variable *result, Label *exit, Label *slowPath)
436 {
437     auto env = GetEnvironment();
438     Label ecmaObj(env);
439     Label isFastTypedArray(env);
440     Label defaultConstr(env);
441     Label notDetached(env);
442 
443     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
444     Bind(&ecmaObj);
445     GateRef arrayType = GetObjectType(LoadHClass(thisValue));
446     BRANCH(IsFastTypeArray(arrayType), &isFastTypedArray, slowPath);
447     Bind(&isFastTypedArray);
448     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
449     Bind(&defaultConstr);
450     GateRef buffer = GetViewedArrayBuffer(thisValue);
451     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
452     Bind(&notDetached);
453 
454     DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
455     GateRef middle = Int64Div(*thisArrLen, Int64(2));
456     DEFVARIABLE(lower, VariableType::INT64(), Int64(0));
457     Label loopHead(env);
458     Label loopEnd(env);
459     Label loopNext(env);
460     Label loopExit(env);
461     Jump(&loopHead);
462     LoopBegin(&loopHead);
463     {
464         BRANCH(Int64NotEqual(*lower, middle), &loopNext, &loopExit);
465         Bind(&loopNext);
466         {
467             DEFVARIABLE(upper, VariableType::INT64(), Int64Sub(Int64Sub(*thisArrLen, *lower), Int64(1)));
468             Label hasException0(env);
469             Label hasException1(env);
470             Label notHasException0(env);
471             GateRef lowerValue = FastGetPropertyByIndex(glue, thisValue,
472                 TruncInt64ToInt32(*lower), arrayType);
473             GateRef upperValue = FastGetPropertyByIndex(glue, thisValue,
474                 TruncInt64ToInt32(*upper), arrayType);
475             BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
476             Bind(&hasException0);
477             {
478                 result->WriteVariable(Exception());
479                 Jump(exit);
480             }
481             Bind(&notHasException0);
482             {
483                 StoreTypedArrayElement(glue, thisValue, *lower, upperValue, arrayType);
484                 StoreTypedArrayElement(glue, thisValue, *upper, lowerValue, arrayType);
485                 BRANCH(HasPendingException(glue), &hasException1, &loopEnd);
486                 Bind(&hasException1);
487                 {
488                     result->WriteVariable(Exception());
489                     Jump(exit);
490                 }
491             }
492         }
493     }
494     Bind(&loopEnd);
495     lower = Int64Add(*lower, Int64(1));
496     LoopEnd(&loopHead);
497     Bind(&loopExit);
498     result->WriteVariable(thisValue);
499     Jump(exit);
500 }
501 
LastIndexOf(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)502 void BuiltinsTypedArrayStubBuilder::LastIndexOf(GateRef glue, GateRef thisValue, GateRef numArgs,
503     Variable *result, Label *exit, Label *slowPath)
504 {
505     auto env = GetEnvironment();
506     Label thisExists(env);
507     Label isHeapObject(env);
508     Label typedArray(env);
509     Label notDetached(env);
510 
511     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
512     Bind(&thisExists);
513     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
514     Bind(&isHeapObject);
515     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
516     Bind(&typedArray);
517     GateRef buffer = GetViewedArrayBuffer(thisValue);
518     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
519     Bind(&notDetached);
520 
521     GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue));
522     Label isEmptyArray(env);
523     Label notEmptyArray(env);
524     BRANCH(Int64Equal(len, Int64(0)), &isEmptyArray, &notEmptyArray);
525     Bind(&isEmptyArray);
526     {
527         result->WriteVariable(IntToTaggedPtr(Int32(-1)));
528         Jump(exit);
529     }
530     Bind(&notEmptyArray);
531 
532     GateRef value = GetCallArg0(numArgs);
533     DEFVARIABLE(relativeFromIndex, VariableType::INT64(), Int64(0));
534     Label findIndex(env);
535     Label isOneArg(env);
536     Label isTwoArg(env);
537     // 2:Indicates the number of parameters passed in.
538     BRANCH(Int64Equal(TruncPtrToInt32(numArgs), Int32(2)), &isTwoArg, &isOneArg);
539     Bind(&isOneArg);
540     {
541         relativeFromIndex = Int64Sub(len, Int64(1));
542         Jump(&findIndex);
543     }
544     Bind(&isTwoArg);
545     {
546         GateRef fromIndex = GetCallArg1(numArgs);
547         Label taggedIsInt(env);
548         BRANCH(TaggedIsInt(fromIndex), &taggedIsInt, slowPath);
549         Bind(&taggedIsInt);
550         GateRef fromIndexInt = SExtInt32ToInt64(TaggedGetInt(fromIndex));
551         Label isFromIndexLessZero(env);
552         Label isFromIndexNotLessZero(env);
553         BRANCH(Int64LessThan(fromIndexInt, Int64(0)), &isFromIndexLessZero, &isFromIndexNotLessZero);
554         Bind(&isFromIndexLessZero);
555         {
556             relativeFromIndex = Int64Add(len, fromIndexInt);
557             Jump(&findIndex);
558         }
559         Bind(&isFromIndexNotLessZero);
560         {
561             Label isFromIndexGreatLen(env);
562             Label isFromIndexNotGreatLen(env);
563             BRANCH(Int64GreaterThan(fromIndexInt, Int64Sub(len, Int64(1))),
564                 &isFromIndexGreatLen, &isFromIndexNotGreatLen);
565             Bind(&isFromIndexGreatLen);
566             {
567                 relativeFromIndex = Int64Sub(len, Int64(1));
568                 Jump(&findIndex);
569             }
570             Bind(&isFromIndexNotGreatLen);
571             {
572                 relativeFromIndex = fromIndexInt;
573                 Jump(&findIndex);
574             }
575         }
576     }
577 
578     Bind(&findIndex);
579     {
580         Label loopHead(env);
581         Label loopEnd(env);
582         Label loopExit(env);
583         Label loopNext(env);
584         Label isFound(env);
585         Jump(&loopHead);
586         LoopBegin(&loopHead);
587         {
588             BRANCH(Int64LessThan(*relativeFromIndex, Int64(0)), &loopExit, &loopNext);
589             Bind(&loopNext);
590             {
591                 GateRef hclass = LoadHClass(thisValue);
592                 GateRef jsType = GetObjectType(hclass);
593                 GateRef ele = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*relativeFromIndex), jsType);
594                 BRANCH(FastStrictEqual(glue, value, ele, ProfileOperation()), &isFound, &loopEnd);
595                 Bind(&isFound);
596                 {
597                     result->WriteVariable(IntToTaggedPtr(*relativeFromIndex));
598                     Jump(exit);
599                 }
600             }
601         }
602         Bind(&loopEnd);
603         relativeFromIndex = Int64Sub(*relativeFromIndex, Int64(1));
604         LoopEnd(&loopHead);
605         Bind(&loopExit);
606         result->WriteVariable(IntToTaggedPtr(Int32(-1)));
607         Jump(exit);
608     }
609 }
610 
IndexOf(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)611 void BuiltinsTypedArrayStubBuilder::IndexOf(GateRef glue, GateRef thisValue, GateRef numArgs,
612     Variable *result, Label *exit, Label *slowPath)
613 {
614     auto env = GetEnvironment();
615     Label ecmaObj(env);
616     Label typedArray(env);
617     Label defaultConstr(env);
618     Label notDetached(env);
619     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
620     Bind(&ecmaObj);
621     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
622     Bind(&typedArray);
623     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
624     Bind(&defaultConstr);
625     GateRef buffer = GetViewedArrayBuffer(thisValue);
626     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
627     Bind(&notDetached);
628 
629     DEFVARIABLE(fromIndex, VariableType::INT64(), Int64(0));
630     DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
631     Label thisIsEmpty(env);
632     Label thisIsNotEmpty(env);
633     Label getFromIndex(env);
634     Label next(env);
635     result->WriteVariable(IntToTaggedPtr(Int32(-1)));
636     BRANCH(Int64Equal(*thisArrLen, Int64(0)), &thisIsEmpty, &thisIsNotEmpty);
637     Bind(&thisIsEmpty);
638     Jump(exit);
639     Bind(&thisIsNotEmpty);
640     // 2 : index of the param
641     BRANCH(Int64Equal(numArgs, IntPtr(2)), &getFromIndex, &next);
642     Bind(&getFromIndex);
643     {
644         GateRef index = GetCallArg1(numArgs);
645         Label taggedIsInt(env);
646         Label lessThanZero(env);
647         Label stillLessThanZero(env);
648         BRANCH(TaggedIsInt(index), &taggedIsInt, slowPath);
649         Bind(&taggedIsInt);
650         fromIndex = SExtInt32ToInt64(TaggedGetInt(index));
651         BRANCH(Int64LessThan(*fromIndex, Int64(0)), &lessThanZero, &next);
652         Bind(&lessThanZero);
653         {
654             fromIndex = Int64Add(*fromIndex, *thisArrLen);
655             BRANCH(Int64LessThan(*fromIndex, Int64(0)), &stillLessThanZero, &next);
656             Bind(&stillLessThanZero);
657             fromIndex = Int64(0);
658             Jump(&next);
659         }
660     }
661     Bind(&next);
662     {
663         GateRef target = GetCallArg0(numArgs);
664         DEFVARIABLE(curIndex, VariableType::INT64(), *fromIndex);
665         Label lessThanLength(env);
666         BRANCH(Int64GreaterThanOrEqual(*curIndex, *thisArrLen), exit, &lessThanLength);
667         Bind(&lessThanLength);
668         {
669             Label loopHead(env);
670             Label loopEnd(env);
671             Label loopNext(env);
672             Label loopExit(env);
673             Jump(&loopHead);
674             LoopBegin(&loopHead);
675             {
676                 BRANCH(Int64LessThan(*curIndex, *thisArrLen), &loopNext, &loopExit);
677                 Bind(&loopNext);
678                 {
679                     GateRef kValue = FastGetPropertyByIndex(glue, thisValue,
680                         TruncInt64ToInt32(*curIndex), GetObjectType(LoadHClass(thisValue)));
681                     Label hasException0(env);
682                     Label notHasException0(env);
683                     BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
684                     Bind(&hasException0);
685                     {
686                         result->WriteVariable(Exception());
687                         Jump(exit);
688                     }
689                     Bind(&notHasException0);
690                     {
691                         Label find(env);
692                         BRANCH(FastStrictEqual(glue, target, kValue, ProfileOperation()), &find, &loopEnd);
693                         Bind(&find);
694                         {
695                             result->WriteVariable(IntToTaggedPtr(*curIndex));
696                             Jump(exit);
697                         }
698                     }
699                 }
700             }
701             Bind(&loopEnd);
702             curIndex = Int64Add(*curIndex, Int64(1));
703             LoopEnd(&loopHead);
704             Bind(&loopExit);
705             Jump(exit);
706         }
707     }
708 }
709 
Find(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)710 void BuiltinsTypedArrayStubBuilder::Find(GateRef glue, GateRef thisValue, GateRef numArgs,
711     Variable *result, Label *exit, Label *slowPath)
712 {
713     auto env = GetEnvironment();
714     Label isHeapObject(env);
715     Label defaultConstr(env);
716     Label typedArray(env);
717     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
718     Bind(&isHeapObject);
719     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
720     Bind(&typedArray);
721     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
722     Bind(&defaultConstr);
723     GateRef callbackFnHandle = GetCallArg0(numArgs);
724     Label arg0HeapObject(env);
725     BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
726     Bind(&arg0HeapObject);
727     Label callable(env);
728     BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
729     Bind(&callable);
730     GateRef argHandle = GetCallArg1(numArgs);
731     GateRef thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
732     DEFVARIABLE(i, VariableType::INT64(), Int64(0));
733     Label loopHead(env);
734     Label loopEnd(env);
735     Label next(env);
736     Label loopExit(env);
737     Jump(&loopHead);
738     LoopBegin(&loopHead);
739     {
740         Label hasException0(env);
741         Label notHasException0(env);
742         BRANCH(Int64LessThan(*i, thisArrLen), &next, &loopExit);
743         Bind(&next);
744         GateRef kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i),
745             GetObjectType(LoadHClass(thisValue)));
746         BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
747         Bind(&hasException0);
748         {
749             result->WriteVariable(Exception());
750             Jump(exit);
751         }
752         Bind(&notHasException0);
753         {
754             GateRef key = Int64ToTaggedInt(*i);
755             Label hasException1(env);
756             Label notHasException1(env);
757             JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
758             callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue };
759             CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
760                 Circuit::NullGate(), callArgs);
761             GateRef retValue = callBuilder.JSCallDispatch();
762             BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
763             Bind(&hasException1);
764             {
765                 result->WriteVariable(retValue);
766                 Jump(exit);
767             }
768             Bind(&notHasException1);
769             {
770                 Label find(env);
771                 BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
772                 Bind(&find);
773                 {
774                     result->WriteVariable(kValue);
775                     Jump(exit);
776                 }
777             }
778         }
779     }
780     Bind(&loopEnd);
781     i = Int64Add(*i, Int64(1));
782     LoopEnd(&loopHead);
783     Bind(&loopExit);
784     Jump(exit);
785 }
786 
Includes(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)787 void BuiltinsTypedArrayStubBuilder::Includes(GateRef glue, GateRef thisValue, GateRef numArgs,
788     Variable *result, Label *exit, Label *slowPath)
789 {
790     auto env = GetEnvironment();
791     Label typedArray(env);
792     Label isHeapObject(env);
793     Label notFound(env);
794     Label thisLenNotZero(env);
795     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
796     Bind(&isHeapObject);
797     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
798     Bind(&typedArray);
799     GateRef thisLen = GetArrayLength(thisValue);
800     BRANCH(Int32Equal(thisLen, Int32(0)), &notFound, &thisLenNotZero);
801     Bind(&thisLenNotZero);
802     {
803         DEFVARIABLE(fromIndex, VariableType::INT32(), Int32(0));
804         Label getArgTwo(env);
805         Label nextProcess(env);
806         BRANCH(Int64Equal(numArgs, IntPtr(2)), &getArgTwo, &nextProcess); // 2: 2 parameters
807         Bind(&getArgTwo);
808         {
809             Label secondArgIsInt(env);
810             GateRef fromIndexTemp = GetCallArg1(numArgs);
811             BRANCH(TaggedIsInt(fromIndexTemp), &secondArgIsInt, slowPath);
812             Bind(&secondArgIsInt);
813             fromIndex = GetInt32OfTInt(fromIndexTemp);
814             BRANCH(Int32GreaterThanOrEqual(*fromIndex, thisLen), &notFound, &nextProcess);
815         }
816         Bind(&nextProcess);
817         {
818             Label setBackZero(env);
819             Label calculateFrom(env);
820             Label nextCheck(env);
821             BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &nextCheck, slowPath);
822             Bind(&nextCheck);
823             {
824                 Label startLoop(env);
825                 BRANCH(Int32LessThan(Int32Add(*fromIndex, thisLen), Int32(0)), &setBackZero, &calculateFrom);
826                 Bind(&setBackZero);
827                 {
828                     fromIndex = Int32(0);
829                     Jump(&startLoop);
830                 }
831                 Bind(&calculateFrom);
832                 Label fromIndexLessThanZero(env);
833                 BRANCH(Int32GreaterThanOrEqual(*fromIndex, Int32(0)), &startLoop, &fromIndexLessThanZero);
834                 Bind(&fromIndexLessThanZero);
835                 {
836                     fromIndex = Int32Add(*fromIndex, thisLen);
837                     Jump(&startLoop);
838                 }
839                 Bind(&startLoop);
840                 GateRef searchElement = GetCallArg0(numArgs);
841                 Label loopHead(env);
842                 Label loopEnd(env);
843                 Label next(env);
844                 Label loopExit(env);
845                 Jump(&loopHead);
846                 LoopBegin(&loopHead);
847                 {
848                     BRANCH(Int32LessThan(*fromIndex, thisLen), &next, &loopExit);
849                     Bind(&next);
850                     {
851                         Label valueFound(env);
852                         GateRef value = FastGetPropertyByIndex(glue, thisValue, *fromIndex,
853                             GetObjectType(LoadHClass(thisValue)));
854                         GateRef valueEqual = StubBuilder::SameValueZero(glue, searchElement, value);
855                         BRANCH(valueEqual, &valueFound, &loopEnd);
856                         Bind(&valueFound);
857                         {
858                             result->WriteVariable(TaggedTrue());
859                             Jump(exit);
860                         }
861                     }
862                 }
863                 Bind(&loopEnd);
864                 fromIndex = Int32Add(*fromIndex, Int32(1));
865                 LoopEnd(&loopHead);
866                 Bind(&loopExit);
867                 Jump(&notFound);
868             }
869         }
870     }
871     Bind(&notFound);
872     {
873         result->WriteVariable(TaggedFalse());
874         Jump(exit);
875     }
876 }
877 
CopyWithin(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)878 void BuiltinsTypedArrayStubBuilder::CopyWithin(GateRef glue, GateRef thisValue, GateRef numArgs,
879     Variable *result, Label *exit, Label *slowPath)
880 {
881     auto env = GetEnvironment();
882     Label isHeapObject(env);
883     Label defaultConstr(env);
884     Label typedArray(env);
885     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
886     Bind(&isHeapObject);
887     GateRef jsType = GetObjectType(LoadHClass(thisValue));
888     BRANCH(IsFastTypeArray(jsType), &typedArray, slowPath);
889     Bind(&typedArray);
890     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
891     Bind(&defaultConstr);
892 
893     DEFVARIABLE(startPos, VariableType::INT64(), Int64(0));
894     DEFVARIABLE(endPos, VariableType::INT64(), Int64(0));
895     Label targetTagExists(env);
896     Label targetTagIsInt(env);
897     Label startTagExists(env);
898     Label startTagIsInt(env);
899     Label afterCallArg1(env);
900     Label endTagExists(env);
901     Label endTagIsInt(env);
902     Label afterCallArg2(env);
903     GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
904     // 0 : index of the param
905     BRANCH(Int64GreaterThanOrEqual(IntPtr(0), numArgs), slowPath, &targetTagExists);
906     Bind(&targetTagExists);
907     GateRef targetTag = GetCallArg0(numArgs);
908     BRANCH(TaggedIsInt(targetTag), &targetTagIsInt, slowPath);
909     Bind(&targetTagIsInt);
910     GateRef argTarget = SExtInt32ToInt64(TaggedGetInt(targetTag));
911     // 1 : index of the param
912     BRANCH(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &afterCallArg1, &startTagExists);
913     Bind(&startTagExists);
914     GateRef startTag = GetCallArg1(numArgs);
915     BRANCH(TaggedIsInt(startTag), &startTagIsInt, slowPath);
916     Bind(&startTagIsInt);
917     startPos = SExtInt32ToInt64(TaggedGetInt(startTag));
918     Jump(&afterCallArg1);
919     Bind(&afterCallArg1);
920     endPos = thisLen;
921     // 2 : index of the param
922     BRANCH(Int64GreaterThanOrEqual(IntPtr(2), numArgs), &afterCallArg2, &endTagExists);
923     Bind(&endTagExists);
924     GateRef endTag = GetCallArg2(numArgs);
925     BRANCH(TaggedIsInt(endTag), &endTagIsInt, slowPath);
926     Bind(&endTagIsInt);
927     endPos = SExtInt32ToInt64(TaggedGetInt(endTag));
928     Jump(&afterCallArg2);
929     Bind(&afterCallArg2);
930 
931     DEFVARIABLE(copyTo, VariableType::INT64(), Int64(0));
932     DEFVARIABLE(copyFrom, VariableType::INT64(), Int64(0));
933     DEFVARIABLE(copyEnd, VariableType::INT64(), Int64(0));
934     DEFVARIABLE(count, VariableType::INT64(), Int64(0));
935     DEFVARIABLE(direction, VariableType::INT64(), Int64(0));
936     Label calculateCountBranch1(env);
937     Label calculateCountBranch2(env);
938     Label afterCalculateCount(env);
939     Label needToAdjustParam(env);
940     Label afterAdjustParam(env);
941     copyTo = CalculatePositionWithLength(argTarget, thisLen);
942     copyFrom = CalculatePositionWithLength(*startPos, thisLen);
943     copyEnd = CalculatePositionWithLength(*endPos, thisLen);
944     BRANCH(Int64LessThan(Int64Sub(*copyEnd, *copyFrom), Int64Sub(thisLen, *copyTo)),
945         &calculateCountBranch1, &calculateCountBranch2);
946     Bind(&calculateCountBranch1);
947     {
948         count = Int64Sub(*copyEnd, *copyFrom);
949         Jump(&afterCalculateCount);
950     }
951     Bind(&calculateCountBranch2);
952     {
953         count = Int64Sub(thisLen, *copyTo);
954         Jump(&afterCalculateCount);
955     }
956     Bind(&afterCalculateCount);
957     {
958         direction = Int64(1);
959         GateRef copyFromVal = *copyFrom;
960         GateRef copyToVal = *copyTo;
961         GateRef countVal = *count;
962         BRANCH(LogicAndBuilder(env).And(Int64LessThan(copyFromVal, copyToVal))
963             .And(Int64LessThan(copyToVal, Int64Add(copyFromVal, countVal))).Done(),
964             &needToAdjustParam, &afterAdjustParam);
965         Bind(&needToAdjustParam);
966         {
967             direction = Int64(-1);
968             copyFrom = Int64Sub(Int64Add(*copyFrom, *count), Int64(1));
969             copyTo = Int64Sub(Int64Add(*copyTo, *count), Int64(1));
970             Jump(&afterAdjustParam);
971         }
972         Bind(&afterAdjustParam);
973         {
974             DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
975             Label loopHead(env);
976             Label loopEnd(env);
977             Label next(env);
978             Label loopExit(env);
979             Jump(&loopHead);
980             LoopBegin(&loopHead);
981             {
982                 Label hasException0(env);
983                 Label notHasException0(env);
984                 BRANCH(Int64GreaterThan(*count, Int64(0)), &next, &loopExit);
985                 Bind(&next);
986                 kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*copyFrom), jsType);
987                 BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
988                 Bind(&hasException0);
989                 {
990                     result->WriteVariable(Exception());
991                     Jump(exit);
992                 }
993                 Bind(&notHasException0);
994                 {
995                     StoreTypedArrayElement(glue, thisValue, *copyTo, *kValue, jsType);
996                     Jump(&loopEnd);
997                 }
998             }
999             Bind(&loopEnd);
1000             copyFrom = Int64Add(*copyFrom, *direction);
1001             copyTo = Int64Add(*copyTo, *direction);
1002             count = Int64Sub(*count, Int64(1));
1003             LoopEnd(&loopHead);
1004             Bind(&loopExit);
1005             result->WriteVariable(thisValue);
1006             Jump(exit);
1007         }
1008     }
1009 }
1010 
ReduceRight(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1011 void BuiltinsTypedArrayStubBuilder::ReduceRight(GateRef glue, GateRef thisValue, GateRef numArgs,
1012     Variable *result, Label *exit, Label *slowPath)
1013 {
1014     auto env = GetEnvironment();
1015     Label ecmaObj(env);
1016     Label defaultConstr(env);
1017     Label atLeastOneArg(env);
1018     Label callbackFnHandleHeapObject(env);
1019     Label callbackFnHandleCallable(env);
1020     Label noTypeError(env);
1021     Label typedArray(env);
1022     Label notDetached(env);
1023 
1024     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
1025     Bind(&ecmaObj);
1026     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
1027     Bind(&typedArray);
1028     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1029     Bind(&defaultConstr);
1030     GateRef buffer = GetViewedArrayBuffer(thisValue);
1031     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
1032     Bind(&notDetached);
1033     GateRef thisLen = GetArrayLength(thisValue);
1034     BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
1035     Bind(&atLeastOneArg);
1036     GateRef callbackFnHandle = GetCallArg0(numArgs);
1037     BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath);
1038     Bind(&callbackFnHandleHeapObject);
1039     BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath);
1040     Bind(&callbackFnHandleCallable);
1041     GateRef thisLenIsZero = Int32Equal(thisLen, Int32(0));
1042     GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2));
1043     BRANCH(BitAnd(thisLenIsZero, numArgsLessThanTwo), slowPath, &noTypeError);
1044     Bind(&noTypeError);
1045     {
1046         DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined());
1047         DEFVARIABLE(k, VariableType::INT32(), Int32Sub(thisLen, Int32(1)));
1048         Label updateAccumulator(env);
1049         Label accumulateBegin(env);
1050         Label defaultValue(env);
1051         BRANCH(numArgsLessThanTwo, &defaultValue, &updateAccumulator);
1052         Bind(&updateAccumulator);
1053         {
1054             accumulator = GetCallArg1(numArgs);
1055             Jump(&accumulateBegin);
1056         }
1057         Bind(&defaultValue);
1058         {
1059             accumulator = FastGetPropertyByIndex(glue, thisValue, *k, GetObjectType(LoadHClass(thisValue)));
1060             k = Int32Sub(*k, Int32(1));
1061             Jump(&accumulateBegin);
1062         }
1063         Bind(&accumulateBegin);
1064         {
1065             // 4 : max value of the param amount
1066             GateRef argsLength = Int32(4);
1067             NewObjectStubBuilder newBuilder(this);
1068             GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
1069             Label loopHead(env);
1070             Label next(env);
1071             Label loopEnd(env);
1072             Label loopExit(env);
1073             Jump(&loopHead);
1074             LoopBegin(&loopHead);
1075             {
1076                 BRANCH(Int32GreaterThanOrEqual(*k, Int32(0)), &next, &loopExit);
1077                 Bind(&next);
1078                 {
1079                     GateRef kValue = FastGetPropertyByIndex(glue, thisValue, *k, GetObjectType(LoadHClass(thisValue)));
1080                     // 0 : the first position
1081                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
1082                     // 1 : the second position
1083                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), kValue);
1084                     // 2 : the third position
1085                     SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
1086                     // 3 : the fourth position
1087                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
1088                     GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
1089                     JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
1090                     callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
1091                     CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr,
1092                         Circuit::NullGate(), callArgs);
1093                     GateRef callResult = callBuilder.JSCallDispatch();
1094                     Label hasException1(env);
1095                     Label notHasException1(env);
1096                     BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
1097                     Bind(&hasException1);
1098                     {
1099                         result->WriteVariable(Exception());
1100                         Jump(exit);
1101                     }
1102                     Bind(&notHasException1);
1103                     {
1104                         accumulator = callResult;
1105                         Jump(&loopEnd);
1106                     }
1107                 }
1108             }
1109             Bind(&loopEnd);
1110             k = Int32Sub(*k, Int32(1));
1111             LoopEnd(&loopHead);
1112             Bind(&loopExit);
1113             result->WriteVariable(*accumulator);
1114             Jump(exit);
1115         }
1116     }
1117 }
1118 
Reduce(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1119 void BuiltinsTypedArrayStubBuilder::Reduce(GateRef glue, GateRef thisValue, GateRef numArgs,
1120     Variable *result, Label *exit, Label *slowPath)
1121 {
1122     auto env = GetEnvironment();
1123     Label ecmaObj(env);
1124     Label defaultConstr(env);
1125     Label atLeastOneArg(env);
1126     Label callbackFnHandleHeapObject(env);
1127     Label callbackFnHandleCallable(env);
1128     Label noTypeError(env);
1129     Label typedArray(env);
1130     Label notDetached(env);
1131 
1132     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
1133     Bind(&ecmaObj);
1134     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
1135     Bind(&typedArray);
1136     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1137     Bind(&defaultConstr);
1138     GateRef buffer = GetViewedArrayBuffer(thisValue);
1139     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
1140     Bind(&notDetached);
1141     GateRef thisLen = GetArrayLength(thisValue);
1142     BRANCH(Int64GreaterThanOrEqual(numArgs, IntPtr(1)), &atLeastOneArg, slowPath);
1143     Bind(&atLeastOneArg);
1144     GateRef callbackFnHandle = GetCallArg0(numArgs);
1145     BRANCH(TaggedIsHeapObject(callbackFnHandle), &callbackFnHandleHeapObject, slowPath);
1146     Bind(&callbackFnHandleHeapObject);
1147     BRANCH(IsCallable(callbackFnHandle), &callbackFnHandleCallable, slowPath);
1148     Bind(&callbackFnHandleCallable);
1149     GateRef thisLenIsZero = Int32Equal(thisLen, Int32(0));
1150     GateRef numArgsLessThanTwo = Int64LessThan(numArgs, IntPtr(2));
1151     BRANCH(BitAnd(thisLenIsZero, numArgsLessThanTwo), slowPath, &noTypeError);
1152     Bind(&noTypeError);
1153     {
1154         DEFVARIABLE(accumulator, VariableType::JS_ANY(), Undefined());
1155         DEFVARIABLE(k, VariableType::INT32(), Int32(0));
1156         Label updateAccumulator(env);
1157         Label accumulateBegin(env);
1158         Label defaultValue(env);
1159         // 2 : index of the param
1160         BRANCH(numArgsLessThanTwo, &defaultValue, &updateAccumulator);
1161         Bind(&updateAccumulator);
1162         {
1163             accumulator = GetCallArg1(numArgs);
1164             Jump(&accumulateBegin);
1165         }
1166         Bind(&defaultValue);
1167         {
1168             accumulator = FastGetPropertyByIndex(glue, thisValue, Int32(0), GetObjectType(LoadHClass(thisValue)));
1169             k = Int32Add(*k, Int32(1));
1170             Jump(&accumulateBegin);
1171         }
1172         Bind(&accumulateBegin);
1173         {
1174             // 4 : max value of the param amount
1175             GateRef argsLength = Int32(4);
1176             NewObjectStubBuilder newBuilder(this);
1177             GateRef argList = newBuilder.NewTaggedArray(glue, argsLength);
1178             Label loopHead(env);
1179             Label next(env);
1180             Label loopEnd(env);
1181             Label loopExit(env);
1182             Jump(&loopHead);
1183             LoopBegin(&loopHead);
1184             {
1185                 BRANCH(Int32LessThan(*k, thisLen), &next, &loopExit);
1186                 Bind(&next);
1187                 {
1188                     GateRef kValue = FastGetPropertyByIndex(glue, thisValue, *k, GetObjectType(LoadHClass(thisValue)));
1189                     // 0 : the first position
1190                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(0), *accumulator);
1191                     // 1 : the second position
1192                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(1), kValue);
1193                     // 2 : the third position
1194                     SetValueToTaggedArray(VariableType::INT32(), glue, argList, Int32(2), IntToTaggedInt(*k));
1195                     // 3 : the fourth position
1196                     SetValueToTaggedArray(VariableType::JS_ANY(), glue, argList, Int32(3), thisValue);
1197                     GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
1198                     JSCallArgs callArgs(JSCallMode::CALL_THIS_ARGV_WITH_RETURN);
1199                     callArgs.callThisArgvWithReturnArgs = { argsLength, argv, Undefined() };
1200                     CallStubBuilder callBuilder(this, glue, callbackFnHandle, argsLength, 0, nullptr,
1201                         Circuit::NullGate(), callArgs);
1202                     GateRef callResult = callBuilder.JSCallDispatch();
1203                     Label hasException1(env);
1204                     Label notHasException1(env);
1205                     BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
1206                     Bind(&hasException1);
1207                     {
1208                         result->WriteVariable(Exception());
1209                         Jump(exit);
1210                     }
1211                     Bind(&notHasException1);
1212                     {
1213                         accumulator = callResult;
1214                         Jump(&loopEnd);
1215                     }
1216                 }
1217             }
1218             Bind(&loopEnd);
1219             k = Int32Add(*k, Int32(1));
1220             LoopEnd(&loopHead);
1221             Bind(&loopExit);
1222             result->WriteVariable(*accumulator);
1223             Jump(exit);
1224         }
1225     }
1226 }
1227 
Every(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1228 void BuiltinsTypedArrayStubBuilder::Every(GateRef glue, GateRef thisValue,  GateRef numArgs,
1229     Variable *result, Label *exit, Label *slowPath)
1230 {
1231     auto env = GetEnvironment();
1232     Label isHeapObject(env);
1233     Label typedArray(env);
1234     Label defaultConstr(env);
1235     Label notDetached(env);
1236 
1237     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1238     Bind(&isHeapObject);
1239     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
1240     Bind(&typedArray);
1241     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1242     Bind(&defaultConstr);
1243     GateRef buffer = GetViewedArrayBuffer(thisValue);
1244     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
1245     Bind(&notDetached);
1246 
1247     Label arg0HeapObject(env);
1248     Label callable(env);
1249     GateRef callbackFnHandle = GetCallArg0(numArgs);
1250     BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
1251     Bind(&arg0HeapObject);
1252     BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
1253     Bind(&callable);
1254     GateRef argHandle = GetCallArg1(numArgs);
1255     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1256     DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
1257     GateRef thisArrlen = GetArrayLength(thisValue);
1258     Label loopHead(env);
1259     Label loopEnd(env);
1260     Label next(env);
1261     Label loopExit(env);
1262     Jump(&loopHead);
1263     LoopBegin(&loopHead);
1264     {
1265         Label hasException0(env);
1266         Label notHasException0(env);
1267         Label hasException1(env);
1268         Label notHasException1(env);
1269         Label retValueIsFalse(env);
1270         BRANCH(Int32LessThan(*i, thisArrlen), &next, &loopExit);
1271         Bind(&next);
1272         kValue = FastGetPropertyByIndex(glue, thisValue, *i, GetObjectType(LoadHClass(thisValue)));
1273         BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
1274         Bind(&hasException0);
1275         {
1276             result->WriteVariable(Exception());
1277             Jump(exit);
1278         }
1279         Bind(&notHasException0);
1280         {
1281             GateRef key = IntToTaggedInt(*i);
1282             JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
1283             callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
1284             CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
1285                 Circuit::NullGate(), callArgs);
1286             GateRef retValue = callBuilder.JSCallDispatch();
1287             BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
1288             Bind(&hasException1);
1289             {
1290                 result->WriteVariable(Exception());
1291                 Jump(exit);
1292             }
1293             Bind(&notHasException1);
1294             {
1295                 BRANCH(TaggedIsFalse(FastToBoolean(retValue)), &retValueIsFalse, &loopEnd);
1296                 Bind(&retValueIsFalse);
1297                 {
1298                     result->WriteVariable(TaggedFalse());
1299                     Jump(exit);
1300                 }
1301             }
1302         }
1303     }
1304     Bind(&loopEnd);
1305     i = Int32Add(*i, Int32(1));
1306     LoopEnd(&loopHead);
1307     Bind(&loopExit);
1308     result->WriteVariable(TaggedTrue());
1309     Jump(exit);
1310 }
1311 
Some(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1312 void BuiltinsTypedArrayStubBuilder::Some(GateRef glue, GateRef thisValue, GateRef numArgs,
1313     Variable *result, Label *exit, Label *slowPath)
1314 {
1315     auto env = GetEnvironment();
1316     Label ecmaObj(env);
1317     Label typedArray(env);
1318     Label thisExists(env);
1319     Label notDetached(env);
1320     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
1321     Bind(&ecmaObj);
1322     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
1323     Bind(&typedArray);
1324     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
1325     Bind(&thisExists);
1326     GateRef buffer = GetViewedArrayBuffer(thisValue);
1327     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
1328     Bind(&notDetached);
1329 
1330     Label arg0HeapObject(env);
1331     Label callable(env);
1332     GateRef callbackFnHandle = GetCallArg0(numArgs);
1333     BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
1334     Bind(&arg0HeapObject);
1335     BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
1336     Bind(&callable);
1337     {
1338         GateRef argHandle = GetCallArg1(numArgs);
1339         DEFVARIABLE(i, VariableType::INT64(), Int64(0));
1340         DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
1341         DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
1342         Label loopHead(env);
1343         Label loopEnd(env);
1344         Label next(env);
1345         Label loopExit(env);
1346         Jump(&loopHead);
1347         LoopBegin(&loopHead);
1348         {
1349             Label hasException0(env);
1350             Label notHasException0(env);
1351             Label callDispatch(env);
1352             Label hasException1(env);
1353             Label notHasException1(env);
1354             BRANCH(Int64LessThan(*i, *thisArrLen), &next, &loopExit);
1355             Bind(&next);
1356             kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i),
1357                 GetObjectType(LoadHClass(thisValue)));
1358             BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
1359             Bind(&hasException0);
1360             {
1361                 result->WriteVariable(Exception());
1362                 Jump(exit);
1363             }
1364             Bind(&notHasException0);
1365             {
1366                 BRANCH(TaggedIsHole(*kValue), &loopEnd, &callDispatch);
1367             }
1368             Bind(&callDispatch);
1369             {
1370                 GateRef key = Int64ToTaggedInt(*i);
1371                 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
1372                 callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
1373                 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
1374                     Circuit::NullGate(), callArgs);
1375                 GateRef retValue = callBuilder.JSCallDispatch();
1376                 BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
1377                 Bind(&hasException1);
1378                 {
1379                     result->WriteVariable(Exception());
1380                     Jump(exit);
1381                 }
1382                 Bind(&notHasException1);
1383                 {
1384                     Label retValueIsTrue(env);
1385                     BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd);
1386                     Bind(&retValueIsTrue);
1387                     {
1388                         result->WriteVariable(TaggedTrue());
1389                         Jump(exit);
1390                     }
1391                 }
1392             }
1393         }
1394         Bind(&loopEnd);
1395         i = Int64Add(*i, Int64(1));
1396         LoopEnd(&loopHead);
1397         Bind(&loopExit);
1398         result->WriteVariable(TaggedFalse());
1399         Jump(exit);
1400     }
1401 }
1402 
Filter(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1403 void BuiltinsTypedArrayStubBuilder::Filter(GateRef glue, GateRef thisValue, GateRef numArgs,
1404     Variable *result, Label *exit, Label *slowPath)
1405 {
1406     auto env = GetEnvironment();
1407     Label thisExists(env);
1408     Label notDetached(env);
1409     Label isEcmaObject(env);
1410     Label isFastTypedArray(env);
1411     Label defaultConstr(env);
1412     Label prototypeIsEcmaObj(env);
1413     Label isProtoChangeMarker(env);
1414     Label accessorNotChanged(env);
1415     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
1416     Bind(&thisExists);
1417     GateRef buffer = GetViewedArrayBuffer(thisValue);
1418     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
1419     Bind(&notDetached);
1420     BRANCH(IsEcmaObject(thisValue), &isEcmaObject, slowPath);
1421     Bind(&isEcmaObject);
1422     GateRef arrayType = GetObjectType(LoadHClass(thisValue));
1423     BRANCH(IsFastTypeArray(arrayType), &isFastTypedArray, slowPath);
1424     Bind(&isFastTypedArray);
1425     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1426     Bind(&defaultConstr);
1427     GateRef prototype = GetPrototypeFromHClass(LoadHClass(thisValue));
1428     BRANCH(IsEcmaObject(prototype), &prototypeIsEcmaObj, slowPath);
1429     Bind(&prototypeIsEcmaObj);
1430     GateRef marker = GetProtoChangeMarkerFromHClass(LoadHClass(prototype));
1431     BRANCH(TaggedIsProtoChangeMarker(marker), &isProtoChangeMarker, slowPath);
1432     Bind(&isProtoChangeMarker);
1433     BRANCH(GetAccessorHasChanged(marker), slowPath, &accessorNotChanged);
1434     Bind(&accessorNotChanged);
1435 
1436     Label arg0HeapObject(env);
1437     Label callable(env);
1438     GateRef callbackFnHandle = GetCallArg0(numArgs);
1439     BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
1440     Bind(&arg0HeapObject);
1441     {
1442         BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
1443         Bind(&callable);
1444         {
1445             GateRef argHandle = GetCallArg1(numArgs);
1446             GateRef thisLen = GetArrayLength(thisValue);
1447             BuiltinsArrayStubBuilder arrayStubBuilder(this);
1448             GateRef kept = arrayStubBuilder.NewArray(glue, ZExtInt32ToInt64(thisLen));
1449             DEFVARIABLE(i, VariableType::INT32(), Int32(0));
1450             DEFVARIABLE(newArrayLen, VariableType::INT32(), Int32(0));
1451             Label loopHead(env);
1452             Label loopEnd(env);
1453             Label next(env);
1454             Label loopExit(env);
1455             Jump(&loopHead);
1456             LoopBegin(&loopHead);
1457             {
1458                 Label hasException0(env);
1459                 Label notHasException0(env);
1460                 Label hasException1(env);
1461                 Label notHasException1(env);
1462                 Label retValueIsTrue(env);
1463                 BRANCH(Int32LessThan(*i, thisLen), &next, &loopExit);
1464                 Bind(&next);
1465                 {
1466                     GateRef kValue = FastGetPropertyByIndex(glue, thisValue, *i, arrayType);
1467                     BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
1468                     Bind(&hasException0);
1469                     {
1470                         result->WriteVariable(Exception());
1471                         Jump(exit);
1472                     }
1473                     Bind(&notHasException0);
1474                     {
1475                         GateRef key = IntToTaggedInt(*i);
1476                         JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
1477                         callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue };
1478                         CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0,
1479                             nullptr, Circuit::NullGate(), callArgs);
1480                         GateRef retValue = callBuilder.JSCallDispatch();
1481                         BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
1482                         Bind(&hasException1);
1483                         {
1484                             result->WriteVariable(Exception());
1485                             Jump(exit);
1486                         }
1487                         Bind(&notHasException1);
1488                         {
1489                             BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &retValueIsTrue, &loopEnd);
1490                             Bind(&retValueIsTrue);
1491                             {
1492                                 arrayStubBuilder.SetValueWithElementsKind(glue, kept, kValue, *newArrayLen,
1493                                     Boolean(true), Int32(static_cast<uint32_t>(ElementsKind::NONE)));
1494                                 newArrayLen = Int32Add(*newArrayLen, Int32(1));
1495                                 Jump(&loopEnd);
1496                             }
1497                         }
1498                     }
1499                 }
1500             }
1501             Bind(&loopEnd);
1502             i = Int32Add(*i, Int32(1));
1503             LoopEnd(&loopHead);
1504             Bind(&loopExit);
1505             Label hasException2(env);
1506             Label notHasException2(env);
1507             NewObjectStubBuilder newBuilder(this);
1508             newBuilder.SetParameters(glue, 0);
1509             GateRef newArray = newBuilder.NewTypedArray(glue, thisValue, arrayType, TruncInt64ToInt32(*newArrayLen));
1510             BRANCH(HasPendingException(glue), &hasException2, &notHasException2);
1511             Bind(&hasException2);
1512             {
1513                 result->WriteVariable(Exception());
1514                 Jump(exit);
1515             }
1516             Bind(&notHasException2);
1517             i = Int32(0);
1518             Label loopHead2(env);
1519             Label loopEnd2(env);
1520             Label next2(env);
1521             Label loopExit2(env);
1522             Jump(&loopHead2);
1523             LoopBegin(&loopHead2);
1524             {
1525                 BRANCH(Int32LessThan(*i, *newArrayLen), &next2, &loopExit2);
1526                 Bind(&next2);
1527                 {
1528                     GateRef kValue = arrayStubBuilder.GetTaggedValueWithElementsKind(kept, *i);
1529                     StoreTypedArrayElement(glue, newArray, ZExtInt32ToInt64(*i), kValue, arrayType);
1530                     Jump(&loopEnd2);
1531                 }
1532             }
1533             Bind(&loopEnd2);
1534             i = Int32Add(*i, Int32(1));
1535             LoopEnd(&loopHead2);
1536             Bind(&loopExit2);
1537 
1538             result->WriteVariable(newArray);
1539             Jump(exit);
1540         }
1541     }
1542 }
1543 
Slice(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1544 void BuiltinsTypedArrayStubBuilder::Slice(GateRef glue, GateRef thisValue, GateRef numArgs,
1545     Variable *result, Label *exit, Label *slowPath)
1546 {
1547     auto env = GetEnvironment();
1548     Label thisExists(env);
1549     Label isEcmaObject(env);
1550     Label isFastTypedArray(env);
1551     Label defaultConstr(env);
1552     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
1553     Bind(&thisExists);
1554     BRANCH(IsEcmaObject(thisValue), &isEcmaObject, slowPath);
1555     Bind(&isEcmaObject);
1556     GateRef arrayType = GetObjectType(LoadHClass(thisValue));
1557     BRANCH(IsFastTypeArray(arrayType), &isFastTypedArray, slowPath);
1558     Bind(&isFastTypedArray);
1559     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
1560     Bind(&defaultConstr);
1561 
1562     DEFVARIABLE(startPos, VariableType::INT64(), Int64(0));
1563     DEFVARIABLE(endPos, VariableType::INT64(), Int64(0));
1564     DEFVARIABLE(newArrayLen, VariableType::INT64(), Int64(0));
1565     Label startTagExists(env);
1566     Label startTagIsInt(env);
1567     Label afterCallArg(env);
1568     Label endTagExists(env);
1569     Label endTagIsInt(env);
1570     Label adjustArrLen(env);
1571     Label newTypedArray(env);
1572     Label writeVariable(env);
1573     Label copyBuffer(env);
1574     Label hasException0(env);
1575     Label notHasException0(env);
1576     GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1577     BRANCH(Int64GreaterThanOrEqual(IntPtr(0), numArgs), slowPath, &startTagExists);
1578     Bind(&startTagExists);
1579     {
1580         GateRef startTag = GetCallArg0(numArgs);
1581         BRANCH(TaggedIsInt(startTag), &startTagIsInt, slowPath);
1582         Bind(&startTagIsInt);
1583         {
1584             startPos = SExtInt32ToInt64(TaggedGetInt(startTag));
1585             endPos = thisLen;
1586             BRANCH(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &afterCallArg, &endTagExists);
1587             Bind(&endTagExists);
1588             {
1589                 GateRef endTag = GetCallArg1(numArgs);
1590                 BRANCH(TaggedIsInt(endTag), &endTagIsInt, slowPath);
1591                 Bind(&endTagIsInt);
1592                 {
1593                     endPos = SExtInt32ToInt64(TaggedGetInt(endTag));
1594                     Jump(&afterCallArg);
1595                 }
1596             }
1597             Bind(&afterCallArg);
1598             {
1599                 startPos = CalculatePositionWithLength(*startPos, thisLen);
1600                 endPos = CalculatePositionWithLength(*endPos, thisLen);
1601                 BRANCH(Int64GreaterThan(*endPos, *startPos), &adjustArrLen, &newTypedArray);
1602                 Bind(&adjustArrLen);
1603                 {
1604                     newArrayLen = Int64Sub(*endPos, *startPos);
1605                     Jump(&newTypedArray);
1606                 }
1607             }
1608         }
1609     }
1610     Bind(&newTypedArray);
1611     {
1612         NewObjectStubBuilder newBuilder(this);
1613         newBuilder.SetParameters(glue, 0);
1614         GateRef newArray = newBuilder.NewTypedArray(glue, thisValue, arrayType, TruncInt64ToInt32(*newArrayLen));
1615         BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
1616         Bind(&hasException0);
1617         {
1618             result->WriteVariable(Exception());
1619             Jump(exit);
1620         }
1621         Bind(&notHasException0);
1622         BRANCH(Int32Equal(TruncInt64ToInt32(*newArrayLen), Int32(0)), &writeVariable, &copyBuffer);
1623         Bind(&copyBuffer);
1624         {
1625             CallNGCRuntime(glue, RTSTUB_ID(CopyTypedArrayBuffer),
1626                            { glue, thisValue, newArray, TruncInt64ToInt32(*startPos), Int32(0),
1627                              TruncInt64ToInt32(*newArrayLen) });
1628             Jump(&writeVariable);
1629         }
1630         Bind(&writeVariable);
1631         {
1632             result->WriteVariable(newArray);
1633             Jump(exit);
1634         }
1635     }
1636 }
1637 
SubArray(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1638 void BuiltinsTypedArrayStubBuilder::SubArray(GateRef glue, GateRef thisValue, GateRef numArgs,
1639     Variable *result, Label *exit, Label *slowPath)
1640 {
1641     auto env = GetEnvironment();
1642     Label ecmaObj(env);
1643     Label typedArray(env);
1644     Label isNotZero(env);
1645     DEFVARIABLE(beginIndex, VariableType::INT32(), Int32(0));
1646     DEFVARIABLE(endIndex, VariableType::INT32(), Int32(0));
1647     DEFVARIABLE(newLength, VariableType::INT32(), Int32(0));
1648 
1649     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
1650     Bind(&ecmaObj);
1651     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
1652     Bind(&typedArray);
1653 
1654     GateRef objHclass = LoadHClass(thisValue);
1655     Label defaultConstructor(env);
1656     BRANCH(HasConstructorByHClass(objHclass), slowPath, &defaultConstructor);
1657     Bind(&defaultConstructor);
1658     GateRef arrayLen = GetArrayLength(thisValue);
1659     GateRef buffer = GetViewedArrayBuffer(thisValue);
1660     Label offHeap(env);
1661     BRANCH(LogicOrBuilder(env).Or(IsJSObjectType(buffer, JSType::JS_ARRAY_BUFFER))
1662         .Or(IsJSObjectType(buffer, JSType::JS_SHARED_ARRAY_BUFFER)).Done(),
1663         &offHeap, slowPath);
1664     Bind(&offHeap);
1665     Label notDetached(env);
1666     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
1667     Bind(&notDetached);
1668 
1669     Label intIndex(env);
1670     GateRef relativeBegin = GetCallArg0(numArgs);
1671     GateRef end = GetCallArg1(numArgs);
1672     BRANCH(TaggedIsInt(relativeBegin), &intIndex, slowPath);
1673     Bind(&intIndex);
1674     GateRef relativeBeginInt = GetInt32OfTInt(relativeBegin);
1675     beginIndex = CalArrayRelativePos(relativeBeginInt, arrayLen);
1676 
1677     Label undefEnd(env);
1678     Label defEnd(env);
1679     Label calNewLength(env);
1680     Label newArray(env);
1681     BRANCH(TaggedIsUndefined(end), &undefEnd, &defEnd);
1682     Bind(&undefEnd);
1683     {
1684         endIndex = arrayLen;
1685         Jump(&calNewLength);
1686     }
1687     Bind(&defEnd);
1688     {
1689         Label intEnd(env);
1690         BRANCH(TaggedIsInt(end), &intEnd, slowPath);
1691         Bind(&intEnd);
1692         {
1693             GateRef endVal = GetInt32OfTInt(end);
1694             endIndex = CalArrayRelativePos(endVal, arrayLen);
1695             Jump(&calNewLength);
1696         }
1697     }
1698     Bind(&calNewLength);
1699     {
1700         GateRef diffLen = Int32Sub(*endIndex, *beginIndex);
1701         Label diffLargeZero(env);
1702         BRANCH(Int32GreaterThan(diffLen, Int32(0)), &diffLargeZero, &newArray);
1703         Bind(&diffLargeZero);
1704         {
1705             newLength = diffLen;
1706             Jump(&newArray);
1707         }
1708     }
1709     Bind(&newArray);
1710     GateRef oldByteLength = Load(VariableType::INT32(), thisValue, IntPtr(JSTypedArray::BYTE_LENGTH_OFFSET));
1711     BRANCH(Int32Equal(arrayLen, Int32(0)), slowPath, &isNotZero);
1712     Bind(&isNotZero);
1713     GateRef elementSize = Int32Div(oldByteLength, arrayLen);
1714     NewObjectStubBuilder newBuilder(this);
1715     *result = newBuilder.NewTaggedSubArray(glue, thisValue, elementSize, *newLength, *beginIndex, objHclass, buffer);
1716     Jump(exit);
1717 }
1718 
With(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1719 void BuiltinsTypedArrayStubBuilder::With(GateRef glue, GateRef thisValue, GateRef numArgs,
1720     Variable *result, Label *exit, Label *slowPath)
1721 {
1722     auto env = GetEnvironment();
1723     DEFVARIABLE(relativeIndex, VariableType::INT64(), Int64(0));
1724     DEFVARIABLE(actualIndex, VariableType::INT64(), Int64(0));
1725     Label isHeapObject(env);
1726     Label typedArray(env);
1727     Label notCOWArray(env);
1728     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
1729     Bind(&isHeapObject);
1730     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
1731     Bind(&typedArray);
1732     BRANCH(IsJsCOWArray(thisValue), slowPath, &notCOWArray);
1733     Bind(&notCOWArray);
1734     GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
1735     GateRef index = GetCallArg0(numArgs);
1736     Label taggedIsInt(env);
1737     BRANCH(TaggedIsInt(index), &taggedIsInt, slowPath);
1738     Bind(&taggedIsInt);
1739     relativeIndex = GetInt64OfTInt(index);
1740     DEFVARIABLE(value, VariableType::JS_ANY(), Undefined());
1741     Label indexGreaterOrEqualZero(env);
1742     Label indexLessZero(env);
1743     Label next(env);
1744     Label notOutOfRange(env);
1745     value = GetCallArg1(numArgs);
1746     GateRef hclass = LoadHClass(thisValue);
1747     GateRef jsType = GetObjectType(hclass);
1748     NewObjectStubBuilder newBuilder(this);
1749     newBuilder.SetParameters(glue, 0);
1750     GateRef newArray = newBuilder.NewTypedArray(glue, thisValue, jsType, TruncInt64ToInt32(thisLen));
1751     Label hasException0(env);
1752     Label notHasException0(env);
1753     BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
1754     Bind(&hasException0);
1755     {
1756         result->WriteVariable(Exception());
1757         Jump(exit);
1758     }
1759     Bind(&notHasException0);
1760     CallNGCRuntime(glue, RTSTUB_ID(CopyTypedArrayBuffer),
1761                    { glue, thisValue, newArray, Int32(0), Int32(0), TruncInt64ToInt32(thisLen) });
1762     BRANCH(Int64GreaterThanOrEqual(*relativeIndex, Int64(0)), &indexGreaterOrEqualZero, &indexLessZero);
1763     Bind(&indexGreaterOrEqualZero);
1764     {
1765         actualIndex = *relativeIndex;
1766         Jump(&next);
1767     }
1768     Bind(&indexLessZero);
1769     {
1770         actualIndex = Int64Add(thisLen, *relativeIndex);
1771         Jump(&next);
1772     }
1773     Bind(&next);
1774     {
1775         BRANCH(BitOr(Int64GreaterThanOrEqual(*actualIndex, thisLen), Int64LessThan(*actualIndex, Int64(0))),
1776             slowPath, &notOutOfRange);
1777         Bind(&notOutOfRange);
1778         {
1779             DEFVARIABLE(k, VariableType::INT64(), Int64(0));
1780             Label loopHead(env);
1781             Label loopEnd(env);
1782             Label loopExit(env);
1783             Label loopNext(env);
1784             Label replaceIndex(env);
1785             Jump(&loopHead);
1786             LoopBegin(&loopHead);
1787             {
1788                 BRANCH(Int64LessThan(*k, thisLen), &loopNext, &loopExit);
1789                 Bind(&loopNext);
1790                 BRANCH(Int64Equal(*k, *actualIndex), &replaceIndex, &loopEnd);
1791                 Bind(&replaceIndex);
1792                 {
1793                     StoreTypedArrayElement(glue, newArray, *k, *value, jsType);
1794                     Jump(&loopEnd);
1795                 }
1796             }
1797             Bind(&loopEnd);
1798             k = Int64Add(*k, Int64(1));
1799             LoopEnd(&loopHead);
1800             Bind(&loopExit);
1801             result->WriteVariable(newArray);
1802             Jump(exit);
1803         }
1804     }
1805 }
1806 
GetByteLength(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)1807 void BuiltinsTypedArrayStubBuilder::GetByteLength([[maybe_unused]] GateRef glue, GateRef thisValue,
1808     [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
1809 {
1810     auto env = GetEnvironment();
1811     Label ecmaObj(env);
1812     Label typedArray(env);
1813     Label Detached(env);
1814     Label notDetached(env);
1815     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
1816     Bind(&ecmaObj);
1817     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
1818     Bind(&typedArray);
1819     GateRef buffer = GetViewedArrayBuffer(thisValue);
1820     BRANCH(IsDetachedBuffer(buffer), &Detached, &notDetached);
1821     Bind(&Detached);
1822     {
1823         *result = IntToTaggedPtr(Int32(0));
1824         Jump(exit);
1825     }
1826     Bind(&notDetached);
1827     {
1828         *result = IntToTaggedPtr(GetArrayLength(thisValue));
1829     }
1830     Jump(exit);
1831 }
1832 
DoSort(GateRef glue,GateRef receiver,Variable * result,Label * exit,Label * slowPath)1833 void BuiltinsTypedArrayStubBuilder::DoSort(
1834     GateRef glue, GateRef receiver, Variable* result, Label* exit, Label* slowPath)
1835 {
1836     auto env = GetEnvironment();
1837     Label entry(env);
1838     Label lenGreaterZero(env);
1839     env->SubCfgEntry(&entry);
1840     GateRef len = ZExtInt32ToInt64(GetArrayLength(receiver));
1841     DEFVARIABLE(i, VariableType::INT64(), Int64(1));
1842     DEFVARIABLE(presentValue, VariableType::JS_ANY(), Undefined());
1843     DEFVARIABLE(middleValue, VariableType::JS_ANY(), Undefined());
1844     DEFVARIABLE(previousValue, VariableType::JS_ANY(), Undefined());
1845     Label loopHead(env);
1846     Label loopEnd(env);
1847     Label loopNext(env);
1848     Label loopExit(env);
1849     Label isNumber(env);
1850     Label hasException0(env);
1851     Label notHasException0(env);
1852 
1853     GateRef jsType = GetObjectType(LoadHClass(receiver));
1854     presentValue = FastGetPropertyByIndex(glue, receiver, Int32(0), jsType);
1855     BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
1856     Bind(&hasException0);
1857     {
1858         result->WriteVariable(Exception());
1859         Jump(exit);
1860     }
1861     Bind(&notHasException0);
1862     {
1863         BRANCH(TaggedIsNumber(*presentValue), &isNumber, slowPath);
1864         Bind(&isNumber);
1865         BRANCH(Int64GreaterThan(len, Int64(0)), &lenGreaterZero, slowPath);
1866         Bind(&lenGreaterZero);
1867 
1868         GateRef isIntOrNot = TaggedIsInt(*presentValue);
1869         GateRef isUint32 = Int32Equal(jsType, Int32(static_cast<int32_t>(JSType::JS_UINT32_ARRAY)));
1870 
1871         Jump(&loopHead);
1872         LoopBegin(&loopHead);
1873         {
1874             BRANCH(Int64LessThan(*i, len), &loopNext, &loopExit);
1875             Bind(&loopNext);
1876 
1877             Label hasException1(env);
1878             Label notHasException1(env);
1879             DEFVARIABLE(beginIndex, VariableType::INT64(), Int64(0));
1880             DEFVARIABLE(endIndex, VariableType::INT64(), *i);
1881             presentValue = FastGetPropertyByIndex(glue, receiver, TruncInt64ToInt32(*i), jsType);
1882             BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
1883             Bind(&hasException1);
1884             {
1885                 result->WriteVariable(Exception());
1886                 Jump(exit);
1887             }
1888             Bind(&notHasException1);
1889             {
1890                 Label loopHead1(env);
1891                 Label loopEnd1(env);
1892                 Label loopNext1(env);
1893                 Label loopExit1(env);
1894 
1895                 Jump(&loopHead1);
1896                 LoopBegin(&loopHead1);
1897                 {
1898                     BRANCH(Int64LessThan(*beginIndex, *endIndex), &loopNext1, &loopExit1);
1899                     Bind(&loopNext1);
1900                     Label hasException2(env);
1901                     Label notHasException2(env);
1902                     GateRef sum = Int64Add(*beginIndex, *endIndex);
1903                     GateRef middleIndex = Int64Div(sum, Int64(2));
1904                     middleValue = FastGetPropertyByIndex(glue, receiver, TruncInt64ToInt32(middleIndex), jsType);
1905                     BRANCH(HasPendingException(glue), &hasException2, &notHasException2);
1906                     Bind(&hasException2);
1907                     {
1908                         result->WriteVariable(Exception());
1909                         Jump(exit);
1910                     }
1911                     Bind(&notHasException2);
1912                     {
1913                         Label goSort(env);
1914                         Label isFloat(env);
1915                         Label isInt(env);
1916                         Label uint32Compare(env);
1917                         Label notUint32(env);
1918                         DEFVARIABLE(compareResult, VariableType::INT32(), Int32(0));
1919                         BRANCH(isUint32, &uint32Compare, &notUint32);
1920                         Bind(&notUint32);
1921                         BRANCH(isIntOrNot, &isInt, &isFloat);
1922 
1923                         Bind(&uint32Compare);
1924                         {
1925                             DEFVARIABLE(middleValueInt64, VariableType::INT64(), Int64(0));
1926                             DEFVARIABLE(presentValueInt64, VariableType::INT64(), Int64(0));
1927                             middleValueInt64 = GetInt64OfTInt(*middleValue);
1928                             presentValueInt64 = GetInt64OfTInt(*presentValue);
1929 
1930                             Label intGreater(env);
1931                             Label intEqualOrNot(env);
1932                             Label intEqual(env);
1933                             Label intLess(env);
1934 
1935                             BRANCH(
1936                                 Int64GreaterThan(*middleValueInt64, *presentValueInt64), &intGreater, &intEqualOrNot);
1937                             Bind(&intGreater);
1938                             {
1939                                 compareResult = Int32(1);
1940                                 Jump(&goSort);
1941                             }
1942                             Bind(&intEqualOrNot);
1943                             {
1944                                 BRANCH(Int64Equal(*middleValueInt64, *presentValueInt64), &intEqual, &intLess);
1945                                 Bind(&intEqual);
1946                                 {
1947                                     compareResult = Int32(0);
1948                                     Jump(&goSort);
1949                                 }
1950                                 Bind(&intLess);
1951                                 {
1952                                     compareResult = Int32(-1);
1953                                     Jump(&goSort);
1954                                 }
1955                             }
1956                         }
1957 
1958                         Bind(&isInt);
1959                         {
1960                             DEFVARIABLE(middleValueInt32, VariableType::INT32(), Int32(0));
1961                             DEFVARIABLE(presentValueInt32, VariableType::INT32(), Int32(0));
1962                             middleValueInt32 = GetInt32OfTInt(*middleValue);
1963                             presentValueInt32 = GetInt32OfTInt(*presentValue);
1964 
1965                             Label intGreater(env);
1966                             Label intEqualOrNot(env);
1967                             Label intEqual(env);
1968                             Label intLess(env);
1969 
1970                             BRANCH(
1971                                 Int32GreaterThan(*middleValueInt32, *presentValueInt32), &intGreater, &intEqualOrNot);
1972                             Bind(&intGreater);
1973                             {
1974                                 compareResult = Int32(1);
1975                                 Jump(&goSort);
1976                             }
1977 
1978                             Bind(&intEqualOrNot);
1979                             {
1980                                 BRANCH(Int32Equal(*middleValueInt32, *presentValueInt32), &intEqual, &intLess);
1981                                 Bind(&intEqual);
1982                                 {
1983                                     compareResult = Int32(0);
1984                                     Jump(&goSort);
1985                                 }
1986                                 Bind(&intLess);
1987                                 {
1988                                     compareResult = Int32(-1);
1989                                     Jump(&goSort);
1990                                 }
1991                             }
1992                         }
1993                         Bind(&isFloat);
1994                         {
1995                             Label floatLess(env);
1996                             Label floatEqual(env);
1997                             Label floatGreater(env);
1998                             Label floatEqualOrNot(env);
1999                             Label float32EqualOrNot(env);
2000                             Label midIsNotNAN(env);
2001                             Label presentIsNotNAN(env);
2002 
2003                             DEFVARIABLE(middleValueFloat64, VariableType::FLOAT64(), Double(0));
2004                             DEFVARIABLE(presentValueFloat64, VariableType::FLOAT64(), Double(0));
2005 
2006                             middleValueFloat64 = GetDoubleOfTDouble(*middleValue);
2007                             presentValueFloat64 = GetDoubleOfTDouble(*presentValue);
2008 
2009                             BRANCH(DoubleIsNAN(*presentValueFloat64), &floatLess, &presentIsNotNAN);
2010                             Bind(&presentIsNotNAN);
2011                             BRANCH(DoubleIsNAN(*middleValueFloat64), &floatGreater, &midIsNotNAN);
2012                             Bind(&midIsNotNAN);
2013 
2014                             BRANCH(DoubleLessThan(*middleValueFloat64, *presentValueFloat64), &floatLess,
2015                                 &floatEqualOrNot);
2016                             Bind(&floatLess);
2017                             {
2018                                 compareResult = Int32(-1);
2019                                 Jump(&goSort);
2020                             }
2021 
2022                             Bind(&floatEqualOrNot);
2023                             {
2024                                 BRANCH(
2025                                     DoubleEqual(*middleValueFloat64, *presentValueFloat64), &floatEqual, &floatGreater);
2026                                 Bind(&floatEqual);
2027                                 {
2028                                     Label mIsPositive0(env);
2029                                     Label mIsNotPositive0(env);
2030                                     GateRef valueEqual = Equal(*middleValue, DoubleToTaggedDoublePtr(Double(0.0)));
2031                                     BRANCH(valueEqual, &mIsPositive0, &mIsNotPositive0);
2032                                     Bind(&mIsPositive0);
2033                                     {
2034                                         valueEqual = Equal(*presentValue, DoubleToTaggedDoublePtr(Double(-0.0)));
2035                                         BRANCH(valueEqual, &floatGreater, &mIsNotPositive0);
2036                                     }
2037                                     Bind(&mIsNotPositive0);
2038                                     {
2039                                         compareResult = Int32(0);
2040                                         Jump(&goSort);
2041                                     }
2042                                 }
2043 
2044                                 Bind(&floatGreater);
2045                                 {
2046                                     compareResult = Int32(1);
2047                                     Jump(&goSort);
2048                                 }
2049                             }
2050                         }
2051                         Bind(&goSort);
2052                         {
2053                             Label less0(env);
2054                             Label greater0(env);
2055                             BRANCH(Int32LessThanOrEqual(*compareResult, Int32(0)), &less0, &greater0);
2056                             Bind(&greater0);
2057                             {
2058                                 endIndex = middleIndex;
2059                                 Jump(&loopEnd1);
2060                             }
2061                             Bind(&less0);
2062                             {
2063                                 beginIndex = middleIndex;
2064                                 beginIndex = Int64Add(*beginIndex, Int64(1));
2065                                 Jump(&loopEnd1);
2066                             }
2067                         }
2068                     }
2069                 }
2070                 Bind(&loopEnd1);
2071                 LoopEnd(&loopHead1);
2072                 Bind(&loopExit1);
2073 
2074                 Label shouldCopy(env);
2075                 GateRef isGreater0 = Int64GreaterThanOrEqual(*endIndex, Int64(0));
2076                 GateRef isLessI = Int64LessThan(*endIndex, *i);
2077                 BRANCH(BitAnd(isGreater0, isLessI), &shouldCopy, &loopEnd);
2078                 Bind(&shouldCopy);
2079                 {
2080                     DEFVARIABLE(j, VariableType::INT64(), *i);
2081                     Label loopHead2(env);
2082                     Label loopEnd2(env);
2083                     Label loopNext2(env);
2084                     Label loopExit2(env);
2085                     Jump(&loopHead2);
2086                     LoopBegin(&loopHead2);
2087                     {
2088                         BRANCH(Int64GreaterThan(*j, *endIndex), &loopNext2, &loopExit2);
2089                         Bind(&loopNext2);
2090                         Label hasException3(env);
2091                         Label notHasException3(env);
2092                         previousValue = FastGetPropertyByIndex(glue, receiver,
2093                             TruncInt64ToInt32(Int64Sub(*j, Int64(1))), jsType);
2094                         BRANCH(HasPendingException(glue), &hasException3, &notHasException3);
2095                         Bind(&hasException3);
2096                         {
2097                             result->WriteVariable(Exception());
2098                             Jump(exit);
2099                         }
2100                         Bind(&notHasException3);
2101                         {
2102                             FastSetPropertyByIndex(glue, *previousValue, receiver, TruncInt64ToInt32(*j), jsType);
2103                             Jump(&loopEnd2);
2104                         }
2105                     }
2106                     Bind(&loopEnd2);
2107                     j = Int64Sub(*j, Int64(1));
2108                     LoopEnd(&loopHead2);
2109                     Bind(&loopExit2);
2110                     FastSetPropertyByIndex(glue, *presentValue, receiver, TruncInt64ToInt32(*j), jsType);
2111                     Jump(&loopEnd);
2112                 }
2113             }
2114         }
2115         Bind(&loopEnd);
2116         i = Int64Add(*i, Int64(1));
2117         LoopEnd(&loopHead);
2118         Bind(&loopExit);
2119         env->SubCfgExit();
2120     }
2121 }
2122 
Sort(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2123 void BuiltinsTypedArrayStubBuilder::Sort(
2124     GateRef glue, GateRef thisValue, GateRef numArgs, Variable* result, Label* exit, Label* slowPath)
2125 {
2126     auto env = GetEnvironment();
2127     Label isHeapObject(env);
2128     Label typedArray(env);
2129     Label defaultConstr(env);
2130     Label argUndefined(env);
2131     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2132     Bind(&isHeapObject);
2133     BRANCH(IsFastTypeArray(GetObjectType(LoadHClass(thisValue))), &typedArray, slowPath);
2134     Bind(&typedArray);
2135     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2136     Bind(&defaultConstr);
2137     GateRef callbackFnHandle = GetCallArg0(numArgs);
2138     BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath);
2139     Bind(&argUndefined);
2140     DoSort(glue, thisValue, result, exit, slowPath);
2141     result->WriteVariable(thisValue);
2142     Jump(exit);
2143 }
2144 
GetByteOffset(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2145 void BuiltinsTypedArrayStubBuilder::GetByteOffset([[maybe_unused]] GateRef glue, GateRef thisValue,
2146     [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
2147 {
2148     auto env = GetEnvironment();
2149     Label ecmaObj(env);
2150     Label typedArray(env);
2151     Label Detached(env);
2152     Label notDetached(env);
2153     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
2154     Bind(&ecmaObj);
2155     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
2156     Bind(&typedArray);
2157     GateRef buffer = GetViewedArrayBuffer(thisValue);
2158     BRANCH(IsDetachedBuffer(buffer), &Detached, &notDetached);
2159     Bind(&Detached);
2160     {
2161         *result = IntToTaggedPtr(Int32(0));
2162         Jump(exit);
2163     }
2164     Bind(&notDetached);
2165     {
2166         *result = IntToTaggedPtr(GetByteOffset(thisValue));
2167     }
2168     Jump(exit);
2169 }
2170 
Set(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2171 void BuiltinsTypedArrayStubBuilder::Set(GateRef glue, GateRef thisValue, GateRef numArgs,
2172     Variable *result, Label *exit, Label *slowPath)
2173 {
2174     auto env = GetEnvironment();
2175     Label thisExists(env);
2176     Label ecmaObj(env);
2177     Label typedArrayIsFast(env);
2178 
2179     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
2180     Bind(&thisExists);
2181     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
2182     Bind(&ecmaObj);
2183     BRANCH(IsFastTypeArray(GetObjectType(LoadHClass(thisValue))), &typedArrayIsFast, slowPath);
2184     Bind(&typedArrayIsFast);
2185     GateRef len = ZExtInt32ToInt64(GetArrayLength(thisValue));
2186     GateRef arrayType = GetObjectType(LoadHClass(thisValue));
2187     Label notEmptyArray(env);
2188     BRANCH(Int64Equal(len, Int64(0)), slowPath, &notEmptyArray);
2189     Bind(&notEmptyArray);
2190     DEFVARIABLE(realOffset, VariableType::INT64(), Int64(0));
2191     DEFVARIABLE(startIndex, VariableType::INT64(), Int64(0));
2192     Label hasOffset(env);
2193     Label hasNoOffset(env);
2194     Label numArgsIsInt(env);
2195     GateRef fromOffset = GetCallArg1(numArgs);
2196     BRANCH(TaggedIsUndefinedOrNull(fromOffset), &hasNoOffset, &hasOffset);
2197     Bind(&hasOffset);
2198     {
2199         Label taggedIsInt(env);
2200         BRANCH(TaggedIsInt(fromOffset), &taggedIsInt, slowPath);
2201         Bind(&taggedIsInt);
2202         GateRef fromIndexToTagged = SExtInt32ToInt64(TaggedGetInt(fromOffset));
2203         Label offsetNotLessZero(env);
2204         BRANCH(Int64LessThan(fromIndexToTagged, Int64(0)), slowPath, &offsetNotLessZero);
2205         Bind(&offsetNotLessZero);
2206         {
2207             realOffset = fromIndexToTagged;
2208             Jump(&hasNoOffset);
2209         }
2210     }
2211     Bind(&hasNoOffset);
2212 
2213     Label srcArrayIsEcmaObj(env);
2214     Label srcArrayIsTypedArray(env);
2215     Label srcArrayIsJsArray(env);
2216     GateRef srcArray = GetCallArg0(numArgs);
2217     BRANCH(IsEcmaObject(srcArray), &srcArrayIsEcmaObj, slowPath);
2218     Bind(&srcArrayIsEcmaObj);
2219     BRANCH(IsTypedArray(srcArray), &srcArrayIsTypedArray, slowPath);
2220     Bind(&srcArrayIsTypedArray);
2221     {
2222         GateRef srcType = GetObjectType(LoadHClass(srcArray));
2223         Label isFastTypeArray(env);
2224         BRANCH(IsFastTypeArray(srcType), &isFastTypeArray, slowPath);
2225         Bind(&isFastTypeArray);
2226         Label isNotSameValue(env);
2227         GateRef targetBuffer = GetViewedArrayBuffer(thisValue);
2228         GateRef srcBuffer = GetViewedArrayBuffer(srcArray);
2229         BRANCH(SameValue(glue, targetBuffer, srcBuffer), slowPath, &isNotSameValue);
2230         Bind(&isNotSameValue);
2231         Label isNotGreaterThanLen(env);
2232         GateRef srcLen = ZExtInt32ToInt64(GetArrayLength(srcArray));
2233         BRANCH(Int64GreaterThan(Int64Add(*realOffset, srcLen), len), slowPath, &isNotGreaterThanLen);
2234         Bind(&isNotGreaterThanLen);
2235         {
2236             Label isSameType(env);
2237             Label isNotSameType(env);
2238             BRANCH(Equal(srcType, arrayType), &isSameType, &isNotSameType);
2239             Bind(&isSameType);
2240             {
2241                 NewObjectStubBuilder newBuilder(this);
2242                 CallNGCRuntime(glue, RTSTUB_ID(CopyTypedArrayBuffer),
2243                                { glue, srcArray, thisValue, Int32(0), TruncInt64ToInt32(*realOffset),
2244                                  TruncInt64ToInt32(srcLen) });
2245                 Jump(exit);
2246             }
2247             Bind(&isNotSameType);
2248             {
2249                 Label loopHead(env);
2250                 Label loopEnd(env);
2251                 Label loopExit(env);
2252                 Label loopNext(env);
2253                 Jump(&loopHead);
2254                 LoopBegin(&loopHead);
2255                 {
2256                     BRANCH(Int64LessThan(*startIndex, srcLen), &loopNext, &loopExit);
2257                     Bind(&loopNext);
2258                     {
2259                         GateRef srcValue = FastGetPropertyByIndex(glue, srcArray, TruncInt64ToInt32(*startIndex),
2260                             GetObjectType(LoadHClass(srcArray)));
2261                         StoreTypedArrayElement(glue, thisValue, *realOffset, srcValue,
2262                             GetObjectType(LoadHClass(thisValue)));
2263                         Jump(&loopEnd);
2264                     }
2265                 }
2266                 Bind(&loopEnd);
2267                 startIndex = Int64Add(*startIndex, Int64(1));
2268                 realOffset = Int64Add(*realOffset, Int64(1));
2269                 LoopEnd(&loopHead);
2270                 Bind(&loopExit);
2271                 result->WriteVariable(Undefined());
2272                 Jump(exit);
2273             }
2274         }
2275     }
2276 }
2277 
FindIndex(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2278 void BuiltinsTypedArrayStubBuilder::FindIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
2279     Variable *result, Label *exit, Label *slowPath)
2280 {
2281     auto env = GetEnvironment();
2282     Label ecmaObj(env);
2283     Label typedArray(env);
2284     Label defaultConstr(env);
2285     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
2286     Bind(&ecmaObj);
2287     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
2288     Bind(&typedArray);
2289     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2290     Bind(&defaultConstr);
2291 
2292     Label arg0HeapObject(env);
2293     Label callable(env);
2294     GateRef callbackFnHandle = GetCallArg0(numArgs);
2295     BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
2296     Bind(&arg0HeapObject);
2297     BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
2298     Bind(&callable);
2299     result->WriteVariable(IntToTaggedPtr(Int32(-1)));
2300 
2301     GateRef argHandle = GetCallArg1(numArgs);
2302     DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
2303     DEFVARIABLE(j, VariableType::INT32(), Int32(0));
2304     Label loopHead(env);
2305     Label loopEnd(env);
2306     Label next(env);
2307     Label loopExit(env);
2308     Jump(&loopHead);
2309     LoopBegin(&loopHead);
2310     {
2311         thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2312         BRANCH(Int64LessThan(ZExtInt32ToInt64(*j), *thisArrLen), &next, &loopExit);
2313         Bind(&next);
2314         {
2315             Label hasException0(env);
2316             Label notHasException0(env);
2317             GateRef kValue = FastGetPropertyByIndex(glue, thisValue, *j, GetObjectType(LoadHClass(thisValue)));
2318             BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
2319             Bind(&hasException0);
2320             {
2321                 result->WriteVariable(Exception());
2322                 Jump(exit);
2323             }
2324             Bind(&notHasException0);
2325             {
2326                 GateRef key = IntToTaggedPtr(*j);
2327                 Label hasException(env);
2328                 Label notHasException(env);
2329                 JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2330                 callArgs.callThisArg3WithReturnArgs = { argHandle, kValue, key, thisValue };
2331                 CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
2332                     Circuit::NullGate(), callArgs);
2333                 GateRef retValue = callBuilder.JSCallDispatch();
2334                 BRANCH(TaggedIsException(retValue), &hasException, &notHasException);
2335                 Bind(&hasException);
2336                 {
2337                     result->WriteVariable(retValue);
2338                     Jump(exit);
2339                 }
2340                 Bind(&notHasException);
2341                 {
2342                     Label find(env);
2343                     BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
2344                     Bind(&find);
2345                     {
2346                         result->WriteVariable(key);
2347                         Jump(exit);
2348                     }
2349                 }
2350             }
2351         }
2352     }
2353     Bind(&loopEnd);
2354     thisArrLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2355     j = Int32Add(*j, Int32(1));
2356     LoopEnd(&loopHead);
2357     Bind(&loopExit);
2358     Jump(exit);
2359 }
2360 
Entries(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2361 void BuiltinsTypedArrayStubBuilder::Entries(GateRef glue, GateRef thisValue, GateRef numArgs,
2362     Variable *result, Label *exit, Label *slowPath)
2363 {
2364     BuildArrayIterator(glue, thisValue, numArgs, result, exit, slowPath, IterationKind::KEY_AND_VALUE);
2365 }
2366 
Keys(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2367 void BuiltinsTypedArrayStubBuilder::Keys(GateRef glue, GateRef thisValue, GateRef numArgs,
2368     Variable *result, Label *exit, Label *slowPath)
2369 {
2370     BuildArrayIterator(glue, thisValue, numArgs, result, exit, slowPath, IterationKind::KEY);
2371 }
2372 
Values(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2373 void BuiltinsTypedArrayStubBuilder::Values(GateRef glue, GateRef thisValue, GateRef numArgs,
2374     Variable *result, Label *exit, Label *slowPath)
2375 {
2376     BuildArrayIterator(glue, thisValue, numArgs, result, exit, slowPath, IterationKind::VALUE);
2377 }
2378 
BuildArrayIterator(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath,IterationKind iteratorKind)2379 void BuiltinsTypedArrayStubBuilder::BuildArrayIterator(GateRef glue, GateRef thisValue,
2380     [[maybe_unused]] GateRef numArgs, Variable *result, Label *exit, Label *slowPath, IterationKind iteratorKind)
2381 {
2382     auto env = GetEnvironment();
2383 
2384     Label thisExists(env);
2385     Label isEcmaObject(env);
2386     Label isTypedArray(env);
2387     BRANCH(TaggedIsUndefinedOrNullOrHole(thisValue), slowPath, &thisExists);
2388     Bind(&thisExists);
2389     BRANCH(IsEcmaObject(thisValue), &isEcmaObject, slowPath);
2390     Bind(&isEcmaObject);
2391     BRANCH(IsTypedArray(thisValue), &isTypedArray, slowPath);
2392     Bind(&isTypedArray);
2393 
2394     NewObjectStubBuilder newBuilder(this);
2395     newBuilder.SetGlue(glue);
2396     GateRef kind = Int32(static_cast<int32_t>(iteratorKind));
2397     newBuilder.CreateJSTypedArrayIterator(result, exit, thisValue, kind);
2398 }
2399 
FindLastIndex(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2400 void BuiltinsTypedArrayStubBuilder::FindLastIndex(GateRef glue, GateRef thisValue, GateRef numArgs,
2401     Variable *result, Label *exit, Label *slowPath)
2402 {
2403     auto env = GetEnvironment();
2404     Label thisExists(env);
2405     Label isHeapObject(env);
2406     Label typedArray(env);
2407     Label arg0HeapObject(env);
2408     Label callable(env);
2409 
2410     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
2411     Bind(&thisExists);
2412     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2413     Bind(&isHeapObject);
2414     BRANCH(IsTypedArray(thisValue), &typedArray, slowPath);
2415     Bind(&typedArray);
2416     GateRef callbackFnHandle = GetCallArg0(numArgs);
2417     BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
2418     Bind(&arg0HeapObject);
2419     BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
2420     Bind(&callable);
2421 
2422     DEFVARIABLE(i, VariableType::INT64(), Int64Sub(ZExtInt32ToInt64(GetArrayLength(thisValue)), Int64(1)));
2423     DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
2424     GateRef argHandle = GetCallArg1(numArgs);
2425     GateRef hclass = LoadHClass(thisValue);
2426     GateRef jsType = GetObjectType(hclass);
2427     Label loopHead(env);
2428     Label loopEnd(env);
2429     Label loopNext(env);
2430     Label loopExit(env);
2431     Jump(&loopHead);
2432     LoopBegin(&loopHead);
2433     {
2434         Label hasException(env);
2435         Label notHasException(env);
2436         BRANCH(Int64LessThan(*i, Int64(0)), &loopExit, &loopNext);
2437         Bind(&loopNext);
2438         kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), jsType);
2439         GateRef key = Int64ToTaggedInt(*i);
2440         JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2441         callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
2442         CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
2443             Circuit::NullGate(), callArgs);
2444         GateRef retValue = callBuilder.JSCallDispatch();
2445         BRANCH(HasPendingException(glue), &hasException, &notHasException);
2446         Bind(&hasException);
2447         {
2448             result->WriteVariable(Exception());
2449             Jump(exit);
2450         }
2451         Bind(&notHasException);
2452         {
2453             Label find(env);
2454             BRANCH(TaggedIsTrue(FastToBoolean(retValue)), &find, &loopEnd);
2455             Bind(&find);
2456             result->WriteVariable(IntToTaggedPtr(*i));
2457             Jump(exit);
2458         }
2459     }
2460     Bind(&loopEnd);
2461     i = Int64Sub(*i, Int64(1));
2462     LoopEnd(&loopHead);
2463     Bind(&loopExit);
2464     result->WriteVariable(IntToTaggedPtr(Int32(-1)));
2465     Jump(exit);
2466 }
2467 
ToSorted(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2468 void BuiltinsTypedArrayStubBuilder::ToSorted(GateRef glue, GateRef thisValue,
2469     GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
2470 {
2471     auto env = GetEnvironment();
2472     Label isHeapObject(env);
2473     Label typedArray(env);
2474     Label defaultConstr(env);
2475     Label argUndefined(env);
2476     Label prototypeIsEcmaObj(env);
2477     Label isProtoChangeMarker(env);
2478     Label accessorNotChanged(env);
2479     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2480     Bind(&isHeapObject);
2481     BRANCH(IsFastTypeArray(GetObjectType(LoadHClass(thisValue))), &typedArray, slowPath);
2482     Bind(&typedArray);
2483     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2484     Bind(&defaultConstr);
2485     GateRef callbackFnHandle = GetCallArg0(numArgs);
2486     BRANCH(TaggedIsUndefined(callbackFnHandle), &argUndefined, slowPath);
2487     Bind(&argUndefined);
2488 
2489     DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
2490     DEFVARIABLE(i, VariableType::INT64(), Int64(0));
2491     GateRef jsType = GetObjectType(LoadHClass(thisValue));
2492     GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2493     NewObjectStubBuilder newBuilder(this);
2494     newBuilder.SetParameters(glue, 0);
2495     GateRef newArray = newBuilder.NewTypedArray(glue, thisValue, jsType, TruncInt64ToInt32(thisLen));
2496     CallNGCRuntime(glue, RTSTUB_ID(CopyTypedArrayBuffer),
2497                    { glue, thisValue, newArray, Int32(0), Int32(0), TruncInt64ToInt32(thisLen) });
2498     DoSort(glue, newArray, result, exit, slowPath);
2499     result->WriteVariable(newArray);
2500     Jump(exit);
2501 }
2502 
Of(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2503 void BuiltinsTypedArrayStubBuilder::Of(GateRef glue, GateRef thisValue,
2504     GateRef numArgs, Variable *result, Label *exit, Label *slowPath)
2505 {
2506     auto env = GetEnvironment();
2507     Label thisExists(env);
2508     Label isEcmaObject(env);
2509     Label isConstructor(env);
2510     Label notDerived(env);
2511     Label thisObjIsECmaObject(env);
2512     Label thisObjIsFastTypedArray(env);
2513     Label defaultConstr(env);
2514     Label numArgsInRange(env);
2515     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
2516     Bind(&thisExists);
2517     BRANCH(IsEcmaObject(thisValue), &isEcmaObject, slowPath);
2518     Bind(&isEcmaObject);
2519     BRANCH(IsConstructor(thisValue), &isConstructor, slowPath);
2520     Bind(&isConstructor);
2521     BRANCH(IsDerived(thisValue), slowPath, &notDerived);
2522     Bind(&notDerived);
2523     // 3: maximum of numArgs
2524     BRANCH(Int32LessThanOrEqual(TruncPtrToInt32(numArgs), Int32(3)), &numArgsInRange, slowPath);
2525     Bind(&numArgsInRange);
2526 
2527     DEFVARIABLE(newArrayLen, VariableType::INT32(), TruncPtrToInt32(numArgs));
2528     NewObjectStubBuilder newBuilder(this);
2529     newBuilder.SetParameters(glue, 0);
2530     GateRef thisObj = newBuilder.NewTypedArrayFromCtor(glue, thisValue, *newArrayLen, slowPath);
2531     GateRef arrayType = GetObjectType(LoadHClass(thisObj));
2532 
2533     BRANCH(IsEcmaObject(thisObj), &thisObjIsECmaObject, slowPath);
2534     Bind(&thisObjIsECmaObject);
2535     BRANCH(IsFastTypeArray(arrayType), &thisObjIsFastTypedArray, slowPath);
2536     Bind(&thisObjIsFastTypedArray);
2537     BRANCH(HasConstructor(thisObj), slowPath, &defaultConstr);
2538     Bind(&defaultConstr);
2539 
2540     DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
2541     Label firstArg(env);
2542     Label secondArg(env);
2543     Label thirdArg(env);
2544     Label writeResult(env);
2545     // 1: first element
2546     BRANCH(Int32LessThanOrEqual(Int32(1), *newArrayLen), &firstArg, &writeResult);
2547     Bind(&firstArg);
2548     {
2549         auto checkValueValid = [this, env](GateRef value) -> GateRef {
2550             return LogicOrBuilder(env).Or(TaggedIsUndefined(value)).Or(TaggedIsNumber(value))
2551                 .Or(TaggedIsString(value)).Done();
2552         };
2553         Label setValue0(env);
2554         Label hasException0(env);
2555         Label notHasException0(env);
2556         kValue = GetCallArg0(numArgs);
2557         BRANCH(checkValueValid(*kValue), &setValue0, slowPath);
2558         Bind(&setValue0);
2559         // 0: first element in newArray
2560         FastSetPropertyByIndex(glue, *kValue, thisObj, Int32(0), arrayType);
2561         BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
2562         Bind(&hasException0);
2563         {
2564             result->WriteVariable(Exception());
2565             Jump(exit);
2566         }
2567         Bind(&notHasException0);
2568         // 2: second element
2569         BRANCH(Int32LessThanOrEqual(Int32(2), *newArrayLen), &secondArg, &writeResult);
2570         Bind(&secondArg);
2571         {
2572             Label setValue1(env);
2573             Label hasException1(env);
2574             Label notHasException1(env);
2575             kValue = GetCallArg1(numArgs);
2576             BRANCH(checkValueValid(*kValue), &setValue1, slowPath);
2577             Bind(&setValue1);
2578             // 1: second element in newArray
2579             FastSetPropertyByIndex(glue, *kValue, thisObj, Int32(1), arrayType);
2580             BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
2581             Bind(&hasException1);
2582             {
2583                 result->WriteVariable(Exception());
2584                 Jump(exit);
2585             }
2586             Bind(&notHasException1);
2587             // 3: third element
2588             BRANCH(Int32LessThanOrEqual(Int32(3), *newArrayLen), &thirdArg, &writeResult);
2589             Bind(&thirdArg);
2590             {
2591                 Label setValue2(env);
2592                 Label hasException2(env);
2593                 kValue = GetCallArg2(numArgs);
2594                 BRANCH(checkValueValid(*kValue), &setValue2, slowPath);
2595                 Bind(&setValue2);
2596                 // 2: third element in newArray
2597                 FastSetPropertyByIndex(glue, *kValue, thisObj, Int32(2), arrayType);
2598                 BRANCH(HasPendingException(glue), &hasException2, &writeResult);
2599                 Bind(&hasException2);
2600                 {
2601                     result->WriteVariable(Exception());
2602                     Jump(exit);
2603                 }
2604             }
2605         }
2606     }
2607 
2608     Bind(&writeResult);
2609     {
2610         result->WriteVariable(thisObj);
2611         Jump(exit);
2612     }
2613 }
2614 
Map(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2615 void BuiltinsTypedArrayStubBuilder::Map(GateRef glue, GateRef thisValue, GateRef numArgs,
2616     Variable *result, Label *exit, Label *slowPath)
2617 {
2618     auto env = GetEnvironment();
2619     Label thisExists(env);
2620     Label isHeapObject(env);
2621     Label defaultConstr(env);
2622     Label typedArrayIsFast(env);
2623     Label prototypeIsEcmaObj(env);
2624     Label isProtoChangeMarker(env);
2625     Label accessorNotChanged(env);
2626     Label notDetached(env);
2627     BRANCH(TaggedIsUndefinedOrNull(thisValue), slowPath, &thisExists);
2628     Bind(&thisExists);
2629     BRANCH(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
2630     Bind(&isHeapObject);
2631     BRANCH(IsFastTypeArray(GetObjectType(LoadHClass(thisValue))), &typedArrayIsFast, slowPath);
2632     Bind(&typedArrayIsFast);
2633     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2634     Bind(&defaultConstr);
2635     GateRef buffer = GetViewedArrayBuffer(thisValue);
2636     BRANCH(IsDetachedBuffer(buffer), slowPath, &notDetached);
2637     Bind(&notDetached);
2638     GateRef prototype = GetPrototypeFromHClass(LoadHClass(thisValue));
2639     BRANCH(IsEcmaObject(prototype), &prototypeIsEcmaObj, slowPath);
2640     Bind(&prototypeIsEcmaObj);
2641     GateRef marker = GetProtoChangeMarkerFromHClass(LoadHClass(prototype));
2642     BRANCH(TaggedIsProtoChangeMarker(marker), &isProtoChangeMarker, slowPath);
2643     Bind(&isProtoChangeMarker);
2644     BRANCH(GetAccessorHasChanged(marker), slowPath, &accessorNotChanged);
2645     Bind(&accessorNotChanged);
2646     Label arg0HeapObject(env);
2647     Label callable(env);
2648     Label next(env);
2649     GateRef thisLen = ZExtInt32ToInt64(GetArrayLength(thisValue));
2650     GateRef callbackFnHandle = GetCallArg0(numArgs);
2651     GateRef jsType = GetObjectType(LoadHClass(thisValue));
2652     BRANCH(TaggedIsHeapObject(callbackFnHandle), &arg0HeapObject, slowPath);
2653     Bind(&arg0HeapObject);
2654     BRANCH(IsCallable(callbackFnHandle), &callable, slowPath);
2655     Bind(&callable);
2656     GateRef argHandle = GetCallArg1(numArgs);
2657     Jump(&next);
2658     Bind(&next);
2659     {
2660         DEFVARIABLE(kValue, VariableType::JS_ANY(), Hole());
2661         DEFVARIABLE(i, VariableType::INT64(), Int64(0));
2662         NewObjectStubBuilder newBuilder(this);
2663         newBuilder.SetParameters(glue, 0);
2664         GateRef newArray = newBuilder.NewTypedArray(glue, thisValue, jsType, TruncInt64ToInt32(thisLen));
2665         Label loopHead(env);
2666         Label loopEnd(env);
2667         Label loopNext(env);
2668         Label loopExit(env);
2669         Jump(&loopHead);
2670         LoopBegin(&loopHead);
2671         {
2672             Label hasException1(env);
2673             Label notHasException1(env);
2674             BRANCH(Int64LessThan(*i, thisLen), &loopNext, &loopExit);
2675             Bind(&loopNext);
2676             kValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*i), jsType);
2677             GateRef key = Int64ToTaggedInt(*i);
2678             JSCallArgs callArgs(JSCallMode::CALL_THIS_ARG3_WITH_RETURN);
2679             callArgs.callThisArg3WithReturnArgs = { argHandle, *kValue, key, thisValue };
2680             CallStubBuilder callBuilder(this, glue, callbackFnHandle, Int32(NUM_MANDATORY_JSFUNC_ARGS), 0, nullptr,
2681                 Circuit::NullGate(), callArgs);
2682             GateRef retValue = callBuilder.JSCallDispatch();
2683             BRANCH(HasPendingException(glue), &hasException1, &notHasException1);
2684             Bind(&hasException1);
2685             result->WriteVariable(Exception());
2686             Jump(exit);
2687 
2688             Bind(&notHasException1);
2689             {
2690                 FastSetPropertyByIndex(glue, retValue, newArray, TruncInt64ToInt32(*i), jsType);
2691                 Jump(&loopEnd);
2692             }
2693         }
2694         Bind(&loopEnd);
2695         i = Int64Add(*i, Int64(1));
2696         LoopEnd(&loopHead);
2697         Bind(&loopExit);
2698         result->WriteVariable(newArray);
2699         Jump(exit);
2700     }
2701 }
2702 
ToReversed(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * result,Label * exit,Label * slowPath)2703 void BuiltinsTypedArrayStubBuilder::ToReversed(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs,
2704     Variable *result, Label *exit, Label *slowPath)
2705 {
2706     auto env = GetEnvironment();
2707     Label ecmaObj(env);
2708     Label defaultConstr(env);
2709     Label isFastTypedArray(env);
2710     BRANCH(IsEcmaObject(thisValue), &ecmaObj, slowPath);
2711     Bind(&ecmaObj);
2712     GateRef arrayType = GetObjectType(LoadHClass(thisValue));
2713     BRANCH(IsFastTypeArray(arrayType), &isFastTypedArray, slowPath);
2714     Bind(&isFastTypedArray);
2715     BRANCH(HasConstructor(thisValue), slowPath, &defaultConstr);
2716     Bind(&defaultConstr);
2717 
2718     DEFVARIABLE(thisArrLen, VariableType::INT64(), ZExtInt32ToInt64(GetArrayLength(thisValue)));
2719     NewObjectStubBuilder newBuilder(this);
2720     newBuilder.SetParameters(glue, 0);
2721     GateRef newArray = newBuilder.NewTypedArray(glue, thisValue, arrayType, TruncInt64ToInt32(*thisArrLen));
2722     DEFVARIABLE(k, VariableType::INT64(), Int64(0));
2723 
2724     Label loopHead(env);
2725     Label loopEnd(env);
2726     Label loopNext(env);
2727     Label loopExit(env);
2728     Jump(&loopHead);
2729     LoopBegin(&loopHead);
2730     {
2731         BRANCH(Int64NotEqual(*k, *thisArrLen), &loopNext, &loopExit);
2732         Bind(&loopNext);
2733         {
2734             DEFVARIABLE(from, VariableType::INT64(), Int64Sub(Int64Sub(*thisArrLen, *k), Int64(1)));
2735             Label hasException0(env);
2736             Label hasException1(env);
2737             Label notHasException0(env);
2738             GateRef fromValue = FastGetPropertyByIndex(glue, thisValue, TruncInt64ToInt32(*from), arrayType);
2739             BRANCH(HasPendingException(glue), &hasException0, &notHasException0);
2740             Bind(&hasException0);
2741             {
2742                 result->WriteVariable(Exception());
2743                 Jump(exit);
2744             }
2745             Bind(&notHasException0);
2746             {
2747                 FastSetPropertyByIndex(glue, fromValue, newArray, TruncInt64ToInt32(*k), arrayType);
2748                 BRANCH(HasPendingException(glue), &hasException1, &loopEnd);
2749                 Bind(&hasException1);
2750                 {
2751                     result->WriteVariable(Exception());
2752                     Jump(exit);
2753                 }
2754             }
2755         }
2756     }
2757     Bind(&loopEnd);
2758     k = Int64Add(*k, Int64(1));
2759     LoopEnd(&loopHead);
2760     Bind(&loopExit);
2761     result->WriteVariable(newArray);
2762     Jump(exit);
2763 }
2764 
FastSetPropertyByIndex(GateRef glue,GateRef value,GateRef array,GateRef index,GateRef jsType)2765 void BuiltinsTypedArrayStubBuilder::FastSetPropertyByIndex(GateRef glue, GateRef value, GateRef array,
2766                                                            GateRef index, GateRef jsType)
2767 {
2768     auto env = GetEnvironment();
2769     Label entryPass(env);
2770     env->SubCfgEntry(&entryPass);
2771     Label exit(env);
2772     Label isDetached(env);
2773     Label notDetached(env);
2774     Label slowPath(env);
2775     Label indexIsvalid(env);
2776     Label notFloatArray(env);
2777     Label valueIsNumber(env);
2778 
2779     GateRef buffer = GetViewedArrayBuffer(array);
2780     BRANCH(IsDetachedBuffer(buffer), &isDetached, &notDetached);
2781     Bind(&isDetached);
2782     {
2783         Jump(&slowPath);
2784     }
2785     Bind(&notDetached);
2786     {
2787         GateRef arrLen = GetArrayLength(array);
2788         BRANCH(Int32GreaterThanOrEqual(index, arrLen), &exit, &indexIsvalid);
2789         Bind(&indexIsvalid);
2790         {
2791             BRANCH(Int32LessThanOrEqual(jsType, Int32(static_cast<int32_t>(JSType::JS_UINT32_ARRAY))),
2792                 &notFloatArray, &slowPath);
2793             Bind(&notFloatArray);
2794             {
2795                 BRANCH(TaggedIsNumber(value), &valueIsNumber, &slowPath);
2796                 Bind(&valueIsNumber);
2797                 {
2798                     GateRef offset = GetByteOffset(array);
2799                     SetValueToBuffer(glue, value, buffer, index, offset, jsType, &slowPath);
2800                     Jump(&exit);
2801                 }
2802             }
2803         }
2804     }
2805     Bind(&slowPath);
2806     {
2807         CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
2808             { array, IntToTaggedInt(index), value, IntToTaggedInt(jsType)});
2809         Jump(&exit);
2810     }
2811     Bind(&exit);
2812     env->SubCfgExit();
2813     return;
2814 }
2815 
SetValueToBuffer(GateRef glue,GateRef value,GateRef buffer,GateRef index,GateRef offset,GateRef jsType,Label * slowPath)2816 void BuiltinsTypedArrayStubBuilder::SetValueToBuffer(GateRef glue, GateRef value, GateRef buffer, GateRef index,
2817                                                      GateRef offset, GateRef jsType, Label *slowPath)
2818 {
2819     auto env = GetEnvironment();
2820     Label entryPass(env);
2821     env->SubCfgEntry(&entryPass);
2822 
2823     Label exit(env);
2824     Label defaultLabel(env);
2825     Label isInt8(env);
2826     Label notInt8(env);
2827     Label isInt16(env);
2828     Label notInt16(env);
2829     Label fastPath(env);
2830     Label valueTypeIsInt(env);
2831     Label valueTypeIsDouble(env);
2832     Label labelBuffer[3] = { Label(env), Label(env), Label(env) };
2833     Label labelBuffer1[3] = { Label(env), Label(env), Label(env) };
2834     Label labelBuffer2[3] = { Label(env), Label(env), Label(env) };
2835     int64_t valueBuffer[3] = {
2836         static_cast<int64_t>(JSType::JS_INT8_ARRAY), static_cast<int64_t>(JSType::JS_UINT8_ARRAY),
2837         static_cast<int64_t>(JSType::JS_UINT8_CLAMPED_ARRAY) };
2838     int64_t valueBuffer1[3] = {
2839         static_cast<int64_t>(JSType::JS_INT16_ARRAY), static_cast<int64_t>(JSType::JS_UINT16_ARRAY),
2840         static_cast<int64_t>(JSType::JS_INT32_ARRAY) };
2841     int64_t valueBuffer2[3] = {
2842         static_cast<int64_t>(JSType::JS_UINT32_ARRAY), static_cast<int64_t>(JSType::JS_FLOAT32_ARRAY),
2843         static_cast<int64_t>(JSType::JS_FLOAT64_ARRAY) };
2844 
2845     GateRef valueType = TaggedIsInt(value);
2846     BRANCH(valueType, &valueTypeIsInt, &valueTypeIsDouble);
2847     Bind(&valueTypeIsInt);
2848     {
2849         GateRef intValue = TruncInt64ToInt32(ChangeTaggedPointerToInt64(value));
2850         GateRef valueLessthanMin = Int32LessThanOrEqual(intValue, Int32(INT32_MIN));
2851         GateRef valueMorethanMax = Int32GreaterThanOrEqual(intValue, Int32(INT32_MAX));
2852         BRANCH(BitOr(valueLessthanMin, valueMorethanMax), slowPath, &fastPath);
2853     }
2854     Bind(&valueTypeIsDouble);
2855     {
2856         GateRef intValue = ChangeFloat64ToInt32(CastInt64ToFloat64(
2857             ChangeTaggedPointerToInt64(value)));
2858         GateRef valueLessthanMin = Int32LessThanOrEqual(intValue, Int32(INT32_MIN));
2859         GateRef valueMorethanMax = Int32GreaterThanOrEqual(intValue, Int32(INT32_MAX));
2860         BRANCH(BitOr(valueLessthanMin, valueMorethanMax), slowPath, &fastPath);
2861     }
2862     Bind(&fastPath);
2863 
2864     BRANCH(Int32LessThanOrEqual(jsType, Int32(static_cast<int32_t>(JSType::JS_UINT8_CLAMPED_ARRAY))),
2865         &isInt8, &notInt8);
2866     Bind(&isInt8);
2867     {
2868         // 3 : this switch has 3 cases
2869         Switch(jsType, &defaultLabel, valueBuffer, labelBuffer, 3);
2870         // 0 : index of this buffer
2871         Bind(&labelBuffer[0]);
2872         {
2873             Label valueIsInt(env);
2874             Label valueIsDouble(env);
2875             GateRef byteIndex = Int32Add(index, offset);
2876             GateRef block = GetDataPointFromBuffer(buffer);
2877             BRANCH(valueType, &valueIsInt, &valueIsDouble);
2878             Bind(&valueIsInt);
2879             {
2880                 GateRef val = TruncInt32ToInt8(TruncInt64ToInt32(ChangeTaggedPointerToInt64(value)));
2881                 Store(VariableType::INT8(), glue, block, byteIndex, val);
2882                 Jump(&exit);
2883             }
2884             Bind(&valueIsDouble);
2885             {
2886                 GateRef val = TruncInt32ToInt8(ChangeFloat64ToInt32(CastInt64ToFloat64(
2887                     ChangeTaggedPointerToInt64(value))));
2888                 Store(VariableType::INT8(), glue, block, byteIndex, val);
2889                 Jump(&exit);
2890             }
2891         }
2892         // 1 : index of this buffer
2893         Bind(&labelBuffer[1]);
2894         {
2895             Label valueIsInt(env);
2896             Label valueIsDouble(env);
2897             GateRef byteIndex = Int32Add(index, offset);
2898             GateRef block = GetDataPointFromBuffer(buffer);
2899             BRANCH(valueType, &valueIsInt, &valueIsDouble);
2900             Bind(&valueIsInt);
2901             {
2902                 GateRef val = TruncInt32ToInt8(TruncInt64ToInt32(ChangeTaggedPointerToInt64(value)));
2903                 Store(VariableType::INT8(), glue, block, byteIndex, val);
2904                 Jump(&exit);
2905             }
2906             Bind(&valueIsDouble);
2907             {
2908                 GateRef val = TruncInt32ToInt8(ChangeFloat64ToInt32(CastInt64ToFloat64(
2909                     ChangeTaggedPointerToInt64(value))));
2910                 Store(VariableType::INT8(), glue, block, byteIndex, val);
2911                 Jump(&exit);
2912             }
2913         }
2914         // 2 : index of this buffer
2915         Bind(&labelBuffer[2]);
2916         {
2917             Label valueIsInt(env);
2918             Label valueIsDouble(env);
2919             GateRef byteIndex = Int32Add(index, offset);
2920             GateRef block = GetDataPointFromBuffer(buffer);
2921             BRANCH(valueType, &valueIsInt, &valueIsDouble);
2922             Bind(&valueIsInt);
2923             {
2924                 GateRef val = TruncInt32ToInt8(TruncInt64ToInt32(ChangeTaggedPointerToInt64(value)));
2925                 Store(VariableType::INT8(), glue, block, byteIndex, val);
2926                 Jump(&exit);
2927             }
2928             Bind(&valueIsDouble);
2929             {
2930                 GateRef val = TruncInt32ToInt8(ChangeFloat64ToInt32(CastInt64ToFloat64(
2931                     ChangeTaggedPointerToInt64(value))));
2932                 Store(VariableType::INT8(), glue, block, byteIndex, val);
2933                 Jump(&exit);
2934             }
2935         }
2936     }
2937 
2938     Bind(&notInt8);
2939     {
2940         BRANCH(Int32LessThanOrEqual(jsType, Int32(static_cast<int32_t>(JSType::JS_INT32_ARRAY))),
2941             &isInt16, &notInt16);
2942         Bind(&isInt16);
2943         {
2944             // 3 : this switch has 3 case
2945             Switch(jsType, &defaultLabel, valueBuffer1, labelBuffer1, 3);
2946             // 0 : index of this buffer
2947             Bind(&labelBuffer1[0]);
2948             {
2949                 Label valueIsInt(env);
2950                 Label valueIsDouble(env);
2951                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::TWO)), offset);
2952                 GateRef block = GetDataPointFromBuffer(buffer);
2953                 BRANCH(valueType, &valueIsInt, &valueIsDouble);
2954                 Bind(&valueIsInt);
2955                 {
2956                     GateRef val = TruncInt32ToInt16(TruncInt64ToInt32(ChangeTaggedPointerToInt64(value)));
2957                     Store(VariableType::INT16(), glue, block, byteIndex, val);
2958                     Jump(&exit);
2959                 }
2960                 Bind(&valueIsDouble);
2961                 {
2962                     GateRef val = TruncInt32ToInt16(ChangeFloat64ToInt32(CastInt64ToFloat64(
2963                         ChangeTaggedPointerToInt64(value))));
2964                     Store(VariableType::INT16(), glue, block, byteIndex, val);
2965                     Jump(&exit);
2966                 }
2967             }
2968             // 1 : index of this buffer
2969             Bind(&labelBuffer1[1]);
2970             {
2971                 Label valueIsInt(env);
2972                 Label valueIsDouble(env);
2973                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::TWO)), offset);
2974                 GateRef block = GetDataPointFromBuffer(buffer);
2975                 BRANCH(valueType, &valueIsInt, &valueIsDouble);
2976                 Bind(&valueIsInt);
2977                 {
2978                     GateRef val = TruncInt32ToInt16(TruncInt64ToInt32(ChangeTaggedPointerToInt64(value)));
2979                     Store(VariableType::INT16(), glue, block, byteIndex, val);
2980                     Jump(&exit);
2981                 }
2982                 Bind(&valueIsDouble);
2983                 {
2984                     GateRef val = TruncInt32ToInt16(ChangeFloat64ToInt32(CastInt64ToFloat64(
2985                         ChangeTaggedPointerToInt64(value))));
2986                     Store(VariableType::INT16(), glue, block, byteIndex, val);
2987                     Jump(&exit);
2988                 }
2989             }
2990             // 2 : index of this buffer
2991             Bind(&labelBuffer1[2]);
2992             {
2993                 Label valueIsInt(env);
2994                 Label valueIsDouble(env);
2995                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::FOUR)), offset);
2996                 GateRef block = GetDataPointFromBuffer(buffer);
2997                 BRANCH(valueType, &valueIsInt, &valueIsDouble);
2998                 Bind(&valueIsInt);
2999                 {
3000                     GateRef val = TruncInt64ToInt32(ChangeTaggedPointerToInt64(value));
3001                     Store(VariableType::INT32(), glue, block, byteIndex, val);
3002                     Jump(&exit);
3003                 }
3004                 Bind(&valueIsDouble);
3005                 {
3006                     GateRef val = ChangeFloat64ToInt32(CastInt64ToFloat64(ChangeTaggedPointerToInt64(value)));
3007                     Store(VariableType::INT32(), glue, block, byteIndex, val);
3008                     Jump(&exit);
3009                 }
3010             }
3011         }
3012         Bind(&notInt16);
3013         {
3014             // 3 : this switch has 3 case
3015             Switch(jsType, &defaultLabel, valueBuffer2, labelBuffer2, 3);
3016             // 0 : index of this buffer
3017             Bind(&labelBuffer2[0]);
3018             {
3019                 Label valueIsInt(env);
3020                 Label valueIsDouble(env);
3021                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::FOUR)), offset);
3022                 GateRef block = GetDataPointFromBuffer(buffer);
3023                 BRANCH(valueType, &valueIsInt, &valueIsDouble);
3024                 Bind(&valueIsInt);
3025                 {
3026                     GateRef val = TruncInt64ToInt32(ChangeTaggedPointerToInt64(value));
3027                     Store(VariableType::INT32(), glue, block, byteIndex, val);
3028                     Jump(&exit);
3029                 }
3030                 Bind(&valueIsDouble);
3031                 {
3032                     GateRef val = ChangeFloat64ToInt32(CastInt64ToFloat64(ChangeTaggedPointerToInt64(value)));
3033                     Store(VariableType::INT32(), glue, block, byteIndex, val);
3034                     Jump(&exit);
3035                 }
3036             }
3037             // 1 : index of this buffer
3038             Bind(&labelBuffer2[1]);
3039             {
3040                 Label valueIsInt(env);
3041                 Label valueIsDouble(env);
3042                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::FOUR)), offset);
3043                 GateRef block = GetDataPointFromBuffer(buffer);
3044                 BRANCH(valueType, &valueIsInt, &valueIsDouble);
3045                 Bind(&valueIsInt);
3046                 {
3047                     GateRef val = TruncInt64ToInt32(ChangeTaggedPointerToInt64(value));
3048                     Store(VariableType::INT32(), glue, block, byteIndex, val);
3049                     Jump(&exit);
3050                 }
3051                 Bind(&valueIsDouble);
3052                 {
3053                     GateRef val = ChangeFloat64ToInt32(CastInt64ToFloat64(ChangeTaggedPointerToInt64(value)));
3054                     Store(VariableType::INT32(), glue, block, byteIndex, val);
3055                     Jump(&exit);
3056                 }
3057             }
3058             // 2 : index of this buffer
3059             Bind(&labelBuffer2[2]);
3060             {
3061                 Label valueIsInt(env);
3062                 Label valueIsDouble(env);
3063                 GateRef byteIndex = Int32Add(Int32Mul(index, Int32(base::ElementSize::EIGHT)), offset);
3064                 GateRef block = GetDataPointFromBuffer(buffer);
3065                 BRANCH(valueType, &valueIsInt, &valueIsDouble);
3066                 Bind(&valueIsInt);
3067                 {
3068                     GateRef val = ChangeTaggedPointerToInt64(value);
3069                     Store(VariableType::INT64(), glue, block, byteIndex, val);
3070                     Jump(&exit);
3071                 }
3072                 Bind(&valueIsDouble);
3073                 {
3074                     GateRef val = ChangeTaggedPointerToInt64(value);
3075                     Store(VariableType::INT64(), glue, block, byteIndex, val);
3076                     Jump(&exit);
3077                 }
3078             }
3079         }
3080     }
3081 
3082     Bind(&defaultLabel);
3083     {
3084         Jump(&exit);
3085     }
3086     Bind(&exit);
3087     env->SubCfgExit();
3088     return;
3089 }
3090 }  // namespace panda::ecmascript::kungfu
3091