• 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 
GetGlobalEnvFromFunction(GateRef glue,GateRef func)158 GateRef BuiltinsStubBuilder::GetGlobalEnvFromFunction(GateRef glue, GateRef func)
159 {
160     auto env0 = GetEnvironment();
161     Label subentry(env0);
162     env0->SubCfgEntry(&subentry);
163     Label exit(env0);
164     Label isUndefined(env0);
165     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
166     GateRef lexicalEnv = GetFunctionLexicalEnv(glue, func);
167     {
168         ASM_ASSERT(GET_MESSAGE_STRING_ID(LexicalEnvIsInvalid),
169             BitOr(TaggedIsUndefined(lexicalEnv),
170                   LogicAndBuilder(env0).And(TaggedIsHeapObject(lexicalEnv))
171                                        .And(IsGlobalEnv(glue, lexicalEnv))
172                                        .Done()));
173     }
174     result = lexicalEnv;
175     BRANCH_UNLIKELY(TaggedIsUndefined(lexicalEnv), &isUndefined, &exit);
176     Bind(&isUndefined);
177     {
178         result = GetGlobalEnv(glue);
179         Jump(&exit);
180     }
181     Bind(&exit);
182     auto res = *result;
183     env0->SubCfgExit();
184     return res;
185 }
186 
GetArgFromArgv(GateRef glue,GateRef index,GateRef numArgs,bool needCheck)187 GateRef BuiltinsStubBuilder::GetArgFromArgv(GateRef glue, GateRef index, GateRef numArgs, bool needCheck)
188 {
189     if (!needCheck) {
190         GateRef argv = GetArgv();
191         return Load(VariableType::JS_ANY(), glue, argv, PtrMul(index, IntPtr(JSTaggedValue::TaggedTypeSize())));
192     }
193     auto env = GetEnvironment();
194     Label entry(env);
195     env->SubCfgEntry(&entry);
196     DEFVARIABLE(arg, VariableType::JS_ANY(), Undefined());
197     Label validIndex(env);
198     Label exit(env);
199     BRANCH(IntPtrGreaterThan(numArgs, index), &validIndex, &exit);
200     Bind(&validIndex);
201     {
202         GateRef argv = GetArgv();
203         arg = Load(VariableType::JS_ANY(), glue, argv, PtrMul(index, IntPtr(JSTaggedValue::TaggedTypeSize())));
204         Jump(&exit);
205     }
206     Bind(&exit);
207     GateRef ret = *arg;
208     env->SubCfgExit();
209     return ret;
210 }
211 
CallSlowPath(GateRef nativeCode,GateRef glue,GateRef globalEnv,GateRef thisValue,GateRef numArgs,GateRef func,GateRef newTarget)212 GateRef BuiltinsStubBuilder::CallSlowPath(GateRef nativeCode, GateRef glue, GateRef globalEnv, GateRef thisValue,
213                                           GateRef numArgs, GateRef func, GateRef newTarget)
214 {
215     auto env = GetEnvironment();
216     Label entry(env);
217     env->SubCfgEntry(&entry);
218     Label exit(env);
219     Label callThis0(env);
220     Label notcallThis0(env);
221     Label notcallThis1(env);
222     Label callThis1(env);
223     Label callThis2(env);
224     Label callThis3(env);
225     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
226     GateRef runtimeCallInfoArgs = PtrAdd(numArgs, IntPtr(NUM_MANDATORY_JSFUNC_ARGS));
227     SetGlueGlobalEnv(glue, globalEnv);
228     BRANCH(Int64Equal(numArgs, IntPtr(0)), &callThis0, &notcallThis0);
229     Bind(&callThis0);
230     {
231         auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue };
232         result = CallBuiltinRuntime(glue, args, false);
233         Jump(&exit);
234     }
235     Bind(&notcallThis0);
236     {
237         BRANCH(Int64Equal(numArgs, IntPtr(1)), &callThis1, &notcallThis1);
238         Bind(&callThis1);
239         {
240             GateRef arg0 = GetCallArg0(numArgs);
241             auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0 };
242             result = CallBuiltinRuntime(glue, args, false);
243             Jump(&exit);
244         }
245         Bind(&notcallThis1);
246         {
247             BRANCH(Int64Equal(numArgs, IntPtr(2)), &callThis2, &callThis3); // 2: args2
248             Bind(&callThis2);
249             {
250                 GateRef arg0 = GetCallArg0(numArgs);
251                 GateRef arg1 = GetCallArg1(numArgs);
252                 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1 };
253                 result = CallBuiltinRuntime(glue, args, false);
254                 Jump(&exit);
255             }
256             Bind(&callThis3);
257             {
258                 GateRef arg0 = GetCallArg0(numArgs);
259                 GateRef arg1 = GetCallArg1(numArgs);
260                 GateRef arg2 = GetCallArg2(numArgs);
261                 auto args = { nativeCode, glue, runtimeCallInfoArgs, func, newTarget, thisValue, arg0, arg1, arg2 };
262                 result = CallBuiltinRuntime(glue, args, false);
263                 Jump(&exit);
264             }
265         }
266     }
267 
268     Bind(&exit);
269     auto ret = *result;
270     env->SubCfgExit();
271     return ret;
272 }
273 
274 #define DECLARE_BUILTINS_STUB_BUILDER(method, type, initValue, ...)                                 \
275 DECLARE_BUILTINS(type##method)                                                                      \
276 {                                                                                                   \
277     auto env = GetEnvironment();                                                                    \
278     DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
279     Label exit(env);                                                                                \
280     Label slowPath(env);                                                                            \
281     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                       \
282     Builtins##type##StubBuilder builder(this, globalEnv);                                           \
283     builder.method(glue, thisValue, numArgs, &res, &exit, &slowPath);                               \
284     Bind(&slowPath);                                                                                \
285     {                                                                                               \
286         res = CallSlowPath(nativeCode, glue, globalEnv, thisValue, numArgs, func, newTarget);       \
287         Jump(&exit);                                                                                \
288     }                                                                                               \
289     Bind(&exit);                                                                                    \
290     Return(*res);                                                                                   \
291 }
292 
293 #define DECLARE_BUILTINS_STUB_BUILDER1(method, type, initValue, ...)                                \
294 DECLARE_BUILTINS(type##method)                                                                      \
295 {                                                                                                   \
296     auto env = GetEnvironment();                                                                    \
297     DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
298     Label thisCollectionObj(env);                                                                   \
299     Label slowPath(env);                                                                            \
300     Label exit(env);                                                                                \
301     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                       \
302     Builtins##type##StubBuilder builder(this, glue, thisValue, numArgs, globalEnv);                 \
303     builder.method(&res, &exit, &slowPath);                                                         \
304     Bind(&slowPath);                                                                                \
305     {                                                                                               \
306         res = CallSlowPath(nativeCode, glue, globalEnv, thisValue, numArgs, func, newTarget);       \
307         Jump(&exit);                                                                                \
308     }                                                                                               \
309     Bind(&exit);                                                                                    \
310     Return(*res);                                                                                   \
311 }
312 
313 // map and set stub function
314 #define DECLARE_BUILTINS_COLLECTION_STUB_BUILDER(method, type, retDefaultValue, ...)                \
315 DECLARE_BUILTINS(type##method)                                                                      \
316 {                                                                                                   \
317     auto env = GetEnvironment();                                                                    \
318     DEFVARIABLE(res, VariableType::JS_ANY(), retDefaultValue);                                      \
319     Label slowPath(env);                                                                            \
320     Label exit(env);                                                                                \
321     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                       \
322     BuiltinsCollectionStubBuilder<JS##type> builder(this, glue, thisValue, numArgs, globalEnv);     \
323     builder.method(&res, &exit, &slowPath);                                                         \
324     Bind(&slowPath);                                                                                \
325     {                                                                                               \
326         res = CallSlowPath(nativeCode, glue, globalEnv, thisValue, numArgs, func, newTarget);       \
327         Jump(&exit);                                                                                \
328     }                                                                                               \
329     Bind(&exit);                                                                                    \
330     Return(*res);                                                                                   \
331 }
332 
333 // map and set stub function
334 #define DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER(method, type, numType, function, retDefaultValue, ...) \
335 DECLARE_BUILTINS(type##method)                                                                        \
336 {                                                                                                     \
337     auto env = GetEnvironment();                                                                      \
338     DEFVARIABLE(res, VariableType::JS_ANY(), retDefaultValue);                                        \
339     Label slowPath(env);                                                                              \
340     Label exit(env);                                                                                  \
341     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                         \
342     BuiltinsDataViewStubBuilder builder(this, globalEnv);                                             \
343     builder.function<DataViewType::numType>(glue, thisValue, numArgs, &res, &exit, &slowPath);        \
344     Bind(&slowPath);                                                                                  \
345     {                                                                                                 \
346         auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(type##method));                      \
347         res = CallSlowPath(nativeCode, glue, globalEnv, thisValue, numArgs, func, newTarget);         \
348         Jump(&exit);                                                                                  \
349     }                                                                                                 \
350     Bind(&exit);                                                                                      \
351     Return(*res);                                                                                     \
352 }
353 
BUILTINS_METHOD_STUB_LIST(DECLARE_BUILTINS_STUB_BUILDER,DECLARE_BUILTINS_STUB_BUILDER1,DECLARE_BUILTINS_COLLECTION_STUB_BUILDER,DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER)354 BUILTINS_METHOD_STUB_LIST(DECLARE_BUILTINS_STUB_BUILDER, DECLARE_BUILTINS_STUB_BUILDER1,
355                           DECLARE_BUILTINS_COLLECTION_STUB_BUILDER, DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER)
356 #undef DECLARE_BUILTINS_STUB_BUILDER
357 #undef DECLARE_BUILTINS_STUB_BUILDER1
358 #undef DECLARE_BUILTINS_COLLECTION_STUB_BUILDER
359 #undef DECLARE_BUILTINS_DATAVIEW_STUB_BUILDER
360 
361 DECLARE_BUILTINS(ArkToolsHashCode)
362 {
363     (void) nativeCode;
364     (void) func;
365     (void) newTarget;
366     (void) thisValue;
367     auto env = GetEnvironment();
368     GateRef key = GetCallArg0(numArgs);
369 
370     Label irHash(env);
371     Label rtHash(env);
372     BRANCH(IntPtrEqual(numArgs, IntPtr(1)), &irHash, &rtHash);
373     Bind(&irHash);
374     {
375         HashStubBuilder hashBuilder(this, glue);
376         GateRef hash = hashBuilder.GetHash(key);
377         Return(env->GetBuilder()->Int32ToTaggedPtr(hash));
378     }
379     Bind(&rtHash);
380     Return(CallRuntime(glue, RTSTUB_ID(GetLinkedHash), { key }));
381 }
382 
383 // aot and builtins public stub function
384 #define DECLARE_AOT_AND_BUILTINS_STUB_BUILDER(stubName, method, type, initValue)                    \
385 DECLARE_BUILTINS(stubName)                                                                          \
386 {                                                                                                   \
387     auto env = GetEnvironment();                                                                    \
388     DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
389     Label exit(env);                                                                                \
390     Label slowPath(env);                                                                            \
391     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                       \
392     Builtins##type##StubBuilder builder(this, globalEnv);                                           \
393     builder.method(glue, thisValue, numArgs, &res, &exit, &slowPath);                               \
394     Bind(&slowPath);                                                                                \
395     {                                                                                               \
396         res = CallSlowPath(nativeCode, glue, globalEnv, thisValue, numArgs, func, newTarget);       \
397         Jump(&exit);                                                                                \
398     }                                                                                               \
399     Bind(&exit);                                                                                    \
400     Return(*res);                                                                                   \
401 }
402 
403 // map and set iterator stub function
404 #define DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER(stubName, method, type, retDefaultValue)             \
405 DECLARE_BUILTINS(stubName)                                                                                     \
406 {                                                                                                              \
407     (void) nativeCode;                                                                                         \
408     (void) func;                                                                                               \
409     (void) newTarget;                                                                                          \
410     auto env = GetEnvironment();                                                                               \
411     DEFVARIABLE(res, VariableType::JS_ANY(), retDefaultValue);                                                 \
412     Label exit(env);                                                                                           \
413     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                                  \
414     BuiltinsCollectionIteratorStubBuilder<JS##type> builder(this, glue, thisValue, numArgs, globalEnv);        \
415     builder.method(&res, &exit);                                                                               \
416     Bind(&exit);                                                                                               \
417     Return(*res);                                                                                              \
418 }
419 
420 #if ENABLE_NEXT_OPTIMIZATION
421     #define NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)                                        \
422         V(ArrayIteratorProtoNext,  ArrayIteratorNext,   Array,            Undefined())               \
423         D(MapIteratorProtoNext,    Next,                MapIterator,      Undefined())               \
424         D(SetIteratorProtoNext,    Next,                SetIterator,      Undefined())
425 #else
426     #define NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)
427 #endif
428 
429 #define AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)                                              \
430     V(StringLocaleCompare,           LocaleCompare,        String,   Undefined())                 \
431     V(StringIteratorProtoNext,       StringIteratorNext,   String,   Undefined())                 \
432     V(ArraySort,                     Sort,                 Array,    Undefined())                 \
433     NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(V, D)
434 
AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(DECLARE_AOT_AND_BUILTINS_STUB_BUILDER,DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER)435 AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD(DECLARE_AOT_AND_BUILTINS_STUB_BUILDER,
436                                        DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER)
437 #undef NEXT_AOT_AND_BUILTINS_STUB_LIST_WITH_METHOD
438 #undef AOT_AND_BUILTINS_STUB_LIST
439 #undef DECLARE_AOT_AND_BUILTINS_STUB_BUILDER
440 #undef DECLARE_BUILTINS_COLLECTION_ITERATOR_STUB_BUILDER
441 
442 #define DECLARE_CONTAINERS_STUB_BUILDER(method, type, initValue)                                    \
443 DECLARE_BUILTINS(type##method)                                                                      \
444 {                                                                                                   \
445     auto env = GetEnvironment();                                                                    \
446     DEFVARIABLE(res, VariableType::JS_ANY(), initValue);                                            \
447     Label exit(env);                                                                                \
448     Label slowPath(env);                                                                            \
449     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                       \
450     Containers##type##StubBuilder builder(this, globalEnv);                                         \
451     builder.method(glue, thisValue, numArgs, &res, &exit, &slowPath);                               \
452     Bind(&slowPath);                                                                                \
453     {                                                                                               \
454         res = CallSlowPath(nativeCode, glue, globalEnv, thisValue, numArgs, func, newTarget);       \
455         Jump(&exit);                                                                                \
456     }                                                                                               \
457     Bind(&exit);                                                                                    \
458     Return(*res);                                                                                   \
459 }
460 
461 BUILTINS_CONTAINERS_STUB_BUILDER(DECLARE_CONTAINERS_STUB_BUILDER)
462 #undef DECLARE_CONTAINERS_STUB_BUILDER
463 
464 DECLARE_BUILTINS(BooleanConstructor)
465 {
466     auto env = GetEnvironment();
467     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
468 
469     Label newTargetIsHeapObject(env);
470     Label newTargetIsJSFunction(env);
471     Label slowPath(env);
472     Label slowPath1(env);
473     Label exit(env);
474 
475     BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
476     Bind(&newTargetIsHeapObject);
477     BRANCH(IsJSFunction(glue, newTarget), &newTargetIsJSFunction, &slowPath);
478     Bind(&newTargetIsJSFunction);
479     {
480         Label intialHClassIsHClass(env);
481         GateRef intialHClass = Load(VariableType::JS_ANY(), glue, newTarget,
482                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
483         BRANCH(IsJSHClass(glue, intialHClass), &intialHClassIsHClass, &slowPath1);
484         Bind(&intialHClassIsHClass);
485         {
486             NewObjectStubBuilder newBuilder(this);
487             newBuilder.SetParameters(glue, 0);
488             Label afterNew(env);
489             newBuilder.NewJSObject(&res, &afterNew, intialHClass);
490             Bind(&afterNew);
491             {
492                 GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
493                 GateRef value = GetArgFromArgv(glue, IntPtr(0), numArgs, true);
494                 Store(VariableType::INT64(), glue, *res, valueOffset, FastToBoolean(glue, value));
495                 Jump(&exit);
496             }
497         }
498         Bind(&slowPath1);
499         {
500             GateRef argv = GetArgv();
501             auto args = { glue, nativeCode, func, thisValue, numArgs, argv, newTarget };
502             res = CallBuiltinRuntimeWithNewTarget(glue, args);
503             Jump(&exit);
504         }
505     }
506     Bind(&slowPath);
507     {
508         GateRef argv = GetArgv();
509         auto args = { glue, nativeCode, func, thisValue, numArgs, argv };
510         res = CallBuiltinRuntime(glue, args, true);
511         Jump(&exit);
512     }
513     Bind(&exit);
514     Return(*res);
515 }
516 
DECLARE_BUILTINS(DateConstructor)517 DECLARE_BUILTINS(DateConstructor)
518 {
519     auto env = GetEnvironment();
520     DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
521 
522     Label newTargetIsHeapObject(env);
523     Label newTargetIsJSFunction(env);
524     Label slowPath(env);
525     Label exit(env);
526 
527     BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath);
528     Bind(&newTargetIsHeapObject);
529     BRANCH(IsJSFunction(glue, newTarget), &newTargetIsJSFunction, &slowPath);
530     Bind(&newTargetIsJSFunction);
531     {
532         Label intialHClassIsHClass(env);
533         GateRef intialHClass = Load(VariableType::JS_ANY(), glue, newTarget,
534                                     IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
535         BRANCH(IsJSHClass(glue, intialHClass), &intialHClassIsHClass, &slowPath);
536         Bind(&intialHClassIsHClass);
537         {
538             Label oneArg(env);
539             Label notOneArg(env);
540             Label newJSDate(env);
541             DEFVARIABLE(timeValue, VariableType::FLOAT64(), Double(0));
542             BRANCH(Int64Equal(numArgs, IntPtr(1)), &oneArg, &notOneArg);
543             Bind(&oneArg);
544             {
545                 Label valueIsNumber(env);
546                 GateRef value = GetArgFromArgv(glue, IntPtr(0));
547                 BRANCH(TaggedIsNumber(value), &valueIsNumber, &slowPath);
548                 Bind(&valueIsNumber);
549                 {
550                     timeValue = CallNGCRuntime(glue, RTSTUB_ID(TimeClip), {GetDoubleOfTNumber(value)});
551                     Jump(&newJSDate);
552                 }
553             }
554             Bind(&notOneArg);
555             {
556                 Label threeArgs(env);
557                 BRANCH(Int64Equal(numArgs, IntPtr(3)), &threeArgs, &slowPath);  // 3: year month day
558                 Bind(&threeArgs);
559                 {
560                     Label numberYearMonthDay(env);
561                     GateRef year = GetArgFromArgv(glue, IntPtr(0));
562                     GateRef month = GetArgFromArgv(glue, IntPtr(1));
563                     GateRef day = GetArgFromArgv(glue, IntPtr(2));
564                     BRANCH(IsNumberYearMonthDay(year, month, day), &numberYearMonthDay, &slowPath);
565                     Bind(&numberYearMonthDay);
566                     {
567                         GateRef y = GetDoubleOfTNumber(year);
568                         GateRef m = GetDoubleOfTNumber(month);
569                         GateRef d = GetDoubleOfTNumber(day);
570                         timeValue = CallNGCRuntime(glue, RTSTUB_ID(SetDateValues), {y, m, d});
571                         Jump(&newJSDate);
572                     }
573                 }
574             }
575             Bind(&newJSDate);
576             {
577                 NewObjectStubBuilder newBuilder(this);
578                 newBuilder.SetParameters(glue, 0);
579                 Label afterNew(env);
580                 newBuilder.NewJSObject(&res, &afterNew, intialHClass);
581                 Bind(&afterNew);
582                 {
583                     GateRef timeValueOffset = IntPtr(JSDate::TIME_VALUE_OFFSET);
584                     Store(VariableType::JS_NOT_POINTER(), glue, *res, timeValueOffset,
585                           DoubleToTaggedDoublePtr(*timeValue));
586                     Jump(&exit);
587                 }
588             }
589         }
590     }
591     Bind(&slowPath);
592     {
593         GateRef argv = GetArgv();
594         res = CallBuiltinRuntimeWithNewTarget(glue, {glue, nativeCode, func, thisValue, numArgs, argv, newTarget});
595         Jump(&exit);
596     }
597     Bind(&exit);
598     Return(*res);
599 }
600 
DECLARE_BUILTINS(NumberConstructor)601 DECLARE_BUILTINS(NumberConstructor)
602 {
603     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);
604     BuiltinsNumberStubBuilder builder(this, glue, thisValue, numArgs, globalEnv);
605     builder.GenNumberConstructor(nativeCode, func, newTarget);
606 }
607 
DECLARE_BUILTINS(ProxyConstructor)608 DECLARE_BUILTINS(ProxyConstructor)
609 {
610     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);
611     BuiltinsProxyStubBuilder builder(this, glue, thisValue, numArgs, globalEnv);
612     builder.GenProxyConstructor(nativeCode, func, newTarget);
613 }
614 
DECLARE_BUILTINS(ArrayConstructor)615 DECLARE_BUILTINS(ArrayConstructor)
616 {
617     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);
618     BuiltinsArrayStubBuilder builder(this, globalEnv);
619     builder.GenArrayConstructor(glue, nativeCode, func, newTarget, thisValue, numArgs);
620 }
621 
DECLARE_BUILTINS(MapConstructor)622 DECLARE_BUILTINS(MapConstructor)
623 {
624     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);
625     LinkedHashTableStubBuilder<LinkedHashMap, LinkedHashMapObject> hashTableBuilder(this, glue, globalEnv);
626     GateRef arg0 = GetArgFromArgv(glue, IntPtr(0), numArgs, true);
627     hashTableBuilder.GenMapSetConstructor(nativeCode, func, newTarget, thisValue, numArgs, arg0, GetArgv());
628 }
629 
DECLARE_BUILTINS(SetConstructor)630 DECLARE_BUILTINS(SetConstructor)
631 {
632     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);
633     LinkedHashTableStubBuilder<LinkedHashSet, LinkedHashSetObject> hashTableBuilder(this, glue, globalEnv);
634     GateRef arg0 = GetArgFromArgv(glue, IntPtr(0), numArgs, true);
635     hashTableBuilder.GenMapSetConstructor(nativeCode, func, newTarget, thisValue, numArgs, arg0, GetArgv());
636 }
637 
638 #define DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER(TYPE, type, index)                                \
639 DECLARE_BUILTINS(type##ArrayConstructor)                                                            \
640 {                                                                                                   \
641     GateRef ctorName = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,                     \
642                                               ConstantIndex::TYPE##_ARRAY_STRING_INDEX);            \
643     GateRef globalEnv = GetGlobalEnvFromFunction(glue, func);                                       \
644     BuiltinsTypedArrayStubBuilder builtinsTypedArrayStubBuilder(this, globalEnv);                   \
645     builtinsTypedArrayStubBuilder.GenTypedArrayConstructor(glue, nativeCode, func, newTarget,       \
646         thisValue, numArgs, ctorName, DataViewType::TYPE);                                          \
647 }
648 BUILTIN_COMPILER_TYPED_ARRAY_TYPES(DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER)
649 #undef DECLARE_BUILTINS_TYPED_ARRAY_STUB_BUILDER
650 }  // namespace panda::ecmascript::kungfu
651