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