• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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