• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &notcallThis0);
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(&notcallThis0);
107     {
108         Branch(Int64Equal(numArgs, IntPtr(1)), &callThis1, &notcallThis1);
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(&notcallThis1);
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, &notOneArg);
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(&notOneArg);
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