• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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