• 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/compiler/builtins/builtins_array_stub_builder.h"
19 #include "ecmascript/compiler/builtins/builtins_dataview_stub_builder.h"
20 #include "ecmascript/compiler/builtins/builtins_function_stub_builder.h"
21 #include "ecmascript/compiler/builtins/builtins_regexp_stub_builder.h"
22 #include "ecmascript/compiler/builtins/builtins_number_stub_builder.h"
23 #include "ecmascript/compiler/builtins/builtins_proxy_stub_builder.h"
24 #include "ecmascript/compiler/builtins/builtins_reflect_stub_builder.h"
25 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
26 #include "ecmascript/compiler/builtins/containers_arraylist_stub_builder.h"
27 #include "ecmascript/compiler/builtins/containers_deque_stub_builder.h"
28 #include "ecmascript/compiler/builtins/containers_hashmap_stub_builder.h"
29 #include "ecmascript/compiler/builtins/containers_hashset_stub_builder.h"
30 #include "ecmascript/compiler/builtins/containers_lightweightmap_stub_builder.h"
31 #include "ecmascript/compiler/builtins/containers_lightweightset_stub_builder.h"
32 #include "ecmascript/compiler/builtins/containers_linkedlist_stub_builder.h"
33 #include "ecmascript/compiler/builtins/containers_list_stub_builder.h"
34 #include "ecmascript/compiler/builtins/containers_plainarray_stub_builder.h"
35 #include "ecmascript/compiler/builtins/containers_queue_stub_builder.h"
36 #include "ecmascript/compiler/builtins/containers_stack_stub_builder.h"
37 #include "ecmascript/compiler/builtins/containers_vector_stub_builder.h"
38 #include "ecmascript/compiler/builtins/builtins_collator_stub_builder.h"
39 #include "ecmascript/compiler/builtins/builtins_collection_iterator_stub_builder.h"
40 #include "ecmascript/compiler/builtins/builtins_collection_stub_builder.h"
41 #include "ecmascript/compiler/builtins/builtins_object_stub_builder.h"
42 #include "ecmascript/compiler/new_object_stub_builder.h"
43 #include "ecmascript/compiler/hash_stub_builder.h"
44 #include "ecmascript/js_date.h"
45 #include "ecmascript/js_primitive_ref.h"
46 #include "ecmascript/linked_hash_table.h"
47 
48 namespace panda::ecmascript::kungfu {
49 #if ECMASCRIPT_ENABLE_BUILTIN_LOG
50 #define DECLARE_BUILTINS(name)                                                                      \
51 void 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 }                                                                                                   \
62 void 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)                                                                      \
67 void 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 }                                                                                                   \
78 void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func,         \
79                                             GateRef newTarget, GateRef thisValue, GateRef numArgs)
80 #else
81 #define DECLARE_BUILTINS(name)                                                                      \
82 void 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 }                                                                                                   \
92 void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func,         \
93                                             GateRef newTarget, GateRef thisValue, GateRef numArgs)
94 #endif
95 #endif
96 
GetCallArg0(GateRef numArg)97 GateRef 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 
GetCallArg1(GateRef numArg)117 GateRef 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 
GetCallArg2(GateRef numArg)137 GateRef 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 
GetArgFromArgv(GateRef index,GateRef numArgs,bool needCheck)158 GateRef 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 
CallSlowPath(GateRef nativeCode,GateRef glue,GateRef thisValue,GateRef numArgs,GateRef func,GateRef newTarget)183 GateRef 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, ...)                                 \
245 DECLARE_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, ...)                                \
263 DECLARE_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, ...)                \
283 DECLARE_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, ...) \
302 DECLARE_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 
BUILTINS_METHOD_STUB_LIST(DECLARE_BUILTINS_STUB_BUILDER,DECLARE_BUILTINS_STUB_BUILDER1,DECLARE_BUILTINS_COLLECTION_STUB_BUILDER,DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER)320 BUILTINS_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 
327 DECLARE_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)                    \
351 DECLARE_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 // map and set iterator stub function
369 #define DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER(stubName, method, type, retDefaultValue)             \
370 DECLARE_BUILTINS(stubName)                                                                                     \
371 {                                                                                                              \
372     (void) nativeCode;                                                                                         \
373     (void) func;                                                                                               \
374     (void) newTarget;                                                                                          \
375     auto env = GetEnvironment();                                                                               \
376     DEFVARIABLE(res, VariableType::JS_ANY(), retDefaultValue);                                                 \
377     Label exit(env);                                                                                           \
378     BuiltinsCollectionIteratorStubBuilder<JS##type> builder(this, glue, thisValue, numArgs);                   \
379     builder.method(&res, &exit);                                                                               \
380     Bind(&exit);                                                                                               \
381     Return(*res);                                                                                              \
382 }
383 
384 #if ENABLE_NEXT_OPTIMIZATION
385     #define NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)                                        \
386         V(ArrayIteratorProtoNext,  ArrayIteratorNext,   Array,            Undefined())               \
387         D(MapIteratorProtoNext,    Next,                MapIterator,      Undefined())               \
388         D(SetIteratorProtoNext,    Next,                SetIterator,      Undefined())
389 #else
390     #define NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)
391 #endif
392 
393 #define AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)                                              \
394     V(StringLocaleCompare,           LocaleCompare,        String,   Undefined())                 \
395     V(StringIteratorProtoNext,       StringIteratorNext,   String,   Undefined())                 \
396     V(ArraySort,                     Sort,                 Array,    Undefined())                 \
397     NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)
398 
AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(DECLARE_AOT_AND_BUILTINS_STUB_BUILDER,DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER)399 AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(DECLARE_AOT_AND_BUILTINS_STUB_BUILDER,
400                                        DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER)
401 #undef NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD
402 #undef AOT_AND_BUILTINS_STUB_LIST
403 #undef DECLARE_AOT_AND_BUILTINS_STUB_BUILDER
404 #undef DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER
405 
406 #define DECLARE_CONTAINERS_STUB_BUILDER(method, type, initValue)                                    \
407 DECLARE_BUILTINS(type##method)                                                                      \
408 {                                                                                                   \
409     auto env = GetEnvironment();                                                                    \
410     DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
411     Label exit(env);                                                                                \
412     Label slowPath(env);                                                                            \
413     Containers##type##StubBuilder builder(this);                                                      \
414     builder.method(glue, thisValue, numArgs, &res, &exit, &slowPath);                               \
415     Bind(&slowPath);                                                                                \
416     {                                                                                               \
417         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget);                  \
418         Jump(&exit);                                                                                \
419     }                                                                                               \
420     Bind(&exit);                                                                                    \
421     Return(*res);                                                                                   \
422 }
423 
424 BUILTINS_CONTAINERS_STUB_BUILDER(DECLARE_CONTAINERS_STUB_BUILDER)
425 #undef DECLARE_CONTAINERS_STUB_BUILDER
426 
427 DECLARE_BUILTINS(BooleanConstructor)
428 {
429     auto env = GetEnvironment();
430     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
431 
432     Label newTargetIsHeapObject(env);
433     Label newTargetIsJSFunction(env);
434     Label slowPath(env);
435     Label slowPath1(env);
436     Label exit(env);
437 
438     BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
439     Bind(&newTargetIsHeapObject);
440     BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
441     Bind(&newTargetIsJSFunction);
442     {
443         Label intialHClassIsHClass(env);
444         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
445                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
446         BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1);
447         Bind(&intialHClassIsHClass);
448         {
449             NewObjectStubBuilder newBuilder(this);
450             newBuilder.SetParameters(glue, 0);
451             Label afterNew(env);
452             newBuilder.NewJSObject(&res, &afterNew, intialHClass);
453             Bind(&afterNew);
454             {
455                 GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
456                 GateRef value = GetArgFromArgv(IntPtr(0), numArgs, true);
457                 Store(VariableType::INT64(), glue, *res, valueOffset, FastToBoolean(value));
458                 Jump(&exit);
459             }
460         }
461         Bind(&slowPath1);
462         {
463             GateRef argv = GetArgv();
464             auto args = { glue, nativeCode, func, thisValue, numArgs, argv, newTarget };
465             res = CallBuiltinRuntimeWithNewTarget(glue, args);
466             Jump(&exit);
467         }
468     }
469     Bind(&slowPath);
470     {
471         GateRef argv = GetArgv();
472         auto args = { glue, nativeCode, func, thisValue, numArgs, argv };
473         res = CallBuiltinRuntime(glue, args, true);
474         Jump(&exit);
475     }
476     Bind(&exit);
477     Return(*res);
478 }
479 
DECLARE_BUILTINS(DateConstructor)480 DECLARE_BUILTINS(DateConstructor)
481 {
482     auto env = GetEnvironment();
483     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
484 
485     Label newTargetIsHeapObject(env);
486     Label newTargetIsJSFunction(env);
487     Label slowPath(env);
488     Label slowPath1(env);
489     Label exit(env);
490 
491     BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
492     Bind(&newTargetIsHeapObject);
493     BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
494     Bind(&newTargetIsJSFunction);
495     {
496         Label intialHClassIsHClass(env);
497         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
498                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
499         BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1);
500         Bind(&intialHClassIsHClass);
501         {
502             Label oneArg(env);
503             Label notOneArg(env);
504             Label newJSDate(env);
505             DEFVARIABLE(timeValue, VariableType::FLOAT64(), Double(0));
506             BRANCH(Int64Equal(numArgs, IntPtr(1)), &oneArg, &notOneArg);
507             Bind(&oneArg);
508             {
509                 Label valueIsNumber(env);
510                 GateRef value = GetArgFromArgv(IntPtr(0));
511                 BRANCH(TaggedIsNumber(value), &valueIsNumber, &slowPath);
512                 Bind(&valueIsNumber);
513                 {
514                     timeValue = CallNGCRuntime(glue, RTSTUB_ID(TimeClip), {GetDoubleOfTNumber(value)});
515                     Jump(&newJSDate);
516                 }
517             }
518             Bind(&notOneArg);
519             {
520                 Label threeArgs(env);
521                 BRANCH(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &slowPath);  // 3: year month day
522                 Bind(&threeArgs);
523                 {
524                     Label numberYearMonthDay(env);
525                     GateRef year = GetArgFromArgv(IntPtr(0));
526                     GateRef month = GetArgFromArgv(IntPtr(1));
527                     GateRef day = GetArgFromArgv(IntPtr(2));
528                     BRANCH(IsNumberYearMonthDay(year, month, day), &numberYearMonthDay, &slowPath);
529                     Bind(&numberYearMonthDay);
530                     {
531                         GateRef y = GetDoubleOfTNumber(year);
532                         GateRef m = GetDoubleOfTNumber(month);
533                         GateRef d = GetDoubleOfTNumber(day);
534                         timeValue = CallNGCRuntime(glue, RTSTUB_ID(SetDateValues), {y, m, d});
535                         Jump(&newJSDate);
536                     }
537                 }
538             }
539             Bind(&newJSDate);
540             {
541                 NewObjectStubBuilder newBuilder(this);
542                 newBuilder.SetParameters(glue, 0);
543                 Label afterNew(env);
544                 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
545                 Bind(&afterNew);
546                 {
547                     GateRef timeValueOffset = IntPtr(JSDate::TIME_VALUE_OFFSET);
548                     Store(VariableType::JS_NOT_POINTER(), glue, *res, timeValueOffset,
549                           DoubleToTaggedDoublePtr(*timeValue));
550                     Jump(&exit);
551                 }
552             }
553         }
554         Bind(&slowPath1);
555         {
556             GateRef argv = GetArgv();
557             res = CallBuiltinRuntimeWithNewTarget(glue,
558                 { glue, nativeCode, func, thisValue, numArgs, argv, newTarget });
559             Jump(&exit);
560         }
561     }
562     Bind(&slowPath);
563     {
564         GateRef argv = GetArgv();
565         res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true);
566         Jump(&exit);
567     }
568     Bind(&exit);
569     Return(*res);
570 }
571 
DECLARE_BUILTINS(NumberConstructor)572 DECLARE_BUILTINS(NumberConstructor)
573 {
574     BuiltinsNumberStubBuilder builder(this, glue, thisValue, numArgs);
575     builder.GenNumberConstructor(nativeCode, func, newTarget);
576 }
577 
DECLARE_BUILTINS(ProxyConstructor)578 DECLARE_BUILTINS(ProxyConstructor)
579 {
580     BuiltinsProxyStubBuilder builder(this, glue, thisValue, numArgs);
581     builder.GenProxyConstructor(nativeCode, func, newTarget);
582 }
583 
DECLARE_BUILTINS(ArrayConstructor)584 DECLARE_BUILTINS(ArrayConstructor)
585 {
586     BuiltinsArrayStubBuilder builder(this);
587     builder.GenArrayConstructor(glue, nativeCode, func, newTarget, thisValue, numArgs);
588 }
589 
DECLARE_BUILTINS(MapConstructor)590 DECLARE_BUILTINS(MapConstructor)
591 {
592     LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> hashTableBuilder(this, glue);
593     GateRef arg0 = GetArgFromArgv(IntPtr(0), numArgs, true);
594     hashTableBuilder.GenMapSetConstructor(nativeCode, func, newTarget, thisValue, numArgs, arg0, GetArgv());
595 }
596 
DECLARE_BUILTINS(SetConstructor)597 DECLARE_BUILTINS(SetConstructor)
598 {
599     LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> hashTableBuilder(this, glue);
600     GateRef arg0 = GetArgFromArgv(IntPtr(0), numArgs, true);
601     hashTableBuilder.GenMapSetConstructor(nativeCode, func, newTarget, thisValue, numArgs, arg0, GetArgv());
602 }
603 
604 #define DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER(TYPE, type, index)                                \
605 DECLARE_BUILTINS(type##ArrayConstructor)                                                            \
606 {                                                                                                   \
607     GateRef ctorName = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,                     \
608                                               ConstantIndex::TYPE##_ARRAY_STRING_INDEX);            \
609     BuiltinsTypedArrayStubBuilder builtinsTypedArrayStubBuilder(this);                              \
610     builtinsTypedArrayStubBuilder.GenTypedArrayConstructor(glue, nativeCode, func, newTarget,       \
611         thisValue, numArgs, ctorName, DataViewType::TYPE);                                          \
612 }
613 BUILTIN_COMPILER_TYPED_ARRAY_TYPES(DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER)
614 #undef DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER
615 }  // namespace panda::ecmascript::kungfu
616