14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_JIT_TASK_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_JIT_TASK_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/common.h"
204514f5e3Sopenharmony_ci#include "ecmascript/platform/mutex.h"
214514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h"
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_ci#include "ecmascript/ic/profile_type_info.h"
244514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h"
254514f5e3Sopenharmony_ci#include "ecmascript/jit/jit_thread.h"
264514f5e3Sopenharmony_ci#include "ecmascript/sustaining_js_handle.h"
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_cinamespace panda::ecmascript {
294514f5e3Sopenharmony_cienum CompileState : uint8_t {
304514f5e3Sopenharmony_ci    SUCCESS = 0,
314514f5e3Sopenharmony_ci    FAIL,
324514f5e3Sopenharmony_ci};
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_cienum RunState : uint8_t {
354514f5e3Sopenharmony_ci    INIT = 0,
364514f5e3Sopenharmony_ci    RUNNING,
374514f5e3Sopenharmony_ci    FINISH
384514f5e3Sopenharmony_ci};
394514f5e3Sopenharmony_ci
404514f5e3Sopenharmony_ciclass JitTaskpool : public Taskpool {
414514f5e3Sopenharmony_cipublic:
424514f5e3Sopenharmony_ci    PUBLIC_API static JitTaskpool *GetCurrentTaskpool();
434514f5e3Sopenharmony_ci    JitTaskpool() = default;
444514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(JitTaskpool);
454514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(JitTaskpool);
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_ci    EcmaVM *GetCompilerVm()
484514f5e3Sopenharmony_ci    {
494514f5e3Sopenharmony_ci        return compilerVm_;
504514f5e3Sopenharmony_ci    }
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ci    void SetCompilerVm(EcmaVM *vm)
534514f5e3Sopenharmony_ci    {
544514f5e3Sopenharmony_ci        LockHolder lock(jitTaskPoolMutex_);
554514f5e3Sopenharmony_ci        compilerVm_ = vm;
564514f5e3Sopenharmony_ci        threadId_ = static_cast<int32_t>(compilerVm_->GetJSThread()->GetThreadId());
574514f5e3Sopenharmony_ci        jitTaskPoolCV_.SignalAll();
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci    void WaitForJitTaskPoolReady()
614514f5e3Sopenharmony_ci    {
624514f5e3Sopenharmony_ci        LockHolder lock(jitTaskPoolMutex_);
634514f5e3Sopenharmony_ci        if (compilerVm_ == nullptr) {
644514f5e3Sopenharmony_ci            jitTaskPoolCV_.Wait(&jitTaskPoolMutex_);
654514f5e3Sopenharmony_ci        }
664514f5e3Sopenharmony_ci    }
674514f5e3Sopenharmony_ci
684514f5e3Sopenharmony_ci    void Initialize(bool needInitJitFort)
694514f5e3Sopenharmony_ci    {
704514f5e3Sopenharmony_ci        Taskpool::Initialize(0, [needInitJitFort](os::thread::native_handle_type thread) {
714514f5e3Sopenharmony_ci            os::thread::SetThreadName(thread, "OS_JIT_Thread");
724514f5e3Sopenharmony_ci            constexpr int32_t priorityVal = 5; // 5: The priority can be set within range [-20, 19]
734514f5e3Sopenharmony_ci            os::thread::SetPriority(os::thread::GetCurrentThreadId(), priorityVal);
744514f5e3Sopenharmony_ci            auto jitVm = JitVM::Create();
754514f5e3Sopenharmony_ci            JitTaskpool::GetCurrentTaskpool()->SetCompilerVm(jitVm);
764514f5e3Sopenharmony_ci            if (needInitJitFort) {
774514f5e3Sopenharmony_ci                JitFort::InitJitFortResource();
784514f5e3Sopenharmony_ci            }
794514f5e3Sopenharmony_ci        }, []([[maybe_unused]] os::thread::native_handle_type thread) {
804514f5e3Sopenharmony_ci            EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm();
814514f5e3Sopenharmony_ci            JitVM::Destroy(compilerVm);
824514f5e3Sopenharmony_ci        });
834514f5e3Sopenharmony_ci    }
844514f5e3Sopenharmony_ci
854514f5e3Sopenharmony_ci    void Destroy()
864514f5e3Sopenharmony_ci    {
874514f5e3Sopenharmony_ci        Taskpool::Destroy(threadId_);
884514f5e3Sopenharmony_ci    }
894514f5e3Sopenharmony_ci
904514f5e3Sopenharmony_ciprivate:
914514f5e3Sopenharmony_ci    uint32_t TheMostSuitableThreadNum(uint32_t threadNum) const override;
924514f5e3Sopenharmony_ci    EcmaVM *compilerVm_ { nullptr };
934514f5e3Sopenharmony_ci    Mutex jitTaskPoolMutex_;
944514f5e3Sopenharmony_ci    ConditionVariable jitTaskPoolCV_;
954514f5e3Sopenharmony_ci    int32_t threadId_ { -1 };
964514f5e3Sopenharmony_ci};
974514f5e3Sopenharmony_ci
984514f5e3Sopenharmony_ciclass JitTask {
994514f5e3Sopenharmony_cipublic:
1004514f5e3Sopenharmony_ci    JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit,
1014514f5e3Sopenharmony_ci        JSHandle<JSFunction> &jsFunction, CompilerTier tier, CString &methodName, int32_t offset,
1024514f5e3Sopenharmony_ci        uint32_t taskThreadId, JitCompileMode mode);
1034514f5e3Sopenharmony_ci    // for ut
1044514f5e3Sopenharmony_ci    JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, uint32_t taskThreadId, JitCompileMode mode);
1054514f5e3Sopenharmony_ci    ~JitTask();
1064514f5e3Sopenharmony_ci    void Optimize();
1074514f5e3Sopenharmony_ci    void Finalize();
1084514f5e3Sopenharmony_ci    void PrepareCompile();
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_ci    void InstallCode();
1114514f5e3Sopenharmony_ci    void InstallOsrCode(JSHandle<MachineCode> &codeObj);
1124514f5e3Sopenharmony_ci    void InstallCodeByCompilerTier(JSHandle<MachineCode> &machineCode,
1134514f5e3Sopenharmony_ci        JSHandle<Method> &methodHandle);
1144514f5e3Sopenharmony_ci    MachineCodeDesc &GetMachineCodeDesc()
1154514f5e3Sopenharmony_ci    {
1164514f5e3Sopenharmony_ci        return codeDesc_;
1174514f5e3Sopenharmony_ci    }
1184514f5e3Sopenharmony_ci
1194514f5e3Sopenharmony_ci    JSHandle<JSFunction> GetJsFunction() const
1204514f5e3Sopenharmony_ci    {
1214514f5e3Sopenharmony_ci        return jsFunction_;
1224514f5e3Sopenharmony_ci    }
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci    int32_t GetOffset() const
1254514f5e3Sopenharmony_ci    {
1264514f5e3Sopenharmony_ci        return offset_;
1274514f5e3Sopenharmony_ci    }
1284514f5e3Sopenharmony_ci
1294514f5e3Sopenharmony_ci    JSHandle<ProfileTypeInfo> GetProfileTypeInfo() const
1304514f5e3Sopenharmony_ci    {
1314514f5e3Sopenharmony_ci        return profileTypeInfo_;
1324514f5e3Sopenharmony_ci    }
1334514f5e3Sopenharmony_ci
1344514f5e3Sopenharmony_ci    bool IsCompileSuccess() const
1354514f5e3Sopenharmony_ci    {
1364514f5e3Sopenharmony_ci        return state_ == CompileState::SUCCESS;
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci
1394514f5e3Sopenharmony_ci    void SetCompileFailed()
1404514f5e3Sopenharmony_ci    {
1414514f5e3Sopenharmony_ci        state_ = CompileState::FAIL;
1424514f5e3Sopenharmony_ci    }
1434514f5e3Sopenharmony_ci
1444514f5e3Sopenharmony_ci    bool IsOsrTask()
1454514f5e3Sopenharmony_ci    {
1464514f5e3Sopenharmony_ci        return offset_ != MachineCode::INVALID_OSR_OFFSET;
1474514f5e3Sopenharmony_ci    }
1484514f5e3Sopenharmony_ci
1494514f5e3Sopenharmony_ci    CompilerTier GetCompilerTier() const
1504514f5e3Sopenharmony_ci    {
1514514f5e3Sopenharmony_ci        return compilerTier_;
1524514f5e3Sopenharmony_ci    }
1534514f5e3Sopenharmony_ci
1544514f5e3Sopenharmony_ci    Jit *GetJit()
1554514f5e3Sopenharmony_ci    {
1564514f5e3Sopenharmony_ci        return jit_;
1574514f5e3Sopenharmony_ci    }
1584514f5e3Sopenharmony_ci
1594514f5e3Sopenharmony_ci    JSThread *GetHostThread()
1604514f5e3Sopenharmony_ci    {
1614514f5e3Sopenharmony_ci        return hostThread_;
1624514f5e3Sopenharmony_ci    }
1634514f5e3Sopenharmony_ci
1644514f5e3Sopenharmony_ci    EcmaVM *GetHostVM()
1654514f5e3Sopenharmony_ci    {
1664514f5e3Sopenharmony_ci        return hostThread_->GetEcmaVM();
1674514f5e3Sopenharmony_ci    }
1684514f5e3Sopenharmony_ci
1694514f5e3Sopenharmony_ci    JSThread *GetCompilerThread()
1704514f5e3Sopenharmony_ci    {
1714514f5e3Sopenharmony_ci        return compilerThread_;
1724514f5e3Sopenharmony_ci    }
1734514f5e3Sopenharmony_ci
1744514f5e3Sopenharmony_ci    JitVM *GetCompilerVM()
1754514f5e3Sopenharmony_ci    {
1764514f5e3Sopenharmony_ci        return static_cast<JitVM*>(compilerThread_->GetEcmaVM());
1774514f5e3Sopenharmony_ci    }
1784514f5e3Sopenharmony_ci
1794514f5e3Sopenharmony_ci    CString GetMethodName() const
1804514f5e3Sopenharmony_ci    {
1814514f5e3Sopenharmony_ci        return methodName_;
1824514f5e3Sopenharmony_ci    }
1834514f5e3Sopenharmony_ci
1844514f5e3Sopenharmony_ci    void SetMethodInfo(CString methodName)
1854514f5e3Sopenharmony_ci    {
1864514f5e3Sopenharmony_ci        methodName_ = methodName;
1874514f5e3Sopenharmony_ci    }
1884514f5e3Sopenharmony_ci
1894514f5e3Sopenharmony_ci    uint32_t GetTaskThreadId() const
1904514f5e3Sopenharmony_ci    {
1914514f5e3Sopenharmony_ci        return taskThreadId_;
1924514f5e3Sopenharmony_ci    }
1934514f5e3Sopenharmony_ci
1944514f5e3Sopenharmony_ci    EcmaContext *GetEcmaContext() const
1954514f5e3Sopenharmony_ci    {
1964514f5e3Sopenharmony_ci        return ecmaContext_;
1974514f5e3Sopenharmony_ci    }
1984514f5e3Sopenharmony_ci
1994514f5e3Sopenharmony_ci    void SetRunState(RunState s)
2004514f5e3Sopenharmony_ci    {
2014514f5e3Sopenharmony_ci        runState_.store(s, std::memory_order_release);
2024514f5e3Sopenharmony_ci    }
2034514f5e3Sopenharmony_ci
2044514f5e3Sopenharmony_ci    void SetRunStateFinish()
2054514f5e3Sopenharmony_ci    {
2064514f5e3Sopenharmony_ci        LockHolder lock(runStateMutex_);
2074514f5e3Sopenharmony_ci        runState_.store(RunState::FINISH);
2084514f5e3Sopenharmony_ci        runStateCondition_.SignalAll();
2094514f5e3Sopenharmony_ci    }
2104514f5e3Sopenharmony_ci
2114514f5e3Sopenharmony_ci    bool IsFinish() const
2124514f5e3Sopenharmony_ci    {
2134514f5e3Sopenharmony_ci        return runState_.load(std::memory_order_acquire) == RunState::FINISH;
2144514f5e3Sopenharmony_ci    }
2154514f5e3Sopenharmony_ci    bool IsRunning() const
2164514f5e3Sopenharmony_ci    {
2174514f5e3Sopenharmony_ci        return runState_.load(std::memory_order_acquire) == RunState::RUNNING;
2184514f5e3Sopenharmony_ci    }
2194514f5e3Sopenharmony_ci    void WaitFinish();
2204514f5e3Sopenharmony_ci    bool IsAsyncTask() const
2214514f5e3Sopenharmony_ci    {
2224514f5e3Sopenharmony_ci        return jitCompileMode_ == JitCompileMode::ASYNC;
2234514f5e3Sopenharmony_ci    }
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_ci    void SetMainThreadCompilerTime(int time)
2264514f5e3Sopenharmony_ci    {
2274514f5e3Sopenharmony_ci        mainThreadCompileTime_ = time;
2284514f5e3Sopenharmony_ci    }
2294514f5e3Sopenharmony_ci
2304514f5e3Sopenharmony_ci    int GetMainThreadCompilerTime() const
2314514f5e3Sopenharmony_ci    {
2324514f5e3Sopenharmony_ci        return mainThreadCompileTime_;
2334514f5e3Sopenharmony_ci    }
2344514f5e3Sopenharmony_ci    static size_t PUBLIC_API ComputePayLoadSize(MachineCodeDesc &codeDesc);
2354514f5e3Sopenharmony_ci
2364514f5e3Sopenharmony_ci    class AsyncTask : public Task {
2374514f5e3Sopenharmony_ci    public:
2384514f5e3Sopenharmony_ci        explicit AsyncTask(std::shared_ptr<JitTask>jitTask, int32_t id) : Task(id), jitTask_(jitTask) { }
2394514f5e3Sopenharmony_ci        virtual ~AsyncTask() override = default;
2404514f5e3Sopenharmony_ci
2414514f5e3Sopenharmony_ci        bool Run(uint32_t threadIndex) override;
2424514f5e3Sopenharmony_ci        EcmaContext *GetEcmaContext() const
2434514f5e3Sopenharmony_ci        {
2444514f5e3Sopenharmony_ci            return jitTask_->GetEcmaContext();
2454514f5e3Sopenharmony_ci        }
2464514f5e3Sopenharmony_ci        EcmaVM *GetHostVM() const
2474514f5e3Sopenharmony_ci        {
2484514f5e3Sopenharmony_ci            return jitTask_->GetHostThread()->GetEcmaVM();
2494514f5e3Sopenharmony_ci        }
2504514f5e3Sopenharmony_ci        bool IsRunning() const
2514514f5e3Sopenharmony_ci        {
2524514f5e3Sopenharmony_ci            return jitTask_->IsRunning();
2534514f5e3Sopenharmony_ci        }
2544514f5e3Sopenharmony_ci        void WaitFinish() const
2554514f5e3Sopenharmony_ci        {
2564514f5e3Sopenharmony_ci            jitTask_->WaitFinish();
2574514f5e3Sopenharmony_ci        }
2584514f5e3Sopenharmony_ci
2594514f5e3Sopenharmony_ci        void Terminated()
2604514f5e3Sopenharmony_ci        {
2614514f5e3Sopenharmony_ci            Task::Terminated();
2624514f5e3Sopenharmony_ci        }
2634514f5e3Sopenharmony_ci
2644514f5e3Sopenharmony_ci        void ReleaseSustainingJSHandle()
2654514f5e3Sopenharmony_ci        {
2664514f5e3Sopenharmony_ci            jitTask_->ReleaseSustainingJSHandle();
2674514f5e3Sopenharmony_ci        }
2684514f5e3Sopenharmony_ci    private:
2694514f5e3Sopenharmony_ci        std::shared_ptr<JitTask> jitTask_ { nullptr };
2704514f5e3Sopenharmony_ci
2714514f5e3Sopenharmony_ci        class AsyncTaskRunScope {
2724514f5e3Sopenharmony_ci        public:
2734514f5e3Sopenharmony_ci            AsyncTaskRunScope(JitTask *jitTask);
2744514f5e3Sopenharmony_ci            ~AsyncTaskRunScope();
2754514f5e3Sopenharmony_ci        private:
2764514f5e3Sopenharmony_ci            JitTask *jitTask_ { nullptr };
2774514f5e3Sopenharmony_ci            JitVM *jitvm_ { nullptr };
2784514f5e3Sopenharmony_ci        };
2794514f5e3Sopenharmony_ci    };
2804514f5e3Sopenharmony_ciprivate:
2814514f5e3Sopenharmony_ci    void SustainingJSHandles();
2824514f5e3Sopenharmony_ci    void ReleaseSustainingJSHandle();
2834514f5e3Sopenharmony_ci    void CloneProfileTypeInfo();
2844514f5e3Sopenharmony_ci    void SetJsFunction(JSHandle<JSFunction> &jsFunction)
2854514f5e3Sopenharmony_ci    {
2864514f5e3Sopenharmony_ci        jsFunction_ = jsFunction;
2874514f5e3Sopenharmony_ci    }
2884514f5e3Sopenharmony_ci
2894514f5e3Sopenharmony_ci    void SetProfileTypeInfo(JSHandle<ProfileTypeInfo> &profileTypeInfo)
2904514f5e3Sopenharmony_ci    {
2914514f5e3Sopenharmony_ci        profileTypeInfo_ = profileTypeInfo;
2924514f5e3Sopenharmony_ci    }
2934514f5e3Sopenharmony_ci
2944514f5e3Sopenharmony_ci    JSThread *hostThread_;
2954514f5e3Sopenharmony_ci    JSThread *compilerThread_;
2964514f5e3Sopenharmony_ci    Jit *jit_;
2974514f5e3Sopenharmony_ci    JSHandle<JSFunction> jsFunction_;
2984514f5e3Sopenharmony_ci    JSHandle<ProfileTypeInfo> profileTypeInfo_;
2994514f5e3Sopenharmony_ci    void *compilerTask_;
3004514f5e3Sopenharmony_ci    MachineCodeDesc codeDesc_;
3014514f5e3Sopenharmony_ci    CompileState state_;
3024514f5e3Sopenharmony_ci    CompilerTier compilerTier_;
3034514f5e3Sopenharmony_ci    CString methodName_;
3044514f5e3Sopenharmony_ci    int32_t offset_;
3054514f5e3Sopenharmony_ci    uint32_t taskThreadId_;
3064514f5e3Sopenharmony_ci    std::unique_ptr<SustainingJSHandle> sustainingJSHandle_;
3074514f5e3Sopenharmony_ci    EcmaContext *ecmaContext_;
3084514f5e3Sopenharmony_ci    JitCompileMode jitCompileMode_;
3094514f5e3Sopenharmony_ci    JitDfx *jitDfx_ { nullptr };
3104514f5e3Sopenharmony_ci    int mainThreadCompileTime_ {0};
3114514f5e3Sopenharmony_ci
3124514f5e3Sopenharmony_ci    std::atomic<RunState> runState_;
3134514f5e3Sopenharmony_ci    Mutex runStateMutex_;
3144514f5e3Sopenharmony_ci    ConditionVariable runStateCondition_;
3154514f5e3Sopenharmony_ci};
3164514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
3174514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_JIT_TASK_H
318