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, ¬callThis0);
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(¬callThis0);
114 {
115 Branch(Int64Equal(numArgs, IntPtr(1)), &callThis1, ¬callThis1);
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(¬callThis1);
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, ¬OneArg);
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(¬OneArg);
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