1 /*
2 * Copyright (c) 2022 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_stubs.h"
17
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/compiler/builtins/builtins_call_signature.h"
20 #include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
21 #include "ecmascript/compiler/builtins/containers_vector_stub_builder.h"
22 #include "ecmascript/compiler/builtins/containers_stub_builder.h"
23 #include "ecmascript/compiler/interpreter_stub-inl.h"
24 #include "ecmascript/compiler/llvm_ir_builder.h"
25 #include "ecmascript/compiler/new_object_stub_builder.h"
26 #include "ecmascript/compiler/stub_builder-inl.h"
27 #include "ecmascript/compiler/variable_type.h"
28 #include "ecmascript/js_date.h"
29 #include "ecmascript/js_primitive_ref.h"
30
31 namespace panda::ecmascript::kungfu {
32 #if ECMASCRIPT_ENABLE_BUILTIN_LOG
33 #define DECLARE_BUILTINS(name) \
34 void name##StubBuilder::GenerateCircuit() \
35 { \
36 GateRef glue = PtrArgument(static_cast<size_t>(BuiltinsArgs::GLUE)); \
37 GateRef nativeCode = PtrArgument(static_cast<size_t>(BuiltinsArgs::NATIVECODE)); \
38 GateRef func = TaggedArgument(static_cast<size_t>(BuiltinsArgs::FUNC)); \
39 GateRef newTarget = TaggedArgument(static_cast<size_t>(BuiltinsArgs::NEWTARGET)); \
40 GateRef thisValue = TaggedArgument(static_cast<size_t>(BuiltinsArgs::THISVALUE)); \
41 GateRef numArgs = PtrArgument(static_cast<size_t>(BuiltinsArgs::NUMARGS)); \
42 DebugPrint(glue, { Int32(GET_MESSAGE_STRING_ID(name)) }); \
43 GenerateCircuitImpl(glue, nativeCode, func, newTarget, thisValue, numArgs); \
44 } \
45 void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func, \
46 GateRef newTarget, GateRef thisValue, GateRef numArgs)
47 #else
48 #define DECLARE_BUILTINS(name) \
49 void name##StubBuilder::GenerateCircuit() \
50 { \
51 GateRef glue = PtrArgument(static_cast<size_t>(BuiltinsArgs::GLUE)); \
52 GateRef nativeCode = PtrArgument(static_cast<size_t>(BuiltinsArgs::NATIVECODE)); \
53 GateRef func = TaggedArgument(static_cast<size_t>(BuiltinsArgs::FUNC)); \
54 GateRef newTarget = TaggedArgument(static_cast<size_t>(BuiltinsArgs::NEWTARGET)); \
55 GateRef thisValue = TaggedArgument(static_cast<size_t>(BuiltinsArgs::THISVALUE)); \
56 GateRef numArgs = PtrArgument(static_cast<size_t>(BuiltinsArgs::NUMARGS)); \
57 GenerateCircuitImpl(glue, nativeCode, func, newTarget, thisValue, numArgs); \
58 } \
59 void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func, \
60 GateRef newTarget, GateRef thisValue, GateRef numArgs)
61 #endif
62
GetArg(GateRef numArgs,GateRef index)63 GateRef BuiltinsStubBuilder::GetArg(GateRef numArgs, GateRef index)
64 {
65 auto env = GetEnvironment();
66 Label entry(env);
67 env->SubCfgEntry(&entry);
68 DEFVARIABLE(arg, VariableType::JS_ANY(), Undefined());
69 Label validIndex(env);
70 Label exit(env);
71 Branch(IntPtrGreaterThan(numArgs, index), &validIndex, &exit);
72 Bind(&validIndex);
73 {
74 GateRef argv = GetArgv();
75 arg = Load(VariableType::JS_ANY(), argv, PtrMul(index, IntPtr(JSTaggedValue::TaggedTypeSize())));
76 Jump(&exit);
77 }
78 Bind(&exit);
79 GateRef ret = *arg;
80 env->SubCfgExit();
81 return ret;
82 }
83
CallSlowPath(GateRef nativeCode,GateRef glue,GateRef thisValue,GateRef numArgs,GateRef func,GateRef newTarget,const char * comment)84 GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, GateRef thisValue,
85 GateRef numArgs, GateRef func, GateRef newTarget, const char* comment)
86 {
87 auto env = GetEnvironment();
88 Label entry(env);
89 env->SubCfgEntry(&entry);
90 Label exit(env);
91 Label callThis0(env);
92 Label notcallThis0(env);
93 Label notcallThis1(env);
94 Label callThis1(env);
95 Label callThis2(env);
96 Label callThis3(env);
97 DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
98 GateRef runtimeCallInfoArgs = PtrAdd(numArgs, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
99 Branch(Int64Equal(numArgs, IntPtr(0)), &callThis0, ¬callThis0);
100 Bind(&callThis0);
101 {
102 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue };
103 result = CallBuiltinRuntime(glue, args, false, comment);
104 Jump(&exit);
105 }
106 Bind(¬callThis0);
107 {
108 Branch(Int64Equal(numArgs, IntPtr(1)), &callThis1, ¬callThis1);
109 Bind(&callThis1);
110 {
111 GateRef arg0 = GetCallArg0(numArgs);
112 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0 };
113 result = CallBuiltinRuntime(glue, args, false, comment);
114 Jump(&exit);
115 }
116 Bind(¬callThis1);
117 {
118 Branch(Int64Equal(numArgs, IntPtr(2)), &callThis2, &callThis3); // 2: args2
119 Bind(&callThis2);
120 {
121 GateRef arg0 = GetCallArg0(numArgs);
122 GateRef arg1 = GetCallArg1(numArgs);
123 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1 };
124 result = CallBuiltinRuntime(glue, args, false, comment);
125 Jump(&exit);
126 }
127 Bind(&callThis3);
128 {
129 GateRef arg0 = GetCallArg0(numArgs);
130 GateRef arg1 = GetCallArg1(numArgs);
131 GateRef arg2 = GetCallArg2(numArgs);
132 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1, arg2 };
133 result = CallBuiltinRuntime(glue, args, false, comment);
134 Jump(&exit);
135 }
136 }
137 }
138
139 Bind(&exit);
140 auto ret = *result;
141 env->SubCfgExit();
142 return ret;
143 }
144
DECLARE_BUILTINS(CharCodeAt)145 DECLARE_BUILTINS(CharCodeAt)
146 {
147 auto env = GetEnvironment();
148 DEFVARIABLE(res, VariableType::JS_ANY(), DoubleToTaggedDoublePtr(Double(base::NAN_VALUE)));
149 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
150
151 Label objNotUndefinedAndNull(env);
152 Label isString(env);
153 Label slowPath(env);
154 Label next(env);
155 Label posTagNotUndefined(env);
156 Label posTagIsInt(env);
157 Label posTagNotInt(env);
158 Label posNotGreaterLen(env);
159 Label posNotLessZero(env);
160 Label exit(env);
161 Label posTagIsDouble(env);
162 Label thisIsHeapobject(env);
163 Label flattenFastPath(env);
164
165 Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
166 Bind(&objNotUndefinedAndNull);
167 {
168 Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
169 Bind(&thisIsHeapobject);
170 Branch(IsString(thisValue), &isString, &slowPath);
171 Bind(&isString);
172 {
173 DEFVARIABLE(thisFlat, VariableType::JS_POINTER(), thisValue);
174 FlattenString(thisValue, &thisFlat, &flattenFastPath, &slowPath);
175 Bind(&flattenFastPath);
176 GateRef thisLen = GetLengthFromString(*thisFlat);
177 Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined);
178 Bind(&posTagNotUndefined);
179 {
180 GateRef posTag = GetCallArg0(numArgs);
181 Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
182 Bind(&posTagIsInt);
183 pos = GetInt32OfTInt(posTag);
184 Jump(&next);
185 Bind(&posTagNotInt);
186 Branch(TaggedIsDouble(posTag), &posTagIsDouble, &slowPath);
187 Bind(&posTagIsDouble);
188 pos = DoubleToInt(glue, GetDoubleOfTDouble(posTag));
189 Jump(&next);
190 }
191 Bind(&next);
192 {
193 Branch(Int32GreaterThanOrEqual(*pos, thisLen), &exit, &posNotGreaterLen);
194 Bind(&posNotGreaterLen);
195 {
196 Branch(Int32LessThan(*pos, Int32(0)), &exit, &posNotLessZero);
197 Bind(&posNotLessZero);
198 {
199 BuiltinsStringStubBuilder stringBuilder(this);
200 res = IntToTaggedPtr(stringBuilder.StringAt(*thisFlat, *pos));
201 Jump(&exit);
202 }
203 }
204 }
205 }
206 }
207 Bind(&slowPath);
208 {
209 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(CharCodeAt));
210 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
211 Jump(&exit);
212 }
213 Bind(&exit);
214 Return(*res);
215 }
216
DECLARE_BUILTINS(IndexOf)217 DECLARE_BUILTINS(IndexOf)
218 {
219 auto env = GetEnvironment();
220 DEFVARIABLE(res, VariableType::JS_ANY(), IntToTaggedPtr(Int32(-1)));
221 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
222
223 Label objNotUndefinedAndNull(env);
224 Label isString(env);
225 Label isSearchString(env);
226 Label slowPath(env);
227 Label next(env);
228 Label resPosGreaterZero(env);
229 Label searchTagIsHeapObject(env);
230 Label posTagNotUndefined(env);
231 Label posTagIsInt(env);
232 Label posTagNotInt(env);
233 Label exit(env);
234 Label posTagIsDouble(env);
235 Label nextCount(env);
236 Label posNotLessThanLen(env);
237 Label thisIsHeapobject(env);
238 Label flattenFastPath(env);
239 Label flattenFastPath1(env);
240
241 Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
242 Bind(&objNotUndefinedAndNull);
243 {
244 Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
245 Bind(&thisIsHeapobject);
246 Branch(IsString(thisValue), &isString, &slowPath);
247 Bind(&isString);
248 {
249 GateRef searchTag = GetCallArg0(numArgs);
250 Branch(TaggedIsHeapObject(searchTag), &searchTagIsHeapObject, &slowPath);
251 Bind(&searchTagIsHeapObject);
252 Branch(IsString(searchTag), &isSearchString, &slowPath);
253 Bind(&isSearchString);
254 {
255 GateRef thisLen = GetLengthFromString(thisValue);
256 Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &next, &posTagNotUndefined);
257 Bind(&posTagNotUndefined);
258 {
259 GateRef posTag = GetCallArg1(numArgs);
260 Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
261 Bind(&posTagIsInt);
262 pos = GetInt32OfTInt(posTag);
263 Jump(&next);
264 Bind(&posTagNotInt);
265 Branch(TaggedIsDouble(posTag), &posTagIsDouble, &slowPath);
266 Bind(&posTagIsDouble);
267 pos = DoubleToInt(glue, GetDoubleOfTDouble(posTag));
268 Jump(&next);
269 }
270 Bind(&next);
271 {
272 Label posGreaterThanZero(env);
273 Label posNotGreaterThanZero(env);
274 Branch(Int32GreaterThan(*pos, Int32(0)), &posGreaterThanZero, &posNotGreaterThanZero);
275 Bind(&posNotGreaterThanZero);
276 {
277 pos = Int32(0);
278 Jump(&nextCount);
279 }
280 Bind(&posGreaterThanZero);
281 {
282 Branch(Int32LessThanOrEqual(*pos, thisLen), &nextCount, &posNotLessThanLen);
283 Bind(&posNotLessThanLen);
284 {
285 pos = thisLen;
286 Jump(&nextCount);
287 }
288 }
289 Bind(&nextCount);
290 {
291 DEFVARIABLE(thisFlat, VariableType::JS_POINTER(), thisValue);
292 DEFVARIABLE(searchFlat, VariableType::JS_POINTER(), searchTag);
293 FlattenString(thisValue, &thisFlat, &flattenFastPath, &slowPath);
294 Bind(&flattenFastPath);
295 FlattenString(searchTag, &searchFlat, &flattenFastPath1, &slowPath);
296 Bind(&flattenFastPath1);
297 BuiltinsStringStubBuilder stringBuilder(this);
298 GateRef resPos = stringBuilder.StringIndexOf(*thisFlat, *searchFlat, *pos);
299 Branch(Int32GreaterThanOrEqual(resPos, Int32(0)), &resPosGreaterZero, &exit);
300 Bind(&resPosGreaterZero);
301 {
302 Label resPosLessZero(env);
303 Branch(Int32LessThanOrEqual(resPos, thisLen), &resPosLessZero, &exit);
304 Bind(&resPosLessZero);
305 {
306 res = IntToTaggedPtr(resPos);
307 Jump(&exit);
308 }
309 }
310 }
311 }
312 }
313 }
314 }
315 Bind(&slowPath);
316 {
317 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(IndexOf));
318 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
319 Jump(&exit);
320 }
321 Bind(&exit);
322 Return(*res);
323 }
324
DECLARE_BUILTINS(Substring)325 DECLARE_BUILTINS(Substring)
326 {
327 auto env = GetEnvironment();
328 DEFVARIABLE(res, VariableType::JS_ANY(), IntToTaggedPtr(Int32(-1)));
329 DEFVARIABLE(start, VariableType::INT32(), Int32(0));
330 DEFVARIABLE(end, VariableType::INT32(), Int32(0));
331 DEFVARIABLE(from, VariableType::INT32(), Int32(0));
332 DEFVARIABLE(to, VariableType::INT32(), Int32(0));
333
334 Label objNotUndefinedAndNull(env);
335 Label isString(env);
336 Label isSearchString(env);
337 Label slowPath(env);
338 Label countStart(env);
339 Label endTagIsUndefined(env);
340 Label startNotGreatZero(env);
341 Label countEnd(env);
342 Label endNotGreatZero(env);
343 Label countFrom(env);
344 Label countRes(env);
345 Label startTagNotUndefined(env);
346 Label posTagIsInt(env);
347 Label posTagNotInt(env);
348 Label exit(env);
349 Label posTagIsDouble(env);
350 Label endTagNotUndefined(env);
351 Label endTagIsInt(env);
352 Label endTagNotInt(env);
353 Label endTagIsDouble(env);
354 Label endGreatZero(env);
355 Label endGreatLen(env);
356 Label startGreatZero(env);
357 Label startGreatEnd(env);
358 Label startNotGreatEnd(env);
359 Label thisIsHeapobject(env);
360 Label flattenFastPath(env);
361
362 Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
363 Bind(&objNotUndefinedAndNull);
364 {
365 Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
366 Bind(&thisIsHeapobject);
367 Branch(IsString(thisValue), &isString, &slowPath);
368 Bind(&isString);
369 {
370 Label next(env);
371 GateRef thisLen = GetLengthFromString(thisValue);
372 Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &startTagNotUndefined);
373 Bind(&startTagNotUndefined);
374 {
375 GateRef startTag = GetCallArg0(numArgs);
376 Branch(TaggedIsInt(startTag), &posTagIsInt, &posTagNotInt);
377 Bind(&posTagIsInt);
378 start = GetInt32OfTInt(startTag);
379 Jump(&next);
380 Bind(&posTagNotInt);
381 Branch(TaggedIsDouble(startTag), &posTagIsDouble, &slowPath);
382 Bind(&posTagIsDouble);
383 start = DoubleToInt(glue, GetDoubleOfTDouble(startTag));
384 Jump(&next);
385 }
386 Bind(&next);
387 {
388 Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &endTagIsUndefined, &endTagNotUndefined);
389 Bind(&endTagIsUndefined);
390 {
391 end = thisLen;
392 Jump(&countStart);
393 }
394 Bind(&endTagNotUndefined);
395 {
396 GateRef endTag = GetCallArg1(numArgs);
397 Branch(TaggedIsInt(endTag), &endTagIsInt, &endTagNotInt);
398 Bind(&endTagIsInt);
399 end = GetInt32OfTInt(endTag);
400 Jump(&countStart);
401 Bind(&endTagNotInt);
402 Branch(TaggedIsDouble(endTag), &endTagIsDouble, &slowPath);
403 Bind(&endTagIsDouble);
404 end = DoubleToInt(glue, GetDoubleOfTDouble(endTag));
405 Jump(&countStart);
406 }
407 }
408 Bind(&countStart);
409 {
410 Label startGreatLen(env);
411 Branch(Int32GreaterThan(*start, Int32(0)), &startGreatZero, &startNotGreatZero);
412 Bind(&startNotGreatZero);
413 {
414 start = Int32(0);
415 Jump(&countEnd);
416 }
417 Bind(&startGreatZero);
418 {
419 Branch(Int32GreaterThan(*start, thisLen), &startGreatLen, &countEnd);
420 Bind(&startGreatLen);
421 {
422 start = thisLen;
423 Jump(&countEnd);
424 }
425 }
426 }
427 Bind(&countEnd);
428 {
429 Branch(Int32GreaterThan(*end, Int32(0)), &endGreatZero, &endNotGreatZero);
430 Bind(&endNotGreatZero);
431 {
432 end = Int32(0);
433 Jump(&countFrom);
434 }
435 Bind(&endGreatZero);
436 {
437 Branch(Int32GreaterThan(*end, thisLen), &endGreatLen, &countFrom);
438 Bind(&endGreatLen);
439 {
440 end = thisLen;
441 Jump(&countFrom);
442 }
443 }
444 }
445 Bind(&countFrom);
446 {
447 Branch(Int32GreaterThan(*start, *end), &startGreatEnd, &startNotGreatEnd);
448 Bind(&startGreatEnd);
449 {
450 from = *end;
451 to = *start;
452 Jump(&countRes);
453 }
454 Bind(&startNotGreatEnd);
455 {
456 from = *start;
457 to = *end;
458 Jump(&countRes);
459 }
460 }
461 Bind(&countRes);
462 {
463 GateRef len = Int32Sub(*to, *from);
464 DEFVARIABLE(thisFlat, VariableType::JS_POINTER(), thisValue);
465 FlattenString(thisValue, &thisFlat, &flattenFastPath, &slowPath);
466 Bind(&flattenFastPath);
467 {
468 BuiltinsStringStubBuilder stringBuilder(this);
469 res = stringBuilder.FastSubString(glue, *thisFlat, *from, len);
470 Jump(&exit);
471 }
472 }
473 }
474 }
475
476 Bind(&slowPath);
477 {
478 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(Substring));
479 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
480 Jump(&exit);
481 }
482 Bind(&exit);
483 Return(*res);
484 }
485
DECLARE_BUILTINS(CharAt)486 DECLARE_BUILTINS(CharAt)
487 {
488 auto env = GetEnvironment();
489 DEFVARIABLE(res, VariableType::JS_POINTER(), Hole());
490 DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
491
492 Label objNotUndefinedAndNull(env);
493 Label isString(env);
494 Label slowPath(env);
495 Label next(env);
496 Label posTagNotUndefined(env);
497 Label posTagIsInt(env);
498 Label posTagNotInt(env);
499 Label posNotGreaterLen(env);
500 Label posGreaterLen(env);
501 Label posNotLessZero(env);
502 Label exit(env);
503 Label posTagIsDouble(env);
504 Label thisIsHeapobject(env);
505 Label flattenFastPath(env);
506
507 Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
508 Bind(&objNotUndefinedAndNull);
509 {
510 Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
511 Bind(&thisIsHeapobject);
512 Branch(IsString(thisValue), &isString, &slowPath);
513 Bind(&isString);
514 {
515 DEFVARIABLE(thisFlat, VariableType::JS_POINTER(), thisValue);
516 FlattenString(thisValue, &thisFlat, &flattenFastPath, &slowPath);
517 Bind(&flattenFastPath);
518 GateRef thisLen = GetLengthFromString(*thisFlat);
519 Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined);
520 Bind(&posTagNotUndefined);
521 {
522 GateRef posTag = GetCallArg0(numArgs);
523 Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
524 Bind(&posTagIsInt);
525 pos = GetInt32OfTInt(posTag);
526 Jump(&next);
527 Bind(&posTagNotInt);
528 Branch(TaggedIsDouble(posTag), &posTagIsDouble, &slowPath);
529 Bind(&posTagIsDouble);
530 pos = DoubleToInt(glue, GetDoubleOfTDouble(posTag));
531 Jump(&next);
532 }
533 Bind(&next);
534 {
535 Branch(Int32GreaterThanOrEqual(*pos, thisLen), &posGreaterLen, &posNotGreaterLen);
536 Bind(&posNotGreaterLen);
537 {
538 Branch(Int32LessThan(*pos, Int32(0)), &posGreaterLen, &posNotLessZero);
539 Bind(&posNotLessZero);
540 {
541 BuiltinsStringStubBuilder stringBuilder(this);
542 res = stringBuilder.CreateFromEcmaString(glue, *thisFlat, *pos);
543 Jump(&exit);
544 }
545 }
546 Bind(&posGreaterLen);
547 {
548 res = GetGlobalConstantValue(
549 VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
550 Jump(&exit);
551 }
552 }
553 }
554 }
555 Bind(&slowPath);
556 {
557 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(CharAt));
558 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
559 Jump(&exit);
560 }
561 Bind(&exit);
562 Return(*res);
563 }
564
DECLARE_BUILTINS(VectorForEach)565 DECLARE_BUILTINS(VectorForEach)
566 {
567 auto env = GetEnvironment();
568 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
569
570 Label exit(env);
571 Label slowPath(env);
572
573 ContainersStubBuilder containersBuilder(this);
574 containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
575 &slowPath, ContainersType::VECTOR_FOREACH);
576 Bind(&slowPath);
577 {
578 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(VectorForEach));
579 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
580 Jump(&exit);
581 }
582 Bind(&exit);
583 Return(*res);
584 }
585
DECLARE_BUILTINS(VectorReplaceAllElements)586 DECLARE_BUILTINS(VectorReplaceAllElements)
587 {
588 auto env = GetEnvironment();
589 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
590
591 Label exit(env);
592 Label slowPath(env);
593
594 ContainersStubBuilder containersBuilder(this);
595 containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
596 &slowPath, ContainersType::VECTOR_REPLACEALLELEMENTS);
597 Bind(&slowPath);
598 {
599 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(VectorReplaceAllElements));
600 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
601 Jump(&exit);
602 }
603 Bind(&exit);
604 Return(*res);
605 }
606
DECLARE_BUILTINS(StackForEach)607 DECLARE_BUILTINS(StackForEach)
608 {
609 auto env = GetEnvironment();
610 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
611
612 Label exit(env);
613 Label slowPath(env);
614
615 ContainersStubBuilder containersBuilder(this);
616 containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
617 &slowPath, ContainersType::STACK_FOREACH);
618 Bind(&slowPath);
619 {
620 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(StackForEach));
621 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
622 Jump(&exit);
623 }
624 Bind(&exit);
625 Return(*res);
626 }
627
DECLARE_BUILTINS(PlainArrayForEach)628 DECLARE_BUILTINS(PlainArrayForEach)
629 {
630 auto env = GetEnvironment();
631 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
632
633 Label exit(env);
634 Label slowPath(env);
635
636 ContainersStubBuilder containersBuilder(this);
637 containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
638 &slowPath, ContainersType::PLAINARRAY_FOREACH);
639 Bind(&slowPath);
640 {
641 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(PlainArrayForEach));
642 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
643 Jump(&exit);
644 }
645 Bind(&exit);
646 Return(*res);
647 }
648
DECLARE_BUILTINS(QueueForEach)649 DECLARE_BUILTINS(QueueForEach)
650 {
651 auto env = GetEnvironment();
652 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
653
654 Label exit(env);
655 Label slowPath(env);
656
657 ContainersStubBuilder containersBuilder(this);
658 containersBuilder.QueueCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
659 &slowPath, ContainersType::QUEUE_FOREACH);
660 Bind(&slowPath);
661 {
662 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(QueueForEach));
663 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
664 Jump(&exit);
665 }
666 Bind(&exit);
667 Return(*res);
668 }
669
DECLARE_BUILTINS(DequeForEach)670 DECLARE_BUILTINS(DequeForEach)
671 {
672 auto env = GetEnvironment();
673 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
674
675 Label exit(env);
676 Label slowPath(env);
677
678 ContainersStubBuilder containersBuilder(this);
679 containersBuilder.DequeCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
680 &slowPath, ContainersType::DEQUE_FOREACH);
681 Bind(&slowPath);
682 {
683 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(DequeForEach));
684 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
685 Jump(&exit);
686 }
687 Bind(&exit);
688 Return(*res);
689 }
690
DECLARE_BUILTINS(LightWeightMapForEach)691 DECLARE_BUILTINS(LightWeightMapForEach)
692 {
693 auto env = GetEnvironment();
694 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
695
696 Label exit(env);
697 Label slowPath(env);
698
699 ContainersStubBuilder containersBuilder(this);
700 containersBuilder.ContainersLightWeightCall(glue, thisValue, numArgs, &res, &exit,
701 &slowPath, ContainersType::LIGHTWEIGHTMAP_FOREACH);
702 Bind(&slowPath);
703 {
704 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(LightWeightMapForEach));
705 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
706 Jump(&exit);
707 }
708 Bind(&exit);
709 Return(*res);
710 }
711
DECLARE_BUILTINS(LightWeightSetForEach)712 DECLARE_BUILTINS(LightWeightSetForEach)
713 {
714 auto env = GetEnvironment();
715 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
716
717 Label exit(env);
718 Label slowPath(env);
719
720 ContainersStubBuilder containersBuilder(this);
721 containersBuilder.ContainersLightWeightCall(glue, thisValue, numArgs, &res, &exit,
722 &slowPath, ContainersType::LIGHTWEIGHTSET_FOREACH);
723 Bind(&slowPath);
724 {
725 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(LightWeightSetForEach));
726 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
727 Jump(&exit);
728 }
729 Bind(&exit);
730 Return(*res);
731 }
732
DECLARE_BUILTINS(HashMapForEach)733 DECLARE_BUILTINS(HashMapForEach)
734 {
735 auto env = GetEnvironment();
736 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
737
738 Label exit(env);
739 Label slowPath(env);
740
741 ContainersStubBuilder containersBuilder(this);
742 containersBuilder.ContainersHashCall(glue, thisValue, numArgs, &res, &exit,
743 &slowPath, ContainersType::HASHMAP_FOREACH);
744 Bind(&slowPath);
745 {
746 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(HashMapForEach));
747 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
748 Jump(&exit);
749 }
750 Bind(&exit);
751 Return(*res);
752 }
753
DECLARE_BUILTINS(HashSetForEach)754 DECLARE_BUILTINS(HashSetForEach)
755 {
756 auto env = GetEnvironment();
757 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
758
759 Label exit(env);
760 Label slowPath(env);
761
762 ContainersStubBuilder containersBuilder(this);
763 containersBuilder.ContainersHashCall(glue, thisValue, numArgs, &res, &exit,
764 &slowPath, ContainersType::HASHSET_FOREACH);
765 Bind(&slowPath);
766 {
767 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(HashSetForEach));
768 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
769 Jump(&exit);
770 }
771 Bind(&exit);
772 Return(*res);
773 }
774
DECLARE_BUILTINS(LinkedListForEach)775 DECLARE_BUILTINS(LinkedListForEach)
776 {
777 auto env = GetEnvironment();
778 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
779
780 Label exit(env);
781 Label slowPath(env);
782
783 ContainersStubBuilder containersBuilder(this);
784 containersBuilder.ContainersLinkedListCall(glue, thisValue, numArgs, &res, &exit,
785 &slowPath, ContainersType::LINKEDLIST_FOREACH);
786 Bind(&slowPath);
787 {
788 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(LinkedListForEach));
789 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
790 Jump(&exit);
791 }
792 Bind(&exit);
793 Return(*res);
794 }
795
DECLARE_BUILTINS(ListForEach)796 DECLARE_BUILTINS(ListForEach)
797 {
798 auto env = GetEnvironment();
799 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
800
801 Label exit(env);
802 Label slowPath(env);
803
804 ContainersStubBuilder containersBuilder(this);
805 containersBuilder.ContainersLinkedListCall(glue, thisValue, numArgs, &res, &exit,
806 &slowPath, ContainersType::LIST_FOREACH);
807 Bind(&slowPath);
808 {
809 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ListForEach));
810 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
811 Jump(&exit);
812 }
813 Bind(&exit);
814 Return(*res);
815 }
816
DECLARE_BUILTINS(ArrayListForEach)817 DECLARE_BUILTINS(ArrayListForEach)
818 {
819 auto env = GetEnvironment();
820 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
821
822 Label exit(env);
823 Label slowPath(env);
824
825 ContainersStubBuilder containersBuilder(this);
826 containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
827 &slowPath, ContainersType::ARRAYLIST_FOREACH);
828 Bind(&slowPath);
829 {
830 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ArrayListForEach));
831 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
832 Jump(&exit);
833 }
834 Bind(&exit);
835 Return(*res);
836 }
837
DECLARE_BUILTINS(ArrayListReplaceAllElements)838 DECLARE_BUILTINS(ArrayListReplaceAllElements)
839 {
840 auto env = GetEnvironment();
841 DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
842
843 Label exit(env);
844 Label slowPath(env);
845
846 ContainersStubBuilder containersBuilder(this);
847 containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
848 &slowPath, ContainersType::ARRAYLIST_REPLACEALLELEMENTS);
849 Bind(&slowPath);
850 {
851 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ArrayListReplaceAllElements));
852 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
853 Jump(&exit);
854 }
855 Bind(&exit);
856 Return(*res);
857 }
858
DECLARE_BUILTINS(FunctionPrototypeApply)859 DECLARE_BUILTINS(FunctionPrototypeApply)
860 {
861 auto env = GetEnvironment();
862 DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
863 Label exit(env);
864 Label slowPath(env);
865 Label targetIsCallable(env);
866 Label targetIsUndefined(env);
867 Label targetNotUndefined(env);
868 Label isHeapObject(env);
869 //1. If IsCallable(func) is false, throw a TypeError exception
870 Branch(TaggedIsHeapObject(thisValue), &isHeapObject, &slowPath);
871 Bind(&isHeapObject);
872 {
873 Branch(IsCallable(thisValue), &targetIsCallable, &slowPath);
874 Bind(&targetIsCallable);
875 {
876 GateRef thisArg = GetCallArg0(numArgs);
877 GateRef arrayObj = GetCallArg1(numArgs);
878 // 2. If argArray is null or undefined, then
879 Branch(TaggedIsUndefined(arrayObj), &targetIsUndefined, &targetNotUndefined);
880 Bind(&targetIsUndefined);
881 {
882 // a. Return Call(func, thisArg).
883 res = JSCallDispatch(glue, thisValue, Int32(0), 0, Circuit::NullGate(),
884 JSCallMode::CALL_GETTER, { thisArg });
885 Jump(&exit);
886 }
887 Bind(&targetNotUndefined);
888 {
889 // 3. Let argList be CreateListFromArrayLike(argArray).
890 GateRef elements = BuildArgumentsListFastElements(glue, arrayObj);
891 Label targetIsHole(env);
892 Label targetNotHole(env);
893 Branch(TaggedIsHole(elements), &targetIsHole, &targetNotHole);
894 Bind(&targetIsHole);
895 {
896 GateRef argList = CreateListFromArrayLike(glue, arrayObj);
897 // 4. ReturnIfAbrupt(argList).
898 Label isPendingException(env);
899 Label noPendingException(env);
900 Branch(HasPendingException(glue), &isPendingException, &noPendingException);
901 Bind(&isPendingException);
902 {
903 Jump(&slowPath);
904 }
905 Bind(&noPendingException);
906 {
907 GateRef argsLength = GetLengthOfTaggedArray(argList);
908 GateRef argv = PtrAdd(argList, IntPtr(TaggedArray::DATA_OFFSET));
909 res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(),
910 JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, argv, thisArg });
911 Jump(&exit);
912 }
913 }
914 Bind(&targetNotHole);
915 {
916 // 6. Return Call(func, thisArg, argList).
917 Label taggedIsStableJsArg(env);
918 Label taggedNotStableJsArg(env);
919 Branch(IsStableJSArguments(glue, arrayObj), &taggedIsStableJsArg, &taggedNotStableJsArg);
920 Bind(&taggedIsStableJsArg);
921 {
922 GateRef hClass = LoadHClass(arrayObj);
923 GateRef PropertyInlinedPropsOffset = IntPtr(JSArguments::LENGTH_INLINE_PROPERTY_INDEX);
924 GateRef result = GetPropertyInlinedProps(arrayObj, hClass, PropertyInlinedPropsOffset);
925 GateRef length = TaggedGetInt(result);
926 GateRef argsLength = MakeArgListWithHole(glue, elements, length);
927 GateRef elementArgv = PtrAdd(elements, IntPtr(TaggedArray::DATA_OFFSET));
928 res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(),
929 JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, elementArgv, thisArg });
930 Jump(&exit);
931 }
932 Bind(&taggedNotStableJsArg);
933 {
934 GateRef length = GetArrayLength(arrayObj);
935 GateRef argsLength = MakeArgListWithHole(glue, elements, length);
936 GateRef elementArgv = PtrAdd(elements, IntPtr(TaggedArray::DATA_OFFSET));
937 res = JSCallDispatch(glue, thisValue, argsLength, 0, Circuit::NullGate(),
938 JSCallMode::CALL_THIS_ARGV_WITH_RETURN, { argsLength, elementArgv, thisArg });
939 Jump(&exit);
940 }
941 }
942 }
943 }
944 }
945
946 Bind(&slowPath);
947 {
948 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
949 Jump(&exit);
950 }
951 Bind(&exit);
952 Return(*res);
953 }
954
DECLARE_BUILTINS(BooleanConstructor)955 DECLARE_BUILTINS(BooleanConstructor)
956 {
957 auto env = GetEnvironment();
958 DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
959
960 Label newTargetIsHeapObject(env);
961 Label newTargetIsJSFunction(env);
962 Label slowPath(env);
963 Label exit(env);
964
965 Branch(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
966 Bind(&newTargetIsHeapObject);
967 Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
968 Bind(&newTargetIsJSFunction);
969 {
970 Label intialHClassIsHClass(env);
971 GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
972 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
973 Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath);
974 Bind(&intialHClassIsHClass);
975 {
976 NewObjectStubBuilder newBuilder(this);
977 newBuilder.SetParameters(glue, 0);
978 Label afterNew(env);
979 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
980 Bind(&afterNew);
981 {
982 GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
983 GateRef value = GetArg(numArgs, IntPtr(0));
984 Store(VariableType::INT64(), glue, *res, valueOffset, FastToBoolean(value));
985 Jump(&exit);
986 }
987 }
988 }
989 Bind(&slowPath);
990 {
991 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(BooleanConstructor));
992 GateRef argv = GetArgv();
993 auto args = { glue, nativeCode, func, thisValue, numArgs, argv };
994 res = CallBuiltinRuntime(glue, args, true, name.c_str());
995 Jump(&exit);
996 }
997 Bind(&exit);
998 Return(*res);
999 }
1000
DECLARE_BUILTINS(DateConstructor)1001 DECLARE_BUILTINS(DateConstructor)
1002 {
1003 auto env = GetEnvironment();
1004 DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
1005
1006 Label newTargetIsHeapObject(env);
1007 Label newTargetIsJSFunction(env);
1008 Label slowPath(env);
1009 Label exit(env);
1010
1011 Branch(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
1012 Bind(&newTargetIsHeapObject);
1013 Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
1014 Bind(&newTargetIsJSFunction);
1015 {
1016 Label intialHClassIsHClass(env);
1017 GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
1018 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1019 Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath);
1020 Bind(&intialHClassIsHClass);
1021 {
1022 Label oneArg(env);
1023 Label notOneArg(env);
1024 Label newJSDate(env);
1025 DEFVARIABLE(timeValue, VariableType::FLOAT64(), Double(0));
1026 Branch(Int64Equal(numArgs, IntPtr(1)), &oneArg, ¬OneArg);
1027 Bind(&oneArg);
1028 {
1029 Label valueIsNumber(env);
1030 GateRef value = GetArgNCheck(IntPtr(0));
1031 Branch(TaggedIsNumber(value), &valueIsNumber, &slowPath);
1032 Bind(&valueIsNumber);
1033 {
1034 timeValue = CallNGCRuntime(glue, RTSTUB_ID(TimeClip), {GetDoubleOfTNumber(value)});
1035 Jump(&newJSDate);
1036 }
1037 }
1038 Bind(¬OneArg);
1039 {
1040 Label threeArgs(env);
1041 Branch(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &slowPath); // 3: year month day
1042 Bind(&threeArgs);
1043 {
1044 Label numberYearMonthDay(env);
1045 GateRef year = GetArgNCheck(IntPtr(0));
1046 GateRef month = GetArgNCheck(IntPtr(1));
1047 GateRef day = GetArgNCheck(IntPtr(2));
1048 Branch(IsNumberYearMonthDay(year, month, day), &numberYearMonthDay, &slowPath);
1049 Bind(&numberYearMonthDay);
1050 {
1051 GateRef y = GetDoubleOfTNumber(year);
1052 GateRef m = GetDoubleOfTNumber(month);
1053 GateRef d = GetDoubleOfTNumber(day);
1054 timeValue = CallNGCRuntime(glue, RTSTUB_ID(SetDateValues), {y, m, d});
1055 Jump(&newJSDate);
1056 }
1057 }
1058 }
1059 Bind(&newJSDate);
1060 {
1061 NewObjectStubBuilder newBuilder(this);
1062 newBuilder.SetParameters(glue, 0);
1063 Label afterNew(env);
1064 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
1065 Bind(&afterNew);
1066 {
1067 GateRef timeValueOffset = IntPtr(JSDate::TIME_VALUE_OFFSET);
1068 Store(VariableType::JS_NOT_POINTER(), glue, *res, timeValueOffset,
1069 DoubleToTaggedDoublePtr(*timeValue));
1070 Jump(&exit);
1071 }
1072 }
1073 }
1074 }
1075 Bind(&slowPath);
1076 {
1077 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(DateConstructor));
1078 GateRef argv = GetArgv();
1079 res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true, name.c_str());
1080 Jump(&exit);
1081 }
1082 Bind(&exit);
1083 Return(*res);
1084 }
1085
DECLARE_BUILTINS(ArrayConstructor)1086 DECLARE_BUILTINS(ArrayConstructor)
1087 {
1088 auto env = GetEnvironment();
1089 DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
1090
1091 Label newTargetIsHeapObject(env);
1092 Label newTargetIsJSFunction(env);
1093 Label slowPath(env);
1094 Label slowPath1(env);
1095 Label exit(env);
1096
1097 Branch(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath1);
1098 Bind(&newTargetIsHeapObject);
1099 Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
1100 Bind(&newTargetIsJSFunction);
1101 {
1102 Label fastGetHclass(env);
1103 Label intialHClassIsHClass(env);
1104 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
1105 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1106 auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
1107 Branch(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath);
1108 Bind(&fastGetHclass);
1109 GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1110 DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0));
1111 Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath);
1112 Bind(&intialHClassIsHClass);
1113 {
1114 Label noArg(env);
1115 Label hasArg(env);
1116 Label arrayCreate(env);
1117 Branch(Int64Equal(numArgs, IntPtr(0)), &noArg, &hasArg);
1118 Bind(&noArg);
1119 {
1120 Jump(&arrayCreate);
1121 }
1122 Bind(&hasArg);
1123 {
1124 Label hasOneArg(env);
1125 Branch(Int64Equal(numArgs, IntPtr(1)), &hasOneArg, &slowPath);
1126 Bind(&hasOneArg);
1127 {
1128 Label argIsNumber(env);
1129 GateRef arg0 = GetArg(numArgs, IntPtr(0));
1130 Branch(TaggedIsNumber(arg0), &argIsNumber, &slowPath);
1131 Bind(&argIsNumber);
1132 {
1133 Label argIsInt(env);
1134 Label argIsDouble(env);
1135 Branch(TaggedIsInt(arg0), &argIsInt, &argIsDouble);
1136 Bind(&argIsInt);
1137 {
1138 Label validIntLength(env);
1139 GateRef intLen = GetInt64OfTInt(arg0);
1140 GateRef isGEZero = Int64GreaterThanOrEqual(intLen, Int64(0));
1141 GateRef isLEMaxLen = Int64LessThanOrEqual(intLen, Int64(JSArray::MAX_ARRAY_INDEX));
1142 Branch(BoolAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath);
1143 Bind(&validIntLength);
1144 {
1145 arrayLength = intLen;
1146 Jump(&arrayCreate);
1147 }
1148 }
1149 Bind(&argIsDouble);
1150 {
1151 Label validDoubleLength(env);
1152 GateRef doubleLength = GetDoubleOfTDouble(arg0);
1153 GateRef doubleToInt = DoubleToInt(glue, doubleLength);
1154 GateRef intToDouble = CastInt64ToFloat64(SExtInt32ToInt64(doubleToInt));
1155 GateRef doubleEqual = DoubleEqual(doubleLength, intToDouble);
1156 GateRef doubleLEMaxLen =
1157 DoubleLessThanOrEqual(doubleLength, Double(JSArray::MAX_ARRAY_INDEX));
1158 Branch(BoolAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath);
1159 Bind(&validDoubleLength);
1160 {
1161 arrayLength = SExtInt32ToInt64(doubleToInt);
1162 Jump(&arrayCreate);
1163 }
1164 }
1165 }
1166 }
1167 }
1168 Bind(&arrayCreate);
1169 {
1170 Label lengthValid(env);
1171 Branch(Int64GreaterThan(*arrayLength, Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid);
1172 Bind(&lengthValid);
1173 {
1174 NewObjectStubBuilder newBuilder(this);
1175 newBuilder.SetParameters(glue, 0);
1176 res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength);
1177 GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1178 Store(VariableType::INT32(), glue, *res, lengthOffset, TruncInt64ToInt32(*arrayLength));
1179 GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
1180 ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1181 SetPropertyInlinedProps(glue, *res, intialHClass, accessor,
1182 Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
1183 SetExtensibleToBitfield(glue, *res, true);
1184 Jump(&exit);
1185 }
1186 }
1187 }
1188 }
1189 Bind(&slowPath);
1190 {
1191 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ArrayConstructor));
1192 GateRef argv = GetArgv();
1193 res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true, name.c_str());
1194 Jump(&exit);
1195 }
1196 Bind(&slowPath1);
1197 {
1198 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ArrayConstructor));
1199 res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
1200 Jump(&exit);
1201 }
1202
1203 Bind(&exit);
1204 Return(*res);
1205 }
1206 } // namespace panda::ecmascript::kungfu
1207