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