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