• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/ecma_vm.h"
17 
18 #include "ecmascript/base/string_helper.h"
19 #include "ecmascript/builtins/builtins.h"
20 #include "ecmascript/builtins/builtins_ark_tools.h"
21 #ifdef ARK_SUPPORT_INTL
22 #include "ecmascript/builtins/builtins_collator.h"
23 #include "ecmascript/builtins/builtins_date_time_format.h"
24 #include "ecmascript/builtins/builtins_number_format.h"
25 #endif
26 #include "ecmascript/builtins/builtins_global.h"
27 #include "ecmascript/builtins/builtins_object.h"
28 #include "ecmascript/builtins/builtins_promise.h"
29 #include "ecmascript/builtins/builtins_promise_handler.h"
30 #include "ecmascript/builtins/builtins_proxy.h"
31 #include "ecmascript/builtins/builtins_regexp.h"
32 #include "ecmascript/compiler/builtins/builtins_call_signature.h"
33 #include "ecmascript/compiler/call_signature.h"
34 #include "ecmascript/compiler/common_stubs.h"
35 #include "ecmascript/compiler/interpreter_stub.h"
36 #include "ecmascript/compiler/rt_call_signature.h"
37 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
38 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
39 #endif
40 #if !WIN_OR_MAC_OR_IOS_PLATFORM
41 #include "ecmascript/dfx/hprof/heap_profiler.h"
42 #include "ecmascript/dfx/hprof/heap_profiler_interface.h"
43 #endif
44 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
45 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
46 #include "ecmascript/debugger/js_debugger_manager.h"
47 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
48 #include "ecmascript/dfx/vmstat/function_call_timer.h"
49 #include "ecmascript/dfx/vmstat/opt_code_profiler.h"
50 #include "ecmascript/dfx/vmstat/runtime_stat.h"
51 #include "ecmascript/ecma_context.h"
52 #include "ecmascript/ecma_string_table.h"
53 #include "ecmascript/global_env.h"
54 #include "ecmascript/global_env_constants-inl.h"
55 #include "ecmascript/global_env_constants.h"
56 #include "ecmascript/interpreter/interpreter-inl.h"
57 #include "ecmascript/jobs/micro_job_queue.h"
58 #include "ecmascript/js_arraybuffer.h"
59 #include "ecmascript/js_for_in_iterator.h"
60 #include "ecmascript/js_native_pointer.h"
61 #include "ecmascript/js_thread.h"
62 #include "ecmascript/jspandafile/constpool_value.h"
63 #include "ecmascript/jspandafile/js_pandafile.h"
64 #include "ecmascript/jspandafile/js_pandafile_manager.h"
65 #include "ecmascript/jspandafile/panda_file_translator.h"
66 #include "ecmascript/jspandafile/program_object.h"
67 #include "ecmascript/mem/concurrent_marker.h"
68 #include "ecmascript/mem/gc_stats.h"
69 #include "ecmascript/mem/heap.h"
70 #include "ecmascript/mem/mem.h"
71 #include "ecmascript/mem/space.h"
72 #include "ecmascript/mem/visitor.h"
73 #include "ecmascript/module/js_module_manager.h"
74 #include "ecmascript/module/module_data_extractor.h"
75 #include "ecmascript/object_factory.h"
76 #include "ecmascript/patch/quick_fix_manager.h"
77 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
78 #include "ecmascript/regexp/regexp_parser_cache.h"
79 #include "ecmascript/runtime_call_id.h"
80 #include "ecmascript/snapshot/mem/snapshot.h"
81 #include "ecmascript/snapshot/mem/snapshot_env.h"
82 #include "ecmascript/stubs/runtime_stubs.h"
83 #include "ecmascript/tagged_array-inl.h"
84 #include "ecmascript/tagged_dictionary.h"
85 #include "ecmascript/tagged_queue.h"
86 #include "ecmascript/tagged_queue.h"
87 #include "ecmascript/taskpool/task.h"
88 #include "ecmascript/taskpool/taskpool.h"
89 #include "ecmascript/ts_types/ts_manager.h"
90 
91 namespace panda::ecmascript {
92 using RandomGenerator = base::RandomGenerator;
93 AOTFileManager *JsStackInfo::loader = nullptr;
94 /* static */
Create(const JSRuntimeOptions & options,EcmaParamConfiguration & config)95 EcmaVM *EcmaVM::Create(const JSRuntimeOptions &options, EcmaParamConfiguration &config)
96 {
97     JSRuntimeOptions newOptions = options;
98     // only define SUPPORT_ENABLE_ASM_INTERP can enable asm-interpreter
99 #if !defined(SUPPORT_ENABLE_ASM_INTERP)
100     newOptions.SetEnableAsmInterpreter(false);
101 #endif
102     auto vm = new EcmaVM(newOptions, config);
103     if (UNLIKELY(vm == nullptr)) {
104         LOG_ECMA(ERROR) << "Failed to create jsvm";
105         return nullptr;
106     }
107     auto jsThread = JSThread::Create(vm);
108     vm->thread_ = jsThread;
109     vm->Initialize();
110     if (JsStackInfo::loader == nullptr) {
111         JsStackInfo::loader = vm->GetJSThread()->GetCurrentEcmaContext()->GetAOTFileManager();
112     }
113 #if defined(__aarch64__) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
114     if (SetThreadInfoCallback != nullptr) {
115         SetThreadInfoCallback(CrashCallback);
116     }
117 #endif
118     return vm;
119 }
120 
121 // static
Destroy(EcmaVM * vm)122 bool EcmaVM::Destroy(EcmaVM *vm)
123 {
124     if (vm != nullptr) {
125         delete vm;
126         vm = nullptr;
127         return true;
128     }
129     return false;
130 }
131 
PreFork()132 void EcmaVM::PreFork()
133 {
134     heap_->CompactHeapBeforeFork();
135     heap_->AdjustSpaceSizeForAppSpawn();
136     heap_->GetReadOnlySpace()->SetReadOnly();
137     heap_->DisableParallelGC();
138 }
139 
PostFork()140 void EcmaVM::PostFork()
141 {
142     RandomGenerator::InitRandom();
143     heap_->SetHeapMode(HeapMode::SHARE);
144     GetAssociatedJSThread()->SetThreadId();
145     heap_->EnableParallelGC();
146 }
147 
EcmaVM(JSRuntimeOptions options,EcmaParamConfiguration config)148 EcmaVM::EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config)
149     : stringTable_(new EcmaStringTable(this)),
150       nativeAreaAllocator_(std::make_unique<NativeAreaAllocator>()),
151       heapRegionAllocator_(std::make_unique<HeapRegionAllocator>()),
152       chunk_(nativeAreaAllocator_.get()),
153       ecmaParamConfiguration_(std::move(config))
154 {
155     options_ = std::move(options);
156     icEnabled_ = options_.EnableIC();
157     optionalLogEnabled_ = options_.EnableOptionalLog();
158     options_.ParseAsmInterOption();
159 }
160 
InitializePGOProfiler()161 void EcmaVM::InitializePGOProfiler()
162 {
163     bool isEnablePGOProfiler = IsEnablePGOProfiler();
164     if (pgoProfiler_ == nullptr) {
165         pgoProfiler_ = PGOProfilerManager::GetInstance()->Build(this, isEnablePGOProfiler);
166     }
167     thread_->SetPGOProfilerEnable(isEnablePGOProfiler);
168 }
169 
ResetPGOProfiler()170 void EcmaVM::ResetPGOProfiler()
171 {
172     if (pgoProfiler_ != nullptr) {
173         bool isEnablePGOProfiler = IsEnablePGOProfiler();
174         PGOProfilerManager::GetInstance()->Reset(pgoProfiler_, isEnablePGOProfiler);
175         thread_->SetPGOProfilerEnable(isEnablePGOProfiler);
176         thread_->CheckOrSwitchPGOStubs();
177     }
178 }
179 
IsEnablePGOProfiler() const180 bool EcmaVM::IsEnablePGOProfiler() const
181 {
182     if (options_.IsWorker()) {
183         return PGOProfilerManager::GetInstance()->IsEnable();
184     }
185     return options_.GetEnableAsmInterpreter() && options_.IsEnablePGOProfiler();
186 }
187 
Initialize()188 bool EcmaVM::Initialize()
189 {
190     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "EcmaVM::Initialize");
191     InitializePGOProfiler();
192     Taskpool::GetCurrentTaskpool()->Initialize();
193 #ifndef PANDA_TARGET_WINDOWS
194     RuntimeStubs::Initialize(thread_);
195 #endif
196     heap_ = new Heap(this);
197     heap_->Initialize();
198     gcStats_ = chunk_.New<GCStats>(heap_, options_.GetLongPauseTime());
199     factory_ = chunk_.New<ObjectFactory>(thread_, heap_);
200     if (UNLIKELY(factory_ == nullptr)) {
201         LOG_FULL(FATAL) << "alloc factory_ failed";
202         UNREACHABLE();
203     }
204     debuggerManager_ = chunk_.New<tooling::JsDebuggerManager>(this);
205     auto context = new EcmaContext(thread_);
206     thread_->PushContext(context);
207     [[maybe_unused]] EcmaHandleScope scope(thread_);
208     context->Initialize();
209     thread_->SetGlueGlobalEnv(reinterpret_cast<GlobalEnv *>(context->GetGlobalEnv().GetTaggedType()));
210     thread_->SetGlobalObject(GetGlobalEnv()->GetGlobalObject());
211     thread_->SetCurrentEcmaContext(context);
212 
213     GenerateInternalNativeMethods();
214     quickFixManager_ = new QuickFixManager();
215     snapshotEnv_ = new SnapshotEnv(this);
216     if (!WIN_OR_MAC_OR_IOS_PLATFORM) {
217         snapshotEnv_->Initialize();
218     }
219     if (options_.GetEnableAsmInterpreter()) {
220         thread_->GetCurrentEcmaContext()->LoadStubFile();
221     }
222 
223     callTimer_ = new FunctionCallTimer();
224 
225     initialized_ = true;
226     return true;
227 }
228 
~EcmaVM()229 EcmaVM::~EcmaVM()
230 {
231     initialized_ = false;
232 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
233     DFXJSNApi::StopCpuProfilerForFile(this);
234 #endif
235 #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
236     DeleteHeapProfile();
237 #endif
238     heap_->WaitAllTasksFinished();
239     Taskpool::GetCurrentTaskpool()->Destroy(thread_->GetThreadId());
240 
241     if (pgoProfiler_ != nullptr) {
242         PGOProfilerManager::GetInstance()->Destroy(pgoProfiler_);
243         pgoProfiler_ = nullptr;
244     }
245 
246 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
247     DumpCallTimeInfo();
248 #endif
249 
250     // clear c_address: c++ pointer delete
251     ClearBufferData();
252     if (!isBundlePack_) {
253         std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(assetPath_);
254         if (jsPandaFile != nullptr) {
255             jsPandaFile->DeleteParsedConstpoolVM(this);
256         }
257     }
258 
259     if (gcStats_ != nullptr) {
260         if (options_.EnableGCStatsPrint()) {
261             gcStats_->PrintStatisticResult();
262         }
263         chunk_.Delete(gcStats_);
264         gcStats_ = nullptr;
265     }
266 
267     if (JsStackInfo::loader == GetJSThread()->GetCurrentEcmaContext()->GetAOTFileManager()) {
268         JsStackInfo::loader = nullptr;
269     }
270 
271     if (heap_ != nullptr) {
272         heap_->Destroy();
273         delete heap_;
274         heap_ = nullptr;
275     }
276 
277     if (debuggerManager_ != nullptr) {
278         chunk_.Delete(debuggerManager_);
279         debuggerManager_ = nullptr;
280     }
281 
282     if (factory_ != nullptr) {
283         chunk_.Delete(factory_);
284         factory_ = nullptr;
285     }
286 
287     if (stringTable_ != nullptr) {
288         delete stringTable_;
289         stringTable_ = nullptr;
290     }
291 
292     if (quickFixManager_ != nullptr) {
293         delete quickFixManager_;
294         quickFixManager_ = nullptr;
295     }
296 
297     if (snapshotEnv_ != nullptr) {
298         delete snapshotEnv_;
299         snapshotEnv_ = nullptr;
300     }
301 
302     if (callTimer_ != nullptr) {
303         delete callTimer_;
304         callTimer_ = nullptr;
305     }
306 
307     if (thread_ != nullptr) {
308         delete thread_;
309         thread_ = nullptr;
310     }
311 }
312 
GetGlobalEnv() const313 JSHandle<GlobalEnv> EcmaVM::GetGlobalEnv() const
314 {
315     return thread_->GetCurrentEcmaContext()->GetGlobalEnv();
316 }
317 
FastCallAot(size_t actualNumArgs,JSTaggedType * args,const JSTaggedType * prevFp)318 JSTaggedValue EcmaVM::FastCallAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp)
319 {
320     INTERPRETER_TRACE(thread_, ExecuteAot);
321     auto entry = thread_->GetRTInterface(kungfu::RuntimeStubCSigns::ID_OptimizedFastCallEntry);
322     // do not modify this log to INFO, this will call many times
323     LOG_ECMA(DEBUG) << "start to execute aot entry: " << (void*)entry;
324     auto res = reinterpret_cast<FastCallAotEntryType>(entry)(thread_->GetGlueAddr(),
325                                                              actualNumArgs,
326                                                              args,
327                                                              reinterpret_cast<uintptr_t>(prevFp));
328     return res;
329 }
330 
CheckStartCpuProfiler()331 void EcmaVM::CheckStartCpuProfiler()
332 {
333 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
334     if (options_.EnableCpuProfilerColdStartMainThread() && options_.GetArkBundleName().compare(bundleName_) == 0 &&
335         !options_.IsWorker() && profiler_ == nullptr) {
336         std::string fileName = options_.GetArkBundleName() + ".cpuprofile";
337         if (!builtins::BuiltinsArkTools::CreateFile(fileName)) {
338             LOG_ECMA(ERROR) << "createFile failed " << fileName;
339             return;
340         } else {
341             DFXJSNApi::StartCpuProfilerForFile(this, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
342             return;
343         }
344     }
345 
346     if (options_.EnableCpuProfilerColdStartWorkerThread() && options_.GetArkBundleName().compare(bundleName_) == 0 &&
347         options_.IsWorker() && profiler_ == nullptr) {
348         std::string fileName = options_.GetArkBundleName() + "_"
349                                + std::to_string(thread_->GetThreadId()) + ".cpuprofile";
350         if (!builtins::BuiltinsArkTools::CreateFile(fileName)) {
351             LOG_ECMA(ERROR) << "createFile failed " << fileName;
352             return;
353         } else {
354             DFXJSNApi::StartCpuProfilerForFile(this, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
355             return;
356         }
357     }
358 #endif
359 }
360 
GetAndClearEcmaUncaughtException() const361 JSHandle<JSTaggedValue> EcmaVM::GetAndClearEcmaUncaughtException() const
362 {
363     JSHandle<JSTaggedValue> exceptionHandle = GetEcmaUncaughtException();
364     thread_->ClearException();  // clear for ohos app
365     return exceptionHandle;
366 }
367 
GetEcmaUncaughtException() const368 JSHandle<JSTaggedValue> EcmaVM::GetEcmaUncaughtException() const
369 {
370     if (!thread_->HasPendingException()) {
371         return JSHandle<JSTaggedValue>();
372     }
373     JSHandle<JSTaggedValue> exceptionHandle(thread_, thread_->GetException());
374     return exceptionHandle;
375 }
376 
PrintJSErrorInfo(const JSHandle<JSTaggedValue> & exceptionInfo) const377 void EcmaVM::PrintJSErrorInfo(const JSHandle<JSTaggedValue> &exceptionInfo) const
378 {
379     EcmaContext::PrintJSErrorInfo(thread_, exceptionInfo);
380 }
381 
ProcessNativeDelete(const WeakRootVisitor & visitor)382 void EcmaVM::ProcessNativeDelete(const WeakRootVisitor &visitor)
383 {
384     auto iter = nativePointerList_.begin();
385     while (iter != nativePointerList_.end()) {
386         JSNativePointer *object = *iter;
387         auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
388         if (fwd == nullptr) {
389             object->Destroy();
390             iter = nativePointerList_.erase(iter);
391         } else {
392             ++iter;
393         }
394     }
395     thread_->GetCurrentEcmaContext()->ProcessNativeDelete(visitor);
396 }
397 
ProcessReferences(const WeakRootVisitor & visitor)398 void EcmaVM::ProcessReferences(const WeakRootVisitor &visitor)
399 {
400     if (thread_->GetCurrentEcmaContext()->GetRegExpParserCache() != nullptr) {
401         thread_->GetCurrentEcmaContext()->GetRegExpParserCache()->Clear();
402     }
403     heap_->ResetNativeBindingSize();
404     // array buffer
405     auto iter = nativePointerList_.begin();
406     while (iter != nativePointerList_.end()) {
407         JSNativePointer *object = *iter;
408         auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
409         if (fwd == nullptr) {
410             object->Destroy();
411             iter = nativePointerList_.erase(iter);
412             continue;
413         }
414         heap_->IncreaseNativeBindingSize(JSNativePointer::Cast(fwd));
415         if (fwd != reinterpret_cast<TaggedObject *>(object)) {
416             *iter = JSNativePointer::Cast(fwd);
417         }
418         ++iter;
419     }
420     thread_->GetCurrentEcmaContext()->ProcessReferences(visitor);
421 }
422 
PushToNativePointerList(JSNativePointer * array)423 void EcmaVM::PushToNativePointerList(JSNativePointer *array)
424 {
425     nativePointerList_.emplace_back(array);
426 }
427 
RemoveFromNativePointerList(JSNativePointer * array)428 void EcmaVM::RemoveFromNativePointerList(JSNativePointer *array)
429 {
430     auto iter = std::find(nativePointerList_.begin(), nativePointerList_.end(), array);
431     if (iter != nativePointerList_.end()) {
432         JSNativePointer *object = *iter;
433         object->Destroy();
434         nativePointerList_.erase(iter);
435     }
436 }
437 
PushToDeregisterModuleList(CString module)438 void EcmaVM::PushToDeregisterModuleList(CString module)
439 {
440     deregisterModuleList_.emplace_back(module);
441 }
442 
RemoveFromDeregisterModuleList(CString module)443 void EcmaVM::RemoveFromDeregisterModuleList(CString module)
444 {
445     auto iter = std::find(deregisterModuleList_.begin(), deregisterModuleList_.end(), module);
446     if (iter != deregisterModuleList_.end()) {
447         deregisterModuleList_.erase(iter);
448     }
449 }
450 
ContainInDeregisterModuleList(CString module)451 bool EcmaVM::ContainInDeregisterModuleList(CString module)
452 {
453     return (std::find(deregisterModuleList_.begin(), deregisterModuleList_.end(), module)
454         != deregisterModuleList_.end());
455 }
456 
ClearBufferData()457 void EcmaVM::ClearBufferData()
458 {
459     for (auto iter : nativePointerList_) {
460         iter->Destroy();
461     }
462     nativePointerList_.clear();
463     thread_->GetCurrentEcmaContext()->ClearBufferData();
464     internalNativeMethods_.clear();
465     workerList_.clear();
466     deregisterModuleList_.clear();
467 }
468 
CollectGarbage(TriggerGCType gcType,GCReason reason) const469 void EcmaVM::CollectGarbage(TriggerGCType gcType, GCReason reason) const
470 {
471     heap_->CollectGarbage(gcType, reason);
472 }
473 
Iterate(const RootVisitor & v,const RootRangeVisitor & rv)474 void EcmaVM::Iterate(const RootVisitor &v, const RootRangeVisitor &rv)
475 {
476     rv(Root::ROOT_VM, ObjectSlot(ToUintPtr(&internalNativeMethods_.front())),
477         ObjectSlot(ToUintPtr(&internalNativeMethods_.back()) + JSTaggedValue::TaggedTypeSize()));
478     if (!WIN_OR_MAC_OR_IOS_PLATFORM) {
479         snapshotEnv_->Iterate(v);
480     }
481 }
482 
483 #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
DeleteHeapProfile()484 void EcmaVM::DeleteHeapProfile()
485 {
486     if (heapProfile_ == nullptr) {
487         return;
488     }
489     const_cast<NativeAreaAllocator *>(GetNativeAreaAllocator())->Delete(heapProfile_);
490     heapProfile_ = nullptr;
491 }
492 
GetHeapProfile()493 HeapProfilerInterface *EcmaVM::GetHeapProfile()
494 {
495     if (heapProfile_ != nullptr) {
496         return heapProfile_;
497     }
498     return nullptr;
499 }
500 
GetOrNewHeapProfile()501 HeapProfilerInterface *EcmaVM::GetOrNewHeapProfile()
502 {
503     if (heapProfile_ != nullptr) {
504         return heapProfile_;
505     }
506     heapProfile_ = const_cast<NativeAreaAllocator *>(GetNativeAreaAllocator())->New<HeapProfiler>(this);
507     ASSERT(heapProfile_ != nullptr);
508     return heapProfile_;
509 }
510 
StartHeapTracking()511 void EcmaVM::StartHeapTracking()
512 {
513     heap_->StartHeapTracking();
514 }
515 
StopHeapTracking()516 void EcmaVM::StopHeapTracking()
517 {
518     heap_->StopHeapTracking();
519 }
520 #endif
521 
522 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
523 void *EcmaVM::InternalMethodTable[] = {
524     reinterpret_cast<void *>(builtins::BuiltinsGlobal::CallJsBoundFunction),
525     reinterpret_cast<void *>(builtins::BuiltinsGlobal::CallJsProxy),
526     reinterpret_cast<void *>(builtins::BuiltinsObject::CreateDataPropertyOnObjectFunctions),
527 #ifdef ARK_SUPPORT_INTL
528     reinterpret_cast<void *>(builtins::BuiltinsCollator::AnonymousCollator),
529     reinterpret_cast<void *>(builtins::BuiltinsDateTimeFormat::AnonymousDateTimeFormat),
530     reinterpret_cast<void *>(builtins::BuiltinsNumberFormat::NumberFormatInternalFormatNumber),
531 #endif
532     reinterpret_cast<void *>(builtins::BuiltinsProxy::InvalidateProxyFunction),
533     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AsyncAwaitFulfilled),
534     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AsyncAwaitRejected),
535     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::ResolveElementFunction),
536     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::Resolve),
537     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::Reject),
538     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::Executor),
539     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AnyRejectElementFunction),
540     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AllSettledResolveElementFunction),
541     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AllSettledRejectElementFunction),
542     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::ThenFinally),
543     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::CatchFinally),
544     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::valueThunkFunction),
545     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::throwerFunction),
546     reinterpret_cast<void *>(JSAsyncGeneratorObject::ProcessorFulfilledFunc),
547     reinterpret_cast<void *>(JSAsyncGeneratorObject::ProcessorRejectedFunc),
548     reinterpret_cast<void *>(JSAsyncFromSyncIterator::AsyncFromSyncIterUnwarpFunction)
549 };
550 
GenerateInternalNativeMethods()551 void EcmaVM::GenerateInternalNativeMethods()
552 {
553     size_t length = static_cast<size_t>(MethodIndex::METHOD_END);
554     constexpr uint32_t numArgs = 2;  // function object and this
555     for (size_t i = 0; i < length; i++) {
556         auto method = factory_->NewMethod(nullptr, MemSpaceType::NON_MOVABLE);
557         method->SetNativePointer(InternalMethodTable[i]);
558         method->SetNativeBit(true);
559         method->SetNumArgsWithCallField(numArgs);
560         method->SetFunctionKind(FunctionKind::NORMAL_FUNCTION);
561         internalNativeMethods_.emplace_back(method.GetTaggedValue());
562     }
563 }
564 
GetMethodByIndex(MethodIndex idx)565 JSTaggedValue EcmaVM::GetMethodByIndex(MethodIndex idx)
566 {
567     auto index = static_cast<uint8_t>(idx);
568     ASSERT(index < internalNativeMethods_.size());
569     return internalNativeMethods_[index];
570 }
571 
TriggerConcurrentCallback(JSTaggedValue result,JSTaggedValue hint)572 void EcmaVM::TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint)
573 {
574     if (concurrentCallback_ == nullptr) {
575         LOG_ECMA(DEBUG) << "Only trigger concurrent callback in taskpool thread";
576         return;
577     }
578 
579     bool success = true;
580     if (result.IsJSPromise()) {
581         // Async concurrent will return Promise
582         auto promise = JSPromise::Cast(result.GetTaggedObject());
583         auto status = promise->GetPromiseState();
584         if (status == PromiseState::PENDING) {
585             result = JSHandle<JSTaggedValue>::Cast(factory_->GetJSError(
586                 ErrorType::ERROR, "Can't return Promise in pending state")).GetTaggedValue();
587         } else {
588             result = promise->GetPromiseResult();
589         }
590 
591         if (status != PromiseState::FULFILLED) {
592             success = false;
593         }
594     }
595 
596     JSHandle<JSTaggedValue> functionValue(thread_, hint);
597     if (!functionValue->IsJSFunction()) {
598         LOG_ECMA(ERROR) << "TriggerConcurrentCallback hint is not function";
599         return;
600     }
601     JSHandle<JSFunction> functionInfo(functionValue);
602     JSTaggedValue extraInfoValue = functionInfo->GetFunctionExtraInfo();
603     if (!extraInfoValue.IsJSNativePointer()) {
604         LOG_ECMA(INFO) << "FunctionExtraInfo is not JSNativePointer";
605         return;
606     }
607     JSHandle<JSNativePointer> extraInfo(thread_, extraInfoValue);
608     void *taskInfo = extraInfo->GetData();
609 
610     concurrentCallback_(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, result)), success,
611                         taskInfo, concurrentData_);
612 }
613 
DumpCallTimeInfo()614 void EcmaVM::DumpCallTimeInfo()
615 {
616     if (callTimer_ != nullptr) {
617         callTimer_->PrintAllStats();
618     }
619 }
620 
WorkersetInfo(EcmaVM * hostVm,EcmaVM * workerVm)621 void EcmaVM::WorkersetInfo(EcmaVM *hostVm, EcmaVM *workerVm)
622 {
623     os::memory::LockHolder lock(mutex_);
624     auto thread = workerVm->GetJSThread();
625     if (thread != nullptr && hostVm != nullptr) {
626         auto tid = thread->GetThreadId();
627         if (tid != 0) {
628             workerList_.emplace(tid, workerVm);
629         }
630     }
631 }
632 
GetWorkerVm(uint32_t tid)633 EcmaVM *EcmaVM::GetWorkerVm(uint32_t tid)
634 {
635     os::memory::LockHolder lock(mutex_);
636     EcmaVM *workerVm = nullptr;
637     if (!workerList_.empty()) {
638         auto iter = workerList_.find(tid);
639         if (iter != workerList_.end()) {
640             workerVm = iter->second;
641         }
642     }
643     return workerVm;
644 }
645 
DeleteWorker(EcmaVM * hostVm,EcmaVM * workerVm)646 bool EcmaVM::DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm)
647 {
648     os::memory::LockHolder lock(mutex_);
649     auto thread = workerVm->GetJSThread();
650     if (hostVm != nullptr && thread != nullptr) {
651         auto tid = thread->GetThreadId();
652         if (tid == 0) {
653             return false;
654         }
655         auto iter = workerList_.find(tid);
656         if (iter != workerList_.end()) {
657             workerList_.erase(iter);
658             return true;
659         }
660         return false;
661     }
662     return false;
663 }
664 
SuspendWorkerVm(uint32_t tid)665 bool EcmaVM::SuspendWorkerVm(uint32_t tid)
666 {
667     os::memory::LockHolder lock(mutex_);
668     if (!workerList_.empty()) {
669         auto iter = workerList_.find(tid);
670         if (iter != workerList_.end()) {
671             return DFXJSNApi::SuspendVM(iter->second);
672         }
673     }
674     return false;
675 }
676 
ResumeWorkerVm(uint32_t tid)677 void EcmaVM::ResumeWorkerVm(uint32_t tid)
678 {
679     os::memory::LockHolder lock(mutex_);
680     if (!workerList_.empty()) {
681         auto iter = workerList_.find(tid);
682         if (iter != workerList_.end()) {
683             DFXJSNApi::ResumeVM(iter->second);
684         }
685     }
686 }
687 }  // namespace panda::ecmascript
688