14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 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_PGO_PROFILER_PGO_UTILS_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_PGO_PROFILER_PGO_UTILS_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include <list>
204514f5e3Sopenharmony_ci#include <string>
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_ci#include "ecmascript/common.h"
234514f5e3Sopenharmony_ci#include "ecmascript/log.h"
244514f5e3Sopenharmony_ci#include "ecmascript/log_wrapper.h"
254514f5e3Sopenharmony_ci#include "ecmascript/platform/mutex.h"
264514f5e3Sopenharmony_ci#include "libpandafile/file.h"
274514f5e3Sopenharmony_ci#include "mem/mem.h"
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_cinamespace panda::ecmascript::pgo {
304514f5e3Sopenharmony_cistatic constexpr Alignment ALIGN_SIZE = Alignment::LOG_ALIGN_4;
314514f5e3Sopenharmony_ciusing PGOMethodId = panda_file::File::EntityId;
324514f5e3Sopenharmony_ciusing ApEntityId = uint32_t;
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ciclass DumpUtils {
354514f5e3Sopenharmony_cipublic:
364514f5e3Sopenharmony_ci    static const std::string ELEMENT_SEPARATOR;
374514f5e3Sopenharmony_ci    static const std::string BLOCK_SEPARATOR;
384514f5e3Sopenharmony_ci    static const std::string TYPE_SEPARATOR;
394514f5e3Sopenharmony_ci    static const std::string BLOCK_START;
404514f5e3Sopenharmony_ci    static const std::string ARRAY_START;
414514f5e3Sopenharmony_ci    static const std::string ARRAY_END;
424514f5e3Sopenharmony_ci    static const std::string NEW_LINE;
434514f5e3Sopenharmony_ci    static const std::string SPACE;
444514f5e3Sopenharmony_ci    static const std::string BLOCK_AND_ARRAY_START;
454514f5e3Sopenharmony_ci    static const std::string VERSION_HEADER;
464514f5e3Sopenharmony_ci    static const std::string PANDA_FILE_INFO_HEADER;
474514f5e3Sopenharmony_ci    static const uint32_t HEX_FORMAT_WIDTH_FOR_32BITS;
484514f5e3Sopenharmony_ci};
494514f5e3Sopenharmony_ci
504514f5e3Sopenharmony_ciclass DumpJsonUtils {
514514f5e3Sopenharmony_cipublic:
524514f5e3Sopenharmony_ci    static inline const std::string ABC_FILE_POOL = "abcFilePool";
534514f5e3Sopenharmony_ci    static inline const std::string ABC_FILE = "abcFile";
544514f5e3Sopenharmony_ci    static inline const std::string RECORD_DETAIL = "recordDetail";
554514f5e3Sopenharmony_ci    static inline const std::string MODULE_NAME = "moduleName";
564514f5e3Sopenharmony_ci    static inline const std::string FUNCTION = "function";
574514f5e3Sopenharmony_ci    static inline const std::string FUNCTION_NAME = "functionName";
584514f5e3Sopenharmony_ci    static inline const std::string TYPE = "type";
594514f5e3Sopenharmony_ci    static inline const std::string TYPE_OFFSET = "typeOffset";
604514f5e3Sopenharmony_ci    static inline const std::string TYPE_NAME = "typeName";
614514f5e3Sopenharmony_ci    static inline const std::string IS_ROOT = "isRoot";
624514f5e3Sopenharmony_ci    static inline const std::string KIND = "kind";
634514f5e3Sopenharmony_ci    static inline const std::string ABC_ID = "abcId";
644514f5e3Sopenharmony_ci    static inline const std::string ID = "id";
654514f5e3Sopenharmony_ci};
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ciclass ApNameUtils {
684514f5e3Sopenharmony_cipublic:
694514f5e3Sopenharmony_ci    static const std::string AP_SUFFIX;
704514f5e3Sopenharmony_ci    static const std::string RUNTIME_AP_PREFIX;
714514f5e3Sopenharmony_ci    static const std::string MERGED_AP_PREFIX;
724514f5e3Sopenharmony_ci    static const std::string DEFAULT_AP_NAME;
734514f5e3Sopenharmony_ci    static std::string PUBLIC_API GetRuntimeApName(const std::string &ohosModuleName);
744514f5e3Sopenharmony_ci    static std::string PUBLIC_API GetMergedApName(const std::string &ohosModuleName);
754514f5e3Sopenharmony_ci    static std::string PUBLIC_API GetOhosPkgApName(const std::string &ohosModuleName);
764514f5e3Sopenharmony_ci
774514f5e3Sopenharmony_ciprivate:
784514f5e3Sopenharmony_ci    static std::string GetBriefApName(const std::string &ohosModuleName);
794514f5e3Sopenharmony_ci};
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ciclass ConcurrentGuardValues {
824514f5e3Sopenharmony_cipublic:
834514f5e3Sopenharmony_ci    mutable std::atomic_int last_tid {0};
844514f5e3Sopenharmony_ci    mutable std::atomic_int count {0};
854514f5e3Sopenharmony_ci    static const int MAX_LOG_COUNT = 30;
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ci    void AddLog(std::string str)
884514f5e3Sopenharmony_ci    {
894514f5e3Sopenharmony_ci        LockHolder lock(mutex_);
904514f5e3Sopenharmony_ci        if (log_.size() >= MAX_LOG_COUNT) {
914514f5e3Sopenharmony_ci            log_.pop_front();
924514f5e3Sopenharmony_ci        }
934514f5e3Sopenharmony_ci        log_.push_back(str + ", tid: " + std::to_string(Gettid()));
944514f5e3Sopenharmony_ci    }
954514f5e3Sopenharmony_ci
964514f5e3Sopenharmony_ci    void AddLogWithDebugLog(std::string str)
974514f5e3Sopenharmony_ci    {
984514f5e3Sopenharmony_ci        AddLog(str);
994514f5e3Sopenharmony_ci        LOG_ECMA(DEBUG) << str;
1004514f5e3Sopenharmony_ci    }
1014514f5e3Sopenharmony_ci
1024514f5e3Sopenharmony_ci    void ClearLog()
1034514f5e3Sopenharmony_ci    {
1044514f5e3Sopenharmony_ci        LockHolder lock(mutex_);
1054514f5e3Sopenharmony_ci        log_.clear();
1064514f5e3Sopenharmony_ci    }
1074514f5e3Sopenharmony_ci
1084514f5e3Sopenharmony_ci    void PrintLog()
1094514f5e3Sopenharmony_ci    {
1104514f5e3Sopenharmony_ci        LockHolder lock(mutex_);
1114514f5e3Sopenharmony_ci        std::ostringstream os;
1124514f5e3Sopenharmony_ci        os << "concurrent guard logs: " << std::endl;
1134514f5e3Sopenharmony_ci        for (auto& str: log_) {
1144514f5e3Sopenharmony_ci            os << str << std::endl;
1154514f5e3Sopenharmony_ci        }
1164514f5e3Sopenharmony_ci        LOG_ECMA(INFO) << os.str();
1174514f5e3Sopenharmony_ci    }
1184514f5e3Sopenharmony_ci
1194514f5e3Sopenharmony_ci    int Gettid()
1204514f5e3Sopenharmony_ci    {
1214514f5e3Sopenharmony_ci        return os::thread::GetCurrentThreadId();
1224514f5e3Sopenharmony_ci    }
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ciprivate:
1254514f5e3Sopenharmony_ci    std::list<std::string> log_;
1264514f5e3Sopenharmony_ci    Mutex mutex_;
1274514f5e3Sopenharmony_ci};
1284514f5e3Sopenharmony_ci
1294514f5e3Sopenharmony_ciclass ConcurrentGuard {
1304514f5e3Sopenharmony_ciprivate:
1314514f5e3Sopenharmony_ci    std::string operation_;
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_cipublic:
1344514f5e3Sopenharmony_ci    ConcurrentGuard(ConcurrentGuardValues& v, std::string operation = ""): operation_(operation), v_(v)
1354514f5e3Sopenharmony_ci    {
1364514f5e3Sopenharmony_ci        v_.AddLogWithDebugLog("[ConcurrentGuard] " + operation_ + " start");
1374514f5e3Sopenharmony_ci        auto tid = v_.Gettid();
1384514f5e3Sopenharmony_ci        auto except = 0;
1394514f5e3Sopenharmony_ci        // Support reenter
1404514f5e3Sopenharmony_ci        if (!v_.count.compare_exchange_strong(except, 1) && v_.last_tid != tid) {
1414514f5e3Sopenharmony_ci            v_.PrintLog();
1424514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "[ConcurrentGuard] total thead count should be 0, but get " << except
1434514f5e3Sopenharmony_ci                            << ", current tid: " << tid << ", last tid: " << v_.last_tid;
1444514f5e3Sopenharmony_ci        }
1454514f5e3Sopenharmony_ci        v_.last_tid = tid;
1464514f5e3Sopenharmony_ci    }
1474514f5e3Sopenharmony_ci    ~ConcurrentGuard()
1484514f5e3Sopenharmony_ci    {
1494514f5e3Sopenharmony_ci        auto tid = v_.Gettid();
1504514f5e3Sopenharmony_ci        auto except = 1;
1514514f5e3Sopenharmony_ci        // Support reenter
1524514f5e3Sopenharmony_ci        if (!v_.count.compare_exchange_strong(except, 0) && v_.last_tid != tid) {
1534514f5e3Sopenharmony_ci            v_.PrintLog();
1544514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "[ConcurrentGuard] total thead count should be 1, but get " << except
1554514f5e3Sopenharmony_ci                            << ", current tid: " << tid << ", last tid: " << v_.last_tid;
1564514f5e3Sopenharmony_ci        }
1574514f5e3Sopenharmony_ci        v_.AddLogWithDebugLog("[ConcurrentGuard] " + operation_ + " end");
1584514f5e3Sopenharmony_ci    };
1594514f5e3Sopenharmony_ci
1604514f5e3Sopenharmony_ciprivate:
1614514f5e3Sopenharmony_ci    ConcurrentGuardValues& v_;
1624514f5e3Sopenharmony_ci};
1634514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::pgo
1644514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_PGO_PROFILER_PGO_UTILS_H
165