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 WaitForJitTaskPoolReady(); 88 Taskpool::Destroy(threadId_); 89 } 90 91 private: 92 uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const override; 93 EcmaVM *compilerVm_ { nullptr }; 94 Mutex jitTaskPoolMutex_; 95 ConditionVariable jitTaskPoolCV_; 96 int32_t threadId_ { -1 }; 97 }; 98 99 class JitTask { 100 public: 101 JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, 102 JSHandle<JSFunction> &jsFunction, CompilerTier tier, CString &methodName, int32_t offset, 103 JitCompileMode mode); 104 // for ut 105 JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, JitCompileMode mode); 106 ~JitTask(); 107 void Optimize(); 108 void Finalize(); 109 void PrepareCompile(); 110 111 void InstallCode(); 112 void InstallOsrCode(JSHandle<MachineCode> &codeObj); 113 void InstallCodeByCompilerTier(JSHandle<MachineCode> &machineCode, 114 JSHandle<Method> &methodHandle); GetMachineCodeDesc()115 MachineCodeDesc &GetMachineCodeDesc() 116 { 117 return codeDesc_; 118 } 119 GetRelocInfo()120 RelocMap &GetRelocInfo() 121 { 122 return relocInfo_; 123 } 124 GetJsFunction()125 JSHandle<JSFunction> GetJsFunction() const 126 { 127 return jsFunction_; 128 } 129 GetOffset()130 int32_t GetOffset() const 131 { 132 return offset_; 133 } 134 GetProfileTypeInfo()135 JSHandle<ProfileTypeInfo> GetProfileTypeInfo() const 136 { 137 return profileTypeInfo_; 138 } 139 IsCompileSuccess()140 bool IsCompileSuccess() const 141 { 142 return state_ == CompileState::SUCCESS; 143 } 144 SetCompileFailed()145 void SetCompileFailed() 146 { 147 state_ = CompileState::FAIL; 148 } 149 IsOsrTask()150 bool IsOsrTask() 151 { 152 return offset_ != MachineCode::INVALID_OSR_OFFSET; 153 } 154 GetCompilerTier()155 CompilerTier GetCompilerTier() const 156 { 157 return compilerTier_; 158 } 159 GetJit()160 Jit *GetJit() 161 { 162 return jit_; 163 } 164 GetHostThread()165 JSThread *GetHostThread() 166 { 167 return hostThread_; 168 } 169 GetHostVM()170 EcmaVM *GetHostVM() 171 { 172 return hostThread_->GetEcmaVM(); 173 } 174 GetCompilerThread()175 JSThread *GetCompilerThread() 176 { 177 return compilerThread_; 178 } 179 GetCompilerVM()180 JitVM *GetCompilerVM() 181 { 182 return static_cast<JitVM*>(compilerThread_->GetEcmaVM()); 183 } 184 GetMethodName()185 CString GetMethodName() const 186 { 187 return methodName_; 188 } 189 SetMethodInfo(CString methodName)190 void SetMethodInfo(CString methodName) 191 { 192 methodName_ = methodName; 193 } 194 GetEcmaContext()195 EcmaContext *GetEcmaContext() const 196 { 197 return ecmaContext_; 198 } 199 SetRunState(RunState s)200 void SetRunState(RunState s) 201 { 202 runState_.store(s, std::memory_order_release); 203 } 204 SetRunStateFinish()205 void SetRunStateFinish() 206 { 207 LockHolder lock(runStateMutex_); 208 runState_.store(RunState::FINISH); 209 runStateCondition_.SignalAll(); 210 } 211 IsFinish()212 bool IsFinish() const 213 { 214 return runState_.load(std::memory_order_acquire) == RunState::FINISH; 215 } IsRunning()216 bool IsRunning() const 217 { 218 return runState_.load(std::memory_order_acquire) == RunState::RUNNING; 219 } 220 void WaitFinish(); IsAsyncTask()221 bool IsAsyncTask() const 222 { 223 return jitCompileMode_.IsAsync(); 224 } 225 SetMainThreadCompilerTime(int time)226 void SetMainThreadCompilerTime(int time) 227 { 228 mainThreadCompileTime_ = time; 229 } 230 GetMainThreadCompilerTime()231 int GetMainThreadCompilerTime() const 232 { 233 return mainThreadCompileTime_; 234 } 235 static size_t PUBLIC_API ComputePayLoadSize(MachineCodeDesc &codeDesc); 236 237 class AsyncTask : public Task { 238 public: AsyncTask(std::shared_ptr<JitTask> jitTask,int32_t id)239 explicit AsyncTask(std::shared_ptr<JitTask>jitTask, int32_t id) : Task(id), jitTask_(jitTask) { } 240 virtual ~AsyncTask() override = default; 241 242 bool Run(uint32_t threadIndex) override; GetEcmaContext()243 EcmaContext *GetEcmaContext() const 244 { 245 return jitTask_->GetEcmaContext(); 246 } GetHostVM()247 EcmaVM *GetHostVM() const 248 { 249 return jitTask_->GetHostThread()->GetEcmaVM(); 250 } IsRunning()251 bool IsRunning() const 252 { 253 return jitTask_->IsRunning(); 254 } WaitFinish()255 void WaitFinish() const 256 { 257 jitTask_->WaitFinish(); 258 } 259 Terminated()260 void Terminated() 261 { 262 Task::Terminated(); 263 } 264 ReleaseSustainingJSHandle()265 void ReleaseSustainingJSHandle() 266 { 267 jitTask_->ReleaseSustainingJSHandle(); 268 } 269 private: 270 std::shared_ptr<JitTask> jitTask_ { nullptr }; 271 272 class AsyncTaskRunScope { 273 public: 274 AsyncTaskRunScope(JitTask *jitTask); 275 ~AsyncTaskRunScope(); 276 private: 277 JitTask *jitTask_ { nullptr }; 278 JitVM *jitvm_ { nullptr }; 279 }; 280 }; 281 private: 282 void SustainingJSHandles(); 283 void ReleaseSustainingJSHandle(); 284 void CloneProfileTypeInfo(); SetJsFunction(JSHandle<JSFunction> & jsFunction)285 void SetJsFunction(JSHandle<JSFunction> &jsFunction) 286 { 287 jsFunction_ = jsFunction; 288 } 289 SetProfileTypeInfo(JSHandle<ProfileTypeInfo> & profileTypeInfo)290 void SetProfileTypeInfo(JSHandle<ProfileTypeInfo> &profileTypeInfo) 291 { 292 profileTypeInfo_ = profileTypeInfo; 293 } 294 295 JSThread *hostThread_; 296 JSThread *compilerThread_; 297 Jit *jit_; 298 JSHandle<JSFunction> jsFunction_; 299 JSHandle<ProfileTypeInfo> profileTypeInfo_; 300 void *compilerTask_; 301 MachineCodeDesc codeDesc_; 302 CompileState state_; 303 CompilerTier compilerTier_; 304 CString methodName_; 305 int32_t offset_; 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 RelocMap relocInfo_; 316 }; 317 } // namespace panda::ecmascript 318 #endif // ECMASCRIPT_JIT_TASK_H 319