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