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