14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_JIT_TASK_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_JIT_TASK_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/common.h" 204514f5e3Sopenharmony_ci#include "ecmascript/platform/mutex.h" 214514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h" 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_ci#include "ecmascript/ic/profile_type_info.h" 244514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h" 254514f5e3Sopenharmony_ci#include "ecmascript/jit/jit_thread.h" 264514f5e3Sopenharmony_ci#include "ecmascript/sustaining_js_handle.h" 274514f5e3Sopenharmony_ci 284514f5e3Sopenharmony_cinamespace panda::ecmascript { 294514f5e3Sopenharmony_cienum CompileState : uint8_t { 304514f5e3Sopenharmony_ci SUCCESS = 0, 314514f5e3Sopenharmony_ci FAIL, 324514f5e3Sopenharmony_ci}; 334514f5e3Sopenharmony_ci 344514f5e3Sopenharmony_cienum RunState : uint8_t { 354514f5e3Sopenharmony_ci INIT = 0, 364514f5e3Sopenharmony_ci RUNNING, 374514f5e3Sopenharmony_ci FINISH 384514f5e3Sopenharmony_ci}; 394514f5e3Sopenharmony_ci 404514f5e3Sopenharmony_ciclass JitTaskpool : public Taskpool { 414514f5e3Sopenharmony_cipublic: 424514f5e3Sopenharmony_ci PUBLIC_API static JitTaskpool *GetCurrentTaskpool(); 434514f5e3Sopenharmony_ci JitTaskpool() = default; 444514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(JitTaskpool); 454514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(JitTaskpool); 464514f5e3Sopenharmony_ci 474514f5e3Sopenharmony_ci EcmaVM *GetCompilerVm() 484514f5e3Sopenharmony_ci { 494514f5e3Sopenharmony_ci return compilerVm_; 504514f5e3Sopenharmony_ci } 514514f5e3Sopenharmony_ci 524514f5e3Sopenharmony_ci void SetCompilerVm(EcmaVM *vm) 534514f5e3Sopenharmony_ci { 544514f5e3Sopenharmony_ci LockHolder lock(jitTaskPoolMutex_); 554514f5e3Sopenharmony_ci compilerVm_ = vm; 564514f5e3Sopenharmony_ci threadId_ = static_cast<int32_t>(compilerVm_->GetJSThread()->GetThreadId()); 574514f5e3Sopenharmony_ci jitTaskPoolCV_.SignalAll(); 584514f5e3Sopenharmony_ci } 594514f5e3Sopenharmony_ci 604514f5e3Sopenharmony_ci void WaitForJitTaskPoolReady() 614514f5e3Sopenharmony_ci { 624514f5e3Sopenharmony_ci LockHolder lock(jitTaskPoolMutex_); 634514f5e3Sopenharmony_ci if (compilerVm_ == nullptr) { 644514f5e3Sopenharmony_ci jitTaskPoolCV_.Wait(&jitTaskPoolMutex_); 654514f5e3Sopenharmony_ci } 664514f5e3Sopenharmony_ci } 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_ci void Initialize(bool needInitJitFort) 694514f5e3Sopenharmony_ci { 704514f5e3Sopenharmony_ci Taskpool::Initialize(0, [needInitJitFort](os::thread::native_handle_type thread) { 714514f5e3Sopenharmony_ci os::thread::SetThreadName(thread, "OS_JIT_Thread"); 724514f5e3Sopenharmony_ci constexpr int32_t priorityVal = 5; // 5: The priority can be set within range [-20, 19] 734514f5e3Sopenharmony_ci os::thread::SetPriority(os::thread::GetCurrentThreadId(), priorityVal); 744514f5e3Sopenharmony_ci auto jitVm = JitVM::Create(); 754514f5e3Sopenharmony_ci JitTaskpool::GetCurrentTaskpool()->SetCompilerVm(jitVm); 764514f5e3Sopenharmony_ci if (needInitJitFort) { 774514f5e3Sopenharmony_ci JitFort::InitJitFortResource(); 784514f5e3Sopenharmony_ci } 794514f5e3Sopenharmony_ci }, []([[maybe_unused]] os::thread::native_handle_type thread) { 804514f5e3Sopenharmony_ci EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm(); 814514f5e3Sopenharmony_ci JitVM::Destroy(compilerVm); 824514f5e3Sopenharmony_ci }); 834514f5e3Sopenharmony_ci } 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_ci void Destroy() 864514f5e3Sopenharmony_ci { 874514f5e3Sopenharmony_ci Taskpool::Destroy(threadId_); 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ciprivate: 914514f5e3Sopenharmony_ci uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const override; 924514f5e3Sopenharmony_ci EcmaVM *compilerVm_ { nullptr }; 934514f5e3Sopenharmony_ci Mutex jitTaskPoolMutex_; 944514f5e3Sopenharmony_ci ConditionVariable jitTaskPoolCV_; 954514f5e3Sopenharmony_ci int32_t threadId_ { -1 }; 964514f5e3Sopenharmony_ci}; 974514f5e3Sopenharmony_ci 984514f5e3Sopenharmony_ciclass JitTask { 994514f5e3Sopenharmony_cipublic: 1004514f5e3Sopenharmony_ci JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, 1014514f5e3Sopenharmony_ci JSHandle<JSFunction> &jsFunction, CompilerTier tier, CString &methodName, int32_t offset, 1024514f5e3Sopenharmony_ci uint32_t taskThreadId, JitCompileMode mode); 1034514f5e3Sopenharmony_ci // for ut 1044514f5e3Sopenharmony_ci JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, uint32_t taskThreadId, JitCompileMode mode); 1054514f5e3Sopenharmony_ci ~JitTask(); 1064514f5e3Sopenharmony_ci void Optimize(); 1074514f5e3Sopenharmony_ci void Finalize(); 1084514f5e3Sopenharmony_ci void PrepareCompile(); 1094514f5e3Sopenharmony_ci 1104514f5e3Sopenharmony_ci void InstallCode(); 1114514f5e3Sopenharmony_ci void InstallOsrCode(JSHandle<MachineCode> &codeObj); 1124514f5e3Sopenharmony_ci void InstallCodeByCompilerTier(JSHandle<MachineCode> &machineCode, 1134514f5e3Sopenharmony_ci JSHandle<Method> &methodHandle); 1144514f5e3Sopenharmony_ci MachineCodeDesc &GetMachineCodeDesc() 1154514f5e3Sopenharmony_ci { 1164514f5e3Sopenharmony_ci return codeDesc_; 1174514f5e3Sopenharmony_ci } 1184514f5e3Sopenharmony_ci 1194514f5e3Sopenharmony_ci JSHandle<JSFunction> GetJsFunction() const 1204514f5e3Sopenharmony_ci { 1214514f5e3Sopenharmony_ci return jsFunction_; 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_ci int32_t GetOffset() const 1254514f5e3Sopenharmony_ci { 1264514f5e3Sopenharmony_ci return offset_; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ci JSHandle<ProfileTypeInfo> GetProfileTypeInfo() const 1304514f5e3Sopenharmony_ci { 1314514f5e3Sopenharmony_ci return profileTypeInfo_; 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ci bool IsCompileSuccess() const 1354514f5e3Sopenharmony_ci { 1364514f5e3Sopenharmony_ci return state_ == CompileState::SUCCESS; 1374514f5e3Sopenharmony_ci } 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ci void SetCompileFailed() 1404514f5e3Sopenharmony_ci { 1414514f5e3Sopenharmony_ci state_ = CompileState::FAIL; 1424514f5e3Sopenharmony_ci } 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_ci bool IsOsrTask() 1454514f5e3Sopenharmony_ci { 1464514f5e3Sopenharmony_ci return offset_ != MachineCode::INVALID_OSR_OFFSET; 1474514f5e3Sopenharmony_ci } 1484514f5e3Sopenharmony_ci 1494514f5e3Sopenharmony_ci CompilerTier GetCompilerTier() const 1504514f5e3Sopenharmony_ci { 1514514f5e3Sopenharmony_ci return compilerTier_; 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci 1544514f5e3Sopenharmony_ci Jit *GetJit() 1554514f5e3Sopenharmony_ci { 1564514f5e3Sopenharmony_ci return jit_; 1574514f5e3Sopenharmony_ci } 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_ci JSThread *GetHostThread() 1604514f5e3Sopenharmony_ci { 1614514f5e3Sopenharmony_ci return hostThread_; 1624514f5e3Sopenharmony_ci } 1634514f5e3Sopenharmony_ci 1644514f5e3Sopenharmony_ci EcmaVM *GetHostVM() 1654514f5e3Sopenharmony_ci { 1664514f5e3Sopenharmony_ci return hostThread_->GetEcmaVM(); 1674514f5e3Sopenharmony_ci } 1684514f5e3Sopenharmony_ci 1694514f5e3Sopenharmony_ci JSThread *GetCompilerThread() 1704514f5e3Sopenharmony_ci { 1714514f5e3Sopenharmony_ci return compilerThread_; 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ci JitVM *GetCompilerVM() 1754514f5e3Sopenharmony_ci { 1764514f5e3Sopenharmony_ci return static_cast<JitVM*>(compilerThread_->GetEcmaVM()); 1774514f5e3Sopenharmony_ci } 1784514f5e3Sopenharmony_ci 1794514f5e3Sopenharmony_ci CString GetMethodName() const 1804514f5e3Sopenharmony_ci { 1814514f5e3Sopenharmony_ci return methodName_; 1824514f5e3Sopenharmony_ci } 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci void SetMethodInfo(CString methodName) 1854514f5e3Sopenharmony_ci { 1864514f5e3Sopenharmony_ci methodName_ = methodName; 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ci uint32_t GetTaskThreadId() const 1904514f5e3Sopenharmony_ci { 1914514f5e3Sopenharmony_ci return taskThreadId_; 1924514f5e3Sopenharmony_ci } 1934514f5e3Sopenharmony_ci 1944514f5e3Sopenharmony_ci EcmaContext *GetEcmaContext() const 1954514f5e3Sopenharmony_ci { 1964514f5e3Sopenharmony_ci return ecmaContext_; 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_ci void SetRunState(RunState s) 2004514f5e3Sopenharmony_ci { 2014514f5e3Sopenharmony_ci runState_.store(s, std::memory_order_release); 2024514f5e3Sopenharmony_ci } 2034514f5e3Sopenharmony_ci 2044514f5e3Sopenharmony_ci void SetRunStateFinish() 2054514f5e3Sopenharmony_ci { 2064514f5e3Sopenharmony_ci LockHolder lock(runStateMutex_); 2074514f5e3Sopenharmony_ci runState_.store(RunState::FINISH); 2084514f5e3Sopenharmony_ci runStateCondition_.SignalAll(); 2094514f5e3Sopenharmony_ci } 2104514f5e3Sopenharmony_ci 2114514f5e3Sopenharmony_ci bool IsFinish() const 2124514f5e3Sopenharmony_ci { 2134514f5e3Sopenharmony_ci return runState_.load(std::memory_order_acquire) == RunState::FINISH; 2144514f5e3Sopenharmony_ci } 2154514f5e3Sopenharmony_ci bool IsRunning() const 2164514f5e3Sopenharmony_ci { 2174514f5e3Sopenharmony_ci return runState_.load(std::memory_order_acquire) == RunState::RUNNING; 2184514f5e3Sopenharmony_ci } 2194514f5e3Sopenharmony_ci void WaitFinish(); 2204514f5e3Sopenharmony_ci bool IsAsyncTask() const 2214514f5e3Sopenharmony_ci { 2224514f5e3Sopenharmony_ci return jitCompileMode_ == JitCompileMode::ASYNC; 2234514f5e3Sopenharmony_ci } 2244514f5e3Sopenharmony_ci 2254514f5e3Sopenharmony_ci void SetMainThreadCompilerTime(int time) 2264514f5e3Sopenharmony_ci { 2274514f5e3Sopenharmony_ci mainThreadCompileTime_ = time; 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci 2304514f5e3Sopenharmony_ci int GetMainThreadCompilerTime() const 2314514f5e3Sopenharmony_ci { 2324514f5e3Sopenharmony_ci return mainThreadCompileTime_; 2334514f5e3Sopenharmony_ci } 2344514f5e3Sopenharmony_ci static size_t PUBLIC_API ComputePayLoadSize(MachineCodeDesc &codeDesc); 2354514f5e3Sopenharmony_ci 2364514f5e3Sopenharmony_ci class AsyncTask : public Task { 2374514f5e3Sopenharmony_ci public: 2384514f5e3Sopenharmony_ci explicit AsyncTask(std::shared_ptr<JitTask>jitTask, int32_t id) : Task(id), jitTask_(jitTask) { } 2394514f5e3Sopenharmony_ci virtual ~AsyncTask() override = default; 2404514f5e3Sopenharmony_ci 2414514f5e3Sopenharmony_ci bool Run(uint32_t threadIndex) override; 2424514f5e3Sopenharmony_ci EcmaContext *GetEcmaContext() const 2434514f5e3Sopenharmony_ci { 2444514f5e3Sopenharmony_ci return jitTask_->GetEcmaContext(); 2454514f5e3Sopenharmony_ci } 2464514f5e3Sopenharmony_ci EcmaVM *GetHostVM() const 2474514f5e3Sopenharmony_ci { 2484514f5e3Sopenharmony_ci return jitTask_->GetHostThread()->GetEcmaVM(); 2494514f5e3Sopenharmony_ci } 2504514f5e3Sopenharmony_ci bool IsRunning() const 2514514f5e3Sopenharmony_ci { 2524514f5e3Sopenharmony_ci return jitTask_->IsRunning(); 2534514f5e3Sopenharmony_ci } 2544514f5e3Sopenharmony_ci void WaitFinish() const 2554514f5e3Sopenharmony_ci { 2564514f5e3Sopenharmony_ci jitTask_->WaitFinish(); 2574514f5e3Sopenharmony_ci } 2584514f5e3Sopenharmony_ci 2594514f5e3Sopenharmony_ci void Terminated() 2604514f5e3Sopenharmony_ci { 2614514f5e3Sopenharmony_ci Task::Terminated(); 2624514f5e3Sopenharmony_ci } 2634514f5e3Sopenharmony_ci 2644514f5e3Sopenharmony_ci void ReleaseSustainingJSHandle() 2654514f5e3Sopenharmony_ci { 2664514f5e3Sopenharmony_ci jitTask_->ReleaseSustainingJSHandle(); 2674514f5e3Sopenharmony_ci } 2684514f5e3Sopenharmony_ci private: 2694514f5e3Sopenharmony_ci std::shared_ptr<JitTask> jitTask_ { nullptr }; 2704514f5e3Sopenharmony_ci 2714514f5e3Sopenharmony_ci class AsyncTaskRunScope { 2724514f5e3Sopenharmony_ci public: 2734514f5e3Sopenharmony_ci AsyncTaskRunScope(JitTask *jitTask); 2744514f5e3Sopenharmony_ci ~AsyncTaskRunScope(); 2754514f5e3Sopenharmony_ci private: 2764514f5e3Sopenharmony_ci JitTask *jitTask_ { nullptr }; 2774514f5e3Sopenharmony_ci JitVM *jitvm_ { nullptr }; 2784514f5e3Sopenharmony_ci }; 2794514f5e3Sopenharmony_ci }; 2804514f5e3Sopenharmony_ciprivate: 2814514f5e3Sopenharmony_ci void SustainingJSHandles(); 2824514f5e3Sopenharmony_ci void ReleaseSustainingJSHandle(); 2834514f5e3Sopenharmony_ci void CloneProfileTypeInfo(); 2844514f5e3Sopenharmony_ci void SetJsFunction(JSHandle<JSFunction> &jsFunction) 2854514f5e3Sopenharmony_ci { 2864514f5e3Sopenharmony_ci jsFunction_ = jsFunction; 2874514f5e3Sopenharmony_ci } 2884514f5e3Sopenharmony_ci 2894514f5e3Sopenharmony_ci void SetProfileTypeInfo(JSHandle<ProfileTypeInfo> &profileTypeInfo) 2904514f5e3Sopenharmony_ci { 2914514f5e3Sopenharmony_ci profileTypeInfo_ = profileTypeInfo; 2924514f5e3Sopenharmony_ci } 2934514f5e3Sopenharmony_ci 2944514f5e3Sopenharmony_ci JSThread *hostThread_; 2954514f5e3Sopenharmony_ci JSThread *compilerThread_; 2964514f5e3Sopenharmony_ci Jit *jit_; 2974514f5e3Sopenharmony_ci JSHandle<JSFunction> jsFunction_; 2984514f5e3Sopenharmony_ci JSHandle<ProfileTypeInfo> profileTypeInfo_; 2994514f5e3Sopenharmony_ci void *compilerTask_; 3004514f5e3Sopenharmony_ci MachineCodeDesc codeDesc_; 3014514f5e3Sopenharmony_ci CompileState state_; 3024514f5e3Sopenharmony_ci CompilerTier compilerTier_; 3034514f5e3Sopenharmony_ci CString methodName_; 3044514f5e3Sopenharmony_ci int32_t offset_; 3054514f5e3Sopenharmony_ci uint32_t taskThreadId_; 3064514f5e3Sopenharmony_ci std::unique_ptr<SustainingJSHandle> sustainingJSHandle_; 3074514f5e3Sopenharmony_ci EcmaContext *ecmaContext_; 3084514f5e3Sopenharmony_ci JitCompileMode jitCompileMode_; 3094514f5e3Sopenharmony_ci JitDfx *jitDfx_ { nullptr }; 3104514f5e3Sopenharmony_ci int mainThreadCompileTime_ {0}; 3114514f5e3Sopenharmony_ci 3124514f5e3Sopenharmony_ci std::atomic<RunState> runState_; 3134514f5e3Sopenharmony_ci Mutex runStateMutex_; 3144514f5e3Sopenharmony_ci ConditionVariable runStateCondition_; 3154514f5e3Sopenharmony_ci}; 3164514f5e3Sopenharmony_ci} // namespace panda::ecmascript 3174514f5e3Sopenharmony_ci#endif // ECMASCRIPT_JIT_TASK_H 318