• 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     JsStackInfo::loader = vm->GetJSThread()->GetCurrentEcmaContext()->GetAOTFileManager();
111 #if defined(__aarch64__) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
112     if (SetThreadInfoCallback != nullptr) {
113         SetThreadInfoCallback(CrashCallback);
114     }
115 #endif
116     return vm;
117 }
118 
119 // static
Destroy(EcmaVM * vm)120 bool EcmaVM::Destroy(EcmaVM *vm)
121 {
122     if (vm != nullptr) {
123         delete vm;
124         vm = nullptr;
125         return true;
126     }
127     return false;
128 }
129 
PreFork()130 void EcmaVM::PreFork()
131 {
132     heap_->CompactHeapBeforeFork();
133     heap_->AdjustSpaceSizeForAppSpawn();
134     heap_->GetReadOnlySpace()->SetReadOnly();
135     heap_->DisableParallelGC();
136 }
137 
PostFork()138 void EcmaVM::PostFork()
139 {
140     RandomGenerator::InitRandom();
141     heap_->SetHeapMode(HeapMode::SHARE);
142     GetAssociatedJSThread()->SetThreadId();
143     heap_->EnableParallelGC();
144 }
145 
EcmaVM(JSRuntimeOptions options,EcmaParamConfiguration config)146 EcmaVM::EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config)
147     : stringTable_(new EcmaStringTable(this)),
148       nativeAreaAllocator_(std::make_unique<NativeAreaAllocator>()),
149       heapRegionAllocator_(std::make_unique<HeapRegionAllocator>()),
150       chunk_(nativeAreaAllocator_.get()),
151       ecmaParamConfiguration_(std::move(config))
152 {
153     options_ = std::move(options);
154     icEnabled_ = options_.EnableIC();
155     optionalLogEnabled_ = options_.EnableOptionalLog();
156     options_.ParseAsmInterOption();
157 }
158 
InitializePGOProfiler()159 void EcmaVM::InitializePGOProfiler()
160 {
161     bool isEnablePGOProfiler = IsEnablePGOProfiler();
162     if (pgoProfiler_ == nullptr) {
163         pgoProfiler_ = PGOProfilerManager::GetInstance()->Build(this, isEnablePGOProfiler);
164     }
165     thread_->SetPGOProfilerEnable(isEnablePGOProfiler);
166 }
167 
ResetPGOProfiler()168 void EcmaVM::ResetPGOProfiler()
169 {
170     if (pgoProfiler_ != nullptr) {
171         bool isEnablePGOProfiler = IsEnablePGOProfiler();
172         PGOProfilerManager::GetInstance()->Reset(pgoProfiler_, isEnablePGOProfiler);
173         thread_->SetPGOProfilerEnable(isEnablePGOProfiler);
174         thread_->CheckOrSwitchPGOStubs();
175     }
176 }
177 
IsEnablePGOProfiler() const178 bool EcmaVM::IsEnablePGOProfiler() const
179 {
180     if (options_.IsWorker()) {
181         return PGOProfilerManager::GetInstance()->IsEnable();
182     }
183     return options_.GetEnableAsmInterpreter() && options_.IsEnablePGOProfiler();
184 }
185 
Initialize()186 bool EcmaVM::Initialize()
187 {
188     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "EcmaVM::Initialize");
189     InitializePGOProfiler();
190     Taskpool::GetCurrentTaskpool()->Initialize();
191 #ifndef PANDA_TARGET_WINDOWS
192     RuntimeStubs::Initialize(thread_);
193 #endif
194     heap_ = new Heap(this);
195     heap_->Initialize();
196     gcStats_ = chunk_.New<GCStats>(heap_, options_.GetLongPauseTime());
197     factory_ = chunk_.New<ObjectFactory>(thread_, heap_);
198     if (UNLIKELY(factory_ == nullptr)) {
199         LOG_FULL(FATAL) << "alloc factory_ failed";
200         UNREACHABLE();
201     }
202     debuggerManager_ = chunk_.New<tooling::JsDebuggerManager>(this);
203     auto context = new EcmaContext(thread_);
204     thread_->PushContext(context);
205     [[maybe_unused]] EcmaHandleScope scope(thread_);
206     context->Initialize();
207     thread_->SetGlueGlobalEnv(reinterpret_cast<GlobalEnv *>(context->GetGlobalEnv().GetTaggedType()));
208     thread_->SetGlobalObject(GetGlobalEnv()->GetGlobalObject());
209     thread_->SetCurrentEcmaContext(context);
210 
211     GenerateInternalNativeMethods();
212     quickFixManager_ = new QuickFixManager();
213     snapshotEnv_ = new SnapshotEnv(this);
214     if (!WIN_OR_MAC_OR_IOS_PLATFORM) {
215         snapshotEnv_->Initialize();
216     }
217     if (options_.GetEnableAsmInterpreter()) {
218         thread_->GetCurrentEcmaContext()->LoadStubFile();
219     }
220 
221     callTimer_ = new FunctionCallTimer();
222 
223     initialized_ = true;
224     return true;
225 }
226 
~EcmaVM()227 EcmaVM::~EcmaVM()
228 {
229     initialized_ = false;
230 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
231     DFXJSNApi::StopCpuProfilerForFile(this);
232 #endif
233 #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
234     DeleteHeapProfile();
235 #endif
236     heap_->WaitAllTasksFinished();
237     Taskpool::GetCurrentTaskpool()->Destroy(thread_->GetThreadId());
238 
239     if (pgoProfiler_ != nullptr) {
240         PGOProfilerManager::GetInstance()->Destroy(pgoProfiler_);
241         pgoProfiler_ = nullptr;
242     }
243 
244 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
245     DumpCallTimeInfo();
246 #endif
247 
248     // clear c_address: c++ pointer delete
249     ClearBufferData();
250     if (!isBundlePack_) {
251         std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(assetPath_);
252         if (jsPandaFile != nullptr) {
253             jsPandaFile->DeleteParsedConstpoolVM(this);
254         }
255     }
256 
257     if (gcStats_ != nullptr) {
258         if (options_.EnableGCStatsPrint()) {
259             gcStats_->PrintStatisticResult();
260         }
261         chunk_.Delete(gcStats_);
262         gcStats_ = nullptr;
263     }
264 
265     if (heap_ != nullptr) {
266         heap_->Destroy();
267         delete heap_;
268         heap_ = nullptr;
269     }
270 
271     if (debuggerManager_ != nullptr) {
272         chunk_.Delete(debuggerManager_);
273         debuggerManager_ = nullptr;
274     }
275 
276     if (factory_ != nullptr) {
277         chunk_.Delete(factory_);
278         factory_ = nullptr;
279     }
280 
281     if (stringTable_ != nullptr) {
282         delete stringTable_;
283         stringTable_ = nullptr;
284     }
285 
286     if (quickFixManager_ != nullptr) {
287         delete quickFixManager_;
288         quickFixManager_ = nullptr;
289     }
290 
291     if (snapshotEnv_ != nullptr) {
292         delete snapshotEnv_;
293         snapshotEnv_ = nullptr;
294     }
295 
296     if (callTimer_ != nullptr) {
297         delete callTimer_;
298         callTimer_ = nullptr;
299     }
300 
301     if (thread_ != nullptr) {
302         delete thread_;
303         thread_ = nullptr;
304     }
305 }
306 
GetGlobalEnv() const307 JSHandle<GlobalEnv> EcmaVM::GetGlobalEnv() const
308 {
309     return thread_->GetCurrentEcmaContext()->GetGlobalEnv();
310 }
311 
FastCallAot(size_t actualNumArgs,JSTaggedType * args,const JSTaggedType * prevFp)312 JSTaggedValue EcmaVM::FastCallAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp)
313 {
314     INTERPRETER_TRACE(thread_, ExecuteAot);
315     auto entry = thread_->GetRTInterface(kungfu::RuntimeStubCSigns::ID_OptimizedFastCallEntry);
316     // do not modify this log to INFO, this will call many times
317     LOG_ECMA(DEBUG) << "start to execute aot entry: " << (void*)entry;
318     auto res = reinterpret_cast<FastCallAotEntryType>(entry)(thread_->GetGlueAddr(),
319                                                              actualNumArgs,
320                                                              args,
321                                                              reinterpret_cast<uintptr_t>(prevFp));
322     return res;
323 }
324 
CheckStartCpuProfiler()325 void EcmaVM::CheckStartCpuProfiler()
326 {
327 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
328     if (options_.EnableCpuProfilerColdStartMainThread() && options_.GetArkBundleName().compare(bundleName_) == 0 &&
329         !options_.IsWorker() && profiler_ == nullptr) {
330         std::string fileName = options_.GetArkBundleName() + ".cpuprofile";
331         if (!builtins::BuiltinsArkTools::CreateFile(fileName)) {
332             LOG_ECMA(ERROR) << "createFile failed " << fileName;
333             return;
334         } else {
335             DFXJSNApi::StartCpuProfilerForFile(this, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
336             return;
337         }
338     }
339 
340     if (options_.EnableCpuProfilerColdStartWorkerThread() && options_.GetArkBundleName().compare(bundleName_) == 0 &&
341         options_.IsWorker() && profiler_ == nullptr) {
342         std::string fileName = options_.GetArkBundleName() + "_"
343                                + std::to_string(thread_->GetThreadId()) + ".cpuprofile";
344         if (!builtins::BuiltinsArkTools::CreateFile(fileName)) {
345             LOG_ECMA(ERROR) << "createFile failed " << fileName;
346             return;
347         } else {
348             DFXJSNApi::StartCpuProfilerForFile(this, fileName, CpuProfiler::INTERVAL_OF_INNER_START);
349             return;
350         }
351     }
352 #endif
353 }
354 
GetAndClearEcmaUncaughtException() const355 JSHandle<JSTaggedValue> EcmaVM::GetAndClearEcmaUncaughtException() const
356 {
357     JSHandle<JSTaggedValue> exceptionHandle = GetEcmaUncaughtException();
358     thread_->ClearException();  // clear for ohos app
359     return exceptionHandle;
360 }
361 
GetEcmaUncaughtException() const362 JSHandle<JSTaggedValue> EcmaVM::GetEcmaUncaughtException() const
363 {
364     if (!thread_->HasPendingException()) {
365         return JSHandle<JSTaggedValue>();
366     }
367     JSHandle<JSTaggedValue> exceptionHandle(thread_, thread_->GetException());
368     return exceptionHandle;
369 }
370 
PrintJSErrorInfo(const JSHandle<JSTaggedValue> & exceptionInfo) const371 void EcmaVM::PrintJSErrorInfo(const JSHandle<JSTaggedValue> &exceptionInfo) const
372 {
373     EcmaContext::PrintJSErrorInfo(thread_, exceptionInfo);
374 }
375 
ProcessNativeDelete(const WeakRootVisitor & visitor)376 void EcmaVM::ProcessNativeDelete(const WeakRootVisitor &visitor)
377 {
378     auto iter = nativePointerList_.begin();
379     while (iter != nativePointerList_.end()) {
380         JSNativePointer *object = *iter;
381         auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
382         if (fwd == nullptr) {
383             object->Destroy();
384             iter = nativePointerList_.erase(iter);
385         } else {
386             ++iter;
387         }
388     }
389     thread_->GetCurrentEcmaContext()->ProcessNativeDelete(visitor);
390 }
391 
ProcessReferences(const WeakRootVisitor & visitor)392 void EcmaVM::ProcessReferences(const WeakRootVisitor &visitor)
393 {
394     if (thread_->GetCurrentEcmaContext()->GetRegExpParserCache() != nullptr) {
395         thread_->GetCurrentEcmaContext()->GetRegExpParserCache()->Clear();
396     }
397     heap_->ResetNativeBindingSize();
398     // array buffer
399     auto iter = nativePointerList_.begin();
400     while (iter != nativePointerList_.end()) {
401         JSNativePointer *object = *iter;
402         auto fwd = visitor(reinterpret_cast<TaggedObject *>(object));
403         if (fwd == nullptr) {
404             object->Destroy();
405             iter = nativePointerList_.erase(iter);
406             continue;
407         }
408         heap_->IncreaseNativeBindingSize(JSNativePointer::Cast(fwd));
409         if (fwd != reinterpret_cast<TaggedObject *>(object)) {
410             *iter = JSNativePointer::Cast(fwd);
411         }
412         ++iter;
413     }
414     thread_->GetCurrentEcmaContext()->ProcessReferences(visitor);
415 }
416 
PushToNativePointerList(JSNativePointer * array)417 void EcmaVM::PushToNativePointerList(JSNativePointer *array)
418 {
419     nativePointerList_.emplace_back(array);
420 }
421 
RemoveFromNativePointerList(JSNativePointer * array)422 void EcmaVM::RemoveFromNativePointerList(JSNativePointer *array)
423 {
424     auto iter = std::find(nativePointerList_.begin(), nativePointerList_.end(), array);
425     if (iter != nativePointerList_.end()) {
426         JSNativePointer *object = *iter;
427         object->Destroy();
428         nativePointerList_.erase(iter);
429     }
430 }
431 
PushToDeregisterModuleList(CString module)432 void EcmaVM::PushToDeregisterModuleList(CString module)
433 {
434     deregisterModuleList_.emplace_back(module);
435 }
436 
RemoveFromDeregisterModuleList(CString module)437 void EcmaVM::RemoveFromDeregisterModuleList(CString module)
438 {
439     auto iter = std::find(deregisterModuleList_.begin(), deregisterModuleList_.end(), module);
440     if (iter != deregisterModuleList_.end()) {
441         deregisterModuleList_.erase(iter);
442     }
443 }
444 
ContainInDeregisterModuleList(CString module)445 bool EcmaVM::ContainInDeregisterModuleList(CString module)
446 {
447     return (std::find(deregisterModuleList_.begin(), deregisterModuleList_.end(), module)
448         != deregisterModuleList_.end());
449 }
450 
ClearBufferData()451 void EcmaVM::ClearBufferData()
452 {
453     for (auto iter : nativePointerList_) {
454         iter->Destroy();
455     }
456     nativePointerList_.clear();
457     thread_->GetCurrentEcmaContext()->ClearBufferData();
458     internalNativeMethods_.clear();
459     workerList_.clear();
460     deregisterModuleList_.clear();
461 }
462 
CollectGarbage(TriggerGCType gcType,GCReason reason) const463 void EcmaVM::CollectGarbage(TriggerGCType gcType, GCReason reason) const
464 {
465     heap_->CollectGarbage(gcType, reason);
466 }
467 
Iterate(const RootVisitor & v,const RootRangeVisitor & rv)468 void EcmaVM::Iterate(const RootVisitor &v, const RootRangeVisitor &rv)
469 {
470     rv(Root::ROOT_VM, ObjectSlot(ToUintPtr(&internalNativeMethods_.front())),
471         ObjectSlot(ToUintPtr(&internalNativeMethods_.back()) + JSTaggedValue::TaggedTypeSize()));
472     if (!WIN_OR_MAC_OR_IOS_PLATFORM) {
473         snapshotEnv_->Iterate(v);
474     }
475 }
476 
477 #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
DeleteHeapProfile()478 void EcmaVM::DeleteHeapProfile()
479 {
480     if (heapProfile_ == nullptr) {
481         return;
482     }
483     const_cast<NativeAreaAllocator *>(GetNativeAreaAllocator())->Delete(heapProfile_);
484     heapProfile_ = nullptr;
485 }
486 
GetHeapProfile()487 HeapProfilerInterface *EcmaVM::GetHeapProfile()
488 {
489     if (heapProfile_ != nullptr) {
490         return heapProfile_;
491     }
492     return nullptr;
493 }
494 
GetOrNewHeapProfile()495 HeapProfilerInterface *EcmaVM::GetOrNewHeapProfile()
496 {
497     if (heapProfile_ != nullptr) {
498         return heapProfile_;
499     }
500     heapProfile_ = const_cast<NativeAreaAllocator *>(GetNativeAreaAllocator())->New<HeapProfiler>(this);
501     ASSERT(heapProfile_ != nullptr);
502     return heapProfile_;
503 }
504 
StartHeapTracking()505 void EcmaVM::StartHeapTracking()
506 {
507     heap_->StartHeapTracking();
508 }
509 
StopHeapTracking()510 void EcmaVM::StopHeapTracking()
511 {
512     heap_->StopHeapTracking();
513 }
514 #endif
515 
516 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
517 void *EcmaVM::InternalMethodTable[] = {
518     reinterpret_cast<void *>(builtins::BuiltinsGlobal::CallJsBoundFunction),
519     reinterpret_cast<void *>(builtins::BuiltinsGlobal::CallJsProxy),
520     reinterpret_cast<void *>(builtins::BuiltinsObject::CreateDataPropertyOnObjectFunctions),
521 #ifdef ARK_SUPPORT_INTL
522     reinterpret_cast<void *>(builtins::BuiltinsCollator::AnonymousCollator),
523     reinterpret_cast<void *>(builtins::BuiltinsDateTimeFormat::AnonymousDateTimeFormat),
524     reinterpret_cast<void *>(builtins::BuiltinsNumberFormat::NumberFormatInternalFormatNumber),
525 #endif
526     reinterpret_cast<void *>(builtins::BuiltinsProxy::InvalidateProxyFunction),
527     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AsyncAwaitFulfilled),
528     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AsyncAwaitRejected),
529     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::ResolveElementFunction),
530     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::Resolve),
531     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::Reject),
532     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::Executor),
533     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AnyRejectElementFunction),
534     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AllSettledResolveElementFunction),
535     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::AllSettledRejectElementFunction),
536     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::ThenFinally),
537     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::CatchFinally),
538     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::valueThunkFunction),
539     reinterpret_cast<void *>(builtins::BuiltinsPromiseHandler::throwerFunction),
540     reinterpret_cast<void *>(JSAsyncGeneratorObject::ProcessorFulfilledFunc),
541     reinterpret_cast<void *>(JSAsyncGeneratorObject::ProcessorRejectedFunc),
542     reinterpret_cast<void *>(JSAsyncFromSyncIterator::AsyncFromSyncIterUnwarpFunction)
543 };
544 
GenerateInternalNativeMethods()545 void EcmaVM::GenerateInternalNativeMethods()
546 {
547     size_t length = static_cast<size_t>(MethodIndex::METHOD_END);
548     constexpr uint32_t numArgs = 2;  // function object and this
549     for (size_t i = 0; i < length; i++) {
550         auto method = factory_->NewMethod(nullptr, MemSpaceType::NON_MOVABLE);
551         method->SetNativePointer(InternalMethodTable[i]);
552         method->SetNativeBit(true);
553         method->SetNumArgsWithCallField(numArgs);
554         method->SetFunctionKind(FunctionKind::NORMAL_FUNCTION);
555         internalNativeMethods_.emplace_back(method.GetTaggedValue());
556     }
557 }
558 
GetMethodByIndex(MethodIndex idx)559 JSTaggedValue EcmaVM::GetMethodByIndex(MethodIndex idx)
560 {
561     auto index = static_cast<uint8_t>(idx);
562     ASSERT(index < internalNativeMethods_.size());
563     return internalNativeMethods_[index];
564 }
565 
TriggerConcurrentCallback(JSTaggedValue result,JSTaggedValue hint)566 void EcmaVM::TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint)
567 {
568     if (concurrentCallback_ == nullptr) {
569         LOG_ECMA(DEBUG) << "Only trigger concurrent callback in taskpool thread";
570         return;
571     }
572 
573     bool success = true;
574     if (result.IsJSPromise()) {
575         // Async concurrent will return Promise
576         auto promise = JSPromise::Cast(result.GetTaggedObject());
577         auto status = promise->GetPromiseState();
578         if (status == PromiseState::PENDING) {
579             result = JSHandle<JSTaggedValue>::Cast(factory_->GetJSError(
580                 ErrorType::ERROR, "Can't return Promise in pending state")).GetTaggedValue();
581         } else {
582             result = promise->GetPromiseResult();
583         }
584 
585         if (status != PromiseState::FULFILLED) {
586             success = false;
587         }
588     }
589 
590     JSHandle<JSTaggedValue> functionValue(thread_, hint);
591     if (!functionValue->IsJSFunction()) {
592         LOG_ECMA(ERROR) << "TriggerConcurrentCallback hint is not function";
593         return;
594     }
595     JSHandle<JSFunction> functionInfo(functionValue);
596     JSTaggedValue extraInfoValue = functionInfo->GetFunctionExtraInfo();
597     if (!extraInfoValue.IsJSNativePointer()) {
598         LOG_ECMA(INFO) << "FunctionExtraInfo is not JSNativePointer";
599         return;
600     }
601     JSHandle<JSNativePointer> extraInfo(thread_, extraInfoValue);
602     void *taskInfo = extraInfo->GetData();
603 
604     concurrentCallback_(JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, result)), success,
605                         taskInfo, concurrentData_);
606 }
607 
DumpCallTimeInfo()608 void EcmaVM::DumpCallTimeInfo()
609 {
610     if (callTimer_ != nullptr) {
611         callTimer_->PrintAllStats();
612     }
613 }
614 
WorkersetInfo(EcmaVM * hostVm,EcmaVM * workerVm)615 void EcmaVM::WorkersetInfo(EcmaVM *hostVm, EcmaVM *workerVm)
616 {
617     os::memory::LockHolder lock(mutex_);
618     auto thread = workerVm->GetJSThread();
619     if (thread != nullptr && hostVm != nullptr) {
620         auto tid = thread->GetThreadId();
621         if (tid != 0) {
622             workerList_.emplace(tid, workerVm);
623         }
624     }
625 }
626 
GetWorkerVm(uint32_t tid)627 EcmaVM *EcmaVM::GetWorkerVm(uint32_t tid)
628 {
629     os::memory::LockHolder lock(mutex_);
630     EcmaVM *workerVm = nullptr;
631     if (!workerList_.empty()) {
632         auto iter = workerList_.find(tid);
633         if (iter != workerList_.end()) {
634             workerVm = iter->second;
635         }
636     }
637     return workerVm;
638 }
639 
DeleteWorker(EcmaVM * hostVm,EcmaVM * workerVm)640 bool EcmaVM::DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm)
641 {
642     os::memory::LockHolder lock(mutex_);
643     auto thread = workerVm->GetJSThread();
644     if (hostVm != nullptr && thread != nullptr) {
645         auto tid = thread->GetThreadId();
646         if (tid == 0) {
647             return false;
648         }
649         auto iter = workerList_.find(tid);
650         if (iter != workerList_.end()) {
651             workerList_.erase(iter);
652             return true;
653         }
654         return false;
655     }
656     return false;
657 }
658 
SuspendWorkerVm(uint32_t tid)659 bool EcmaVM::SuspendWorkerVm(uint32_t tid)
660 {
661     os::memory::LockHolder lock(mutex_);
662     if (!workerList_.empty()) {
663         auto iter = workerList_.find(tid);
664         if (iter != workerList_.end()) {
665             return DFXJSNApi::SuspendVM(iter->second);
666         }
667     }
668     return false;
669 }
670 
ResumeWorkerVm(uint32_t tid)671 void EcmaVM::ResumeWorkerVm(uint32_t tid)
672 {
673     os::memory::LockHolder lock(mutex_);
674     if (!workerList_.empty()) {
675         auto iter = workerList_.find(tid);
676         if (iter != workerList_.end()) {
677             DFXJSNApi::ResumeVM(iter->second);
678         }
679     }
680 }
681 }  // namespace panda::ecmascript
682