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