• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/compiler/builtins/builtins_stubs.h"
17 
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h"
20 #include "ecmascript/compiler/builtins/builtins_call_signature.h"
21 #include "ecmascript/compiler/builtins/builtins_function_stub_builder.h"
22 #include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
23 #include "ecmascript/compiler/builtins/builtins_number_stub_builder.h"
24 #include "ecmascript/compiler/builtins/containers_vector_stub_builder.h"
25 #include "ecmascript/compiler/builtins/containers_stub_builder.h"
26 #include "ecmascript/compiler/builtins/builtins_collection_stub_builder.h"
27 #include "ecmascript/compiler/builtins/builtins_object_stub_builder.h"
28 #include "ecmascript/compiler/typed_array_stub_builder.h"
29 #include "ecmascript/compiler/interpreter_stub-inl.h"
30 #include "ecmascript/compiler/llvm_ir_builder.h"
31 #include "ecmascript/compiler/new_object_stub_builder.h"
32 #include "ecmascript/compiler/stub_builder-inl.h"
33 #include "ecmascript/compiler/stub_builder.h"
34 #include "ecmascript/compiler/variable_type.h"
35 #include "ecmascript/js_date.h"
36 #include "ecmascript/js_primitive_ref.h"
37 
38 namespace panda::ecmascript::kungfu {
39 #if ECMASCRIPT_ENABLE_BUILTIN_LOG
40 #define DECLARE_BUILTINS(name)                                                                      \
41 void name##StubBuilder::GenerateCircuit()                                                           \
42 {                                                                                                   \
43     GateRef glue = PtrArgument(static_cast<size_t>(BuiltinsArgs::GLUE));                            \
44     GateRef nativeCode = PtrArgument(static_cast<size_t>(BuiltinsArgs::NATIVECODE));                \
45     GateRef func = TaggedArgument(static_cast<size_t>(BuiltinsArgs::FUNC));                         \
46     GateRef newTarget = TaggedArgument(static_cast<size_t>(BuiltinsArgs::NEWTARGET));               \
47     GateRef thisValue = TaggedArgument(static_cast<size_t>(BuiltinsArgs::THISVALUE));               \
48     GateRef numArgs = PtrArgument(static_cast<size_t>(BuiltinsArgs::NUMARGS));                      \
49     DebugPrint(glue, { Int32(GET_MESSAGE_STRING_ID(name)) });                                       \
50     GenerateCircuitImpl(glue, nativeCode, func, newTarget, thisValue, numArgs);                     \
51 }                                                                                                   \
52 void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func,         \
53                                             GateRef newTarget, GateRef thisValue, GateRef numArgs)
54 #else
55 #define DECLARE_BUILTINS(name)                                                                      \
56 void name##StubBuilder::GenerateCircuit()                                                           \
57 {                                                                                                   \
58     GateRef glue = PtrArgument(static_cast<size_t>(BuiltinsArgs::GLUE));                            \
59     GateRef nativeCode = PtrArgument(static_cast<size_t>(BuiltinsArgs::NATIVECODE));                \
60     GateRef func = TaggedArgument(static_cast<size_t>(BuiltinsArgs::FUNC));                         \
61     GateRef newTarget = TaggedArgument(static_cast<size_t>(BuiltinsArgs::NEWTARGET));               \
62     GateRef thisValue = TaggedArgument(static_cast<size_t>(BuiltinsArgs::THISVALUE));               \
63     GateRef numArgs = PtrArgument(static_cast<size_t>(BuiltinsArgs::NUMARGS));                      \
64     GenerateCircuitImpl(glue, nativeCode, func, newTarget, thisValue, numArgs);                     \
65 }                                                                                                   \
66 void name##StubBuilder::GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func,         \
67                                             GateRef newTarget, GateRef thisValue, GateRef numArgs)
68 #endif
69 
GetArg(GateRef numArgs,GateRef index)70 GateRef BuiltinsStubBuilder::GetArg(GateRef numArgs, GateRef index)
71 {
72     auto env = GetEnvironment();
73     Label entry(env);
74     env->SubCfgEntry(&entry);
75     DEFVARIABLE(arg, VariableType::JS_ANY(), Undefined());
76     Label validIndex(env);
77     Label exit(env);
78     Branch(IntPtrGreaterThan(numArgs, index), &validIndex, &exit);
79     Bind(&validIndex);
80     {
81         GateRef argv = GetArgv();
82         arg = Load(VariableType::JS_ANY(), argv, PtrMul(index, IntPtr(JSTaggedValue::TaggedTypeSize())));
83         Jump(&exit);
84     }
85     Bind(&exit);
86     GateRef ret = *arg;
87     env->SubCfgExit();
88     return ret;
89 }
90 
CallSlowPath(GateRef nativeCode,GateRef glue,GateRef thisValue,GateRef numArgs,GateRef func,GateRef newTarget,const char * comment)91 GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, GateRef thisValue,
92                                           GateRef numArgs, GateRef func, GateRef newTarget, const char* comment)
93 {
94     auto env = GetEnvironment();
95     Label entry(env);
96     env->SubCfgEntry(&entry);
97     Label exit(env);
98     Label callThis0(env);
99     Label notcallThis0(env);
100     Label notcallThis1(env);
101     Label callThis1(env);
102     Label callThis2(env);
103     Label callThis3(env);
104     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
105     GateRef runtimeCallInfoArgs = PtrAdd(numArgs, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
106     Branch(Int64Equal(numArgs, IntPtr(0)), &callThis0, &notcallThis0);
107     Bind(&callThis0);
108     {
109         auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue };
110         result = CallBuiltinRuntime(glue, args, false, comment);
111         Jump(&exit);
112     }
113     Bind(&notcallThis0);
114     {
115         Branch(Int64Equal(numArgs, IntPtr(1)), &callThis1, &notcallThis1);
116         Bind(&callThis1);
117         {
118             GateRef arg0 = GetCallArg0(numArgs);
119             auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0 };
120             result = CallBuiltinRuntime(glue, args, false, comment);
121             Jump(&exit);
122         }
123         Bind(&notcallThis1);
124         {
125             Branch(Int64Equal(numArgs, IntPtr(2)), &callThis2, &callThis3); // 2: args2
126             Bind(&callThis2);
127             {
128                 GateRef arg0 = GetCallArg0(numArgs);
129                 GateRef arg1 = GetCallArg1(numArgs);
130                 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1 };
131                 result = CallBuiltinRuntime(glue, args, false, comment);
132                 Jump(&exit);
133             }
134             Bind(&callThis3);
135             {
136                 GateRef arg0 = GetCallArg0(numArgs);
137                 GateRef arg1 = GetCallArg1(numArgs);
138                 GateRef arg2 = GetCallArg2(numArgs);
139                 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1, arg2 };
140                 result = CallBuiltinRuntime(glue, args, false, comment);
141                 Jump(&exit);
142             }
143         }
144     }
145 
146     Bind(&exit);
147     auto ret = *result;
148     env->SubCfgExit();
149     return ret;
150 }
151 
152 #define DECLARE_BUILTINS_WITH_STRING_STUB_BUILDER(method, resultVariableType, initValue)            \
153 DECLARE_BUILTINS(String##method)                                                                    \
154 {                                                                                                   \
155     auto env = GetEnvironment();                                                                    \
156     DEFVARIABLE(res, VariableType::resultVariableType(), initValue);                                \
157     Label exit(env);                                                                                \
158     Label slowPath(env);                                                                            \
159     BuiltinsStringStubBuilder stringStubBuilder(this);                                              \
160     stringStubBuilder.method(glue, thisValue, numArgs, &res, &exit, &slowPath);                     \
161     Bind(&slowPath);                                                                                \
162     {                                                                                               \
163         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(String##method));                  \
164         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());    \
165         Jump(&exit);                                                                                \
166     }                                                                                               \
167     Bind(&exit);                                                                                    \
168     Return(*res);                                                                                   \
169 }
170 
171 #define BUILTINS_WITH_STRING_STUB_BUILDER(V)                                        \
172     V(CharAt,       JS_POINTER, Hole())                                             \
173     V(FromCharCode, JS_ANY,     Hole())                                             \
174     V(CharCodeAt,   JS_ANY,     DoubleToTaggedDoublePtr(Double(base::NAN_VALUE)))   \
175     V(IndexOf,      JS_ANY,     IntToTaggedPtr(Int32(-1)))                          \
176     V(Substring,    JS_ANY,     IntToTaggedPtr(Int32(-1)))                          \
177     V(Replace,      JS_ANY,     Undefined())                                        \
178     V(Trim,         JS_ANY,     Undefined())                                        \
179     V(Slice,        JS_ANY,     Undefined())
180 
DECLARE_BUILTINS(LocaleCompare)181 DECLARE_BUILTINS(LocaleCompare)
182 {
183     auto env = GetEnvironment();
184     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
185     Label exit(env);
186     Label slowPath(env);
187     BuiltinsStringStubBuilder stringStubBuilder(this);
188     stringStubBuilder.LocaleCompare(glue, thisValue, numArgs, &res, &exit, &slowPath);
189     Bind(&slowPath);
190     {
191         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(LocaleCompare));
192         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
193         Jump(&exit);
194     }
195     Bind(&exit);
196     Return(*res);
197 }
198 
199 BUILTINS_WITH_STRING_STUB_BUILDER(DECLARE_BUILTINS_WITH_STRING_STUB_BUILDER)
200 
201 #undef DECLARE_BUILTINS_WITH_STRING_STUB_BUILDER
202 #undef BUILTINS_WITH_STRING_STUB_BUILDER
203 
DECLARE_BUILTINS(FunctionPrototypeApply)204 DECLARE_BUILTINS(FunctionPrototypeApply)
205 {
206     auto env = GetEnvironment();
207     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
208     Label exit(env);
209     Label slowPath(env);
210     BuiltinsFunctionStubBuilder functionStubBuilder(this);
211     functionStubBuilder.Apply(glue, thisValue, numArgs, &res, &exit, &slowPath);
212     Bind(&slowPath);
213     {
214         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(FunctionPrototypeApply));
215         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
216         Jump(&exit);
217     }
218     Bind(&exit);
219     Return(*res);
220 }
221 
222 #define DECLARE_BUILTINS_WITH_CONTAINERS_STUB_BUILDER(StubName, Method, methodType, resultVariableType)     \
223 DECLARE_BUILTINS(StubName)                                                                                  \
224 {                                                                                                           \
225     auto env = GetEnvironment();                                                                            \
226     DEFVARIABLE(res, VariableType::resultVariableType(), Undefined());                                      \
227     Label exit(env);                                                                                        \
228     Label slowPath(env);                                                                                    \
229     ContainersStubBuilder containersBuilder(this);                                                          \
230     containersBuilder.Method(glue, thisValue, numArgs, &res, &exit, &slowPath, ContainersType::methodType); \
231     Bind(&slowPath);                                                                                        \
232     {                                                                                                       \
233         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(StubName));                                \
234         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());            \
235         Jump(&exit);                                                                                        \
236     }                                                                                                       \
237     Bind(&exit);                                                                                            \
238     Return(*res);                                                                                           \
239 }
240 
241 #define BUILTINS_WITH_CONTAINERS_STUB_BUILDER(V) \
242     V(ArrayListForEach,            ContainersCommonFuncCall,  ARRAYLIST_FOREACH,            JS_POINTER) \
243     V(DequeForEach,                DequeCommonFuncCall,       DEQUE_FOREACH,                JS_POINTER) \
244     V(HashMapForEach,              ContainersHashCall,        HASHMAP_FOREACH,              JS_POINTER) \
245     V(HashSetForEach,              ContainersHashCall,        HASHSET_FOREACH,              JS_POINTER) \
246     V(LightWeightMapForEach,       ContainersLightWeightCall, LIGHTWEIGHTMAP_FOREACH,       JS_POINTER) \
247     V(LightWeightSetForEach,       ContainersLightWeightCall, LIGHTWEIGHTSET_FOREACH,       JS_POINTER) \
248     V(LinkedListForEach,           ContainersLinkedListCall,  LINKEDLIST_FOREACH,           JS_POINTER) \
249     V(ListForEach,                 ContainersLinkedListCall,  LIST_FOREACH,                 JS_POINTER) \
250     V(PlainArrayForEach,           ContainersCommonFuncCall,  PLAINARRAY_FOREACH,           JS_POINTER) \
251     V(QueueForEach,                QueueCommonFuncCall,       QUEUE_FOREACH,                JS_POINTER) \
252     V(StackForEach,                ContainersCommonFuncCall,  STACK_FOREACH,                JS_POINTER) \
253     V(VectorForEach,               ContainersCommonFuncCall,  VECTOR_FOREACH,               JS_POINTER) \
254     V(ArrayListReplaceAllElements, ContainersCommonFuncCall,  ARRAYLIST_REPLACEALLELEMENTS, JS_POINTER) \
255     V(VectorReplaceAllElements,    ContainersCommonFuncCall,  VECTOR_REPLACEALLELEMENTS,    JS_POINTER)
256 
257 BUILTINS_WITH_CONTAINERS_STUB_BUILDER(DECLARE_BUILTINS_WITH_CONTAINERS_STUB_BUILDER)
258 
259 #undef DECLARE_BUILTINS_WITH_CONTAINERS_STUB_BUILDER
260 #undef BUILTINS_WITH_CONTAINERS_STUB_BUILDER
261 
262 #define DECLARE_BUILTINS_WITH_ARRAY_STUB_BUILDER(Method, resultVariableType)                        \
263 DECLARE_BUILTINS(Array##Method)                                                                     \
264 {                                                                                                   \
265     auto env = GetEnvironment();                                                                    \
266     DEFVARIABLE(res, VariableType::resultVariableType(), Undefined());                              \
267     Label exit(env);                                                                                \
268     Label slowPath(env);                                                                            \
269     BuiltinsArrayStubBuilder arrayStubBuilder(this);                                                \
270     arrayStubBuilder.Method(glue, thisValue, numArgs, &res, &exit, &slowPath);                      \
271     Bind(&slowPath);                                                                                \
272     {                                                                                               \
273         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(Array##Method));                   \
274         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());    \
275         Jump(&exit);                                                                                \
276     }                                                                                               \
277     Bind(&exit);                                                                                    \
278     Return(*res);                                                                                   \
279 }
280 
281 #define BUILTINS_WITH_ARRAY_STUB_BUILDER(V) \
282     V(Concat,       JS_ANY)                 \
283     V(Filter,       JS_POINTER)             \
284     V(Find,         JS_ANY)                 \
285     V(FindIndex,    JS_ANY)                 \
286     V(From,         JS_ANY)                 \
287     V(Splice,       JS_ANY)                 \
288     V(ForEach,      JS_ANY)                 \
289     V(IndexOf,      JS_ANY)                 \
290     V(LastIndexOf,  JS_ANY)                 \
291     V(Pop,          JS_ANY)                 \
292     V(Slice,        JS_POINTER)             \
293     V(Reduce,       JS_ANY)                 \
294     V(Reverse,      JS_POINTER)             \
295     V(Push,         JS_ANY)                 \
296     V(Values,       JS_POINTER)             \
297     V(Includes,     JS_ANY)
298 
DECLARE_BUILTINS(SORT)299 DECLARE_BUILTINS(SORT)
300 {
301     auto env = GetEnvironment();
302     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
303     Label exit(env);
304     Label slowPath(env);
305     BuiltinsArrayStubBuilder arrayStubBuilder(this);
306     arrayStubBuilder.Sort(glue, thisValue, numArgs, &res, &exit, &slowPath);
307     Bind(&slowPath);
308     {
309         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(SORT));
310         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
311         Jump(&exit);
312     }
313     Bind(&exit);
314     Return(*res);
315 }
316 
317 BUILTINS_WITH_ARRAY_STUB_BUILDER(DECLARE_BUILTINS_WITH_ARRAY_STUB_BUILDER)
318 
319 #undef DECLARE_BUILTINS_WITH_ARRAY_STUB_BUILDER
320 #undef BUILTINS_WITH_ARRAY_STUB_BUILDER
321 
DECLARE_BUILTINS(BooleanConstructor)322 DECLARE_BUILTINS(BooleanConstructor)
323 {
324     auto env = GetEnvironment();
325     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
326 
327     Label newTargetIsHeapObject(env);
328     Label newTargetIsJSFunction(env);
329     Label slowPath(env);
330     Label slowPath1(env);
331     Label slowPath2(env);
332     Label exit(env);
333 
334     Branch(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath1);
335     Bind(&newTargetIsHeapObject);
336     Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
337     Bind(&newTargetIsJSFunction);
338     {
339         Label intialHClassIsHClass(env);
340         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
341                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
342         Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath2);
343         Bind(&intialHClassIsHClass);
344         {
345             NewObjectStubBuilder newBuilder(this);
346             newBuilder.SetParameters(glue, 0);
347             Label afterNew(env);
348             newBuilder.NewJSObject(&res, &afterNew, intialHClass);
349             Bind(&afterNew);
350             {
351                 GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
352                 GateRef value = GetArg(numArgs, IntPtr(0));
353                 Store(VariableType::INT64(), glue, *res, valueOffset, FastToBoolean(value));
354                 Jump(&exit);
355             }
356         }
357         Bind(&slowPath2);
358         {
359             auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(BooleanConstructor));
360             GateRef argv = GetArgv();
361             auto args = { glue, nativeCode, func, thisValue, numArgs, argv, newTarget };
362             res = CallBuiltinRuntimeWithNewTarget(glue, args, name.c_str());
363             Jump(&exit);
364         }
365     }
366     Bind(&slowPath);
367     {
368         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(BooleanConstructor));
369         GateRef argv = GetArgv();
370         auto args = { glue, nativeCode, func, thisValue, numArgs, argv };
371         res = CallBuiltinRuntime(glue, args, true, name.c_str());
372         Jump(&exit);
373     }
374     Bind(&slowPath1);
375     {
376         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(BooleanConstructor));
377         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
378         Jump(&exit);
379     }
380     Bind(&exit);
381     Return(*res);
382 }
383 
DECLARE_BUILTINS(NumberConstructor)384 DECLARE_BUILTINS(NumberConstructor)
385 {
386     auto env = GetEnvironment();
387     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
388     DEFVARIABLE(numberValue, VariableType::JS_ANY(), IntToTaggedPtr(IntPtr(0)));
389     Label thisCollectionObj(env);
390     Label slowPath(env);
391     Label slowPath1(env);
392     Label slowPath2(env);
393     Label exit(env);
394 
395     Label hasArg(env);
396     Label numberCreate(env);
397     Label newTargetIsHeapObject(env);
398     Branch(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath1);
399     Bind(&newTargetIsHeapObject);
400     Branch(Int64GreaterThan(numArgs, IntPtr(0)), &hasArg, &numberCreate);
401     Bind(&hasArg);
402     {
403         GateRef value = GetArgNCheck(Int32(0));
404         Label number(env);
405         Branch(TaggedIsNumber(value), &number, &slowPath);
406         Bind(&number);
407         {
408             numberValue = value;
409             res = value;
410             Jump(&numberCreate);
411         }
412     }
413 
414     Bind(&numberCreate);
415     Label newObj(env);
416     Label newTargetIsJSFunction(env);
417     Branch(TaggedIsUndefined(newTarget), &exit, &newObj);
418     Bind(&newObj);
419     {
420         Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
421         Bind(&newTargetIsJSFunction);
422         {
423             Label intialHClassIsHClass(env);
424             GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
425                 IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
426             Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath2);
427             Bind(&intialHClassIsHClass);
428             {
429                 NewObjectStubBuilder newBuilder(this);
430                 newBuilder.SetParameters(glue, 0);
431                 Label afterNew(env);
432                 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
433                 Bind(&afterNew);
434                 {
435                     GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
436                     Store(VariableType::INT64(), glue, *res, valueOffset, *numberValue);
437                     Jump(&exit);
438                 }
439             }
440             Bind(&slowPath2);
441             {
442                 auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(NumberConstructor));
443                 GateRef argv = GetArgv();
444                 res = CallBuiltinRuntimeWithNewTarget(glue,
445                     { glue, nativeCode, func, thisValue, numArgs, argv, newTarget }, name.c_str());
446                 Jump(&exit);
447             }
448         }
449     }
450 
451     Bind(&slowPath);
452     {
453         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(NumberConstructor));
454         GateRef argv = GetArgv();
455         res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true, name.c_str());
456         Jump(&exit);
457     }
458     Bind(&slowPath1);
459     {
460         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(NumberConstructor));
461         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
462         Jump(&exit);
463     }
464     Bind(&exit);
465     Return(*res);
466 }
467 
DECLARE_BUILTINS(DateConstructor)468 DECLARE_BUILTINS(DateConstructor)
469 {
470     auto env = GetEnvironment();
471     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
472 
473     Label newTargetIsHeapObject(env);
474     Label newTargetIsJSFunction(env);
475     Label slowPath(env);
476     Label slowPath1(env);
477     Label slowPath2(env);
478     Label exit(env);
479 
480     Branch(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath1);
481     Bind(&newTargetIsHeapObject);
482     Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
483     Bind(&newTargetIsJSFunction);
484     {
485         Label intialHClassIsHClass(env);
486         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget,
487                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
488         Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath2);
489         Bind(&intialHClassIsHClass);
490         {
491             Label oneArg(env);
492             Label notOneArg(env);
493             Label newJSDate(env);
494             DEFVARIABLE(timeValue, VariableType::FLOAT64(), Double(0));
495             Branch(Int64Equal(numArgs, IntPtr(1)), &oneArg, &notOneArg);
496             Bind(&oneArg);
497             {
498                 Label valueIsNumber(env);
499                 GateRef value = GetArgNCheck(IntPtr(0));
500                 Branch(TaggedIsNumber(value), &valueIsNumber, &slowPath);
501                 Bind(&valueIsNumber);
502                 {
503                     timeValue = CallNGCRuntime(glue, RTSTUB_ID(TimeClip), {GetDoubleOfTNumber(value)});
504                     Jump(&newJSDate);
505                 }
506             }
507             Bind(&notOneArg);
508             {
509                 Label threeArgs(env);
510                 Branch(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &slowPath);  // 3: year month day
511                 Bind(&threeArgs);
512                 {
513                     Label numberYearMonthDay(env);
514                     GateRef year = GetArgNCheck(IntPtr(0));
515                     GateRef month = GetArgNCheck(IntPtr(1));
516                     GateRef day = GetArgNCheck(IntPtr(2));
517                     Branch(IsNumberYearMonthDay(year, month, day), &numberYearMonthDay, &slowPath);
518                     Bind(&numberYearMonthDay);
519                     {
520                         GateRef y = GetDoubleOfTNumber(year);
521                         GateRef m = GetDoubleOfTNumber(month);
522                         GateRef d = GetDoubleOfTNumber(day);
523                         timeValue = CallNGCRuntime(glue, RTSTUB_ID(SetDateValues), {y, m, d});
524                         Jump(&newJSDate);
525                     }
526                 }
527             }
528             Bind(&newJSDate);
529             {
530                 NewObjectStubBuilder newBuilder(this);
531                 newBuilder.SetParameters(glue, 0);
532                 Label afterNew(env);
533                 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
534                 Bind(&afterNew);
535                 {
536                     GateRef timeValueOffset = IntPtr(JSDate::TIME_VALUE_OFFSET);
537                     Store(VariableType::JS_NOT_POINTER(), glue, *res, timeValueOffset,
538                           DoubleToTaggedDoublePtr(*timeValue));
539                     Jump(&exit);
540                 }
541             }
542         }
543         Bind(&slowPath2);
544         {
545             auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(DateConstructor));
546             GateRef argv = GetArgv();
547             res = CallBuiltinRuntimeWithNewTarget(glue, { glue, nativeCode, func, thisValue, numArgs, argv, newTarget },
548                 name.c_str());
549             Jump(&exit);
550         }
551     }
552     Bind(&slowPath);
553     {
554         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(DateConstructor));
555         GateRef argv = GetArgv();
556         res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true, name.c_str());
557         Jump(&exit);
558     }
559     Bind(&slowPath1);
560     {
561         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(DateConstructor));
562         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
563         Jump(&exit);
564     }
565     Bind(&exit);
566     Return(*res);
567 }
568 
DECLARE_BUILTINS(ArrayConstructor)569 DECLARE_BUILTINS(ArrayConstructor)
570 {
571     auto env = GetEnvironment();
572     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
573 
574     Label newTargetIsHeapObject(env);
575     Label newTargetIsJSFunction(env);
576     Label slowPath(env);
577     Label slowPath1(env);
578     Label slowPath2(env);
579     Label exit(env);
580 
581     Branch(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath1);
582     Bind(&newTargetIsHeapObject);
583     Branch(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath);
584     Bind(&newTargetIsJSFunction);
585     {
586         Label fastGetHclass(env);
587         Label intialHClassIsHClass(env);
588         GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
589         GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
590         auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
591         Branch(Equal(arrayFunc, newTarget), &fastGetHclass, &slowPath2);
592         Bind(&fastGetHclass);
593         GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
594         DEFVARIABLE(arrayLength, VariableType::INT64(), Int64(0));
595         Branch(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath2);
596         Bind(&intialHClassIsHClass);
597         {
598             Label noArg(env);
599             Label hasArg(env);
600             Label arrayCreate(env);
601             Branch(Int64Equal(numArgs, IntPtr(0)), &noArg, &hasArg);
602             Bind(&noArg);
603             {
604                 Jump(&arrayCreate);
605             }
606             Bind(&hasArg);
607             {
608                 Label hasOneArg(env);
609                 Branch(Int64Equal(numArgs, IntPtr(1)), &hasOneArg, &slowPath);
610                 Bind(&hasOneArg);
611                 {
612                     Label argIsNumber(env);
613                     GateRef arg0 = GetArg(numArgs, IntPtr(0));
614                     Branch(TaggedIsNumber(arg0), &argIsNumber, &slowPath);
615                     Bind(&argIsNumber);
616                     {
617                         Label argIsInt(env);
618                         Label argIsDouble(env);
619                         Branch(TaggedIsInt(arg0), &argIsInt, &argIsDouble);
620                         Bind(&argIsInt);
621                         {
622                             Label validIntLength(env);
623                             GateRef intLen = GetInt64OfTInt(arg0);
624                             GateRef isGEZero = Int64GreaterThanOrEqual(intLen, Int64(0));
625                             GateRef isLEMaxLen = Int64LessThanOrEqual(intLen, Int64(JSArray::MAX_ARRAY_INDEX));
626                             Branch(BoolAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath);
627                             Bind(&validIntLength);
628                             {
629                                 arrayLength = intLen;
630                                 Jump(&arrayCreate);
631                             }
632                         }
633                         Bind(&argIsDouble);
634                         {
635                             Label validDoubleLength(env);
636                             GateRef doubleLength = GetDoubleOfTDouble(arg0);
637                             GateRef doubleToInt = DoubleToInt(glue, doubleLength);
638                             GateRef intToDouble = CastInt64ToFloat64(SExtInt32ToInt64(doubleToInt));
639                             GateRef doubleEqual = DoubleEqual(doubleLength, intToDouble);
640                             GateRef doubleLEMaxLen =
641                                 DoubleLessThanOrEqual(doubleLength, Double(JSArray::MAX_ARRAY_INDEX));
642                             Branch(BoolAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath);
643                             Bind(&validDoubleLength);
644                             {
645                                 arrayLength = SExtInt32ToInt64(doubleToInt);
646                                 Jump(&arrayCreate);
647                             }
648                         }
649                     }
650                 }
651             }
652             Bind(&arrayCreate);
653             {
654                 Label lengthValid(env);
655                 Branch(Int64GreaterThan(*arrayLength, Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid);
656                 Bind(&lengthValid);
657                 {
658                     NewObjectStubBuilder newBuilder(this);
659                     newBuilder.SetParameters(glue, 0);
660                     res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength);
661                     GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
662                     Store(VariableType::INT32(), glue, *res, lengthOffset, TruncInt64ToInt32(*arrayLength));
663                     GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
664                                                               ConstantIndex::ARRAY_LENGTH_ACCESSOR);
665                     SetPropertyInlinedProps(glue, *res, intialHClass, accessor,
666                                             Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
667                     SetExtensibleToBitfield(glue, *res, true);
668                     Jump(&exit);
669                 }
670             }
671         }
672         Bind(&slowPath2);
673         {
674             auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ArrayConstructor));
675             GateRef argv = GetArgv();
676             res = CallBuiltinRuntimeWithNewTarget(glue, { glue, nativeCode, func, thisValue, numArgs, argv, newTarget },
677                 name.c_str());
678             Jump(&exit);
679         }
680     }
681     Bind(&slowPath);
682     {
683         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ArrayConstructor));
684         GateRef argv = GetArgv();
685         res = CallBuiltinRuntime(glue, { glue, nativeCode, func, thisValue, numArgs, argv }, true, name.c_str());
686         Jump(&exit);
687     }
688     Bind(&slowPath1);
689     {
690         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(ArrayConstructor));
691         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
692         Jump(&exit);
693     }
694 
695     Bind(&exit);
696     Return(*res);
697 }
698 
699 #define DECLARE_BUILTINS_OBJECT_STUB_BUILDER(type, method, retType, retDefaultValue)                \
700 DECLARE_BUILTINS(type##method)                                                                      \
701 {                                                                                                   \
702     auto env = GetEnvironment();                                                                    \
703     DEFVARIABLE(res, retType, retDefaultValue);                                                     \
704     Label thisCollectionObj(env);                                                                   \
705     Label slowPath(env);                                                                            \
706     Label exit(env);                                                                                \
707     BuiltinsObjectStubBuilder builder(this, glue, thisValue, numArgs);                              \
708     builder.method(&res, &exit, &slowPath);                                                         \
709     Bind(&slowPath);                                                                                \
710     {                                                                                               \
711         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(type##method));                    \
712         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());    \
713         Jump(&exit);                                                                                \
714     }                                                                                               \
715     Bind(&exit);                                                                                    \
716     Return(*res);                                                                                   \
717 }
718 
719 // Object.protetype.ToString
720 DECLARE_BUILTINS_OBJECT_STUB_BUILDER(Object, ToString, VariableType::JS_ANY(), Undefined());
721 // Object.protetype.Create
722 DECLARE_BUILTINS_OBJECT_STUB_BUILDER(Object, Create, VariableType::JS_ANY(), Undefined());
723 // Object.protetype.Assign
724 DECLARE_BUILTINS_OBJECT_STUB_BUILDER(Object, Assign, VariableType::JS_ANY(), Undefined());
725 // Object.protetype.HasOwnProperty
726 DECLARE_BUILTINS_OBJECT_STUB_BUILDER(Object, HasOwnProperty, VariableType::JS_ANY(), TaggedFalse());
727 // Object.protetype.Keys
728 DECLARE_BUILTINS_OBJECT_STUB_BUILDER(Object, Keys, VariableType::JS_ANY(), Undefined());
729 #undef DECLARE_BUILTINS_OBJECT_STUB_BUILDER
730 
731 #define DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(type, method, retType, retDefaultValue)            \
732 DECLARE_BUILTINS(type##method)                                                                      \
733 {                                                                                                   \
734     auto env = GetEnvironment();                                                                    \
735     DEFVARIABLE(res, retType, retDefaultValue);                                                     \
736     Label slowPath(env);                                                                            \
737     Label exit(env);                                                                                \
738     BuiltinsCollectionStubBuilder<JS##type> builder(this, glue, thisValue, numArgs);                \
739     builder.method(&res, &exit, &slowPath);                                                         \
740     Bind(&slowPath);                                                                                \
741     {                                                                                               \
742         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(type##method));                    \
743         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());    \
744         Jump(&exit);                                                                                \
745     }                                                                                               \
746     Bind(&exit);                                                                                    \
747     Return(*res);                                                                                   \
748 }
749 
750 // Set.protetype.Clear
751 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Set, Clear, VariableType::JS_ANY(), Undefined());
752 // Set.protetype.Values
753 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Set, Values, VariableType::JS_ANY(), Undefined());
754 // Set.protetype.Entries
755 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Set, Entries, VariableType::JS_ANY(), Undefined());
756 // Set.protetype.ForEach
757 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Set, ForEach, VariableType::JS_ANY(), Undefined());
758 // Set.protetype.Add
759 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Set, Add, VariableType::JS_ANY(), Undefined());
760 // Set.protetype.Delete
761 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Set, Delete, VariableType::JS_ANY(), Undefined());
762 // Set.protetype.Has
763 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Set, Has, VariableType::JS_ANY(), Undefined());
764 // Map.protetype.Clear
765 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, Clear, VariableType::JS_ANY(), Undefined());
766 // Map.protetype.Values
767 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, Values, VariableType::JS_ANY(), Undefined());
768 // Map.protetype.Entries
769 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, Entries, VariableType::JS_ANY(), Undefined());
770 // Map.protetype.Keys
771 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, Keys, VariableType::JS_ANY(), Undefined());
772 // Map.protetype.ForEach
773 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, ForEach, VariableType::JS_ANY(), Undefined());
774 // Map.protetype.set
775 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, Set, VariableType::JS_ANY(), Undefined());
776 // Map.protetype.Delete
777 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, Delete, VariableType::JS_ANY(), Undefined());
778 // Map.protetype.Has
779 DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(Map, Has, VariableType::JS_ANY(), Undefined());
780 #undef DECLARE_BUILTINS_COLLECTION_STUB_BUILDER
781 
782 #define DECLARE_BUILTINS_NUMBER_STUB_BUILDER(type, method, retType, retDefaultValue)                \
783 DECLARE_BUILTINS(type##method)                                                                      \
784 {                                                                                                   \
785     auto env = GetEnvironment();                                                                    \
786     DEFVARIABLE(res, retType, retDefaultValue);                                                     \
787     Label slowPath(env);                                                                            \
788     Label exit(env);                                                                                \
789     BuiltinsNumberStubBuilder builder(this, glue, thisValue, numArgs);                              \
790     builder.method(&res, &exit, &slowPath);                                                         \
791     Bind(&slowPath);                                                                                \
792     {                                                                                               \
793         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(type##method));                    \
794         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());    \
795         Jump(&exit);                                                                                \
796     }                                                                                               \
797     Bind(&exit);                                                                                    \
798     Return(*res);                                                                                   \
799 }
800 
801 // Number.ParseFloat
802 DECLARE_BUILTINS_NUMBER_STUB_BUILDER(Number, ParseFloat, VariableType::JS_ANY(), Undefined());
803 #undef DECLARE_BUILTINS_NUMBER_STUB_BUILDER
804 
805 #define DECLARE_BUILTINS_TYPEDARRAY_STUB_BUILDER(type, method, retType, retDefaultValue)            \
806 DECLARE_BUILTINS(type##method)                                                                      \
807 {                                                                                                   \
808     auto env = GetEnvironment();                                                                    \
809     DEFVARIABLE(res, retType, retDefaultValue);                                                     \
810     Label slowPath(env);                                                                            \
811     Label exit(env);                                                                                \
812     GateRef begin = GetCallArg0(numArgs);                                                           \
813     GateRef end = GetCallArg1(numArgs);                                                             \
814     TypedArrayStubBuilder builder(this);                                                            \
815     builder.method(glue, thisValue, begin, end, &res, &exit, &slowPath);                            \
816     Bind(&slowPath);                                                                                \
817     {                                                                                               \
818         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(type##method));                    \
819         res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());    \
820         Jump(&exit);                                                                                \
821     }                                                                                               \
822     Bind(&exit);                                                                                    \
823     Return(*res);                                                                                   \
824 }
825 
826 // TypedArray.Subarray
827 DECLARE_BUILTINS_TYPEDARRAY_STUB_BUILDER(TypedArray, SubArray, VariableType::JS_ANY(), Undefined());
828 #undef DECLARE_BUILTINS_TYPEDARRAY_STUB_BUILDER
829 }  // namespace panda::ecmascript::kungfu
830