• 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 "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