1 /*
2 * Copyright (c) 2021-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/builtins/builtins_ark_tools.h"
17
18 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
19 #include "ecmascript/dfx/vmstat/opt_code_profiler.h"
20 #include "ecmascript/mem/verification.h"
21 #include "ecmascript/property_detector-inl.h"
22 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
23 #include "ecmascript/linked_hash_table.h"
24 #include "builtins_typedarray.h"
25 #include "ecmascript/jit/jit.h"
26
27 #if defined(PANDA_TARGET_ARM64)
28 /* Note: If not open ArkTools option(set by `persist.ark.mem_config_property openArkTools`), */
29 /* ArkTools return Empty Implementation */
30 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
31 #define RETURN_IF_DISALLOW_ARKTOOLS(thread) \
32 do { \
33 if (!((thread)->GetEcmaVM()->GetJSOptions().IsOpenArkTools())) { \
34 return JSTaggedValue::Undefined(); \
35 } \
36 } while (0)
37 #else
38 #define RETURN_IF_DISALLOW_ARKTOOLS(thread) static_cast<void>(0) // NOLINT(cppcoreguidelines-macro-usage)
39 #endif
40
41 namespace panda::ecmascript::builtins {
42 using StringHelper = base::StringHelper;
43
44 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
45 constexpr char FILEDIR[] = "/data/storage/el2/base/files/";
46 #endif
47
ObjectDump(EcmaRuntimeCallInfo * info)48 JSTaggedValue BuiltinsArkTools::ObjectDump(EcmaRuntimeCallInfo *info)
49 {
50 ASSERT(info);
51 JSThread *thread = info->GetThread();
52 RETURN_IF_DISALLOW_ARKTOOLS(thread);
53 [[maybe_unused]] EcmaHandleScope handleScope(thread);
54
55 JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, GetCallArg(info, 0));
56 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
57 // The default log level of ace_engine and js_runtime is error
58 LOG_ECMA(ERROR) << ": " << EcmaStringAccessor(str).ToStdString();
59
60 uint32_t numArgs = info->GetArgsNumber();
61 for (uint32_t i = 1; i < numArgs; i++) {
62 JSHandle<JSTaggedValue> obj = GetCallArg(info, i);
63 std::ostringstream oss;
64 obj->Dump(oss);
65
66 // The default log level of ace_engine and js_runtime is error
67 LOG_ECMA(ERROR) << ": " << oss.str();
68 }
69
70 return JSTaggedValue::Undefined();
71 }
72
CompareHClass(EcmaRuntimeCallInfo * info)73 JSTaggedValue BuiltinsArkTools::CompareHClass(EcmaRuntimeCallInfo *info)
74 {
75 ASSERT(info);
76 JSThread *thread = info->GetThread();
77 RETURN_IF_DISALLOW_ARKTOOLS(thread);
78 [[maybe_unused]] EcmaHandleScope handleScope(thread);
79
80 JSHandle<JSTaggedValue> obj1 = GetCallArg(info, 0);
81 JSHandle<JSTaggedValue> obj2 = GetCallArg(info, 1);
82 JSHClass *obj1Hclass = obj1->GetTaggedObject()->GetClass();
83 JSHClass *obj2Hclass = obj2->GetTaggedObject()->GetClass();
84 std::ostringstream oss;
85 obj1Hclass->Dump(oss);
86 obj2Hclass->Dump(oss);
87 bool res = (obj1Hclass == obj2Hclass);
88 if (!res) {
89 LOG_ECMA(ERROR) << "These two object don't share the same hclass:" << oss.str();
90 }
91 return JSTaggedValue(res);
92 }
93
DumpHClass(EcmaRuntimeCallInfo * info)94 JSTaggedValue BuiltinsArkTools::DumpHClass(EcmaRuntimeCallInfo *info)
95 {
96 ASSERT(info);
97 JSThread *thread = info->GetThread();
98 RETURN_IF_DISALLOW_ARKTOOLS(thread);
99 [[maybe_unused]] EcmaHandleScope handleScope(thread);
100
101 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
102 JSHClass *objHclass = obj->GetTaggedObject()->GetClass();
103 std::ostringstream oss;
104 objHclass->Dump(oss);
105
106 LOG_ECMA(ERROR) << "hclass:" << oss.str();
107 return JSTaggedValue::Undefined();
108 }
109
GetInlinedPropertiesCount(EcmaRuntimeCallInfo * info)110 JSTaggedValue BuiltinsArkTools::GetInlinedPropertiesCount(EcmaRuntimeCallInfo *info)
111 {
112 ASSERT(info);
113 JSThread *thread = info->GetThread();
114 RETURN_IF_DISALLOW_ARKTOOLS(thread);
115 [[maybe_unused]] EcmaHandleScope handleScope(thread);
116
117 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
118 JSHClass *objHclass = obj->GetTaggedObject()->GetClass();
119 return JSTaggedValue(objHclass->GetInlinedProperties());
120 }
121
IsTSHClass(EcmaRuntimeCallInfo * info)122 JSTaggedValue BuiltinsArkTools::IsTSHClass(EcmaRuntimeCallInfo *info)
123 {
124 ASSERT(info);
125 JSThread *thread = info->GetThread();
126 RETURN_IF_DISALLOW_ARKTOOLS(thread);
127 [[maybe_unused]] EcmaHandleScope handleScope(thread);
128
129 ASSERT(info->GetArgsNumber() == 1);
130 JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
131 JSHClass *hclass = object->GetTaggedObject()->GetClass();
132 bool isAOTHClass = hclass->IsAOT();
133 return GetTaggedBoolean(isAOTHClass);
134 }
135
GetHClass(EcmaRuntimeCallInfo * info)136 JSTaggedValue BuiltinsArkTools::GetHClass(EcmaRuntimeCallInfo *info)
137 {
138 ASSERT(info);
139 JSThread *thread = info->GetThread();
140 RETURN_IF_DISALLOW_ARKTOOLS(thread);
141 [[maybe_unused]] EcmaHandleScope handleScope(thread);
142
143 ASSERT(info->GetArgsNumber() == 1);
144 JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
145 JSHClass *hclass = object->GetTaggedObject()->GetClass();
146 return JSTaggedValue(hclass);
147 }
148
IsSlicedString(EcmaRuntimeCallInfo * info)149 JSTaggedValue BuiltinsArkTools::IsSlicedString(EcmaRuntimeCallInfo *info)
150 {
151 ASSERT(info);
152 JSThread *thread = info->GetThread();
153 RETURN_IF_DISALLOW_ARKTOOLS(thread);
154 [[maybe_unused]] EcmaHandleScope handleScope(thread);
155
156 ASSERT(info->GetArgsNumber() == 1);
157 JSHandle<JSTaggedValue> str = GetCallArg(info, 0);
158 return GetTaggedBoolean(str->IsSlicedString());
159 }
160
IsTreeString(EcmaRuntimeCallInfo * info)161 JSTaggedValue BuiltinsArkTools::IsTreeString(EcmaRuntimeCallInfo *info)
162 {
163 ASSERT(info);
164 JSThread *thread = info->GetThread();
165 RETURN_IF_DISALLOW_ARKTOOLS(thread);
166 [[maybe_unused]] EcmaHandleScope handleScope(thread);
167
168 ASSERT(info->GetArgsNumber() == 1);
169 JSHandle<JSTaggedValue> str = GetCallArg(info, 0);
170 return GetTaggedBoolean(str->IsTreeString());
171 }
172
IsStableJsArray(EcmaRuntimeCallInfo * info)173 JSTaggedValue BuiltinsArkTools::IsStableJsArray(EcmaRuntimeCallInfo *info)
174 {
175 DISALLOW_GARBAGE_COLLECTION;
176 ASSERT(info);
177 JSThread *thread = info->GetThread();
178 RETURN_IF_DISALLOW_ARKTOOLS(thread);
179 [[maybe_unused]] EcmaHandleScope handleScope(thread);
180
181 ASSERT(info->GetArgsNumber() == 1);
182 JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
183 return (object->IsStableJSArray(thread)) ?
184 GetTaggedBoolean(true) : GetTaggedBoolean(false);
185 }
186
HasConstructor(EcmaRuntimeCallInfo * info)187 JSTaggedValue BuiltinsArkTools::HasConstructor(EcmaRuntimeCallInfo *info)
188 {
189 DISALLOW_GARBAGE_COLLECTION;
190 ASSERT(info);
191 JSThread *thread = info->GetThread();
192 RETURN_IF_DISALLOW_ARKTOOLS(thread);
193 [[maybe_unused]] EcmaHandleScope handleScope(thread);
194
195 ASSERT(info->GetArgsNumber() == 1);
196 JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
197 return (object->IsHeapObject() && object->GetHeapObject()->GetClass()->HasConstructor()) ?
198 GetTaggedBoolean(true) : GetTaggedBoolean(false);
199 }
200
IsNotHoleProperty(EcmaRuntimeCallInfo * info)201 JSTaggedValue BuiltinsArkTools::IsNotHoleProperty(EcmaRuntimeCallInfo *info)
202 {
203 DISALLOW_GARBAGE_COLLECTION;
204 ASSERT(info);
205 JSThread *thread = info->GetThread();
206 RETURN_IF_DISALLOW_ARKTOOLS(thread);
207 [[maybe_unused]] EcmaHandleScope handleScope(thread);
208
209 ASSERT(info->GetArgsNumber() == 2); // 2 : object and key
210 JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
211 JSTaggedValue key = GetCallArg(info, 1).GetTaggedValue();
212 JSHClass *hclass = object->GetTaggedObject()->GetClass();
213 int entry = JSHClass::FindPropertyEntry(thread, hclass, key);
214 if (entry == -1) {
215 return GetTaggedBoolean(false);
216 }
217 PropertyAttributes attr = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject())->GetAttr(entry);
218 return GetTaggedBoolean(attr.IsNotHole());
219 }
220
HiddenStackSourceFile(EcmaRuntimeCallInfo * info)221 JSTaggedValue BuiltinsArkTools::HiddenStackSourceFile(EcmaRuntimeCallInfo *info)
222 {
223 DISALLOW_GARBAGE_COLLECTION;
224 ASSERT(info);
225 JSThread *thread = info->GetThread();
226 RETURN_IF_DISALLOW_ARKTOOLS(thread);
227 thread->SetEnableStackSourceFile(false);
228 return JSTaggedValue::True();
229 }
230
ExcutePendingJob(EcmaRuntimeCallInfo * info)231 JSTaggedValue BuiltinsArkTools::ExcutePendingJob(EcmaRuntimeCallInfo *info)
232 {
233 ASSERT(info);
234 JSThread *thread = info->GetThread();
235 RETURN_IF_DISALLOW_ARKTOOLS(thread);
236 [[maybe_unused]] EcmaHandleScope handleScope(thread);
237
238 thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
239 return JSTaggedValue::True();
240 }
241
GetLexicalEnv(EcmaRuntimeCallInfo * info)242 JSTaggedValue BuiltinsArkTools::GetLexicalEnv(EcmaRuntimeCallInfo *info)
243 {
244 ASSERT(info);
245 JSThread *thread = info->GetThread();
246 RETURN_IF_DISALLOW_ARKTOOLS(thread);
247 [[maybe_unused]] EcmaHandleScope handleScope(thread);
248
249 ASSERT(info->GetArgsNumber() == 1);
250 JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
251 if (object->IsHeapObject() && object->IsJSFunction()) {
252 JSHandle<JSFunction> function = JSHandle<JSFunction>::Cast(object);
253 return function->GetLexicalEnv();
254 }
255 return JSTaggedValue::Null();
256 }
257
ForceFullGC(EcmaRuntimeCallInfo * info)258 JSTaggedValue BuiltinsArkTools::ForceFullGC(EcmaRuntimeCallInfo *info)
259 {
260 ASSERT(info);
261 JSThread *thread = info->GetThread();
262 std::string data = JsStackInfo::BuildJsStackTrace(thread, true);
263 LOG_ECMA(INFO) << "ArkTools ForceFullGC " << data;
264
265 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
266 heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::TRIGGER_BY_JS);
267 SharedHeap::GetInstance()->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::TRIGGER_BY_JS>(
268 thread);
269 heap->GetHeapPrepare();
270 return JSTaggedValue::True();
271 }
272
HintGC(EcmaRuntimeCallInfo * info)273 JSTaggedValue BuiltinsArkTools::HintGC(EcmaRuntimeCallInfo *info)
274 {
275 ASSERT(info);
276 JSThread *thread = info->GetThread();
277 int value = 0;
278 if (info->GetArgsNumber() == 1) {
279 value = JSTaggedValue::ToInt8(thread, GetCallArg(info, 0));
280 if (value < static_cast<int>(MemoryReduceDegree::LOW)
281 || value > static_cast<int>(MemoryReduceDegree::HIGH)) {
282 CString errorMsg = "ArkTools.hintGC parameter value should be larger than "
283 + ToCString(static_cast<int>(MemoryReduceDegree::LOW))
284 + "and less than "
285 + ToCString(static_cast<int>(MemoryReduceDegree::HIGH));
286 THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::ERROR, errorMsg.c_str(),
287 JSTaggedValue::Exception());
288 }
289 }
290 return JSTaggedValue(const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->
291 CheckAndTriggerHintGC(MemoryReduceDegree(value), GCReason::TRIGGER_BY_JS));
292 }
293
RemoveAOTFlag(EcmaRuntimeCallInfo * info)294 JSTaggedValue BuiltinsArkTools::RemoveAOTFlag(EcmaRuntimeCallInfo *info)
295 {
296 ASSERT(info);
297 JSThread *thread = info->GetThread();
298 RETURN_IF_DISALLOW_ARKTOOLS(thread);
299 [[maybe_unused]] EcmaHandleScope handleScope(thread);
300
301 ASSERT(info->GetArgsNumber() == 1);
302 JSHandle<JSTaggedValue> object = GetCallArg(info, 0);
303 if (object->IsHeapObject() && object->IsJSFunction()) {
304 JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(object);
305 JSHandle<Method> method = JSHandle<Method>(thread, func->GetMethod());
306 method->SetAotCodeBit(false);
307 }
308
309 return JSTaggedValue::Undefined();
310 }
311
CheckCircularImport(EcmaRuntimeCallInfo * info)312 JSTaggedValue BuiltinsArkTools::CheckCircularImport(EcmaRuntimeCallInfo *info)
313 {
314 ASSERT(info);
315 JSThread *thread = info->GetThread();
316 RETURN_IF_DISALLOW_ARKTOOLS(thread);
317 [[maybe_unused]] EcmaHandleScope handleScope(thread);
318 JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, GetCallArg(info, 0));
319 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
320 bool printOtherCircular = false;
321 if (info->GetArgsNumber() == 2) { // 2: input number
322 printOtherCircular = GetCallArg(info, 1).GetTaggedValue().ToBoolean();
323 }
324 CList<CString> referenceList;
325 // str: bundleName/moduleName/xxx/xxx
326 CString string = ConvertToString(str.GetTaggedValue());
327 LOG_ECMA(INFO) << "checkCircularImport begin with: "<< string;
328 SourceTextModule::CheckCircularImportTool(thread, string, referenceList, printOtherCircular);
329 return JSTaggedValue::Undefined();
330 }
331
HashCode(EcmaRuntimeCallInfo * info)332 JSTaggedValue BuiltinsArkTools::HashCode(EcmaRuntimeCallInfo *info)
333 {
334 ASSERT(info);
335 JSThread *thread = info->GetThread();
336 RETURN_IF_DISALLOW_ARKTOOLS(thread);
337 [[maybe_unused]] EcmaHandleScope handleScope(thread);
338 JSHandle<JSTaggedValue> key = GetCallArg(info, 0);
339 return JSTaggedValue(LinkedHash::Hash(thread, key.GetTaggedValue()));
340 }
341
PrintMegaICStat(EcmaRuntimeCallInfo * info)342 JSTaggedValue BuiltinsArkTools::PrintMegaICStat(EcmaRuntimeCallInfo *info)
343 {
344 JSThread *thread = info->GetThread();
345 BUILTINS_API_TRACE(thread, Global, PrintMegaICStat);
346 [[maybe_unused]] EcmaHandleScope handleScope(thread);
347 // start vm runtime stat statistic
348 #if ECMASCRIPT_ENABLE_MEGA_PROFILER
349 thread->GetCurrentEcmaContext()->PrintMegaICStat();
350 #endif
351 return JSTaggedValue::Undefined();
352 }
353
354 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
StartCpuProfiler(EcmaRuntimeCallInfo * info)355 JSTaggedValue BuiltinsArkTools::StartCpuProfiler(EcmaRuntimeCallInfo *info)
356 {
357 ASSERT(info);
358 JSThread *thread = info->GetThread();
359 RETURN_IF_DISALLOW_ARKTOOLS(thread);
360 [[maybe_unused]] EcmaHandleScope handleScope(thread);
361
362 auto vm = thread->GetEcmaVM();
363
364 // get file name
365 JSHandle<JSTaggedValue> fileNameValue = GetCallArg(info, 0);
366 std::string fileName = "";
367 if (fileNameValue->IsString()) {
368 JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, fileNameValue);
369 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
370 fileName = EcmaStringAccessor(str).ToStdString() + ".cpuprofile";
371 } else {
372 fileName = GetProfileName();
373 }
374
375 if (!CreateFile(fileName)) {
376 LOG_ECMA(ERROR) << "CreateFile failed " << fileName;
377 }
378
379 // get sampling interval
380 JSHandle<JSTaggedValue> samplingIntervalValue = GetCallArg(info, 1);
381 uint32_t interval = 500; // 500:Default Sampling interval 500 microseconds
382 if (samplingIntervalValue->IsNumber()) {
383 interval = JSTaggedValue::ToUint32(thread, samplingIntervalValue);
384 }
385
386 DFXJSNApi::StartCpuProfilerForFile(vm, fileName, interval);
387 return JSTaggedValue::Undefined();
388 }
389
StopCpuProfiler(EcmaRuntimeCallInfo * info)390 JSTaggedValue BuiltinsArkTools::StopCpuProfiler(EcmaRuntimeCallInfo *info)
391 {
392 JSThread *thread = info->GetThread();
393 RETURN_IF_DISALLOW_ARKTOOLS(thread);
394 [[maybe_unused]] EcmaHandleScope handleScope(thread);
395 auto vm = thread->GetEcmaVM();
396 DFXJSNApi::StopCpuProfilerForFile(vm);
397
398 return JSTaggedValue::Undefined();
399 }
400
GetProfileName()401 std::string BuiltinsArkTools::GetProfileName()
402 {
403 char time1[16] = {0}; // 16:Time format length
404 char time2[16] = {0}; // 16:Time format length
405 time_t timep = std::time(nullptr);
406 struct tm nowTime1;
407 localtime_r(&timep, &nowTime1);
408 size_t result = 0;
409 result = strftime(time1, sizeof(time1), "%Y%m%d", &nowTime1);
410 if (result == 0) {
411 LOG_ECMA(ERROR) << "get time failed";
412 return "";
413 }
414 result = strftime(time2, sizeof(time2), "%H%M%S", &nowTime1);
415 if (result == 0) {
416 LOG_ECMA(ERROR) << "get time failed";
417 return "";
418 }
419 std::string profileName = "cpuprofile-";
420 profileName += time1;
421 profileName += "TO";
422 profileName += time2;
423 profileName += ".cpuprofile";
424 return profileName;
425 }
426
CreateFile(std::string & fileName)427 bool BuiltinsArkTools::CreateFile(std::string &fileName)
428 {
429 std::string path = FILEDIR + fileName;
430 if (access(path.c_str(), F_OK) == 0) {
431 if (access(path.c_str(), W_OK) == 0) {
432 fileName = path;
433 return true;
434 }
435 LOG_ECMA(ERROR) << "file create failed, W_OK false";
436 return false;
437 }
438 const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IRGRP; // -rw-r--
439 int fd = creat(path.c_str(), defaultMode);
440 if (fd == -1) {
441 fd = creat(fileName.c_str(), defaultMode);
442 if (fd == -1) {
443 LOG_ECMA(ERROR) << "file create failed, errno = "<< errno;
444 return false;
445 }
446 close(fd);
447 return true;
448 } else {
449 fileName = path;
450 close(fd);
451 return true;
452 }
453 }
454 #endif
455
456 // It is used to check whether an object is a proto, and this function can be
457 // used to check whether the state machine of IC is faulty.
IsPrototype(EcmaRuntimeCallInfo * info)458 JSTaggedValue BuiltinsArkTools::IsPrototype(EcmaRuntimeCallInfo *info)
459 {
460 ASSERT(info);
461 JSThread *thread = info->GetThread();
462 RETURN_IF_DISALLOW_ARKTOOLS(thread);
463 [[maybe_unused]] EcmaHandleScope handleScope(thread);
464
465 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
466 JSHClass *objHclass = obj->GetTaggedObject()->GetClass();
467 return JSTaggedValue(objHclass->IsPrototype());
468 }
469
470 // It is used to check whether a function is aot compiled.
IsAOTCompiled(EcmaRuntimeCallInfo * info)471 JSTaggedValue BuiltinsArkTools::IsAOTCompiled(EcmaRuntimeCallInfo *info)
472 {
473 ASSERT(info);
474 JSThread *thread = info->GetThread();
475 RETURN_IF_DISALLOW_ARKTOOLS(thread);
476 [[maybe_unused]] EcmaHandleScope handleScope(thread);
477
478 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
479 JSHandle<JSFunction> func(thread, obj.GetTaggedValue());
480 return JSTaggedValue(func->IsCompiledCode());
481 }
482
483 // It is used to check whether two functions have same profileTypeInfo
IsSameProfileTypeInfo(EcmaRuntimeCallInfo * info)484 JSTaggedValue BuiltinsArkTools::IsSameProfileTypeInfo(EcmaRuntimeCallInfo *info)
485 {
486 ASSERT(info);
487 JSThread *thread = info->GetThread();
488 RETURN_IF_DISALLOW_ARKTOOLS(thread);
489 [[maybe_unused]] EcmaHandleScope handleScope(thread);
490 JSHandle<JSFunction> func0 = JSHandle<JSFunction>::Cast(GetCallArg(info, 0));
491 JSHandle<JSFunction> func1 = JSHandle<JSFunction>::Cast(GetCallArg(info, 1));
492 return JSTaggedValue(func0->GetProfileTypeInfo() == func1->GetProfileTypeInfo());
493 }
494
495 // It is used to check whether a function has valid profileTypeInfo
IsProfileTypeInfoValid(EcmaRuntimeCallInfo * info)496 JSTaggedValue BuiltinsArkTools::IsProfileTypeInfoValid(EcmaRuntimeCallInfo *info)
497 {
498 ASSERT(info);
499 JSThread *thread = info->GetThread();
500 RETURN_IF_DISALLOW_ARKTOOLS(thread);
501 [[maybe_unused]] EcmaHandleScope handleScope(thread);
502 JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(GetCallArg(info, 0));
503 return JSTaggedValue(func->GetProfileTypeInfo().IsTaggedArray());
504 }
505
IsOnHeap(EcmaRuntimeCallInfo * info)506 JSTaggedValue BuiltinsArkTools::IsOnHeap(EcmaRuntimeCallInfo *info)
507 {
508 ASSERT(info);
509 JSThread *thread = info->GetThread();
510 RETURN_IF_DISALLOW_ARKTOOLS(thread);
511 [[maybe_unused]] EcmaHandleScope handleScope(thread);
512
513 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
514 return JSTaggedValue(obj.GetTaggedValue().GetTaggedObject()->GetClass()->IsOnHeapFromBitField());
515 }
516
517 // It is used to check whether a function is aot compiled and deopted at runtime.
IsAOTDeoptimized(EcmaRuntimeCallInfo * info)518 JSTaggedValue BuiltinsArkTools::IsAOTDeoptimized(EcmaRuntimeCallInfo *info)
519 {
520 ASSERT(info);
521 JSThread *thread = info->GetThread();
522 RETURN_IF_DISALLOW_ARKTOOLS(thread);
523 [[maybe_unused]] EcmaHandleScope handleScope(thread);
524
525 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
526 JSHandle<JSFunction> func(thread, obj.GetTaggedValue());
527 bool isAotCompiled = func->IsCompiledCode();
528 if (isAotCompiled) {
529 Method *method = func->GetCallTarget();
530 uint32_t deoptedCount = method->GetDeoptThreshold();
531 uint32_t deoptThreshold = thread->GetEcmaVM()->GetJSOptions().GetDeoptThreshold();
532 return JSTaggedValue(deoptedCount != deoptThreshold);
533 }
534
535 return JSTaggedValue(false);
536 }
537
CheckDeoptStatus(EcmaRuntimeCallInfo * info)538 JSTaggedValue BuiltinsArkTools::CheckDeoptStatus(EcmaRuntimeCallInfo *info)
539 {
540 ASSERT(info);
541 JSThread *thread = info->GetThread();
542 RETURN_IF_DISALLOW_ARKTOOLS(thread);
543 [[maybe_unused]] EcmaHandleScope handleScope(thread);
544
545 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
546 JSHandle<JSFunction> func(thread, obj.GetTaggedValue());
547 Method *method = func->GetCallTarget();
548 bool isAotCompiled = func->IsCompiledCode();
549 uint16_t threshold = method->GetDeoptThreshold();
550 if (threshold > 0) {
551 return JSTaggedValue(isAotCompiled);
552 }
553 // check status before deopt
554 JSHandle<JSTaggedValue> hasDeopt = GetCallArg(info, 1);
555 if (hasDeopt->IsFalse()) {
556 return JSTaggedValue(!isAotCompiled);
557 }
558 if (!hasDeopt->IsTrue()) {
559 return JSTaggedValue(false);
560 }
561 // check status after deopt
562 if (isAotCompiled ||
563 func->IsCompiledFastCall() ||
564 method->GetDeoptType() != kungfu::DeoptType::NONE ||
565 method->GetCodeEntryOrLiteral() == 0) {
566 return JSTaggedValue(false);
567 }
568 return JSTaggedValue(true);
569 }
570
PrintTypedOpProfiler(EcmaRuntimeCallInfo * info)571 JSTaggedValue BuiltinsArkTools::PrintTypedOpProfiler(EcmaRuntimeCallInfo *info)
572 {
573 ASSERT(info);
574 JSThread *thread = info->GetThread();
575 RETURN_IF_DISALLOW_ARKTOOLS(thread);
576 [[maybe_unused]] EcmaHandleScope handleScope(thread);
577
578 JSHandle<JSTaggedValue> opStrVal = GetCallArg(info, 0);
579 std::string opStr = EcmaStringAccessor(opStrVal.GetTaggedValue()).ToStdString();
580 TypedOpProfiler *profiler = thread->GetCurrentEcmaContext()->GetTypdOpProfiler();
581 if (profiler != nullptr) {
582 profiler->Print(opStr);
583 }
584 return JSTaggedValue::Undefined();
585 }
586
ClearTypedOpProfiler(EcmaRuntimeCallInfo * info)587 JSTaggedValue BuiltinsArkTools::ClearTypedOpProfiler(EcmaRuntimeCallInfo *info)
588 {
589 ASSERT(info);
590 JSThread *thread = info->GetThread();
591 RETURN_IF_DISALLOW_ARKTOOLS(thread);
592 [[maybe_unused]] EcmaHandleScope handleScope(thread);
593
594 TypedOpProfiler *profiler = thread->GetCurrentEcmaContext()->GetTypdOpProfiler();
595 if (profiler != nullptr) {
596 profiler->Clear();
597 }
598 return JSTaggedValue::Undefined();
599 }
600
GetAPIVersion(EcmaRuntimeCallInfo * info)601 JSTaggedValue BuiltinsArkTools::GetAPIVersion(EcmaRuntimeCallInfo *info)
602 {
603 ASSERT(info);
604 JSThread *thread = info->GetThread();
605 RETURN_IF_DISALLOW_ARKTOOLS(thread);
606 [[maybe_unused]] EcmaHandleScope handleScope(thread);
607
608 return JSTaggedValue(thread->GetEcmaVM()->GetVMAPIVersion());
609 }
610
SetAPIVersion(EcmaRuntimeCallInfo * info)611 JSTaggedValue BuiltinsArkTools::SetAPIVersion(EcmaRuntimeCallInfo *info)
612 {
613 ASSERT(info);
614 JSThread *thread = info->GetThread();
615 RETURN_IF_DISALLOW_ARKTOOLS(thread);
616 [[maybe_unused]] EcmaHandleScope handleScope(thread);
617
618 JSHandle<JSTaggedValue> value = GetCallArg(info, 0);
619 if (value->IsInt()) {
620 thread->GetEcmaVM()->SetVMAPIVersion(value->GetInt());
621 }
622 return JSTaggedValue::Undefined();
623 }
624
GetElementsKind(EcmaRuntimeCallInfo * info)625 JSTaggedValue BuiltinsArkTools::GetElementsKind(EcmaRuntimeCallInfo *info)
626 {
627 ASSERT(info);
628 JSThread *thread = info->GetThread();
629 RETURN_IF_DISALLOW_ARKTOOLS(thread);
630 [[maybe_unused]] EcmaHandleScope handleScope(thread);
631
632 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
633 JSHClass *hclass = obj->GetTaggedObject()->GetClass();
634 ElementsKind kind = hclass->GetElementsKind();
635 return JSTaggedValue(Elements::ToUint(kind));
636 }
637
IsRegExpReplaceDetectorValid(EcmaRuntimeCallInfo * info)638 JSTaggedValue BuiltinsArkTools::IsRegExpReplaceDetectorValid(EcmaRuntimeCallInfo *info)
639 {
640 ASSERT(info);
641 JSThread *thread = info->GetThread();
642 RETURN_IF_DISALLOW_ARKTOOLS(thread);
643 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
644 return JSTaggedValue(PropertyDetector::IsRegExpReplaceDetectorValid(env));
645 }
646
IsRegExpFlagsDetectorValid(EcmaRuntimeCallInfo * info)647 JSTaggedValue BuiltinsArkTools::IsRegExpFlagsDetectorValid(EcmaRuntimeCallInfo *info)
648 {
649 ASSERT(info);
650 JSThread *thread = info->GetThread();
651 RETURN_IF_DISALLOW_ARKTOOLS(thread);
652 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
653 return JSTaggedValue(PropertyDetector::IsRegExpFlagsDetectorValid(env));
654 }
655
IsNumberStringNotRegexpLikeDetectorValid(EcmaRuntimeCallInfo * info)656 JSTaggedValue BuiltinsArkTools::IsNumberStringNotRegexpLikeDetectorValid(EcmaRuntimeCallInfo *info)
657 {
658 ASSERT(info);
659 JSThread *thread = info->GetThread();
660 RETURN_IF_DISALLOW_ARKTOOLS(thread);
661 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
662 return JSTaggedValue(PropertyDetector::IsNumberStringNotRegexpLikeDetectorValid(env));
663 }
664
IsSymbolIteratorDetectorValid(EcmaRuntimeCallInfo * info)665 JSTaggedValue BuiltinsArkTools::IsSymbolIteratorDetectorValid(EcmaRuntimeCallInfo *info)
666 {
667 ASSERT(info);
668 JSThread *thread = info->GetThread();
669 RETURN_IF_DISALLOW_ARKTOOLS(thread);
670 [[maybe_unused]] EcmaHandleScope handleScope(thread);
671
672 JSHandle<JSTaggedValue> kind = GetCallArg(info, 0);
673 if (!kind->IsString()) {
674 return JSTaggedValue::Undefined();
675 }
676 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
677 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
678 JSHandle<EcmaString> mapString = factory->NewFromUtf8ReadOnly("Map");
679 if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(mapString))) {
680 return JSTaggedValue(PropertyDetector::IsMapIteratorDetectorValid(env));
681 }
682 JSHandle<EcmaString> setString = factory->NewFromUtf8ReadOnly("Set");
683 if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(setString))) {
684 return JSTaggedValue(PropertyDetector::IsSetIteratorDetectorValid(env));
685 }
686 JSHandle<EcmaString> stringString = factory->NewFromUtf8ReadOnly("String");
687 if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(stringString))) {
688 return JSTaggedValue(PropertyDetector::IsStringIteratorDetectorValid(env));
689 }
690 JSHandle<EcmaString> arrayString = factory->NewFromUtf8ReadOnly("Array");
691 if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(arrayString))) {
692 return JSTaggedValue(PropertyDetector::IsArrayIteratorDetectorValid(env));
693 }
694 JSHandle<EcmaString> typedarrayString = factory->NewFromUtf8ReadOnly("TypedArray");
695 if (JSTaggedValue::Equal(thread, kind, JSHandle<JSTaggedValue>(typedarrayString))) {
696 return JSTaggedValue(PropertyDetector::IsTypedArrayIteratorDetectorValid(env));
697 }
698 return JSTaggedValue::Undefined();
699 }
700
TimeInUs(EcmaRuntimeCallInfo * info)701 JSTaggedValue BuiltinsArkTools::TimeInUs([[maybe_unused]] EcmaRuntimeCallInfo *info)
702 {
703 [[maybe_unused]] JSThread *thread = info->GetThread();
704 RETURN_IF_DISALLOW_ARKTOOLS(thread);
705 ClockScope scope;
706 return JSTaggedValue(scope.GetCurTime());
707 }
708
709 #if ECMASCRIPT_ENABLE_COLLECTING_OPCODES
StartCollectingOpcodes(EcmaRuntimeCallInfo * info)710 JSTaggedValue BuiltinsArkTools::StartCollectingOpcodes([[maybe_unused]] EcmaRuntimeCallInfo *info)
711 {
712 std::unordered_map<BytecodeInstruction::Opcode, int> bytecodeStatsMap;
713 [[maybe_unused]] JSThread *thread = info->GetThread();
714 RETURN_IF_DISALLOW_ARKTOOLS(thread);
715 EcmaVM *vm = thread->GetEcmaVM();
716 vm->SetBytecodeStatsStack(bytecodeStatsMap);
717 [[maybe_unused]] EcmaHandleScope handleScope(thread);
718 JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, GetCallArg(info, 0));
719 auto msg = EcmaStringAccessor(str).ToCString();
720 LOG_ECMA(ERROR) << msg.c_str();
721 return JSTaggedValue::Undefined();
722 }
723
StopCollectingOpcodes(EcmaRuntimeCallInfo * info)724 JSTaggedValue BuiltinsArkTools::StopCollectingOpcodes([[maybe_unused]] EcmaRuntimeCallInfo *info)
725 {
726 [[maybe_unused]] JSThread *thread = info->GetThread();
727 RETURN_IF_DISALLOW_ARKTOOLS(thread);
728 EcmaVM *vm = thread->GetEcmaVM();
729 vm->PrintCollectedByteCode();
730 std::stack<std::unordered_map<BytecodeInstruction::Opcode, int>> &bytecodeStatsStack_ =
731 vm->GetBytecodeStatsStack();
732 bytecodeStatsStack_.pop();
733 [[maybe_unused]] EcmaHandleScope handleScope(thread);
734 JSHandle<EcmaString> str = JSTaggedValue::ToString(thread, GetCallArg(info, 0));
735 auto msg = EcmaStringAccessor(str).ToCString();
736 LOG_ECMA(ERROR) << msg.c_str();
737 return JSTaggedValue::Undefined();
738 }
739 #endif
740
741 #if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT
StartScopeLockStats(EcmaRuntimeCallInfo * info)742 JSTaggedValue BuiltinsArkTools::StartScopeLockStats(EcmaRuntimeCallInfo *info)
743 {
744 JSThread *thread = info->GetThread();
745 RETURN_IF_DISALLOW_ARKTOOLS(thread);
746 auto vm = thread->GetEcmaVM();
747 vm->StartCollectingScopeLockStats();
748 LOG_FULL(INFO) << "Start Collecting ArkCompiler Scope-Lock Stats";
749 return JSTaggedValue::Undefined();
750 }
751
StopScopeLockStats(EcmaRuntimeCallInfo * info)752 JSTaggedValue BuiltinsArkTools::StopScopeLockStats(EcmaRuntimeCallInfo *info)
753 {
754 JSThread *thread = info->GetThread();
755 RETURN_IF_DISALLOW_ARKTOOLS(thread);
756 auto vm = thread->GetEcmaVM();
757 LOG_FULL(INFO) << "Stop Collecting ArkCompiler Scope-Lock Stats: "
758 << " ThreadStateTransition count: " << vm->GetUpdateThreadStateTransCount()
759 << " , Entered Scope But NO State Transition count: " << (vm->GetEnterJsiNativeScopeCount() +
760 vm->GetEnterFastNativeScopeCount() +
761 vm->GetEnterThreadManagedScopeCount() -
762 vm->GetUpdateThreadStateTransCount())
763 << " , String-Table Lock count: " << vm->GetStringTableLockCount();
764 vm->ResetScopeLockStats();
765 vm->StopCollectingScopeLockStats();
766 return JSTaggedValue::Undefined();
767 }
768 #endif
769
UnimplementedBuiltin(char const * name,EcmaRuntimeCallInfo * info)770 static JSTaggedValue UnimplementedBuiltin(char const *name, [[maybe_unused]] EcmaRuntimeCallInfo *info)
771 {
772 ASSERT(info);
773 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
774 LOG_ECMA(DEBUG) << "Enter unimplemented ArkTools." << name;
775 return JSTaggedValue::Undefined();
776 }
777
BuiltinFail(JSThread * thread,char const * msg)778 static JSTaggedValue BuiltinFail(JSThread *thread, char const *msg)
779 {
780 [[maybe_unused]] EcmaHandleScope handleScope(thread);
781 THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::ERROR, msg, JSTaggedValue::Exception());
782 }
783
NotSupportedBuiltin(char const * name,EcmaRuntimeCallInfo * info)784 static JSTaggedValue NotSupportedBuiltin(char const *name, [[maybe_unused]] EcmaRuntimeCallInfo *info)
785 {
786 ASSERT(info);
787 JSThread *thread = info->GetThread();
788 RETURN_IF_DISALLOW_ARKTOOLS(thread);
789 std::string msg = std::string(name) + " is not supported";
790 return BuiltinFail(thread, msg.c_str());
791 }
792
793 // empty function for regress-xxx test cases
PrepareFunctionForOptimization(EcmaRuntimeCallInfo * info)794 JSTaggedValue BuiltinsArkTools::PrepareFunctionForOptimization([[maybe_unused]] EcmaRuntimeCallInfo *info)
795 {
796 return UnimplementedBuiltin(__func__, info);
797 }
798
799 // empty function for regress-xxx test cases
OptimizeFunctionOnNextCall(EcmaRuntimeCallInfo * info)800 JSTaggedValue BuiltinsArkTools::OptimizeFunctionOnNextCall([[maybe_unused]] EcmaRuntimeCallInfo *info)
801 {
802 return UnimplementedBuiltin(__func__, info);
803 }
804
805 // empty function for regress-xxx test cases
OptimizeMaglevOnNextCall(EcmaRuntimeCallInfo * info)806 JSTaggedValue BuiltinsArkTools::OptimizeMaglevOnNextCall([[maybe_unused]] EcmaRuntimeCallInfo *info)
807 {
808 return UnimplementedBuiltin(__func__, info);
809 }
810
811 // empty function for regress-xxx test cases
DeoptimizeFunction(EcmaRuntimeCallInfo * info)812 JSTaggedValue BuiltinsArkTools::DeoptimizeFunction([[maybe_unused]] EcmaRuntimeCallInfo *info)
813 {
814 return UnimplementedBuiltin(__func__, info);
815 }
816
817 // empty function for regress-xxx test cases
OptimizeOsr(EcmaRuntimeCallInfo * info)818 JSTaggedValue BuiltinsArkTools::OptimizeOsr([[maybe_unused]] EcmaRuntimeCallInfo *info)
819 {
820 return UnimplementedBuiltin(__func__, info);
821 }
822
823 // empty function for regress-xxx test cases
NeverOptimizeFunction(EcmaRuntimeCallInfo * info)824 JSTaggedValue BuiltinsArkTools::NeverOptimizeFunction([[maybe_unused]] EcmaRuntimeCallInfo *info)
825 {
826 return UnimplementedBuiltin(__func__, info);
827 }
828
HeapObjectVerify(EcmaRuntimeCallInfo * info)829 JSTaggedValue BuiltinsArkTools::HeapObjectVerify([[maybe_unused]] EcmaRuntimeCallInfo *info)
830 {
831 JSThread *thread = info->GetThread();
832 RETURN_IF_DISALLOW_ARKTOOLS(thread);
833 CHECK(info && info->GetArgsNumber() == 1);
834 JSHandle<JSTaggedValue> arg = GetCallArg(info, 0);
835
836 if (arg->IsHeapObject()) {
837 JSHandle<TaggedObject> obj(arg);
838 CHECK(obj->GetClass()->GetClass()->IsHClass());
839
840 size_t failCount = 0;
841 VerifyObjectVisitor heapVerifier(thread->GetEcmaVM()->GetHeap(), &failCount);
842 heapVerifier(*obj);
843 CHECK(failCount == 0);
844 }
845 return JSTaggedValue::True();
846 }
847
848 // empty function for regress-xxx test cases
DisableOptimizationFinalization(EcmaRuntimeCallInfo * info)849 JSTaggedValue BuiltinsArkTools::DisableOptimizationFinalization([[maybe_unused]] EcmaRuntimeCallInfo *info)
850 {
851 return UnimplementedBuiltin(__func__, info);
852 }
853
854 // empty function for regress-xxx test cases
DeoptimizeNow(EcmaRuntimeCallInfo * info)855 JSTaggedValue BuiltinsArkTools::DeoptimizeNow([[maybe_unused]] EcmaRuntimeCallInfo *info)
856 {
857 return UnimplementedBuiltin(__func__, info);
858 }
859
860 // empty function for regress-xxx test cases
WaitForBackgroundOptimization(EcmaRuntimeCallInfo * info)861 JSTaggedValue BuiltinsArkTools::WaitForBackgroundOptimization([[maybe_unused]] EcmaRuntimeCallInfo *info)
862 {
863 return UnimplementedBuiltin(__func__, info);
864 }
865
Gc(EcmaRuntimeCallInfo * info)866 JSTaggedValue BuiltinsArkTools::Gc([[maybe_unused]] EcmaRuntimeCallInfo *info)
867 {
868 JSThread *thread = info->GetThread();
869 RETURN_IF_DISALLOW_ARKTOOLS(thread);
870 TriggerGCType gctype = TriggerGCType::FULL_GC;
871
872 if (info->GetArgsNumber() != 0) {
873 JSHandle<JSTaggedValue> arg = GetCallArg(info, 0);
874 if (arg->IsECMAObject()) {
875 return BuiltinFail(thread, "ArkTools.gc object parameter is not supported");
876 }
877 gctype = TriggerGCType::YOUNG_GC;
878 }
879 thread->GetEcmaVM()->CollectGarbage(gctype, GCReason::EXTERNAL_TRIGGER);
880 return JSTaggedValue::Undefined();
881 }
882
883 // empty function for pgoAssertType
PGOAssertType(EcmaRuntimeCallInfo * info)884 JSTaggedValue BuiltinsArkTools::PGOAssertType([[maybe_unused]] EcmaRuntimeCallInfo *info)
885 {
886 LOG_ECMA(DEBUG) << "Enter PGOAssertType";
887 [[maybe_unused]] JSThread *thread = info->GetThread();
888 RETURN_IF_DISALLOW_ARKTOOLS(thread);
889 return JSTaggedValue::Undefined();
890 }
891
ToLength(EcmaRuntimeCallInfo * info)892 JSTaggedValue BuiltinsArkTools::ToLength([[maybe_unused]] EcmaRuntimeCallInfo *info)
893 {
894 ASSERT(info);
895 JSThread *thread = info->GetThread();
896 RETURN_IF_DISALLOW_ARKTOOLS(thread);
897 [[maybe_unused]] EcmaHandleScope handleScope(thread);
898 JSHandle<JSTaggedValue> key = GetCallArg(info, 0);
899 return JSTaggedValue::ToLength(thread, key);
900 }
901
902 template <typename Pred>
TestElementsKind(EcmaRuntimeCallInfo * info,Pred const & pred)903 static JSTaggedValue TestElementsKind([[maybe_unused]] EcmaRuntimeCallInfo *info, Pred const &pred)
904 {
905 JSThread *thread = info->GetThread();
906 RETURN_IF_DISALLOW_ARKTOOLS(thread);
907 CHECK(info && info->GetArgsNumber() == 1);
908 JSHandle<JSTaggedValue> arg = base::BuiltinsBase::GetCallArg(info, 0);
909 CHECK(thread->GetEcmaVM()->IsEnableElementsKind());
910 CHECK(arg->IsJSObject());
911 ElementsKind kind = JSHandle<JSObject>::Cast(arg)->GetClass()->GetElementsKind();
912 return JSTaggedValue(pred(kind));
913 }
914
HasDictionaryElements(EcmaRuntimeCallInfo * info)915 JSTaggedValue BuiltinsArkTools::HasDictionaryElements([[maybe_unused]] EcmaRuntimeCallInfo *info)
916 {
917 JSThread *thread = info->GetThread();
918 RETURN_IF_DISALLOW_ARKTOOLS(thread);
919 CHECK(info && info->GetArgsNumber() == 1);
920 JSHandle<JSTaggedValue> arg = base::BuiltinsBase::GetCallArg(info, 0);
921 CHECK(thread->GetEcmaVM()->IsEnableElementsKind());
922 CHECK(arg->IsJSObject());
923 JSHandle<JSObject> obj(arg);
924 bool isDict = obj->GetClass()->IsDictionaryElement();
925 CHECK(isDict == ElementAccessor::IsDictionaryMode(obj));
926 CHECK(isDict == (obj->GetClass()->GetElementsKind() == ElementsKind::DICTIONARY));
927 return JSTaggedValue(isDict);
928 }
929
HasHoleyElements(EcmaRuntimeCallInfo * info)930 JSTaggedValue BuiltinsArkTools::HasHoleyElements([[maybe_unused]] EcmaRuntimeCallInfo *info)
931 {
932 return TestElementsKind(info, [](ElementsKind kind) {
933 return (helpers::ToUnderlying(kind) & helpers::ToUnderlying(ElementsKind::HOLE)) != 0;
934 });
935 }
936
HasSmiElements(EcmaRuntimeCallInfo * info)937 JSTaggedValue BuiltinsArkTools::HasSmiElements([[maybe_unused]] EcmaRuntimeCallInfo *info)
938 {
939 return TestElementsKind(info, [](ElementsKind kind) {
940 return kind == ElementsKind::INT || kind == ElementsKind::HOLE_INT;
941 });
942 }
943
HasDoubleElements(EcmaRuntimeCallInfo * info)944 JSTaggedValue BuiltinsArkTools::HasDoubleElements([[maybe_unused]] EcmaRuntimeCallInfo *info)
945 {
946 return TestElementsKind(info, [](ElementsKind kind) {
947 return kind == ElementsKind::NUMBER || kind == ElementsKind::HOLE_NUMBER;
948 });
949 }
950
HasObjectElements(EcmaRuntimeCallInfo * info)951 JSTaggedValue BuiltinsArkTools::HasObjectElements([[maybe_unused]] EcmaRuntimeCallInfo *info)
952 {
953 return TestElementsKind(info, [](ElementsKind kind) {
954 ElementsKind noHole = static_cast<ElementsKind>(helpers::ToUnderlying(kind)
955 & ~helpers::ToUnderlying(ElementsKind::HOLE));
956 return noHole == ElementsKind::STRING || noHole == ElementsKind::OBJECT || noHole == ElementsKind::TAGGED;
957 });
958 }
959
ArrayBufferDetach(EcmaRuntimeCallInfo * info)960 JSTaggedValue BuiltinsArkTools::ArrayBufferDetach([[maybe_unused]] EcmaRuntimeCallInfo *info)
961 {
962 JSThread *thread = info->GetThread();
963 RETURN_IF_DISALLOW_ARKTOOLS(thread);
964 CHECK(info && info->GetArgsNumber() == 1);
965 [[maybe_unused]] EcmaHandleScope handleScope(thread);
966 JSHandle<JSTaggedValue> obj1 = GetCallArg(info, 0);
967 JSHandle<JSArrayBuffer> arrBuf = JSHandle<JSArrayBuffer>::Cast(obj1);
968 arrBuf->Detach(thread);
969 return JSTaggedValue::Undefined();
970 }
971
HaveSameMap(EcmaRuntimeCallInfo * info)972 JSTaggedValue BuiltinsArkTools::HaveSameMap([[maybe_unused]] EcmaRuntimeCallInfo *info)
973 {
974 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
975 CHECK(info && info->GetArgsNumber() == 2); // 2 args
976 JSHandle<JSTaggedValue> obj1 = GetCallArg(info, 0);
977 JSHandle<JSTaggedValue> obj2 = GetCallArg(info, 1);
978 CHECK(obj1->IsHeapObject() && obj2->IsHeapObject());
979 return JSTaggedValue(obj1->GetTaggedObject()->GetClass() == obj2->GetTaggedObject()->GetClass());
980 }
981
IsSameHeapObject(EcmaRuntimeCallInfo * info)982 JSTaggedValue BuiltinsArkTools::IsSameHeapObject([[maybe_unused]] EcmaRuntimeCallInfo *info)
983 {
984 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
985 CHECK(info && info->GetArgsNumber() == 2); // 2 args
986 JSHandle<JSTaggedValue> obj1 = GetCallArg(info, 0);
987 JSHandle<JSTaggedValue> obj2 = GetCallArg(info, 1);
988 if (obj1->IsDouble() && obj2->IsDouble()) {
989 return JSTaggedValue(false); // mocked result
990 }
991 CHECK(obj1->IsHeapObject() && obj2->IsHeapObject());
992 return JSTaggedValue(obj1->GetTaggedObject() == obj2->GetTaggedObject());
993 }
994
995 // mock builtin
IsSmi(EcmaRuntimeCallInfo * info)996 JSTaggedValue BuiltinsArkTools::IsSmi([[maybe_unused]] EcmaRuntimeCallInfo *info)
997 {
998 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
999 CHECK(info && info->GetArgsNumber() == 1);
1000 return JSTaggedValue(info->GetCallArg(0)->IsInt());
1001 }
1002
CreatePrivateSymbol(EcmaRuntimeCallInfo * info)1003 JSTaggedValue BuiltinsArkTools::CreatePrivateSymbol([[maybe_unused]] EcmaRuntimeCallInfo *info)
1004 {
1005 JSThread *thread = info->GetThread();
1006 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1007 CHECK(info && info->GetArgsNumber() == 1);
1008 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1009 JSHandle<JSTaggedValue> symbolName = GetCallArg(info, 0);
1010 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1011 JSHandle<JSSymbol> privateNameSymbol = factory->NewPrivateNameSymbol(symbolName);
1012 JSHandle<JSTaggedValue> symbolValue = JSHandle<JSTaggedValue>::Cast(privateNameSymbol);
1013 return symbolValue.GetTaggedValue();
1014 }
1015
IsArray(EcmaRuntimeCallInfo * info)1016 JSTaggedValue BuiltinsArkTools::IsArray([[maybe_unused]] EcmaRuntimeCallInfo *info)
1017 {
1018 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1019 CHECK(info && info->GetArgsNumber() == 1);
1020 return JSTaggedValue(info->GetCallArg(0)->IsJSArray());
1021 }
1022
CreateDataProperty(EcmaRuntimeCallInfo * info)1023 JSTaggedValue BuiltinsArkTools::CreateDataProperty([[maybe_unused]] EcmaRuntimeCallInfo *info)
1024 {
1025 JSThread *thread = info->GetThread();
1026 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1027 CHECK(info && info->GetArgsNumber() == 3); // 3 args
1028 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1029 CHECK(GetCallArg(info, 0)->IsJSObject());
1030 JSHandle<JSObject> obj(GetCallArg(info, 0)); // 0: object
1031 JSHandle<JSTaggedValue> key = GetCallArg(info, 1); // 1: property key
1032 JSHandle<JSTaggedValue> value = GetCallArg(info, 2); // 2: property value
1033 JSObject::CreateDataPropertyOrThrow(thread, obj, key, value);
1034 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1035 return value.GetTaggedValue();
1036 }
1037
FunctionGetInferredName(EcmaRuntimeCallInfo * info)1038 JSTaggedValue BuiltinsArkTools::FunctionGetInferredName([[maybe_unused]] EcmaRuntimeCallInfo *info)
1039 {
1040 JSThread *thread = info->GetThread();
1041 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1042 CHECK(info && info->GetArgsNumber() == 1);
1043 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1044 JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
1045 if (obj->IsJSFunction()) {
1046 JSHandle<JSFunction> funcObj = JSHandle<JSFunction>::Cast(obj);
1047 std::string name = Method::ConstCast(funcObj->GetMethod().GetTaggedObject())->ParseFunctionName();
1048 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1049 return factory->NewFromStdString(name).GetTaggedValue();
1050 }
1051 return thread->GlobalConstants()->GetHandledEmptyString().GetTaggedValue();
1052 }
1053
StringLessThan(EcmaRuntimeCallInfo * info)1054 JSTaggedValue BuiltinsArkTools::StringLessThan([[maybe_unused]] EcmaRuntimeCallInfo *info)
1055 {
1056 JSThread *thread = info->GetThread();
1057 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1058 CHECK(info && info->GetArgsNumber() == 2); // 2 args
1059 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1060 JSHandle<JSTaggedValue> x = GetCallArg(info, 0);
1061 JSHandle<JSTaggedValue> y = GetCallArg(info, 1);
1062 ComparisonResult result = JSTaggedValue::Compare(thread, x, y);
1063 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1064 return JSTaggedValue(ComparisonResult::LESS == result);
1065 }
1066
StringMaxLength(EcmaRuntimeCallInfo * info)1067 JSTaggedValue BuiltinsArkTools::StringMaxLength([[maybe_unused]] EcmaRuntimeCallInfo *info)
1068 {
1069 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1070 CHECK(info && info->GetArgsNumber() == 0);
1071 return JSTaggedValue(static_cast<uint32_t>(EcmaString::MAX_STRING_LENGTH) - 1);
1072 }
1073
ArrayBufferMaxByteLength(EcmaRuntimeCallInfo * info)1074 JSTaggedValue BuiltinsArkTools::ArrayBufferMaxByteLength([[maybe_unused]] EcmaRuntimeCallInfo *info)
1075 {
1076 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1077 CHECK(info && info->GetArgsNumber() == 0);
1078 return JSTaggedValue(INT_MAX);
1079 }
1080
TypedArrayMaxLength(EcmaRuntimeCallInfo * info)1081 JSTaggedValue BuiltinsArkTools::TypedArrayMaxLength([[maybe_unused]] EcmaRuntimeCallInfo *info)
1082 {
1083 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1084 CHECK(info && info->GetArgsNumber() == 0);
1085 return JSTaggedValue(BuiltinsTypedArray::MAX_ARRAY_INDEX);
1086 }
1087
MaxSmi(EcmaRuntimeCallInfo * info)1088 JSTaggedValue BuiltinsArkTools::MaxSmi([[maybe_unused]] EcmaRuntimeCallInfo *info)
1089 {
1090 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1091 CHECK(info && info->GetArgsNumber() == 0);
1092 return JSTaggedValue(INT32_MAX);
1093 }
1094
Is64Bit(EcmaRuntimeCallInfo * info)1095 JSTaggedValue BuiltinsArkTools::Is64Bit([[maybe_unused]] EcmaRuntimeCallInfo *info)
1096 {
1097 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1098 CHECK(info && info->GetArgsNumber() == 0);
1099 return JSTaggedValue(sizeof(void*) == 8); // 8 is 64bit pointer size
1100 }
1101
1102 // empty function for regress-xxx test cases
FinalizeOptimization(EcmaRuntimeCallInfo * info)1103 JSTaggedValue BuiltinsArkTools::FinalizeOptimization([[maybe_unused]] EcmaRuntimeCallInfo *info)
1104 {
1105 return UnimplementedBuiltin(__func__, info);
1106 }
1107
EnsureFeedbackVectorForFunction(EcmaRuntimeCallInfo * info)1108 JSTaggedValue BuiltinsArkTools::EnsureFeedbackVectorForFunction([[maybe_unused]] EcmaRuntimeCallInfo *info)
1109 {
1110 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1111 CHECK(info && info->GetArgsNumber() == 1);
1112 CHECK(info->GetCallArg(0)->IsJSFunction());
1113 JSHandle<JSFunction> func(info->GetCallArg(0));
1114 auto prof = func->GetProfileTypeInfo();
1115 CHECK(prof.IsUndefined() || prof.GetHeapObject()->GetClass()->IsTaggedArray());
1116 return JSTaggedValue(!prof.IsUndefined());
1117 }
1118
1119 // empty function for regress-xxx test cases
CompileBaseline(EcmaRuntimeCallInfo * info)1120 JSTaggedValue BuiltinsArkTools::CompileBaseline([[maybe_unused]] EcmaRuntimeCallInfo *info)
1121 {
1122 return UnimplementedBuiltin(__func__, info);
1123 }
1124
DebugGetLoadedScriptIds(EcmaRuntimeCallInfo * info)1125 JSTaggedValue BuiltinsArkTools::DebugGetLoadedScriptIds([[maybe_unused]] EcmaRuntimeCallInfo *info)
1126 {
1127 return UnimplementedBuiltin(__func__, info);
1128 }
1129
ToFastProperties(EcmaRuntimeCallInfo * info)1130 JSTaggedValue BuiltinsArkTools::ToFastProperties([[maybe_unused]] EcmaRuntimeCallInfo *info)
1131 {
1132 JSThread *thread = info->GetThread();
1133 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1134 CHECK(info && info->GetArgsNumber() == 1);
1135 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1136 JSHandle<JSTaggedValue> arg = info->GetCallArg(0);
1137
1138 if (arg->IsJSObject() && !arg->IsJSGlobalObject()) {
1139 JSHandle<JSObject> obj(arg);
1140 // NOTE: extracted from JSHClass::OptimizeAsFastElements
1141 if (obj->GetJSHClass()->IsDictionaryMode()) {
1142 JSObject::OptimizeAsFastProperties(thread, obj);
1143 } else {
1144 JSHClass::OptimizeAsFastProperties(thread, obj);
1145 }
1146 }
1147 return arg.GetTaggedValue();
1148 }
1149
AbortJS(EcmaRuntimeCallInfo * info)1150 JSTaggedValue BuiltinsArkTools::AbortJS([[maybe_unused]] EcmaRuntimeCallInfo *info)
1151 {
1152 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1153 CHECK(info && info->GetArgsNumber() == 1);
1154 CHECK(info->GetCallArg(0)->IsString());
1155 JSHandle<EcmaString> msg(info->GetCallArg(0));
1156 std::cerr << "AbortJS: " << EcmaStringAccessor(msg).ToCString(StringConvertedUsage::PRINT) << std::endl;
1157 panda::PrintStack(std::cerr);
1158 std::abort();
1159 }
1160
InternalizeString(EcmaRuntimeCallInfo * info)1161 JSTaggedValue BuiltinsArkTools::InternalizeString([[maybe_unused]] EcmaRuntimeCallInfo *info)
1162 {
1163 JSThread *thread = info->GetThread();
1164 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1165 CHECK(info && info->GetArgsNumber() == 1);
1166 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1167 CHECK(info->GetCallArg(0)->IsString());
1168 return JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(info->GetCallArg(0)));
1169 }
1170
1171 // empty function for regress-xxx test cases
HandleDebuggerStatement(EcmaRuntimeCallInfo * info)1172 JSTaggedValue BuiltinsArkTools::HandleDebuggerStatement([[maybe_unused]] EcmaRuntimeCallInfo *info)
1173 {
1174 return UnimplementedBuiltin(__func__, info);
1175 }
1176
1177 // empty function for regress-xxx test cases
SetAllocationTimeout(EcmaRuntimeCallInfo * info)1178 JSTaggedValue BuiltinsArkTools::SetAllocationTimeout([[maybe_unused]] EcmaRuntimeCallInfo *info)
1179 {
1180 return UnimplementedBuiltin(__func__, info);
1181 }
1182
HasFastProperties(EcmaRuntimeCallInfo * info)1183 JSTaggedValue BuiltinsArkTools::HasFastProperties([[maybe_unused]] EcmaRuntimeCallInfo *info)
1184 {
1185 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1186 CHECK(info && info->GetArgsNumber() == 1);
1187 CHECK(info->GetCallArg(0)->IsJSObject());
1188 JSHandle<JSObject> obj(info->GetCallArg(0));
1189 return JSTaggedValue(!obj->GetClass()->IsDictionaryMode());
1190 }
1191
HasOwnConstDataProperty(EcmaRuntimeCallInfo * info)1192 JSTaggedValue BuiltinsArkTools::HasOwnConstDataProperty([[maybe_unused]] EcmaRuntimeCallInfo *info)
1193 {
1194 JSThread *thread = info->GetThread();
1195 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1196 CHECK(info && info->GetArgsNumber() == 2); // 2 args
1197 JSHandle<JSTaggedValue> rec = info->GetCallArg(0);
1198 JSHandle<JSTaggedValue> prop = info->GetCallArg(1);
1199
1200 if (!(prop->IsNumber() || prop->IsString() || prop->IsSymbol())) {
1201 return JSTaggedValue::Undefined();
1202 }
1203 if (!rec->IsJSObject()) {
1204 return JSTaggedValue::Undefined();
1205 }
1206
1207 JSHandle<JSObject> obj(rec);
1208 ObjectOperator op(thread, rec, rec, prop, OperatorType::OWN);
1209 if (!op.IsFound()) {
1210 return JSTaggedValue::False();
1211 }
1212 if (!op.IsAccessorDescriptor()) {
1213 return JSTaggedValue(op.GetAttr().IsConstProps());
1214 }
1215 return JSTaggedValue::Undefined();
1216 }
1217
GetHoleNaNUpper(EcmaRuntimeCallInfo * info)1218 JSTaggedValue BuiltinsArkTools::GetHoleNaNUpper([[maybe_unused]] EcmaRuntimeCallInfo *info)
1219 {
1220 return NotSupportedBuiltin(__func__, info);
1221 }
1222
GetHoleNaNLower(EcmaRuntimeCallInfo * info)1223 JSTaggedValue BuiltinsArkTools::GetHoleNaNLower([[maybe_unused]] EcmaRuntimeCallInfo *info)
1224 {
1225 return NotSupportedBuiltin(__func__, info);
1226 }
1227
1228 // empty function for regress-xxx test cases
SystemBreak(EcmaRuntimeCallInfo * info)1229 JSTaggedValue BuiltinsArkTools::SystemBreak([[maybe_unused]] EcmaRuntimeCallInfo *info)
1230 {
1231 return UnimplementedBuiltin(__func__, info);
1232 }
1233
1234 // empty function for regress-xxx test cases
ScheduleBreak(EcmaRuntimeCallInfo * info)1235 JSTaggedValue BuiltinsArkTools::ScheduleBreak([[maybe_unused]] EcmaRuntimeCallInfo *info)
1236 {
1237 return UnimplementedBuiltin(__func__, info);
1238 }
1239
EnqueueMicrotask(EcmaRuntimeCallInfo * info)1240 JSTaggedValue BuiltinsArkTools::EnqueueMicrotask([[maybe_unused]] EcmaRuntimeCallInfo *info)
1241 {
1242 JSThread *thread = info->GetThread();
1243 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1244 CHECK(info && info->GetArgsNumber() == 1);
1245 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1246 CHECK(info->GetCallArg(0)->IsJSFunction());
1247 JSHandle<JSFunction> func(info->GetCallArg(0));
1248
1249 JSHandle<job::MicroJobQueue> queue = thread->GetCurrentEcmaContext()->GetMicroJobQueue();
1250 JSHandle<TaggedArray> argv(thread->GlobalConstants()->GetHandledEmptyArray());
1251
1252 job::MicroJobQueue::EnqueueJob(thread, queue, job::QueueType::QUEUE_PROMISE, func, argv);
1253 return JSTaggedValue::Undefined();
1254 }
1255
DebugPrint(EcmaRuntimeCallInfo * info)1256 JSTaggedValue BuiltinsArkTools::DebugPrint([[maybe_unused]] EcmaRuntimeCallInfo *info)
1257 {
1258 return UnimplementedBuiltin(__func__, info);
1259 }
1260
1261 // empty function for regress-xxx test cases
GetOptimizationStatus(EcmaRuntimeCallInfo * info)1262 JSTaggedValue BuiltinsArkTools::GetOptimizationStatus([[maybe_unused]] EcmaRuntimeCallInfo *info)
1263 {
1264 return UnimplementedBuiltin(__func__, info);
1265 }
1266
GetUndetectable(EcmaRuntimeCallInfo * info)1267 JSTaggedValue BuiltinsArkTools::GetUndetectable([[maybe_unused]] EcmaRuntimeCallInfo *info)
1268 {
1269 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1270 ASSERT(info && info->GetArgsNumber() == 0);
1271 return JSTaggedValue::Undefined(); // undetectable is just undefined
1272 }
1273
SetKeyedProperty(EcmaRuntimeCallInfo * info)1274 JSTaggedValue BuiltinsArkTools::SetKeyedProperty([[maybe_unused]] EcmaRuntimeCallInfo *info)
1275 {
1276 JSThread *thread = info->GetThread();
1277 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1278 CHECK(info && info->GetArgsNumber() == 3); // 3 args
1279 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1280 JSHandle<JSTaggedValue> obj = info->GetCallArg(0); // 0: object
1281 JSHandle<JSTaggedValue> key = info->GetCallArg(1); // 1: property key
1282 JSHandle<JSTaggedValue> val = info->GetCallArg(2); // 2: property value
1283
1284 JSTaggedValue::SetProperty(thread, obj, key, val, true);
1285 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1286 return JSTaggedValue::Undefined();
1287 }
1288
DisassembleFunction(EcmaRuntimeCallInfo * info)1289 JSTaggedValue BuiltinsArkTools::DisassembleFunction([[maybe_unused]] EcmaRuntimeCallInfo *info)
1290 {
1291 return UnimplementedBuiltin(__func__, info);
1292 }
1293
TryMigrateInstance(EcmaRuntimeCallInfo * info)1294 JSTaggedValue BuiltinsArkTools::TryMigrateInstance([[maybe_unused]] EcmaRuntimeCallInfo *info)
1295 {
1296 return NotSupportedBuiltin(__func__, info);
1297 }
1298
InLargeObjectSpace(EcmaRuntimeCallInfo * info)1299 JSTaggedValue BuiltinsArkTools::InLargeObjectSpace([[maybe_unused]] EcmaRuntimeCallInfo *info)
1300 {
1301 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1302 CHECK(info && info->GetArgsNumber() == 1);
1303 JSHandle<JSTaggedValue> arg = info->GetCallArg(0);
1304 CHECK(arg->IsHeapObject());
1305 Region *region = Region::ObjectAddressToRange(arg->GetTaggedObject());
1306 return JSTaggedValue(region->InHugeObjectSpace());
1307 }
1308
PerformMicrotaskCheckpoint(EcmaRuntimeCallInfo * info)1309 JSTaggedValue BuiltinsArkTools::PerformMicrotaskCheckpoint([[maybe_unused]] EcmaRuntimeCallInfo *info)
1310 {
1311 JSThread *thread = info->GetThread();
1312 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1313 ASSERT(info && info->GetArgsNumber() == 0);
1314 thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
1315 return JSTaggedValue::Undefined();
1316 }
1317
IsJSReceiver(EcmaRuntimeCallInfo * info)1318 JSTaggedValue BuiltinsArkTools::IsJSReceiver([[maybe_unused]] EcmaRuntimeCallInfo *info)
1319 {
1320 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1321 ASSERT(info && info->GetArgsNumber() == 1);
1322 return JSTaggedValue(info->GetCallArg(0)->IsECMAObject());
1323 }
1324
IsDictPropertyConstTrackingEnabled(EcmaRuntimeCallInfo * info)1325 JSTaggedValue BuiltinsArkTools::IsDictPropertyConstTrackingEnabled([[maybe_unused]] EcmaRuntimeCallInfo *info)
1326 {
1327 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1328 ASSERT(info && info->GetArgsNumber() == 0);
1329 return JSTaggedValue(false);
1330 }
1331
1332 // mock builtin
AllocateHeapNumber(EcmaRuntimeCallInfo * info)1333 JSTaggedValue BuiltinsArkTools::AllocateHeapNumber([[maybe_unused]] EcmaRuntimeCallInfo *info)
1334 {
1335 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1336 ASSERT(info && info->GetArgsNumber() == 0);
1337 return JSTaggedValue(0.0);
1338 }
1339
ConstructConsString(EcmaRuntimeCallInfo * info)1340 JSTaggedValue BuiltinsArkTools::ConstructConsString([[maybe_unused]] EcmaRuntimeCallInfo *info)
1341 {
1342 JSThread *thread = info->GetThread();
1343 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1344 CHECK(info && info->GetArgsNumber() == 2); // 2 args
1345 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1346 CHECK(info->GetCallArg(0)->IsString());
1347 CHECK(info->GetCallArg(1)->IsString());
1348 JSHandle<EcmaString> str1(info->GetCallArg(0));
1349 JSHandle<EcmaString> str2(info->GetCallArg(1));
1350
1351 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1352 return factory->ConcatFromString(str1, str2).GetTaggedValue();
1353 }
1354
1355 // empty function for regress-xxx test cases
CompleteInobjectSlackTracking(EcmaRuntimeCallInfo * info)1356 JSTaggedValue BuiltinsArkTools::CompleteInobjectSlackTracking([[maybe_unused]] EcmaRuntimeCallInfo *info)
1357 {
1358 return UnimplementedBuiltin(__func__, info);
1359 }
1360
NormalizeElements(EcmaRuntimeCallInfo * info)1361 JSTaggedValue BuiltinsArkTools::NormalizeElements([[maybe_unused]] EcmaRuntimeCallInfo *info)
1362 {
1363 JSThread *thread = info->GetThread();
1364 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1365 CHECK(info && info->GetArgsNumber() == 1);
1366 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1367 CHECK(info->GetCallArg(0)->IsJSObject());
1368 JSHandle<JSObject> obj(info->GetCallArg(0));
1369 JSObject::ElementsToDictionary(thread, obj);
1370 return obj.GetTaggedValue();
1371 }
1372
Call(EcmaRuntimeCallInfo * info)1373 JSTaggedValue BuiltinsArkTools::Call([[maybe_unused]] EcmaRuntimeCallInfo *info)
1374 {
1375 JSThread *thread = info->GetThread();
1376 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1377 static constexpr uint32_t MIN_ARGS = 2;
1378 CHECK(info && info->GetArgsNumber() >= MIN_ARGS);
1379 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1380 uint32_t argc = info->GetArgsNumber() - MIN_ARGS;
1381 JSHandle<JSTaggedValue> callee = info->GetCallArg(0);
1382 JSHandle<JSTaggedValue> receiver = info->GetCallArg(1);
1383
1384 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1385 EcmaRuntimeCallInfo *calleeInfo = EcmaInterpreter::NewRuntimeCallInfo(thread, callee, receiver, undefined, argc);
1386 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1387 for (uint32_t i = 0; i < argc; ++i) {
1388 calleeInfo->SetCallArg(i, info->GetCallArg(i + MIN_ARGS).GetTaggedValue());
1389 }
1390 return JSFunction::Call(calleeInfo);
1391 }
1392
1393 // empty function for regress-xxx test cases
DebugPushPromise(EcmaRuntimeCallInfo * info)1394 JSTaggedValue BuiltinsArkTools::DebugPushPromise([[maybe_unused]] EcmaRuntimeCallInfo *info)
1395 {
1396 return UnimplementedBuiltin(__func__, info);
1397 }
1398
1399 // empty function for regress-xxx test cases
SetForceSlowPath(EcmaRuntimeCallInfo * info)1400 JSTaggedValue BuiltinsArkTools::SetForceSlowPath([[maybe_unused]] EcmaRuntimeCallInfo *info)
1401 {
1402 return UnimplementedBuiltin(__func__, info);
1403 }
1404
1405 // empty function for regress-xxx test cases
NotifyContextDisposed(EcmaRuntimeCallInfo * info)1406 JSTaggedValue BuiltinsArkTools::NotifyContextDisposed([[maybe_unused]] EcmaRuntimeCallInfo *info)
1407 {
1408 return UnimplementedBuiltin(__func__, info);
1409 }
1410
1411 // empty function for regress-xxx test cases
OptimizeObjectForAddingMultipleProperties(EcmaRuntimeCallInfo * info)1412 JSTaggedValue BuiltinsArkTools::OptimizeObjectForAddingMultipleProperties([[maybe_unused]] EcmaRuntimeCallInfo *info)
1413 {
1414 return UnimplementedBuiltin(__func__, info);
1415 }
1416
1417 // empty function for regress-xxx test cases
IsBeingInterpreted(EcmaRuntimeCallInfo * info)1418 JSTaggedValue BuiltinsArkTools::IsBeingInterpreted([[maybe_unused]] EcmaRuntimeCallInfo *info)
1419 {
1420 return UnimplementedBuiltin(__func__, info);
1421 }
1422
1423 // empty function for regress-xxx test cases
ClearFunctionFeedback(EcmaRuntimeCallInfo * info)1424 JSTaggedValue BuiltinsArkTools::ClearFunctionFeedback([[maybe_unused]] EcmaRuntimeCallInfo *info)
1425 {
1426 return UnimplementedBuiltin(__func__, info);
1427 }
1428
JitCompileSync(EcmaRuntimeCallInfo * info)1429 JSTaggedValue BuiltinsArkTools::JitCompileSync(EcmaRuntimeCallInfo *info)
1430 {
1431 JSThread *thread = info->GetThread();
1432 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1433 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1434
1435 JSHandle<JSTaggedValue> thisValue = GetCallArg(info, 0);
1436 if (!thisValue->IsJSFunction()) {
1437 return JSTaggedValue::False();
1438 }
1439 JSHandle<JSFunction> jsFunction(thisValue);
1440 Jit::Compile(thread->GetEcmaVM(), jsFunction, CompilerTier::Tier::FAST,
1441 MachineCode::INVALID_OSR_OFFSET, JitCompileMode::Mode::SYNC);
1442 return JSTaggedValue::True();
1443 }
1444
JitCompileAsync(EcmaRuntimeCallInfo * info)1445 JSTaggedValue BuiltinsArkTools::JitCompileAsync(EcmaRuntimeCallInfo *info)
1446 {
1447 JSThread *thread = info->GetThread();
1448 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1449 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1450
1451 JSHandle<JSTaggedValue> thisValue = GetCallArg(info, 0);
1452 if (!thisValue->IsJSFunction()) {
1453 return JSTaggedValue::False();
1454 }
1455 JSHandle<JSFunction> jsFunction(thisValue);
1456 Jit::Compile(thread->GetEcmaVM(), jsFunction, CompilerTier::Tier::FAST,
1457 MachineCode::INVALID_OSR_OFFSET, JitCompileMode::Mode::ASYNC);
1458 return JSTaggedValue::True();
1459 }
1460
WaitJitCompileFinish(EcmaRuntimeCallInfo * info)1461 JSTaggedValue BuiltinsArkTools::WaitJitCompileFinish(EcmaRuntimeCallInfo *info)
1462 {
1463 JSThread *thread = info->GetThread();
1464 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1465 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1466
1467 JSHandle<JSTaggedValue> thisValue = GetCallArg(info, 0);
1468 if (!thisValue->IsJSFunction()) {
1469 return JSTaggedValue::False();
1470 }
1471 JSHandle<JSFunction> jsFunction(thisValue);
1472
1473 auto jit = Jit::GetInstance();
1474 if (!jit->IsEnableFastJit()) {
1475 return JSTaggedValue::False();
1476 }
1477 while (!jsFunction->GetMachineCode().IsMachineCodeObject()) {
1478 // just spin check
1479 thread->SetInstallMachineCode(true);
1480 thread->CheckSafepoint();
1481 }
1482 return JSTaggedValue::True();
1483 }
1484
WaitAllJitCompileFinish(EcmaRuntimeCallInfo * info)1485 JSTaggedValue BuiltinsArkTools::WaitAllJitCompileFinish(EcmaRuntimeCallInfo *info)
1486 {
1487 JSThread *thread = info->GetThread();
1488 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1489
1490 auto jit = Jit::GetInstance();
1491 if (!jit->IsEnableFastJit()) {
1492 return JSTaggedValue::False();
1493 }
1494 while (Jit::GetInstance()->GetRunningTaskCnt(thread->GetEcmaVM())) {
1495 thread->SetInstallMachineCode(true);
1496 thread->CheckSafepoint();
1497 }
1498 thread->SetPGOProfilerEnable(false);
1499 thread->CheckOrSwitchPGOStubs();
1500 thread->GetEcmaVM()->GetJSOptions().SetEnablePGOProfiler(false);
1501 return JSTaggedValue::True();
1502 }
1503
IsInFastJit(EcmaRuntimeCallInfo * info)1504 JSTaggedValue BuiltinsArkTools::IsInFastJit(EcmaRuntimeCallInfo *info)
1505 {
1506 JSThread *thread = info->GetThread();
1507 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1508 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1509
1510 JSTaggedType *currentFrame = const_cast<JSTaggedType*>(thread->GetCurrentFrame());
1511 for (FrameIterator it(currentFrame, thread); !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
1512 if (!it.IsJSFrame()) {
1513 continue;
1514 }
1515 return (it.IsOptimizedJSFunctionFrame() || it.IsFastJitFunctionFrame() ?
1516 JSTaggedValue::True() : JSTaggedValue::False());
1517 }
1518 return JSTaggedValue::False();
1519 }
1520
StartRuntimeStat(EcmaRuntimeCallInfo * msg)1521 JSTaggedValue BuiltinsArkTools::StartRuntimeStat(EcmaRuntimeCallInfo *msg)
1522 {
1523 JSThread *thread = msg->GetThread();
1524 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1525 BUILTINS_API_TRACE(thread, Global, StartRuntimeStat);
1526 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1527 // start vm runtime stat statistic
1528 thread->GetEcmaVM()->SetRuntimeStatEnable(true);
1529 return JSTaggedValue::Undefined();
1530 }
1531
StopRuntimeStat(EcmaRuntimeCallInfo * msg)1532 JSTaggedValue BuiltinsArkTools::StopRuntimeStat(EcmaRuntimeCallInfo *msg)
1533 {
1534 JSThread *thread = msg->GetThread();
1535 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1536 BUILTINS_API_TRACE(thread, Global, StopRuntimeStat);
1537 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1538 // stop vm runtime stat statistic
1539 thread->GetEcmaVM()->SetRuntimeStatEnable(false);
1540 return JSTaggedValue::Undefined();
1541 }
1542
IterateFrame(EcmaRuntimeCallInfo * info)1543 JSTaggedValue BuiltinsArkTools::IterateFrame(EcmaRuntimeCallInfo *info)
1544 {
1545 ASSERT(info);
1546 JSThread *thread = info->GetThread();
1547 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1548 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1549
1550 JSTaggedType *currentFrame = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
1551
1552 class DummyRootVisitor final : public RootVisitor {
1553 public:
1554 DummyRootVisitor() = default;
1555 ~DummyRootVisitor() = default;
1556
1557 void VisitRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot slot) override {}
1558 void VisitRangeRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot start,
1559 [[maybe_unused]] ObjectSlot end) override {}
1560 void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base,
1561 [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject) override {}
1562 };
1563 DummyRootVisitor visitor;
1564
1565 for (FrameIterator it(currentFrame, thread); !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
1566 bool ret = it.IteratorStackMap(visitor);
1567 FrameType type = it.GetFrameType();
1568 int delta = it.ComputeDelta();
1569 kungfu::CalleeRegAndOffsetVec calleeRegInfo;
1570 it.GetCalleeRegAndOffsetVec(calleeRegInfo);
1571 LOG_BUILTINS(INFO) << "IterateFrameType: " << (int)type;
1572 LOG_BUILTINS(INFO) << "IterateFrameDelta: " << delta;
1573 LOG_BUILTINS(INFO) << "IterateFrameCalleeRegInfo: " << calleeRegInfo.size();
1574 if (!ret) {
1575 break;
1576 }
1577 }
1578
1579 for (FrameIterator it(currentFrame, thread); !it.Done(); it.Advance<GCVisitedFlag::DEOPT>()) {
1580 FrameType type = it.GetFrameType();
1581 int delta = it.ComputeDelta();
1582 kungfu::CalleeRegAndOffsetVec calleeRegInfo;
1583 it.GetCalleeRegAndOffsetVec(calleeRegInfo);
1584 LOG_BUILTINS(INFO) << "DeoptIterateFrameType: " << (int)type;
1585 LOG_BUILTINS(INFO) << "DeoptIterateFrameDelta: " << delta;
1586 LOG_BUILTINS(INFO) << "DeoptIterateFrameCalleeRegInfo: " << calleeRegInfo.size();
1587 }
1588
1589 return JSTaggedValue::Undefined();
1590 }
1591
TriggerSharedGC(EcmaRuntimeCallInfo * info)1592 JSTaggedValue BuiltinsArkTools::TriggerSharedGC(EcmaRuntimeCallInfo *info)
1593 {
1594 ASSERT(info);
1595 JSThread *thread = info->GetThread();
1596 RETURN_IF_DISALLOW_ARKTOOLS(thread);
1597 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1598 JSTaggedValue type = GetCallArg(info, 0).GetTaggedValue();
1599 auto globalConst = thread->GlobalConstants();
1600 SharedHeap *sHeap = SharedHeap::GetInstance();
1601 sHeap->WaitGCFinished(thread);
1602 if (JSTaggedValue::StrictEqual(globalConst->GetSharedGcCause(), type)) {
1603 sHeap->TriggerConcurrentMarking<TriggerGCType::SHARED_GC, GCReason::TRIGGER_BY_JS>(thread);
1604 sHeap->WaitGCFinished(thread);
1605 } else if (JSTaggedValue::StrictEqual(globalConst->GetSharedPartialGcCause(), type)) {
1606 sHeap->TriggerConcurrentMarking<TriggerGCType::SHARED_PARTIAL_GC, GCReason::TRIGGER_BY_JS>(thread);
1607 sHeap->WaitGCFinished(thread);
1608 } else if (JSTaggedValue::StrictEqual(globalConst->GetSharedFullGcCause(), type)) {
1609 sHeap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::TRIGGER_BY_JS>(thread);
1610 }
1611 return JSTaggedValue::Undefined();
1612 }
1613
InYoungSpace(EcmaRuntimeCallInfo * info)1614 JSTaggedValue BuiltinsArkTools::InYoungSpace(EcmaRuntimeCallInfo *info)
1615 {
1616 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1617 CHECK(info && info->GetArgsNumber() == 1);
1618 JSHandle<JSTaggedValue> arg = info->GetCallArg(0);
1619 CHECK(arg->IsHeapObject());
1620 Region *region = Region::ObjectAddressToRange(arg->GetTaggedObject());
1621 return JSTaggedValue(region->InYoungSpace());
1622 }
1623
InOldSpace(EcmaRuntimeCallInfo * info)1624 JSTaggedValue BuiltinsArkTools::InOldSpace(EcmaRuntimeCallInfo *info)
1625 {
1626 RETURN_IF_DISALLOW_ARKTOOLS(info->GetThread());
1627 CHECK(info && info->GetArgsNumber() == 1);
1628 JSHandle<JSTaggedValue> arg = info->GetCallArg(0);
1629 CHECK(arg->IsHeapObject());
1630 Region *region = Region::ObjectAddressToRange(arg->GetTaggedObject());
1631 return JSTaggedValue(region->InOldSpace());
1632 }
1633
CreateNapiObject(EcmaRuntimeCallInfo * msg)1634 JSTaggedValue BuiltinsArkTools::CreateNapiObject(EcmaRuntimeCallInfo *msg)
1635 {
1636 JSThread *thread = msg->GetThread();
1637 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1638 JSHandle<JSObject> jsObject(factory->CreateNapiObject());
1639 return jsObject.GetTaggedValue();
1640 }
1641 } // namespace panda::ecmascript::builtins
1642