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