• 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)84 GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, GateRef thisValue,
85     GateRef numArgs, GateRef func, GateRef newTarget)
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         result = CallBuiltinRuntime(glue, { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue });
103         Jump(&exit);
104     }
105     Bind(&notcallThis0);
106     {
107         Branch(Int64Equal(numArgs, IntPtr(1)), &callThis1, &notcallThis1);
108         Bind(&callThis1);
109         {
110             GateRef arg0 = GetCallArg0();
111             result =
112                 CallBuiltinRuntime(glue, { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0 });
113             Jump(&exit);
114         }
115         Bind(&notcallThis1);
116         {
117             Branch(Int64Equal(numArgs, IntPtr(2)), &callThis2, &callThis3); // 2: args2
118             Bind(&callThis2);
119             {
120                 GateRef arg0 = GetCallArg0();
121                 GateRef arg1 = GetCallArg1();
122                 result = CallBuiltinRuntime(glue,
123                     { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1 });
124                 Jump(&exit);
125             }
126             Bind(&callThis3);
127             {
128                 GateRef arg0 = GetCallArg0();
129                 GateRef arg1 = GetCallArg1();
130                 GateRef arg2 = GetCallArg2();
131                 result = CallBuiltinRuntime(glue,
132                     { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1, arg2 });
133                 Jump(&exit);
134             }
135         }
136     }
137 
138     Bind(&exit);
139     auto ret = *result;
140     env->SubCfgExit();
141     return ret;
142 }
143 
DECLARE_BUILTINS(CharCodeAt)144 DECLARE_BUILTINS(CharCodeAt)
145 {
146     auto env = GetEnvironment();
147     DEFVARIABLE(res, VariableType::JS_ANY(), DoubleToTaggedDoublePtr(Double(base::NAN_VALUE)));
148     DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
149 
150     Label objNotUndefinedAndNull(env);
151     Label isString(env);
152     Label slowPath(env);
153     Label next(env);
154     Label posTagNotUndefined(env);
155     Label posTagIsInt(env);
156     Label posTagNotInt(env);
157     Label posNotGreaterLen(env);
158     Label posNotLessZero(env);
159     Label exit(env);
160     Label posTagIsDouble(env);
161     Label thisIsHeapobject(env);
162 
163     Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
164     Bind(&objNotUndefinedAndNull);
165     {
166         Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
167         Bind(&thisIsHeapobject);
168         Branch(IsString(thisValue), &isString, &slowPath);
169         Bind(&isString);
170         {
171             GateRef thisLen = GetLengthFromString(thisValue);
172             Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined);
173             Bind(&posTagNotUndefined);
174             {
175                 GateRef posTag = GetCallArg0();
176                 Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
177                 Bind(&posTagIsInt);
178                 pos = GetInt32OfTInt(posTag);
179                 Jump(&next);
180                 Bind(&posTagNotInt);
181                 Branch(TaggedIsDouble(posTag), &posTagIsDouble, &slowPath);
182                 Bind(&posTagIsDouble);
183                 pos = DoubleToInt(glue, GetDoubleOfTDouble(posTag));
184                 Jump(&next);
185             }
186             Bind(&next);
187             {
188                 Branch(Int32GreaterThanOrEqual(*pos, thisLen), &exit, &posNotGreaterLen);
189                 Bind(&posNotGreaterLen);
190                 {
191                     Branch(Int32LessThan(*pos, Int32(0)), &exit, &posNotLessZero);
192                     Bind(&posNotLessZero);
193                     {
194                         BuiltinsStringStubBuilder stringBuilder(this);
195                         res = IntToTaggedPtr(stringBuilder.StringAt(thisValue, *pos));
196                         Jump(&exit);
197                     }
198                 }
199             }
200         }
201     }
202     Bind(&slowPath);
203     {
204         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
205         Jump(&exit);
206     }
207     Bind(&exit);
208     Return(*res);
209 }
210 
DECLARE_BUILTINS(IndexOf)211 DECLARE_BUILTINS(IndexOf)
212 {
213     auto env = GetEnvironment();
214     DEFVARIABLE(res, VariableType::JS_ANY(), IntToTaggedPtr(Int32(-1)));
215     DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
216 
217     Label objNotUndefinedAndNull(env);
218     Label isString(env);
219     Label isSearchString(env);
220     Label slowPath(env);
221     Label next(env);
222     Label resPosGreaterZero(env);
223     Label searchTagIsHeapObject(env);
224     Label posTagNotUndefined(env);
225     Label posTagIsInt(env);
226     Label posTagNotInt(env);
227     Label exit(env);
228     Label posTagIsDouble(env);
229     Label nextCount(env);
230     Label posNotLessThanLen(env);
231     Label thisIsHeapobject(env);
232 
233     Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
234     Bind(&objNotUndefinedAndNull);
235     {
236         Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
237         Bind(&thisIsHeapobject);
238         Branch(IsString(thisValue), &isString, &slowPath);
239         Bind(&isString);
240         {
241             GateRef searchTag = GetCallArg0();
242             Branch(TaggedIsHeapObject(searchTag), &searchTagIsHeapObject, &slowPath);
243             Bind(&searchTagIsHeapObject);
244             Branch(IsString(searchTag), &isSearchString, &slowPath);
245             Bind(&isSearchString);
246             {
247                 GateRef thisLen = GetLengthFromString(thisValue);
248                 Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &next, &posTagNotUndefined);
249                 Bind(&posTagNotUndefined);
250                 {
251                     GateRef posTag = GetCallArg1();
252                     Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
253                     Bind(&posTagIsInt);
254                     pos = GetInt32OfTInt(posTag);
255                     Jump(&next);
256                     Bind(&posTagNotInt);
257                     Branch(TaggedIsDouble(posTag), &posTagIsDouble, &slowPath);
258                     Bind(&posTagIsDouble);
259                     pos = DoubleToInt(glue, GetDoubleOfTDouble(posTag));
260                     Jump(&next);
261                 }
262                 Bind(&next);
263                 {
264                     Label posGreaterThanZero(env);
265                     Label posNotGreaterThanZero(env);
266                     Branch(Int32GreaterThan(*pos, Int32(0)), &posGreaterThanZero, &posNotGreaterThanZero);
267                     Bind(&posNotGreaterThanZero);
268                     {
269                         pos = Int32(0);
270                         Jump(&nextCount);
271                     }
272                     Bind(&posGreaterThanZero);
273                     {
274                         Branch(Int32LessThanOrEqual(*pos, thisLen), &nextCount, &posNotLessThanLen);
275                         Bind(&posNotLessThanLen);
276                         {
277                             pos = thisLen;
278                             Jump(&nextCount);
279                         }
280                     }
281                     Bind(&nextCount);
282                     {
283                         BuiltinsStringStubBuilder stringBuilder(this);
284                         GateRef resPos = stringBuilder.StringIndexOf(thisValue, searchTag, *pos);
285                         Branch(Int32GreaterThanOrEqual(resPos, Int32(0)), &resPosGreaterZero, &exit);
286                         Bind(&resPosGreaterZero);
287                         {
288                             Label resPosLessZero(env);
289                             Branch(Int32LessThanOrEqual(resPos, thisLen), &resPosLessZero, &exit);
290                             Bind(&resPosLessZero);
291                             {
292                                 res = IntToTaggedPtr(resPos);
293                                 Jump(&exit);
294                             }
295                         }
296                     }
297                 }
298             }
299         }
300     }
301     Bind(&slowPath);
302     {
303         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
304         Jump(&exit);
305     }
306     Bind(&exit);
307     Return(*res);
308 }
309 
DECLARE_BUILTINS(Substring)310 DECLARE_BUILTINS(Substring)
311 {
312     auto env = GetEnvironment();
313     DEFVARIABLE(res, VariableType::JS_ANY(), IntToTaggedPtr(Int32(-1)));
314     DEFVARIABLE(start, VariableType::INT32(), Int32(0));
315     DEFVARIABLE(end, VariableType::INT32(), Int32(0));
316     DEFVARIABLE(from, VariableType::INT32(), Int32(0));
317     DEFVARIABLE(to, VariableType::INT32(), Int32(0));
318 
319     Label objNotUndefinedAndNull(env);
320     Label isString(env);
321     Label isSearchString(env);
322     Label slowPath(env);
323     Label countStart(env);
324     Label endTagIsUndefined(env);
325     Label startNotGreatZero(env);
326     Label countEnd(env);
327     Label endNotGreatZero(env);
328     Label countFrom(env);
329     Label countRes(env);
330     Label startTagNotUndefined(env);
331     Label posTagIsInt(env);
332     Label posTagNotInt(env);
333     Label exit(env);
334     Label posTagIsDouble(env);
335     Label endTagNotUndefined(env);
336     Label endTagIsInt(env);
337     Label endTagNotInt(env);
338     Label endTagIsDouble(env);
339     Label endGreatZero(env);
340     Label endGreatLen(env);
341     Label startGreatZero(env);
342     Label startGreatEnd(env);
343     Label startNotGreatEnd(env);
344     Label thisIsHeapobject(env);
345 
346     Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
347     Bind(&objNotUndefinedAndNull);
348     {
349         Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
350         Bind(&thisIsHeapobject);
351         Branch(IsString(thisValue), &isString, &slowPath);
352         Bind(&isString);
353         {
354             Label next(env);
355             GateRef thisLen = GetLengthFromString(thisValue);
356             Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &startTagNotUndefined);
357             Bind(&startTagNotUndefined);
358             {
359                 GateRef startTag = GetCallArg0();
360                 Branch(TaggedIsInt(startTag), &posTagIsInt, &posTagNotInt);
361                 Bind(&posTagIsInt);
362                 start = GetInt32OfTInt(startTag);
363                 Jump(&next);
364                 Bind(&posTagNotInt);
365                 Branch(TaggedIsDouble(startTag), &posTagIsDouble, &slowPath);
366                 Bind(&posTagIsDouble);
367                 start = DoubleToInt(glue, GetDoubleOfTDouble(startTag));
368                 Jump(&next);
369             }
370             Bind(&next);
371             {
372                 Branch(Int64GreaterThanOrEqual(IntPtr(1), numArgs), &endTagIsUndefined, &endTagNotUndefined);
373                 Bind(&endTagIsUndefined);
374                 {
375                     end = thisLen;
376                     Jump(&countStart);
377                 }
378                 Bind(&endTagNotUndefined);
379                 {
380                     GateRef endTag = GetCallArg1();
381                     Branch(TaggedIsInt(endTag), &endTagIsInt, &endTagNotInt);
382                     Bind(&endTagIsInt);
383                     end = GetInt32OfTInt(endTag);
384                     Jump(&countStart);
385                     Bind(&endTagNotInt);
386                     Branch(TaggedIsDouble(endTag), &endTagIsDouble, &slowPath);
387                     Bind(&endTagIsDouble);
388                     end = DoubleToInt(glue, GetDoubleOfTDouble(endTag));
389                     Jump(&countStart);
390                 }
391             }
392             Bind(&countStart);
393             {
394                 Label startGreatLen(env);
395                 Branch(Int32GreaterThan(*start, Int32(0)), &startGreatZero, &startNotGreatZero);
396                 Bind(&startNotGreatZero);
397                 {
398                     start = Int32(0);
399                     Jump(&countEnd);
400                 }
401                 Bind(&startGreatZero);
402                 {
403                     Branch(Int32GreaterThan(*start, thisLen), &startGreatLen, &countEnd);
404                     Bind(&startGreatLen);
405                     {
406                         start = thisLen;
407                         Jump(&countEnd);
408                     }
409                 }
410             }
411             Bind(&countEnd);
412             {
413                 Branch(Int32GreaterThan(*end, Int32(0)), &endGreatZero, &endNotGreatZero);
414                 Bind(&endNotGreatZero);
415                 {
416                     end = Int32(0);
417                     Jump(&countFrom);
418                 }
419                 Bind(&endGreatZero);
420                 {
421                     Branch(Int32GreaterThan(*end, thisLen), &endGreatLen, &countFrom);
422                     Bind(&endGreatLen);
423                     {
424                         end = thisLen;
425                         Jump(&countFrom);
426                     }
427                 }
428             }
429             Bind(&countFrom);
430             {
431                 Branch(Int32GreaterThan(*start, *end), &startGreatEnd, &startNotGreatEnd);
432                 Bind(&startGreatEnd);
433                 {
434                     from = *end;
435                     to = *start;
436                     Jump(&countRes);
437                 }
438                 Bind(&startNotGreatEnd);
439                 {
440                     from = *start;
441                     to = *end;
442                     Jump(&countRes);
443                 }
444             }
445             Bind(&countRes);
446             {
447                 BuiltinsStringStubBuilder stringBuilder(this);
448                 GateRef len = Int32Sub(*to, *from);
449                 Label isUtf8(env);
450                 Label isUtf16(env);
451                 Branch(IsUtf8String(thisValue), &isUtf8, &isUtf16);
452                 Bind(&isUtf8);
453                 {
454                     res = stringBuilder.FastSubUtf8String(glue, thisValue, *from, len);
455                     Jump(&exit);
456                 }
457                 Bind(&isUtf16);
458                 {
459                     res = stringBuilder.FastSubUtf16String(glue, thisValue, *from, len);
460                     Jump(&exit);
461                 }
462             }
463         }
464     }
465 
466     Bind(&slowPath);
467     {
468         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
469         Jump(&exit);
470     }
471     Bind(&exit);
472     Return(*res);
473 }
474 
DECLARE_BUILTINS(CharAt)475 DECLARE_BUILTINS(CharAt)
476 {
477     auto env = GetEnvironment();
478     DEFVARIABLE(res, VariableType::JS_POINTER(), Hole());
479     DEFVARIABLE(pos, VariableType::INT32(), Int32(0));
480 
481     Label objNotUndefinedAndNull(env);
482     Label isString(env);
483     Label slowPath(env);
484     Label next(env);
485     Label posTagNotUndefined(env);
486     Label posTagIsInt(env);
487     Label posTagNotInt(env);
488     Label posNotGreaterLen(env);
489     Label posGreaterLen(env);
490     Label posNotLessZero(env);
491     Label exit(env);
492     Label posTagIsDouble(env);
493     Label thisIsHeapobject(env);
494 
495     Branch(TaggedIsUndefinedOrNull(thisValue), &slowPath, &objNotUndefinedAndNull);
496     Bind(&objNotUndefinedAndNull);
497     {
498         Branch(TaggedIsHeapObject(thisValue), &thisIsHeapobject, &slowPath);
499         Bind(&thisIsHeapobject);
500         Branch(IsString(thisValue), &isString, &slowPath);
501         Bind(&isString);
502         {
503             GateRef thisLen = GetLengthFromString(thisValue);
504             Branch(Int64GreaterThanOrEqual(IntPtr(0), numArgs), &next, &posTagNotUndefined);
505             Bind(&posTagNotUndefined);
506             {
507                 GateRef posTag = GetCallArg0();
508                 Branch(TaggedIsInt(posTag), &posTagIsInt, &posTagNotInt);
509                 Bind(&posTagIsInt);
510                 pos = GetInt32OfTInt(posTag);
511                 Jump(&next);
512                 Bind(&posTagNotInt);
513                 Branch(TaggedIsDouble(posTag), &posTagIsDouble, &slowPath);
514                 Bind(&posTagIsDouble);
515                 pos = DoubleToInt(glue, GetDoubleOfTDouble(posTag));
516                 Jump(&next);
517             }
518             Bind(&next);
519             {
520                 Branch(Int32GreaterThanOrEqual(*pos, thisLen), &posGreaterLen, &posNotGreaterLen);
521                 Bind(&posNotGreaterLen);
522                 {
523                     Branch(Int32LessThan(*pos, Int32(0)), &posGreaterLen, &posNotLessZero);
524                     Bind(&posNotLessZero);
525                     {
526                         BuiltinsStringStubBuilder stringBuilder(this);
527                         res = stringBuilder.CreateFromEcmaString(glue, thisValue, *pos);
528                         Jump(&exit);
529                     }
530                 }
531                 Bind(&posGreaterLen);
532                 {
533                     res = GetGlobalConstantValue(
534                         VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
535                     Jump(&exit);
536                 }
537             }
538         }
539     }
540     Bind(&slowPath);
541     {
542         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
543         Jump(&exit);
544     }
545     Bind(&exit);
546     Return(*res);
547 }
548 
DECLARE_BUILTINS(VectorForEach)549 DECLARE_BUILTINS(VectorForEach)
550 {
551     auto env = GetEnvironment();
552     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
553 
554     Label exit(env);
555     Label slowPath(env);
556 
557     ContainersStubBuilder containersBuilder(this);
558     containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
559         &slowPath, ContainersType::VECTOR_FOREACH);
560     Bind(&slowPath);
561     {
562         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
563         Jump(&exit);
564     }
565     Bind(&exit);
566     Return(*res);
567 }
568 
DECLARE_BUILTINS(VectorReplaceAllElements)569 DECLARE_BUILTINS(VectorReplaceAllElements)
570 {
571     auto env = GetEnvironment();
572     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
573 
574     Label exit(env);
575     Label slowPath(env);
576 
577     ContainersStubBuilder containersBuilder(this);
578     containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
579         &slowPath, ContainersType::VECTOR_REPLACEALLELEMENTS);
580     Bind(&slowPath);
581     {
582         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
583         Jump(&exit);
584     }
585     Bind(&exit);
586     Return(*res);
587 }
588 
DECLARE_BUILTINS(StackForEach)589 DECLARE_BUILTINS(StackForEach)
590 {
591     auto env = GetEnvironment();
592     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
593 
594     Label exit(env);
595     Label slowPath(env);
596 
597     ContainersStubBuilder containersBuilder(this);
598     containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
599         &slowPath, ContainersType::STACK_FOREACH);
600     Bind(&slowPath);
601     {
602         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
603         Jump(&exit);
604     }
605     Bind(&exit);
606     Return(*res);
607 }
608 
DECLARE_BUILTINS(PlainArrayForEach)609 DECLARE_BUILTINS(PlainArrayForEach)
610 {
611     auto env = GetEnvironment();
612     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
613 
614     Label exit(env);
615     Label slowPath(env);
616 
617     ContainersStubBuilder containersBuilder(this);
618     containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
619         &slowPath, ContainersType::PLAINARRAY_FOREACH);
620     Bind(&slowPath);
621     {
622         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
623         Jump(&exit);
624     }
625     Bind(&exit);
626     Return(*res);
627 }
628 
DECLARE_BUILTINS(QueueForEach)629 DECLARE_BUILTINS(QueueForEach)
630 {
631     auto env = GetEnvironment();
632     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
633 
634     Label exit(env);
635     Label slowPath(env);
636 
637     ContainersStubBuilder containersBuilder(this);
638     containersBuilder.QueueCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
639         &slowPath, ContainersType::QUEUE_FOREACH);
640     Bind(&slowPath);
641     {
642         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
643         Jump(&exit);
644     }
645     Bind(&exit);
646     Return(*res);
647 }
648 
DECLARE_BUILTINS(DequeForEach)649 DECLARE_BUILTINS(DequeForEach)
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.DequeCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
659         &slowPath, ContainersType::DEQUE_FOREACH);
660     Bind(&slowPath);
661     {
662         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
663         Jump(&exit);
664     }
665     Bind(&exit);
666     Return(*res);
667 }
668 
DECLARE_BUILTINS(LightWeightMapForEach)669 DECLARE_BUILTINS(LightWeightMapForEach)
670 {
671     auto env = GetEnvironment();
672     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
673 
674     Label exit(env);
675     Label slowPath(env);
676 
677     ContainersStubBuilder containersBuilder(this);
678     containersBuilder.ContainersLightWeightCall(glue, thisValue, numArgs, &res, &exit,
679         &slowPath, ContainersType::LIGHTWEIGHTMAP_FOREACH);
680     Bind(&slowPath);
681     {
682         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
683         Jump(&exit);
684     }
685     Bind(&exit);
686     Return(*res);
687 }
688 
DECLARE_BUILTINS(LightWeightSetForEach)689 DECLARE_BUILTINS(LightWeightSetForEach)
690 {
691     auto env = GetEnvironment();
692     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
693 
694     Label exit(env);
695     Label slowPath(env);
696 
697     ContainersStubBuilder containersBuilder(this);
698     containersBuilder.ContainersLightWeightCall(glue, thisValue, numArgs, &res, &exit,
699         &slowPath, ContainersType::LIGHTWEIGHTSET_FOREACH);
700     Bind(&slowPath);
701     {
702         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
703         Jump(&exit);
704     }
705     Bind(&exit);
706     Return(*res);
707 }
708 
DECLARE_BUILTINS(HashMapForEach)709 DECLARE_BUILTINS(HashMapForEach)
710 {
711     auto env = GetEnvironment();
712     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
713 
714     Label exit(env);
715     Label slowPath(env);
716 
717     ContainersStubBuilder containersBuilder(this);
718     containersBuilder.ContainersHashCall(glue, thisValue, numArgs, &res, &exit,
719         &slowPath, ContainersType::HASHMAP_FOREACH);
720     Bind(&slowPath);
721     {
722         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
723         Jump(&exit);
724     }
725     Bind(&exit);
726     Return(*res);
727 }
728 
DECLARE_BUILTINS(HashSetForEach)729 DECLARE_BUILTINS(HashSetForEach)
730 {
731     auto env = GetEnvironment();
732     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
733 
734     Label exit(env);
735     Label slowPath(env);
736 
737     ContainersStubBuilder containersBuilder(this);
738     containersBuilder.ContainersHashCall(glue, thisValue, numArgs, &res, &exit,
739         &slowPath, ContainersType::HASHSET_FOREACH);
740     Bind(&slowPath);
741     {
742         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
743         Jump(&exit);
744     }
745     Bind(&exit);
746     Return(*res);
747 }
748 
DECLARE_BUILTINS(LinkedListForEach)749 DECLARE_BUILTINS(LinkedListForEach)
750 {
751     auto env = GetEnvironment();
752     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
753 
754     Label exit(env);
755     Label slowPath(env);
756 
757     ContainersStubBuilder containersBuilder(this);
758     containersBuilder.ContainersLinkedListCall(glue, thisValue, numArgs, &res, &exit,
759         &slowPath, ContainersType::LINKEDLIST_FOREACH);
760     Bind(&slowPath);
761     {
762         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
763         Jump(&exit);
764     }
765     Bind(&exit);
766     Return(*res);
767 }
768 
DECLARE_BUILTINS(ListForEach)769 DECLARE_BUILTINS(ListForEach)
770 {
771     auto env = GetEnvironment();
772     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
773 
774     Label exit(env);
775     Label slowPath(env);
776 
777     ContainersStubBuilder containersBuilder(this);
778     containersBuilder.ContainersLinkedListCall(glue, thisValue, numArgs, &res, &exit,
779         &slowPath, ContainersType::LIST_FOREACH);
780     Bind(&slowPath);
781     {
782         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
783         Jump(&exit);
784     }
785     Bind(&exit);
786     Return(*res);
787 }
788 
DECLARE_BUILTINS(ArrayListForEach)789 DECLARE_BUILTINS(ArrayListForEach)
790 {
791     auto env = GetEnvironment();
792     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
793 
794     Label exit(env);
795     Label slowPath(env);
796 
797     ContainersStubBuilder containersBuilder(this);
798     containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
799         &slowPath, ContainersType::ARRAYLIST_FOREACH);
800     Bind(&slowPath);
801     {
802         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
803         Jump(&exit);
804     }
805     Bind(&exit);
806     Return(*res);
807 }
808 
DECLARE_BUILTINS(ArrayListReplaceAllElements)809 DECLARE_BUILTINS(ArrayListReplaceAllElements)
810 {
811     auto env = GetEnvironment();
812     DEFVARIABLE(res, VariableType::JS_POINTER(), Undefined());
813 
814     Label exit(env);
815     Label slowPath(env);
816 
817     ContainersStubBuilder containersBuilder(this);
818     containersBuilder.ContainersCommonFuncCall(glue, thisValue, numArgs, &res, &exit,
819         &slowPath, ContainersType::ARRAYLIST_REPLACEALLELEMENTS);
820     Bind(&slowPath);
821     {
822         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);
823         Jump(&exit);
824     }
825     Bind(&exit);
826     Return(*res);
827 }
828 
DECLARE_BUILTINS(BooleanConstructor)829 DECLARE_BUILTINS(BooleanConstructor)
830 {
831     auto env = GetEnvironment();
832     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
833 
834     Label newTargetIsJSFunction(env);
835     Label slowPath(env);
836     Label exit(env);
837 
838     Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
839     Bind(&newTargetIsJSFunction);
840     {
841         Label intialHClassIsHClass(env);
842         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
843                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
844         Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath);
845         Bind(&intialHClassIsHClass);
846         {
847             NewObjectStubBuilder newBuilder(this);
848             newBuilder.SetParameters(glue, 0);
849             Label afterNew(env);
850             newBuilder.NewJSObject(&res, &afterNew, intialHClass);
851             Bind(&afterNew);
852             {
853                 GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
854                 GateRef value = GetArg(numArgs, IntPtr(0));
855                 Store(VariableType::INT64(), glue, *res, valueOffset, FastToBoolean(value));
856                 Jump(&exit);
857             }
858         }
859     }
860     Bind(&slowPath);
861     {
862         GateRef argv = GetArgv();
863         res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true);
864         Jump(&exit);
865     }
866     Bind(&exit);
867     Return(*res);
868 }
869 
DECLARE_BUILTINS(DateConstructor)870 DECLARE_BUILTINS(DateConstructor)
871 {
872     auto env = GetEnvironment();
873     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
874 
875     Label newTargetIsJSFunction(env);
876     Label slowPath(env);
877     Label exit(env);
878 
879     Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
880     Bind(&newTargetIsJSFunction);
881     {
882         Label intialHClassIsHClass(env);
883         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
884                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
885         Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath);
886         Bind(&intialHClassIsHClass);
887         {
888             Label oneArg(env);
889             Label notOneArg(env);
890             Label newJSDate(env);
891             DEFVARIABLE(timeValue, VariableType::FLOAT64(), Double(0));
892             Branch(Int64Equal(numArgs, IntPtr(1)), &oneArg, &notOneArg);
893             Bind(&oneArg);
894             {
895                 Label valueIsNumber(env);
896                 GateRef value = GetArgNCheck(IntPtr(0));
897                 Branch(TaggedIsNumber(value), &valueIsNumber, &slowPath);
898                 Bind(&valueIsNumber);
899                 {
900                     timeValue = CallNGCRuntime(glue, RTSTUB_ID(TimeClip), {GetDoubleOfTNumber(value)});
901                     Jump(&newJSDate);
902                 }
903             }
904             Bind(&notOneArg);
905             {
906                 Label threeArgs(env);
907                 Branch(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &slowPath);  // 3: year month day
908                 Bind(&threeArgs);
909                 {
910                     Label numberYearMonthDay(env);
911                     GateRef year = GetArgNCheck(IntPtr(0));
912                     GateRef month = GetArgNCheck(IntPtr(1));
913                     GateRef day = GetArgNCheck(IntPtr(2));
914                     Branch(IsNumberYearMonthDay(year, month, day), &numberYearMonthDay, &slowPath);
915                     Bind(&numberYearMonthDay);
916                     {
917                         GateRef y = GetDoubleOfTNumber(year);
918                         GateRef m = GetDoubleOfTNumber(month);
919                         GateRef d = GetDoubleOfTNumber(day);
920                         timeValue = CallNGCRuntime(glue, RTSTUB_ID(SetDateValues), {y, m, d});
921                         Jump(&newJSDate);
922                     }
923                 }
924             }
925             Bind(&newJSDate);
926             {
927                 NewObjectStubBuilder newBuilder(this);
928                 newBuilder.SetParameters(glue, 0);
929                 Label afterNew(env);
930                 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
931                 Bind(&afterNew);
932                 {
933                     GateRef timeValueOffset = IntPtr(JSDate::TIME_VALUE_OFFSET);
934                     Store(VariableType::JS_NOT_POINTER(), glue, *res, timeValueOffset,
935                           DoubleToTaggedDoublePtr(*timeValue));
936                     Jump(&exit);
937                 }
938             }
939         }
940     }
941     Bind(&slowPath);
942     {
943         GateRef argv = GetArgv();
944         res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true);
945         Jump(&exit);
946     }
947     Bind(&exit);
948     Return(*res);
949 }
950 
DECLARE_BUILTINS(ArrayConstructor)951 DECLARE_BUILTINS(ArrayConstructor)
952 {
953     auto env = GetEnvironment();
954     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
955 
956     Label newTargetIsJSFunction(env);
957     Label slowPath(env);
958     Label exit(env);
959 
960     Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
961     Bind(&newTargetIsJSFunction);
962     {
963         Label fastGetHclass(env);
964         Label intialHClassIsHClass(env);
965         GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
966         GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
967         auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
968         Branch(Equal(ChangeTaggedPointerToInt64(arrayFunc), ChangeTaggedPointerToInt64(newTarget)), &fastGetHclass,
969             &slowPath);
970         Bind(&fastGetHclass);
971         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
972         DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0));
973         Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath);
974         Bind(&intialHClassIsHClass);
975         {
976             Label noArg(env);
977             Label hasArg(env);
978             Label arrayCreate(env);
979             Branch(Int64Equal(numArgs, IntPtr(0)), &noArg, &hasArg);
980             Bind(&noArg);
981             {
982                 Jump(&arrayCreate);
983             }
984             Bind(&hasArg);
985             {
986                 Label hasOneArg(env);
987                 Branch(Int64Equal(numArgs, IntPtr(1)), &hasOneArg, &slowPath);
988                 Bind(&hasOneArg);
989                 {
990                     Label argIsNumber(env);
991                     GateRef arg0 = GetArg(numArgs, IntPtr(0));
992                     Branch(TaggedIsNumber(arg0), &argIsNumber, &slowPath);
993                     Bind(&argIsNumber);
994                     {
995                         Label argIsInt(env);
996                         Label argIsDouble(env);
997                         Branch(TaggedIsInt(arg0), &argIsInt, &argIsDouble);
998                         Bind(&argIsInt);
999                         {
1000                             Label validIntLength(env);
1001                             GateRef intLen = GetInt64OfTInt(arg0);
1002                             GateRef isGEZero = Int64GreaterThanOrEqual(intLen, Int64(0));
1003                             GateRef isLEMaxLen = Int64LessThanOrEqual(intLen, Int64(JSArray::MAX_ARRAY_INDEX));
1004                             Branch(BoolAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath);
1005                             Bind(&validIntLength);
1006                             {
1007                                 arrayLength = intLen;
1008                                 Jump(&arrayCreate);
1009                             }
1010                         }
1011                         Bind(&argIsDouble);
1012                         {
1013                             Label validDoubleLength(env);
1014                             GateRef doubleLength = GetDoubleOfTDouble(arg0);
1015                             GateRef doubleToInt = DoubleToInt(glue, doubleLength);
1016                             GateRef intToDouble = CastInt64ToFloat64(SExtInt32ToInt64(doubleToInt));
1017                             GateRef doubleEqual = DoubleEqual(doubleLength, intToDouble);
1018                             GateRef doubleLEMaxLen =
1019                                 DoubleLessThanOrEqual(doubleLength, Double(JSArray::MAX_ARRAY_INDEX));
1020                             Branch(BoolAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath);
1021                             Bind(&validDoubleLength);
1022                             {
1023                                 arrayLength = SExtInt32ToInt64(doubleToInt);
1024                                 Jump(&arrayCreate);
1025                             }
1026                         }
1027                     }
1028                 }
1029             }
1030             Bind(&arrayCreate);
1031             {
1032                 NewObjectStubBuilder newBuilder(this);
1033                 newBuilder.SetParameters(glue, 0);
1034                 Label afterNew(env);
1035                 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
1036                 Bind(&afterNew);
1037                 {
1038                     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
1039                     Store(VariableType::JS_ANY(), glue, *res, lengthOffset, Int64ToTaggedInt(*arrayLength));
1040                     GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
1041                                                               ConstantIndex::ARRAY_LENGTH_ACCESSOR);
1042                     SetPropertyInlinedProps(glue, *res, intialHClass, accessor,
1043                                             Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
1044                     SetExtensibleToBitfield(glue, *res, true);
1045                     Jump(&exit);
1046                 }
1047             }
1048         }
1049     }
1050     Bind(&slowPath);
1051     {
1052         GateRef argv = GetArgv();
1053         res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true);
1054         Jump(&exit);
1055     }
1056 
1057     Bind(&exit);
1058     Return(*res);
1059 }
1060 }  // namespace panda::ecmascript::kungfu