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