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