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