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, ¬callThis0);
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(¬callThis0);
206 {
207 BRANCH(Int64Equal(numArgs, IntPtr(1)), &callThis1, ¬callThis1);
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(¬callThis1);
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, ¬OneArg);
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(¬OneArg);
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