diff --git a/ecmascript/base/config.h b/ecmascript/base/config.h index c8d03a02be511fc80c8ed3205f0a7e6c6e297a14..229c2eba8c86adcd58d0b1a37a2789183fc93626 100644 --- a/ecmascript/base/config.h +++ b/ecmascript/base/config.h @@ -22,6 +22,7 @@ namespace panda::ecmascript { #define ECMASCRIPT_ENABLE_RUNTIME_STAT 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ECMASCRIPT_ENABLE_IC 1 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define ECMASCRIPT_ENABLE_THREAD_CHECK 0 } // namespace panda::ecmascript #endif // ECMASCRIPT_BASE_CONFIG_H diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index afa964b5a12c8f40210ae22c70243ff2951218ef..94c5079c8586313a860ddc126f212a018091898a 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -18,6 +18,7 @@ #include +#include "ecmascript/base/config.h" #include "ecmascript/ecma_string_table.h" #include "ecmascript/global_handle_collection.h" #include "ecmascript/js_handle.h" @@ -27,6 +28,7 @@ #include "ecmascript/mem/c_string.h" #include "ecmascript/mem/chunk_containers.h" #include "ecmascript/mem/gc_stats.h" +#include "ecmascript/mem/heap.h" #include "ecmascript/mem/heap_roots.h" #include "ecmascript/mem/space.h" #include "ecmascript/snapshot/mem/snapshot_serialize.h" @@ -239,6 +241,14 @@ public: JSThread *GetJSThread() const { +#if defined(ECMASCRIPT_ENABLE_THREAD_CHECK) && ECMASCRIPT_ENABLE_THREAD_CHECK + ThreadPool *pool = GetHeap()->GetThreadPool(); + // Exclude GC thread + if (!pool->IsInThreadPool(std::this_thread::get_id()) && + thread_->GetThreadId() != JSThread::GetCurrentThreadId()) { + LOG(FATAL, RUNTIME) << "Fatal: ecma_vm cannot run in multi-thread!"; + } +#endif return thread_; } diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index f2352867b9ef8d99579a91b8946df96b78b13597..86022c917022be48dc42ce431cb77fb5f56f8456 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -36,7 +36,7 @@ JSThread *JSThread::Create(Runtime *runtime, PandaVM *vm) } JSThread::JSThread(Runtime *runtime, PandaVM *vm) - : ManagedThread(NON_INITIALIZED_THREAD_ID, runtime->GetInternalAllocator(), vm, + : ManagedThread(GetCurrentThreadId(), runtime->GetInternalAllocator(), vm, Thread::ThreadType::THREAD_TYPE_MANAGED) { SetLanguageContext(runtime->GetLanguageContext(panda_file::SourceLang::ECMASCRIPT)); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index eef175a525e535a575b3759f799927c91aea043a..647440ba568cccdb1e528de66865e3174e86ad8c 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -178,6 +178,16 @@ public: return internalCallParams_; } + ThreadId GetThreadId() const + { + return GetId(); + } + + static ThreadId GetCurrentThreadId() + { + return os::thread::GetCurrentThreadId(); + } + void IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor); private: diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index b2c50569f4a145a5ec0e8e9f8ac87cfd7d923739..d0a1a458e5f94b0e76af8b2d927eafac2897e556 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -901,7 +901,7 @@ int32_t ArrayRef::Length([[maybe_unused]] const EcmaVM *vm) Local ArrayRef::GetValueAt(const EcmaVM *vm, Local obj, uint32_t index) { - JSThread *thread = vm->GetAssociatedJSThread(); + JSThread *thread = vm->GetJSThread(); JSHandle object = JSNApiHelper::ToJSHandle(obj); JSHandle result = JSArray::FastGetPropertyByValue(thread, object, index); return JSNApiHelper::ToLocal(result); @@ -909,7 +909,7 @@ Local ArrayRef::GetValueAt(const EcmaVM *vm, Local obj, bool ArrayRef::SetValueAt(const EcmaVM *vm, Local obj, uint32_t index, Local value) { - JSThread *thread = vm->GetAssociatedJSThread(); + JSThread *thread = vm->GetJSThread(); JSHandle objectHandle = JSNApiHelper::ToJSHandle(obj); JSHandle valueHandle = JSNApiHelper::ToJSHandle(value); return JSArray::FastSetPropertyByValue(thread, objectHandle, index, valueHandle); diff --git a/ecmascript/napi/test/jsnapi_tests.cpp b/ecmascript/napi/test/jsnapi_tests.cpp index a8eb17ef376a66b4c471da3308feebabe6df9879..8e146169a4446d8ed9821325139d6fb355cc1494 100644 --- a/ecmascript/napi/test/jsnapi_tests.cpp +++ b/ecmascript/napi/test/jsnapi_tests.cpp @@ -66,6 +66,11 @@ Local FunctionCallback(EcmaVM *vm, Local, const LocalGetJSThread()->GetThreadId() != JSThread::GetCurrentThreadId()); +} + HWTEST_F_L0(JSNApiTests, GetGlobalObject) { LocalScope scope(vm_); @@ -74,6 +79,13 @@ HWTEST_F_L0(JSNApiTests, GetGlobalObject) ASSERT_TRUE(globalObject->IsObject()); } +HWTEST_F_L0(JSNApiTests, ThreadIdCheck) +{ + EXPECT_TRUE(vm_->GetJSThread()->GetThreadId() == JSThread::GetCurrentThreadId()); + std::thread testThread(ThreadCheck, vm_); + testThread.join(); +} + HWTEST_F_L0(JSNApiTests, RegisterFunction) { LocalScope scope(vm_); diff --git a/ecmascript/thread/thread_pool.h b/ecmascript/thread/thread_pool.h index 7af95c55db3a6da561bd190e4d359e284c507e7a..ee14791b1218296d99611db06c1b9f2babae3924 100644 --- a/ecmascript/thread/thread_pool.h +++ b/ecmascript/thread/thread_pool.h @@ -112,6 +112,16 @@ public: return threadNum_; } + bool IsInThreadPool(std::thread::id id) const + { + for (auto &worker : workers_) { + if (worker.get_id() == id) { + return true; + } + } + return false; + } + private: NO_COPY_SEMANTIC(ThreadPool); NO_MOVE_SEMANTIC(ThreadPool);