1 /* 2 * Copyright (c) 2023-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 #ifndef ECMASCRIPT_JIT_TASK_H 17 #define ECMASCRIPT_JIT_TASK_H 18 19 #include "ecmascript/common.h" 20 #include "ecmascript/platform/mutex.h" 21 #include "ecmascript/ecma_vm.h" 22 23 #include "ecmascript/ic/profile_type_info.h" 24 #include "ecmascript/jit/jit.h" 25 #include "ecmascript/jit/jit_thread.h" 26 #include "ecmascript/sustaining_js_handle.h" 27 28 namespace panda::ecmascript { 29 enum CompileState : uint8_t { 30 SUCCESS = 0, 31 FAIL, 32 }; 33 34 enum RunState : uint8_t { 35 INIT = 0, 36 RUNNING, 37 FINISH 38 }; 39 40 class JitTaskpool : public Taskpool { 41 public: 42 PUBLIC_API static JitTaskpool *GetCurrentTaskpool(); 43 JitTaskpool() = default; 44 NO_COPY_SEMANTIC(JitTaskpool); 45 NO_MOVE_SEMANTIC(JitTaskpool); 46 GetCompilerVm()47 EcmaVM *GetCompilerVm() 48 { 49 return compilerVm_; 50 } 51 SetCompilerVm(EcmaVM *vm)52 void SetCompilerVm(EcmaVM *vm) 53 { 54 LockHolder lock(jitTaskPoolMutex_); 55 compilerVm_ = vm; 56 threadId_ = static_cast<int32_t>(compilerVm_->GetJSThread()->GetThreadId()); 57 jitTaskPoolCV_.SignalAll(); 58 } 59 WaitForJitTaskPoolReady()60 void WaitForJitTaskPoolReady() 61 { 62 LockHolder lock(jitTaskPoolMutex_); 63 if (compilerVm_ == nullptr) { 64 jitTaskPoolCV_.Wait(&jitTaskPoolMutex_); 65 } 66 } 67 Initialize(bool needInitJitFort)68 void Initialize(bool needInitJitFort) 69 { 70 Taskpool::Initialize(0, [needInitJitFort](os::thread::native_handle_type thread) { 71 os::thread::SetThreadName(thread, "OS_JIT_Thread"); 72 constexpr int32_t priorityVal = 5; // 5: The priority can be set within range [-20, 19] 73 os::thread::SetPriority(os::thread::GetCurrentThreadId(), priorityVal); 74 auto jitVm = JitVM::Create(); 75 JitTaskpool::GetCurrentTaskpool()->SetCompilerVm(jitVm); 76 if (needInitJitFort) { 77 JitFort::InitJitFortResource(); 78 } 79 }, []([[maybe_unused]] os::thread::native_handle_type thread) { 80 EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm(); 81 JitVM::Destroy(compilerVm); 82 }); 83 } 84 Destroy()85 void Destroy() 86 { 87 Taskpool::Destroy(threadId_); 88 } 89 90 private: 91 uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const override; 92 EcmaVM *compilerVm_ { nullptr }; 93 Mutex jitTaskPoolMutex_; 94 ConditionVariable jitTaskPoolCV_; 95 int32_t threadId_ { -1 }; 96 }; 97 98 class JitTask { 99 public: 100 JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, 101 JSHandle<JSFunction> &jsFunction, CompilerTier tier, CString &methodName, int32_t offset, 102 uint32_t taskThreadId, JitCompileMode mode); 103 // for ut 104 JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, uint32_t taskThreadId, JitCompileMode mode); 105 ~JitTask(); 106 void Optimize(); 107 void Finalize(); 108 void PrepareCompile(); 109 110 void InstallCode(); 111 void InstallOsrCode(JSHandle<MachineCode> &codeObj); 112 void InstallCodeByCompilerTier(JSHandle<MachineCode> &machineCode, 113 JSHandle<Method> &methodHandle); GetMachineCodeDesc()114 MachineCodeDesc &GetMachineCodeDesc() 115 { 116 return codeDesc_; 117 } 118 GetJsFunction() const119 JSHandle<JSFunction> GetJsFunction() const 120 { 121 return jsFunction_; 122 } 123 GetOffset() const124 int32_t GetOffset() const 125 { 126 return offset_; 127 } 128 GetProfileTypeInfo() const129 JSHandle<ProfileTypeInfo> GetProfileTypeInfo() const 130 { 131 return profileTypeInfo_; 132 } 133 IsCompileSuccess() const134 bool IsCompileSuccess() const 135 { 136 return state_ == CompileState::SUCCESS; 137 } 138 SetCompileFailed()139 void SetCompileFailed() 140 { 141 state_ = CompileState::FAIL; 142 } 143 IsOsrTask()144 bool IsOsrTask() 145 { 146 return offset_ != MachineCode::INVALID_OSR_OFFSET; 147 } 148 GetCompilerTier() const149 CompilerTier GetCompilerTier() const 150 { 151 return compilerTier_; 152 } 153 GetJit()154 Jit *GetJit() 155 { 156 return jit_; 157 } 158 GetHostThread()159 JSThread *GetHostThread() 160 { 161 return hostThread_; 162 } 163 GetHostVM()164 EcmaVM *GetHostVM() 165 { 166 return hostThread_->GetEcmaVM(); 167 } 168 GetCompilerThread()169 JSThread *GetCompilerThread() 170 { 171 return compilerThread_; 172 } 173 GetCompilerVM()174 JitVM *GetCompilerVM() 175 { 176 return static_cast<JitVM*>(compilerThread_->GetEcmaVM()); 177 } 178 GetMethodName() const179 CString GetMethodName() const 180 { 181 return methodName_; 182 } 183 SetMethodInfo(CString methodName)184 void SetMethodInfo(CString methodName) 185 { 186 methodName_ = methodName; 187 } 188 GetTaskThreadId() const189 uint32_t GetTaskThreadId() const 190 { 191 return taskThreadId_; 192 } 193 GetEcmaContext() const194 EcmaContext *GetEcmaContext() const 195 { 196 return ecmaContext_; 197 } 198 SetRunState(RunState s)199 void SetRunState(RunState s) 200 { 201 runState_.store(s, std::memory_order_release); 202 } 203 SetRunStateFinish()204 void SetRunStateFinish() 205 { 206 LockHolder lock(runStateMutex_); 207 runState_.store(RunState::FINISH); 208 runStateCondition_.SignalAll(); 209 } 210 IsFinish() const211 bool IsFinish() const 212 { 213 return runState_.load(std::memory_order_acquire) == RunState::FINISH; 214 } IsRunning() const215 bool IsRunning() const 216 { 217 return runState_.load(std::memory_order_acquire) == RunState::RUNNING; 218 } 219 void WaitFinish(); IsAsyncTask() const220 bool IsAsyncTask() const 221 { 222 return jitCompileMode_ == JitCompileMode::ASYNC; 223 } 224 SetMainThreadCompilerTime(int time)225 void SetMainThreadCompilerTime(int time) 226 { 227 mainThreadCompileTime_ = time; 228 } 229 GetMainThreadCompilerTime() const230 int GetMainThreadCompilerTime() const 231 { 232 return mainThreadCompileTime_; 233 } 234 static size_t PUBLIC_API ComputePayLoadSize(MachineCodeDesc &codeDesc); 235 236 class AsyncTask : public Task { 237 public: AsyncTask(std::shared_ptr<JitTask>jitTask, int32_t id)238 explicit AsyncTask(std::shared_ptr<JitTask>jitTask, int32_t id) : Task(id), jitTask_(jitTask) { } 239 virtual ~AsyncTask() override = default; 240 241 bool Run(uint32_t threadIndex) override; GetEcmaContext() const242 EcmaContext *GetEcmaContext() const 243 { 244 return jitTask_->GetEcmaContext(); 245 } GetHostVM() const246 EcmaVM *GetHostVM() const 247 { 248 return jitTask_->GetHostThread()->GetEcmaVM(); 249 } IsRunning() const250 bool IsRunning() const 251 { 252 return jitTask_->IsRunning(); 253 } WaitFinish() const254 void WaitFinish() const 255 { 256 jitTask_->WaitFinish(); 257 } 258 Terminated()259 void Terminated() 260 { 261 Task::Terminated(); 262 } 263 ReleaseSustainingJSHandle()264 void ReleaseSustainingJSHandle() 265 { 266 jitTask_->ReleaseSustainingJSHandle(); 267 } 268 private: 269 std::shared_ptr<JitTask> jitTask_ { nullptr }; 270 271 class AsyncTaskRunScope { 272 public: 273 AsyncTaskRunScope(JitTask *jitTask); 274 ~AsyncTaskRunScope(); 275 private: 276 JitTask *jitTask_ { nullptr }; 277 JitVM *jitvm_ { nullptr }; 278 }; 279 }; 280 private: 281 void SustainingJSHandles(); 282 void ReleaseSustainingJSHandle(); 283 void CloneProfileTypeInfo(); SetJsFunction(JSHandle<JSFunction> &jsFunction)284 void SetJsFunction(JSHandle<JSFunction> &jsFunction) 285 { 286 jsFunction_ = jsFunction; 287 } 288 SetProfileTypeInfo(JSHandle<ProfileTypeInfo> &profileTypeInfo)289 void SetProfileTypeInfo(JSHandle<ProfileTypeInfo> &profileTypeInfo) 290 { 291 profileTypeInfo_ = profileTypeInfo; 292 } 293 294 JSThread *hostThread_; 295 JSThread *compilerThread_; 296 Jit *jit_; 297 JSHandle<JSFunction> jsFunction_; 298 JSHandle<ProfileTypeInfo> profileTypeInfo_; 299 void *compilerTask_; 300 MachineCodeDesc codeDesc_; 301 CompileState state_; 302 CompilerTier compilerTier_; 303 CString methodName_; 304 int32_t offset_; 305 uint32_t taskThreadId_; 306 std::unique_ptr<SustainingJSHandle> sustainingJSHandle_; 307 EcmaContext *ecmaContext_; 308 JitCompileMode jitCompileMode_; 309 JitDfx *jitDfx_ { nullptr }; 310 int mainThreadCompileTime_ {0}; 311 312 std::atomic<RunState> runState_; 313 Mutex runStateMutex_; 314 ConditionVariable runStateCondition_; 315 }; 316 } // namespace panda::ecmascript 317 #endif // ECMASCRIPT_JIT_TASK_H 318