* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_JIT_TASK_H
#define ECMASCRIPT_JIT_TASK_H
#include "common_components/taskpool/taskpool.h"
#include "ecmascript/checkpoint/thread_state_transition.h"
#include "ecmascript/common.h"
#include "ecmascript/dependent_infos.h"
#include "ecmascript/compiler/lazy_deopt_dependency.h"
#include "ecmascript/platform/mutex.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/ic/profile_type_info.h"
#include "ecmascript/jit/jit.h"
#include "ecmascript/jit/jit_thread.h"
#include "ecmascript/sustaining_js_handle.h"
namespace panda::ecmascript {
enum CompileState : uint8_t {
SUCCESS = 0,
FAIL,
};
enum RunState : uint8_t {
INIT = 0,
RUNNING,
FINISH
};
class JitTaskpool : public common::Taskpool {
public:
PUBLIC_API static JitTaskpool *GetCurrentTaskpool();
JitTaskpool() = default;
NO_COPY_SEMANTIC(JitTaskpool);
NO_MOVE_SEMANTIC(JitTaskpool);
EcmaVM *GetCompilerVm()
{
return compilerVm_;
}
void SetCompilerVm(EcmaVM *vm)
{
LockHolder lock(jitTaskPoolMutex_);
compilerVm_ = vm;
threadId_ = static_cast<int32_t>(compilerVm_->GetJSThread()->GetThreadId());
jitTaskPoolCV_.SignalAll();
}
void WaitForJitTaskPoolReady()
{
LockHolder lock(jitTaskPoolMutex_);
if (compilerVm_ == nullptr) {
jitTaskPoolCV_.Wait(&jitTaskPoolMutex_);
}
}
void Initialize(bool needInitJitFort)
{
common::Taskpool::Initialize(0, [needInitJitFort](os::thread::native_handle_type thread) {
os::thread::SetThreadName(thread, "OS_JIT_Thread");
constexpr int32_t priorityVal = 5;
os::thread::SetPriority(os::thread::GetCurrentThreadId(), priorityVal);
auto jitVm = JitVM::Create();
JitTaskpool::GetCurrentTaskpool()->SetCompilerVm(jitVm);
if (needInitJitFort) {
JitFort::InitJitFortResource();
}
}, []([[maybe_unused]] os::thread::native_handle_type thread) {
EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm();
JitVM::Destroy(compilerVm);
});
}
void Destroy()
{
WaitForJitTaskPoolReady();
common::Taskpool::Destroy(threadId_);
}
private:
uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const override;
EcmaVM *compilerVm_ { nullptr };
Mutex jitTaskPoolMutex_;
ConditionVariable jitTaskPoolCV_;
int32_t threadId_ { -1 };
};
class JitAsyncTaskRunScope {
public:
JitAsyncTaskRunScope(JitTask *task);
~JitAsyncTaskRunScope();
private:
JitTask *task_;
JitVM *jitvm_;
};
class JitTask {
public:
JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit,
JSHandle<JSFunction> &jsFunction, CompilerTier tier, CString &methodName, int32_t offset,
JitCompileMode mode);
JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, JitCompileMode mode);
virtual ~JitTask();
void Optimize();
void Finalize();
void PrepareCompile();
virtual void InstallCode();
void InstallOsrCode(JSHandle<MachineCode> &codeObj);
void InstallCodeByCompilerTier(JSHandle<MachineCode> &machineCode,
JSHandle<Method> &methodHandle);
kungfu::LazyDeoptAllDependencies *GetDependencies()
{
return dependencies_;
}
MachineCodeDesc &GetMachineCodeDesc()
{
return codeDesc_;
}
JSHandle<JSFunction> GetJsFunction() const
{
return jsFunction_;
}
int32_t GetOffset() const
{
return offset_;
}
JSHandle<ProfileTypeInfo> GetProfileTypeInfo() const
{
return profileTypeInfo_;
}
bool IsCompileSuccess() const
{
return state_ == CompileState::SUCCESS;
}
void SetCompileFailed()
{
state_ = CompileState::FAIL;
}
bool IsOsrTask()
{
return offset_ != MachineCode::INVALID_OSR_OFFSET;
}
CompilerTier GetCompilerTier() const
{
return compilerTier_;
}
Jit *GetJit()
{
return jit_;
}
void *GetCompilerTask()
{
return compilerTask_;
}
JSThread *GetHostThread()
{
return hostThread_;
}
EcmaVM *GetHostVM()
{
return hostThread_->GetEcmaVM();
}
JSThread *GetCompilerThread()
{
return compilerThread_;
}
JitVM *GetCompilerVM()
{
return static_cast<JitVM*>(compilerThread_->GetEcmaVM());
}
CString GetMethodName() const
{
return methodName_;
}
void SetMethodInfo(CString methodName)
{
methodName_ = methodName;
}
void SetRunState(RunState s)
{
runState_.store(s, std::memory_order_release);
}
void SetRunStateFinish()
{
LockHolder lock(runStateMutex_);
runState_.store(RunState::FINISH);
runStateCondition_.SignalAll();
}
bool IsFinish() const
{
return runState_.load(std::memory_order_acquire) == RunState::FINISH;
}
bool IsRunning() const
{
return runState_.load(std::memory_order_acquire) == RunState::RUNNING;
}
void WaitFinish();
bool IsAsyncTask() const
{
return jitCompileMode_.IsAsync();
}
void SetMainThreadCompilerTime(int time)
{
mainThreadCompileTime_ = time;
}
int GetMainThreadCompilerTime() const
{
return mainThreadCompileTime_;
}
static size_t PUBLIC_API ComputePayLoadSize(MachineCodeDesc &codeDesc);
SustainingJSHandle *GetSustainingJSHandle()
{
return sustainingJSHandle_.get();
}
class AsyncTask : public common::Task {
public:
explicit AsyncTask(std::shared_ptr<JitTask>jitTask, int32_t id) : common::Task(id), jitTask_(jitTask) { }
virtual ~AsyncTask() override = default;
bool Run(uint32_t threadIndex) override;
EcmaVM *GetHostVM() const
{
return jitTask_->GetHostThread()->GetEcmaVM();
}
void Terminated()
{
common::Task::Terminated();
}
private:
std::shared_ptr<JitTask> jitTask_ { nullptr };
};
private:
void SustainingJSHandles();
void ReleaseSustainingJSHandle();
void CloneProfileTypeInfo();
void SetJsFunction(JSHandle<JSFunction> &jsFunction)
{
jsFunction_ = jsFunction;
}
void SetProfileTypeInfo(JSHandle<ProfileTypeInfo> &profileTypeInfo)
{
profileTypeInfo_ = profileTypeInfo;
}
JSThread *hostThread_;
JSThread *compilerThread_;
Jit *jit_;
JSHandle<JSFunction> jsFunction_;
JSHandle<ProfileTypeInfo> profileTypeInfo_;
void *compilerTask_;
kungfu::LazyDeoptAllDependencies *dependencies_ {nullptr};
MachineCodeDesc codeDesc_;
CompileState state_;
CompilerTier compilerTier_;
CString methodName_;
int32_t offset_;
std::unique_ptr<SustainingJSHandle> sustainingJSHandle_;
JitCompileMode jitCompileMode_;
JitDfx *jitDfx_ { nullptr };
int mainThreadCompileTime_ {0};
std::atomic<RunState> runState_;
Mutex runStateMutex_;
ConditionVariable runStateCondition_;
};
}
#endif