1/*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/compiler/builtins/builtins_stubs.h"
17
18#include "ecmascript/base/number_helper.h"
19#include "ecmascript/compiler/builtins/builtins_array_stub_builder.h"
20#include "ecmascript/compiler/builtins/builtins_call_signature.h"
21#include "ecmascript/compiler/builtins/builtins_dataview_stub_builder.h"
22#include "ecmascript/compiler/builtins/builtins_function_stub_builder.h"
23#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
24#include "ecmascript/compiler/builtins/builtins_regexp_stub_builder.h"
25#include "ecmascript/compiler/builtins/builtins_number_stub_builder.h"
26#include "ecmascript/compiler/builtins/builtins_proxy_stub_builder.h"
27#include "ecmascript/compiler/builtins/builtins_reflect_stub_builder.h"
28#include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
29#include "ecmascript/compiler/builtins/containers_vector_stub_builder.h"
30#include "ecmascript/compiler/builtins/containers_stub_builder.h"
31#include "ecmascript/compiler/builtins/builtins_collator_stub_builder.h"
32#include "ecmascript/compiler/builtins/builtins_collection_stub_builder.h"
33#include "ecmascript/compiler/builtins/builtins_object_stub_builder.h"
34#include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h"
35#include "ecmascript/compiler/interpreter_stub-inl.h"
36#include "ecmascript/compiler/new_object_stub_builder.h"
37#include "ecmascript/compiler/stub_builder-inl.h"
38#include "ecmascript/compiler/stub_builder.h"
39#include "ecmascript/compiler/hash_stub_builder.h"
40#include "ecmascript/compiler/variable_type.h"
41#include "ecmascript/js_dataview.h"
42#include "ecmascript/js_date.h"
43#include "ecmascript/js_primitive_ref.h"
44#include "ecmascript/linked_hash_table.h"
45#include "ecmascript/js_set.h"
46#include "ecmascript/js_map.h"
47
48namespace panda::ecmascript::kungfu {
49#if ECMASCRIPT_ENABLE_BUILTIN_LOG
50#define DECLARE_BUILTINS(name)                                                                      \
51void name##StubBuilder::GenerateCircuit()                                                           \
52{                                                                                                   \
53    GateRef glue = PtrArgument(static_cast<size_t>(BuiltinsArgs::GLUE));                            \
54    GateRef nativeCode = PtrArgument(static_cast<size_t>(BuiltinsArgs::NATIVECODE));                \
55    GateRef func = TaggedArgument(static_cast<size_t>(BuiltinsArgs::FUNC));                         \
56    GateRef newTarget = TaggedArgument(static_cast<size_t>(BuiltinsArgs::NEWTARGET));               \
57    GateRef thisValue = TaggedArgument(static_cast<size_t>(BuiltinsArgs::THISVALUE));               \
58    GateRef numArgs = PtrArgument(static_cast<size_t>(BuiltinsArgs::NUMARGS));                      \
59    DebugPrint(glue, { Int32(GET_MESSAGE_STRING_ID(name)) });                                       \
60    GenerateCircuitImpl(glue, nativeCode, func, newTarget, thisValue, numArgs);                     \
61}                                                                                                   \
62void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func,         \
63                                            GateRef newTarget, GateRef thisValue, GateRef numArgs)
64#else
65#ifndef NDEBUG
66#define DECLARE_BUILTINS(name)                                                                      \
67void name##StubBuilder::GenerateCircuit()                                                           \
68{                                                                                                   \
69    GateRef glue = PtrArgument(static_cast<size_t>(BuiltinsArgs::GLUE));                            \
70    GateRef nativeCode = PtrArgument(static_cast<size_t>(BuiltinsArgs::NATIVECODE));                \
71    GateRef func = TaggedArgument(static_cast<size_t>(BuiltinsArgs::FUNC));                         \
72    GateRef newTarget = TaggedArgument(static_cast<size_t>(BuiltinsArgs::NEWTARGET));               \
73    GateRef thisValue = TaggedArgument(static_cast<size_t>(BuiltinsArgs::THISVALUE));               \
74    GateRef numArgs = PtrArgument(static_cast<size_t>(BuiltinsArgs::NUMARGS));                      \
75    CallRuntime(glue, RTSTUB_ID(ForceGC), {});                                                      \
76    GenerateCircuitImpl(glue, nativeCode, func, newTarget, thisValue, numArgs);                     \
77}                                                                                                   \
78void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func,         \
79                                            GateRef newTarget, GateRef thisValue, GateRef numArgs)
80#else
81#define DECLARE_BUILTINS(name)                                                                      \
82void name##StubBuilder::GenerateCircuit()                                                           \
83{                                                                                                   \
84    GateRef glue = PtrArgument(static_cast<size_t>(BuiltinsArgs::GLUE));                            \
85    GateRef nativeCode = PtrArgument(static_cast<size_t>(BuiltinsArgs::NATIVECODE));                \
86    GateRef func = TaggedArgument(static_cast<size_t>(BuiltinsArgs::FUNC));                         \
87    GateRef newTarget = TaggedArgument(static_cast<size_t>(BuiltinsArgs::NEWTARGET));               \
88    GateRef thisValue = TaggedArgument(static_cast<size_t>(BuiltinsArgs::THISVALUE));               \
89    GateRef numArgs = PtrArgument(static_cast<size_t>(BuiltinsArgs::NUMARGS));                      \
90    GenerateCircuitImpl(glue, nativeCode, func, newTarget, thisValue, numArgs);                     \
91}                                                                                                   \
92void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func,         \
93                                            GateRef newTarget, GateRef thisValue, GateRef numArgs)
94#endif
95#endif
96
97GateRef BuiltinsStubBuilder::GetCallArg0(GateRef numArg)
98{
99    auto env = GetEnvironment();
100    Label subentry(env);
101    env->SubCfgEntry(&subentry);
102    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
103    Label isValid(env);
104    Label exit(env);
105    BRANCH(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(0)), &isValid, &exit);
106    Bind(&isValid);
107    {
108        result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG0_OR_ARGV));
109        Jump(&exit);
110    }
111    Bind(&exit);
112    auto res = *result;
113    env->SubCfgExit();
114    return res;
115}
116
117GateRef BuiltinsStubBuilder::GetCallArg1(GateRef numArg)
118{
119    auto env = GetEnvironment();
120    Label subentry(env);
121    env->SubCfgEntry(&subentry);
122    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
123    Label isValid(env);
124    Label exit(env);
125    BRANCH(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(1)), &isValid, &exit);
126    Bind(&isValid);
127    {
128        result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG1));
129        Jump(&exit);
130    }
131    Bind(&exit);
132    auto res = *result;
133    env->SubCfgExit();
134    return res;
135}
136
137GateRef BuiltinsStubBuilder::GetCallArg2(GateRef numArg)
138{
139    auto env = GetEnvironment();
140    Label subentry(env);
141    env->SubCfgEntry(&subentry);
142    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
143    Label isValid(env);
144    Label exit(env);
145    // 2: 2 args
146    BRANCH(Int32GreaterThan(TruncPtrToInt32(numArg), Int32(2)), &isValid, &exit);
147    Bind(&isValid);
148    {
149        result = TaggedArgument(static_cast<size_t>(BuiltinsArgs::ARG2));
150        Jump(&exit);
151    }
152    Bind(&exit);
153    auto res = *result;
154    env->SubCfgExit();
155    return res;
156}
157
158GateRef BuiltinsStubBuilder::GetArgFromArgv(GateRef index, GateRef numArgs, bool needCheck)
159{
160    if (!needCheck) {
161        GateRef argv = GetArgv();
162        return Load(VariableType::JS_ANY(), argv, PtrMul(index, IntPtr(JSTaggedValue::TaggedTypeSize())));
163    }
164    auto env = GetEnvironment();
165    Label entry(env);
166    env->SubCfgEntry(&entry);
167    DEFVARIABLE(arg, VariableType::JS_ANY(), Undefined());
168    Label validIndex(env);
169    Label exit(env);
170    BRANCH(IntPtrGreaterThan(numArgs, index), &validIndex, &exit);
171    Bind(&validIndex);
172    {
173        GateRef argv = GetArgv();
174        arg = Load(VariableType::JS_ANY(), argv, PtrMul(index, IntPtr(JSTaggedValue::TaggedTypeSize())));
175        Jump(&exit);
176    }
177    Bind(&exit);
178    GateRef ret = *arg;
179    env->SubCfgExit();
180    return ret;
181}
182
183GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, GateRef thisValue,
184                                          GateRef numArgs, GateRef func, GateRef newTarget)
185{
186    auto env = GetEnvironment();
187    Label entry(env);
188    env->SubCfgEntry(&entry);
189    Label exit(env);
190    Label callThis0(env);
191    Label notcallThis0(env);
192    Label notcallThis1(env);
193    Label callThis1(env);
194    Label callThis2(env);
195    Label callThis3(env);
196    DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
197    GateRef runtimeCallInfoArgs = PtrAdd(numArgs, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
198    BRANCH(Int64Equal(numArgs, IntPtr(0)), &callThis0, &notcallThis0);
199    Bind(&callThis0);
200    {
201        auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue };
202        result = CallBuiltinRuntime(glue, args, false);
203        Jump(&exit);
204    }
205    Bind(&notcallThis0);
206    {
207        BRANCH(Int64Equal(numArgs, IntPtr(1)), &callThis1, &notcallThis1);
208        Bind(&callThis1);
209        {
210            GateRef arg0 = GetCallArg0(numArgs);
211            auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0 };
212            result = CallBuiltinRuntime(glue, args, false);
213            Jump(&exit);
214        }
215        Bind(&notcallThis1);
216        {
217            BRANCH(Int64Equal(numArgs, IntPtr(2)), &callThis2, &callThis3); // 2: args2
218            Bind(&callThis2);
219            {
220                GateRef arg0 = GetCallArg0(numArgs);
221                GateRef arg1 = GetCallArg1(numArgs);
222                auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1 };
223                result = CallBuiltinRuntime(glue, args, false);
224                Jump(&exit);
225            }
226            Bind(&callThis3);
227            {
228                GateRef arg0 = GetCallArg0(numArgs);
229                GateRef arg1 = GetCallArg1(numArgs);
230                GateRef arg2 = GetCallArg2(numArgs);
231                auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1, arg2 };
232                result = CallBuiltinRuntime(glue, args, false);
233                Jump(&exit);
234            }
235        }
236    }
237
238    Bind(&exit);
239    auto ret = *result;
240    env->SubCfgExit();
241    return ret;
242}
243
244#define DECLARE_BUILTINS_STUB_BUILDER(method, type, initValue)                                      \
245DECLARE_BUILTINS(type##method)                                                                      \
246{                                                                                                   \
247    auto env = GetEnvironment();                                                                    \
248    DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
249    Label exit(env);                                                                                \
250    Label slowPath(env);                                                                            \
251    Builtins##type##StubBuilder builder(this);                                                      \
252    builder.method(glue, thisValue, numArgs, &res, &exit, &slowPath);                               \
253    Bind(&slowPath);                                                                                \
254    {                                                                                               \
255        res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);                  \
256        Jump(&exit);                                                                                \
257    }                                                                                               \
258    Bind(&exit);                                                                                    \
259    Return(*res);                                                                                   \
260}
261
262#define DECLARE_BUILTINS_STUB_BUILDER1(method, type, initValue)                                     \
263DECLARE_BUILTINS(type##method)                                                                      \
264{                                                                                                   \
265    auto env = GetEnvironment();                                                                    \
266    DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
267    Label thisCollectionObj(env);                                                                   \
268    Label slowPath(env);                                                                            \
269    Label exit(env);                                                                                \
270    Builtins##type##StubBuilder builder(this, glue, thisValue, numArgs);                            \
271    builder.method(&res, &exit, &slowPath);                                                         \
272    Bind(&slowPath);                                                                                \
273    {                                                                                               \
274        res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);                  \
275        Jump(&exit);                                                                                \
276    }                                                                                               \
277    Bind(&exit);                                                                                    \
278    Return(*res);                                                                                   \
279}
280
281// map and set stub function
282#define DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(method, type, retDefaultValue)                     \
283DECLARE_BUILTINS(type##method)                                                                      \
284{                                                                                                   \
285    auto env = GetEnvironment();                                                                    \
286    DEFVARIABLE(res, VariableType::JS_ANY(), retDefaultValue);                                      \
287    Label slowPath(env);                                                                            \
288    Label exit(env);                                                                                \
289    BuiltinsCollectionStubBuilder<JS##type> builder(this, glue, thisValue, numArgs);                \
290    builder.method(&res, &exit, &slowPath);                                                         \
291    Bind(&slowPath);                                                                                \
292    {                                                                                               \
293        res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);                  \
294        Jump(&exit);                                                                                \
295    }                                                                                               \
296    Bind(&exit);                                                                                    \
297    Return(*res);                                                                                   \
298}
299
300// map and set stub function
301#define DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER(method, type, numType, function, retDefaultValue)    \
302DECLARE_BUILTINS(type##method)                                                                      \
303{                                                                                                   \
304    auto env = GetEnvironment();                                                                    \
305    DEFVARIABLE(res, VariableType::JS_ANY(), retDefaultValue);                                      \
306    Label slowPath(env);                                                                            \
307    Label exit(env);                                                                                \
308    BuiltinsDataViewStubBuilder builder(this);                                                      \
309    builder.function<DataViewType::numType>(glue, thisValue, numArgs, &res, &exit, &slowPath);      \
310    Bind(&slowPath);                                                                                \
311    {                                                                                               \
312        auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(type##method));                    \
313        res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);                  \
314        Jump(&exit);                                                                                \
315    }                                                                                               \
316    Bind(&exit);                                                                                    \
317    Return(*res);                                                                                   \
318}
319
320BUILTINS_METHOD_STUB_LIST(DECLARE_BUILTINS_STUB_BUILDER, DECLARE_BUILTINS_STUB_BUILDER1,
321                          DECLARE_BUILTINS_COLLECTION_STUB_BUILDER, DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER)
322#undef DECLARE_BUILTINS_STUB_BUILDER
323#undef DECLARE_BUILTINS_STUB_BUILDER1
324#undef DECLARE_BUILTINS_COLLECTION_STUB_BUILDER
325#undef DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER
326
327DECLARE_BUILTINS(ArkToolsHashCode)
328{
329    (void) nativeCode;
330    (void) func;
331    (void) newTarget;
332    (void) thisValue;
333    auto env = GetEnvironment();
334    GateRef key = GetCallArg0(numArgs);
335
336    Label irHash(env);
337    Label rtHash(env);
338    BRANCH(IntPtrEqual(numArgs, IntPtr(1)), &irHash, &rtHash);
339    Bind(&irHash);
340    {
341        HashStubBuilder hashBuilder(this, glue);
342        GateRef hash = hashBuilder.GetHash(key);
343        Return(env->GetBuilder()->Int32ToTaggedPtr(hash));
344    }
345    Bind(&rtHash);
346    Return(CallRuntime(glue, RTSTUB_ID(GetLinkedHash), { key }));
347}
348
349// aot and builtins public stub function
350#define DECLARE_AOT_AND_BUILTINS_STUB_BUILDER(stubName, method, type, initValue)                    \
351DECLARE_BUILTINS(stubName)                                                                          \
352{                                                                                                   \
353    auto env = GetEnvironment();                                                                    \
354    DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
355    Label exit(env);                                                                                \
356    Label slowPath(env);                                                                            \
357    Builtins##type##StubBuilder builder(this);                                                      \
358    builder.method(glue, thisValue, numArgs, &res, &exit, &slowPath);                               \
359    Bind(&slowPath);                                                                                \
360    {                                                                                               \
361        res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);                  \
362        Jump(&exit);                                                                                \
363    }                                                                                               \
364    Bind(&exit);                                                                                    \
365    Return(*res);                                                                                   \
366}
367
368#define AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V)                                                 \
369    V(StringLocaleCompare,              LocaleCompare,      String, Undefined())                  \
370    V(StringIteratorProtoNext,  StringIteratorNext, String, Undefined())                          \
371    V(ArraySort,           Sort,               Array,  Undefined())
372
373AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(DECLARE_AOT_AND_BUILTINS_STUB_BUILDER)
374#undef AOT_AND_BUILTINS_STUB_LIST
375#undef DECLARE_AOT_AND_BUILTINS_STUB_BUILDER
376
377// containers stub function
378#define DECLARE_BUILTINS_WITH_CONTAINERS_STUB_BUILDER(funcName, type, method, methodType, resultVariableType)   \
379DECLARE_BUILTINS(type##funcName)                                                                                \
380{                                                                                                               \
381    auto env = GetEnvironment();                                                                                \
382    DEFVARIABLE(res, VariableType::resultVariableType(), Undefined());                                          \
383    Label exit(env);                                                                                            \
384    Label slowPath(env);                                                                                        \
385    ContainersStubBuilder containersBuilder(this);                                                              \
386    containersBuilder.method(glue, thisValue, numArgs, &res, &exit, &slowPath, ContainersType::methodType);     \
387    Bind(&slowPath);                                                                                            \
388    {                                                                                                           \
389        res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);                              \
390        Jump(&exit);                                                                                            \
391    }                                                                                                           \
392    Bind(&exit);                                                                                                \
393    Return(*res);                                                                                               \
394}
395
396BUILTINS_WITH_CONTAINERS_STUB_BUILDER(DECLARE_BUILTINS_WITH_CONTAINERS_STUB_BUILDER)
397#undef DECLARE_BUILTINS_WITH_CONTAINERS_STUB_BUILDER
398
399DECLARE_BUILTINS(BooleanConstructor)
400{
401    auto env = GetEnvironment();
402    DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
403
404    Label newTargetIsHeapObject(env);
405    Label newTargetIsJSFunction(env);
406    Label slowPath(env);
407    Label slowPath1(env);
408    Label exit(env);
409
410    BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
411    Bind(&newTargetIsHeapObject);
412    BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
413    Bind(&newTargetIsJSFunction);
414    {
415        Label intialHClassIsHClass(env);
416        GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
417                                    IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
418        BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1);
419        Bind(&intialHClassIsHClass);
420        {
421            NewObjectStubBuilder newBuilder(this);
422            newBuilder.SetParameters(glue, 0);
423            Label afterNew(env);
424            newBuilder.NewJSObject(&res, &afterNew, intialHClass);
425            Bind(&afterNew);
426            {
427                GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
428                GateRef value = GetArgFromArgv(IntPtr(0), numArgs, true);
429                Store(VariableType::INT64(), glue, *res, valueOffset, FastToBoolean(value));
430                Jump(&exit);
431            }
432        }
433        Bind(&slowPath1);
434        {
435            GateRef argv = GetArgv();
436            auto args = { glue, nativeCode, func, thisValue, numArgs, argv, newTarget };
437            res = CallBuiltinRuntimeWithNewTarget(glue, args);
438            Jump(&exit);
439        }
440    }
441    Bind(&slowPath);
442    {
443        GateRef argv = GetArgv();
444        auto args = { glue, nativeCode, func, thisValue, numArgs, argv };
445        res = CallBuiltinRuntime(glue, args, true);
446        Jump(&exit);
447    }
448    Bind(&exit);
449    Return(*res);
450}
451
452DECLARE_BUILTINS(DateConstructor)
453{
454    auto env = GetEnvironment();
455    DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
456
457    Label newTargetIsHeapObject(env);
458    Label newTargetIsJSFunction(env);
459    Label slowPath(env);
460    Label slowPath1(env);
461    Label exit(env);
462
463    BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
464    Bind(&newTargetIsHeapObject);
465    BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
466    Bind(&newTargetIsJSFunction);
467    {
468        Label intialHClassIsHClass(env);
469        GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
470                                    IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
471        BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1);
472        Bind(&intialHClassIsHClass);
473        {
474            Label oneArg(env);
475            Label notOneArg(env);
476            Label newJSDate(env);
477            DEFVARIABLE(timeValue, VariableType::FLOAT64(), Double(0));
478            BRANCH(Int64Equal(numArgs, IntPtr(1)), &oneArg, &notOneArg);
479            Bind(&oneArg);
480            {
481                Label valueIsNumber(env);
482                GateRef value = GetArgFromArgv(IntPtr(0));
483                BRANCH(TaggedIsNumber(value), &valueIsNumber, &slowPath);
484                Bind(&valueIsNumber);
485                {
486                    timeValue = CallNGCRuntime(glue, RTSTUB_ID(TimeClip), {GetDoubleOfTNumber(value)});
487                    Jump(&newJSDate);
488                }
489            }
490            Bind(&notOneArg);
491            {
492                Label threeArgs(env);
493                BRANCH(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &slowPath);  // 3: year month day
494                Bind(&threeArgs);
495                {
496                    Label numberYearMonthDay(env);
497                    GateRef year = GetArgFromArgv(IntPtr(0));
498                    GateRef month = GetArgFromArgv(IntPtr(1));
499                    GateRef day = GetArgFromArgv(IntPtr(2));
500                    BRANCH(IsNumberYearMonthDay(year, month, day), &numberYearMonthDay, &slowPath);
501                    Bind(&numberYearMonthDay);
502                    {
503                        GateRef y = GetDoubleOfTNumber(year);
504                        GateRef m = GetDoubleOfTNumber(month);
505                        GateRef d = GetDoubleOfTNumber(day);
506                        timeValue = CallNGCRuntime(glue, RTSTUB_ID(SetDateValues), {y, m, d});
507                        Jump(&newJSDate);
508                    }
509                }
510            }
511            Bind(&newJSDate);
512            {
513                NewObjectStubBuilder newBuilder(this);
514                newBuilder.SetParameters(glue, 0);
515                Label afterNew(env);
516                newBuilder.NewJSObject(&res, &afterNew, intialHClass);
517                Bind(&afterNew);
518                {
519                    GateRef timeValueOffset = IntPtr(JSDate::TIME_VALUE_OFFSET);
520                    Store(VariableType::JS_NOT_POINTER(), glue, *res, timeValueOffset,
521                          DoubleToTaggedDoublePtr(*timeValue));
522                    Jump(&exit);
523                }
524            }
525        }
526        Bind(&slowPath1);
527        {
528            GateRef argv = GetArgv();
529            res = CallBuiltinRuntimeWithNewTarget(glue,
530                { glue, nativeCode, func, thisValue, numArgs, argv, newTarget });
531            Jump(&exit);
532        }
533    }
534    Bind(&slowPath);
535    {
536        GateRef argv = GetArgv();
537        res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true);
538        Jump(&exit);
539    }
540    Bind(&exit);
541    Return(*res);
542}
543
544DECLARE_BUILTINS(NumberConstructor)
545{
546    BuiltinsNumberStubBuilder builder(this, glue, thisValue, numArgs);
547    builder.GenNumberConstructor(nativeCode, func, newTarget);
548}
549
550DECLARE_BUILTINS(ProxyConstructor)
551{
552    BuiltinsProxyStubBuilder builder(this, glue, thisValue, numArgs);
553    builder.GenProxyConstructor(nativeCode, func, newTarget);
554}
555
556DECLARE_BUILTINS(ArrayConstructor)
557{
558    BuiltinsArrayStubBuilder builder(this);
559    builder.GenArrayConstructor(glue, nativeCode, func, newTarget, thisValue, numArgs);
560}
561
562DECLARE_BUILTINS(MapConstructor)
563{
564    LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> hashTableBuilder(this, glue);
565    GateRef arg0 = GetArgFromArgv(IntPtr(0), numArgs, true);
566    hashTableBuilder.GenMapSetConstructor(nativeCode, func, newTarget, thisValue, numArgs, arg0, GetArgv());
567}
568
569DECLARE_BUILTINS(SetConstructor)
570{
571    LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> hashTableBuilder(this, glue);
572    GateRef arg0 = GetArgFromArgv(IntPtr(0), numArgs, true);
573    hashTableBuilder.GenMapSetConstructor(nativeCode, func, newTarget, thisValue, numArgs, arg0, GetArgv());
574}
575
576#define DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER(TYPE, type, index)                                \
577DECLARE_BUILTINS(type##ArrayConstructor)                                                            \
578{                                                                                                   \
579    GateRef ctorName = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,                     \
580                                              ConstantIndex::TYPE##_ARRAY_STRING_INDEX);            \
581    BuiltinsTypedArrayStubBuilder builtinsTypedArrayStubBuilder(this);                              \
582    builtinsTypedArrayStubBuilder.GenTypedArrayConstructor(glue, nativeCode, func, newTarget,       \
583        thisValue, numArgs, ctorName, DataViewType::TYPE);                                          \
584}
585BUILTIN_COMPILER_TYPED_ARRAY_TYPES(DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER)
586#undef DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER
587}  // namespace panda::ecmascript::kungfu
588