14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022 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#include "ecmascript/jspandafile/js_pandafile.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/program_object.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_cinamespace panda::ecmascript {
214514f5e3Sopenharmony_cinamespace {
224514f5e3Sopenharmony_ciconst CString OHOS_PKG_ABC_PATH_ROOT = "/ets/";  // abc file always under /ets/ dir in HAP/HSP
234514f5e3Sopenharmony_ci}  // namespace
244514f5e3Sopenharmony_cibool JSPandaFile::loadedFirstPandaFile = false;
254514f5e3Sopenharmony_ciJSPandaFile::JSPandaFile(const panda_file::File *pf, const CString &descriptor)
264514f5e3Sopenharmony_ci    : pf_(pf), desc_(descriptor)
274514f5e3Sopenharmony_ci{
284514f5e3Sopenharmony_ci    ASSERT(pf_ != nullptr);
294514f5e3Sopenharmony_ci    CheckIsBundlePack();
304514f5e3Sopenharmony_ci    if (isBundlePack_) {
314514f5e3Sopenharmony_ci        InitializeUnMergedPF();
324514f5e3Sopenharmony_ci    } else {
334514f5e3Sopenharmony_ci        InitializeMergedPF();
344514f5e3Sopenharmony_ci    }
354514f5e3Sopenharmony_ci    checksum_ = pf->GetHeader()->checksum;
364514f5e3Sopenharmony_ci    isNewVersion_ = pf_->GetHeader()->version > OLD_VERSION;
374514f5e3Sopenharmony_ci    if (!loadedFirstPandaFile && !isBundlePack_) {
384514f5e3Sopenharmony_ci        // Tag the first merged abc to use constant string. The lifetime of this first panda file is the same
394514f5e3Sopenharmony_ci        // as the vm. And make sure the first pandafile is the same at the compile time and runtime.
404514f5e3Sopenharmony_ci        isFirstPandafile_ = false;
414514f5e3Sopenharmony_ci        loadedFirstPandaFile = true;
424514f5e3Sopenharmony_ci    }
434514f5e3Sopenharmony_ci}
444514f5e3Sopenharmony_ci
454514f5e3Sopenharmony_civoid JSPandaFile::CheckIsBundlePack()
464514f5e3Sopenharmony_ci{
474514f5e3Sopenharmony_ci    Span<const uint32_t> classIndexes = pf_->GetClasses();
484514f5e3Sopenharmony_ci    for (const uint32_t index : classIndexes) {
494514f5e3Sopenharmony_ci        panda_file::File::EntityId classId(index);
504514f5e3Sopenharmony_ci        if (pf_->IsExternal(classId)) {
514514f5e3Sopenharmony_ci            continue;
524514f5e3Sopenharmony_ci        }
534514f5e3Sopenharmony_ci        panda_file::ClassDataAccessor cda(*pf_, classId);
544514f5e3Sopenharmony_ci        cda.EnumerateFields([&](panda_file::FieldDataAccessor &fieldAccessor) -> void {
554514f5e3Sopenharmony_ci            panda_file::File::EntityId fieldNameId = fieldAccessor.GetNameId();
564514f5e3Sopenharmony_ci            panda_file::File::StringData sd = GetStringData(fieldNameId);
574514f5e3Sopenharmony_ci            const char *fieldName = utf::Mutf8AsCString(sd.data);
584514f5e3Sopenharmony_ci            if (std::strcmp(IS_COMMON_JS, fieldName) == 0 || std::strcmp(MODULE_RECORD_IDX, fieldName) == 0) {
594514f5e3Sopenharmony_ci                isBundlePack_ = false;
604514f5e3Sopenharmony_ci            }
614514f5e3Sopenharmony_ci        });
624514f5e3Sopenharmony_ci        if (!isBundlePack_) {
634514f5e3Sopenharmony_ci            return;
644514f5e3Sopenharmony_ci        }
654514f5e3Sopenharmony_ci    }
664514f5e3Sopenharmony_ci}
674514f5e3Sopenharmony_ci
684514f5e3Sopenharmony_civoid JSPandaFile::CheckIsRecordWithBundleName(const CString &entry)
694514f5e3Sopenharmony_ci{
704514f5e3Sopenharmony_ci    size_t pos = entry.find('/');
714514f5e3Sopenharmony_ci    if (pos == CString::npos) {
724514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "CheckIsRecordWithBundleName Invalid parameter entry";
734514f5e3Sopenharmony_ci    }
744514f5e3Sopenharmony_ci
754514f5e3Sopenharmony_ci    CString bundleName = entry.substr(0, pos);
764514f5e3Sopenharmony_ci    size_t bundleNameLen = bundleName.length();
774514f5e3Sopenharmony_ci    for (auto info : jsRecordInfo_) {
784514f5e3Sopenharmony_ci        if (info.first.find(PACKAGE_PATH_SEGMENT) != CString::npos ||
794514f5e3Sopenharmony_ci            info.first.find(NPM_PATH_SEGMENT) != CString::npos) {
804514f5e3Sopenharmony_ci            continue;
814514f5e3Sopenharmony_ci        }
824514f5e3Sopenharmony_ci        CString recordName = info.first;
834514f5e3Sopenharmony_ci        // Confirm whether the current record is new or old by judging whether the recordName has a bundleName
844514f5e3Sopenharmony_ci        if (!(recordName.length() > bundleNameLen && (recordName.compare(0, bundleNameLen, bundleName) == 0))) {
854514f5e3Sopenharmony_ci            isRecordWithBundleName_ = false;
864514f5e3Sopenharmony_ci        }
874514f5e3Sopenharmony_ci        return;
884514f5e3Sopenharmony_ci    }
894514f5e3Sopenharmony_ci}
904514f5e3Sopenharmony_ci
914514f5e3Sopenharmony_ciJSPandaFile::~JSPandaFile()
924514f5e3Sopenharmony_ci{
934514f5e3Sopenharmony_ci    if (pf_ != nullptr) {
944514f5e3Sopenharmony_ci        delete pf_;
954514f5e3Sopenharmony_ci        pf_ = nullptr;
964514f5e3Sopenharmony_ci    }
974514f5e3Sopenharmony_ci
984514f5e3Sopenharmony_ci    constpoolMap_.clear();
994514f5e3Sopenharmony_ci    for (auto& each : jsRecordInfo_) {
1004514f5e3Sopenharmony_ci        delete each.second;
1014514f5e3Sopenharmony_ci    }
1024514f5e3Sopenharmony_ci    jsRecordInfo_.clear();
1034514f5e3Sopenharmony_ci    methodLiteralMap_.clear();
1044514f5e3Sopenharmony_ci    ClearNameMap();
1054514f5e3Sopenharmony_ci    if (methodLiterals_ != nullptr) {
1064514f5e3Sopenharmony_ci        JSPandaFileManager::FreeBuffer(methodLiterals_);
1074514f5e3Sopenharmony_ci        methodLiterals_ = nullptr;
1084514f5e3Sopenharmony_ci    }
1094514f5e3Sopenharmony_ci}
1104514f5e3Sopenharmony_ci
1114514f5e3Sopenharmony_ciuint32_t JSPandaFile::GetOrInsertConstantPool(ConstPoolType type, uint32_t offset,
1124514f5e3Sopenharmony_ci                                              const CUnorderedMap<uint32_t, uint64_t> *constpoolMap)
1134514f5e3Sopenharmony_ci{
1144514f5e3Sopenharmony_ci    CUnorderedMap<uint32_t, uint64_t> *map = nullptr;
1154514f5e3Sopenharmony_ci    if (constpoolMap != nullptr && !IsBundlePack()) {
1164514f5e3Sopenharmony_ci        map = const_cast<CUnorderedMap<uint32_t, uint64_t> *>(constpoolMap);
1174514f5e3Sopenharmony_ci    } else {
1184514f5e3Sopenharmony_ci        map = &constpoolMap_;
1194514f5e3Sopenharmony_ci    }
1204514f5e3Sopenharmony_ci    auto it = map->find(offset);
1214514f5e3Sopenharmony_ci    if (it != map->cend()) {
1224514f5e3Sopenharmony_ci        ConstPoolValue value(it->second);
1234514f5e3Sopenharmony_ci        return value.GetConstpoolIndex();
1244514f5e3Sopenharmony_ci    }
1254514f5e3Sopenharmony_ci    ASSERT(constpoolIndex_ != UINT32_MAX);
1264514f5e3Sopenharmony_ci    uint32_t index = constpoolIndex_++;
1274514f5e3Sopenharmony_ci    ConstPoolValue value(type, index);
1284514f5e3Sopenharmony_ci    map->emplace(offset, value.GetValue());
1294514f5e3Sopenharmony_ci    return index;
1304514f5e3Sopenharmony_ci}
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_civoid JSPandaFile::InitializeUnMergedPF()
1334514f5e3Sopenharmony_ci{
1344514f5e3Sopenharmony_ci    Span<const uint32_t> classIndexes = pf_->GetClasses();
1354514f5e3Sopenharmony_ci    numClasses_ = classIndexes.size();
1364514f5e3Sopenharmony_ci    JSRecordInfo* info = new JSRecordInfo();
1374514f5e3Sopenharmony_ci    for (const uint32_t index : classIndexes) {
1384514f5e3Sopenharmony_ci        panda_file::File::EntityId classId(index);
1394514f5e3Sopenharmony_ci        if (pf_->IsExternal(classId)) {
1404514f5e3Sopenharmony_ci            continue;
1414514f5e3Sopenharmony_ci        }
1424514f5e3Sopenharmony_ci        panda_file::ClassDataAccessor cda(*pf_, classId);
1434514f5e3Sopenharmony_ci        numMethods_ += cda.GetMethodsNumber();
1444514f5e3Sopenharmony_ci        const char *desc = utf::Mutf8AsCString(cda.GetDescriptor());
1454514f5e3Sopenharmony_ci        if (info->moduleRecordIdx == -1 && std::strcmp(MODULE_CLASS, desc) == 0) {
1464514f5e3Sopenharmony_ci            cda.EnumerateFields([&](panda_file::FieldDataAccessor &fieldAccessor) -> void {
1474514f5e3Sopenharmony_ci                panda_file::File::EntityId fieldNameId = fieldAccessor.GetNameId();
1484514f5e3Sopenharmony_ci                panda_file::File::StringData sd = GetStringData(fieldNameId);
1494514f5e3Sopenharmony_ci                CString fieldName = utf::Mutf8AsCString(sd.data);
1504514f5e3Sopenharmony_ci                if (fieldName != desc_) {
1514514f5e3Sopenharmony_ci                    info->moduleRecordIdx = fieldAccessor.GetValue<int32_t>().value();
1524514f5e3Sopenharmony_ci                    info->classId = index;
1534514f5e3Sopenharmony_ci                    return;
1544514f5e3Sopenharmony_ci                }
1554514f5e3Sopenharmony_ci            });
1564514f5e3Sopenharmony_ci        }
1574514f5e3Sopenharmony_ci        if (!info->isCjs && std::strcmp(COMMONJS_CLASS, desc) == 0) {
1584514f5e3Sopenharmony_ci            info->classId = index;
1594514f5e3Sopenharmony_ci            info->isCjs = true;
1604514f5e3Sopenharmony_ci        }
1614514f5e3Sopenharmony_ci        if (!info->isSharedModule && std::strcmp(IS_SHARED_MODULE, desc) == 0) {
1624514f5e3Sopenharmony_ci            info->isSharedModule = true;
1634514f5e3Sopenharmony_ci        }
1644514f5e3Sopenharmony_ci        if (!info->hasTopLevelAwait && std::strcmp(HASTLA_CLASS, desc) == 0) {
1654514f5e3Sopenharmony_ci            info->hasTopLevelAwait = true;
1664514f5e3Sopenharmony_ci        }
1674514f5e3Sopenharmony_ci    }
1684514f5e3Sopenharmony_ci    jsRecordInfo_.insert({JSPandaFile::ENTRY_FUNCTION_NAME, info});
1694514f5e3Sopenharmony_ci    methodLiterals_ =
1704514f5e3Sopenharmony_ci        static_cast<MethodLiteral *>(JSPandaFileManager::AllocateBuffer(sizeof(MethodLiteral) * numMethods_));
1714514f5e3Sopenharmony_ci    methodLiteralMap_.reserve(numMethods_);
1724514f5e3Sopenharmony_ci}
1734514f5e3Sopenharmony_ci
1744514f5e3Sopenharmony_civoid JSPandaFile::InitializeMergedPF()
1754514f5e3Sopenharmony_ci{
1764514f5e3Sopenharmony_ci    Span<const uint32_t> classIndexes = pf_->GetClasses();
1774514f5e3Sopenharmony_ci    numClasses_ = classIndexes.size();
1784514f5e3Sopenharmony_ci    for (const uint32_t index : classIndexes) {
1794514f5e3Sopenharmony_ci        panda_file::File::EntityId classId(index);
1804514f5e3Sopenharmony_ci        if (pf_->IsExternal(classId)) {
1814514f5e3Sopenharmony_ci            continue;
1824514f5e3Sopenharmony_ci        }
1834514f5e3Sopenharmony_ci        panda_file::ClassDataAccessor cda(*pf_, classId);
1844514f5e3Sopenharmony_ci        numMethods_ += cda.GetMethodsNumber();
1854514f5e3Sopenharmony_ci        JSRecordInfo* info = new JSRecordInfo();
1864514f5e3Sopenharmony_ci        info->classId = index;
1874514f5e3Sopenharmony_ci        bool hasCjsFiled = false;
1884514f5e3Sopenharmony_ci        bool hasJsonFiled = false;
1894514f5e3Sopenharmony_ci        CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
1904514f5e3Sopenharmony_ci        CString recordName = ParseEntryPoint(desc);
1914514f5e3Sopenharmony_ci        cda.EnumerateFields([&](panda_file::FieldDataAccessor &fieldAccessor) -> void {
1924514f5e3Sopenharmony_ci            panda_file::File::EntityId fieldNameId = fieldAccessor.GetNameId();
1934514f5e3Sopenharmony_ci            panda_file::File::StringData sd = GetStringData(fieldNameId);
1944514f5e3Sopenharmony_ci            const char *fieldName = utf::Mutf8AsCString(sd.data);
1954514f5e3Sopenharmony_ci            if (std::strcmp(IS_COMMON_JS, fieldName) == 0) {
1964514f5e3Sopenharmony_ci                hasCjsFiled = true;
1974514f5e3Sopenharmony_ci                info->isCjs = fieldAccessor.GetValue<bool>().value();
1984514f5e3Sopenharmony_ci            } else if (std::strcmp(IS_JSON_CONTENT, fieldName) == 0) {
1994514f5e3Sopenharmony_ci                hasJsonFiled = true;
2004514f5e3Sopenharmony_ci                info->isJson = true;
2014514f5e3Sopenharmony_ci                info->jsonStringId = fieldAccessor.GetValue<uint32_t>().value();
2024514f5e3Sopenharmony_ci            } else if (std::strcmp(MODULE_RECORD_IDX, fieldName) == 0) {
2034514f5e3Sopenharmony_ci                info->moduleRecordIdx = fieldAccessor.GetValue<int32_t>().value();
2044514f5e3Sopenharmony_ci            } else if (std::strcmp(IS_SHARED_MODULE, fieldName) == 0) {
2054514f5e3Sopenharmony_ci                info->isSharedModule = fieldAccessor.GetValue<bool>().value();
2064514f5e3Sopenharmony_ci            } else if (std::strcmp(HAS_TOP_LEVEL_AWAIT, fieldName) == 0) {
2074514f5e3Sopenharmony_ci                info->hasTopLevelAwait = fieldAccessor.GetValue<bool>().value();
2084514f5e3Sopenharmony_ci            } else if (std::strcmp(LAZY_IMPORT, fieldName) == 0) {
2094514f5e3Sopenharmony_ci                info->lazyImportIdx = fieldAccessor.GetValue<uint32_t>().value();
2104514f5e3Sopenharmony_ci            } else if (std::strlen(fieldName) > PACKAGE_NAME_LEN &&
2114514f5e3Sopenharmony_ci                       std::strncmp(fieldName, PACKAGE_NAME, PACKAGE_NAME_LEN) == 0) {
2124514f5e3Sopenharmony_ci                info->npmPackageName = fieldName + PACKAGE_NAME_LEN;
2134514f5e3Sopenharmony_ci            } else {
2144514f5e3Sopenharmony_ci                npmEntries_.emplace(recordName, fieldName);
2154514f5e3Sopenharmony_ci            }
2164514f5e3Sopenharmony_ci        });
2174514f5e3Sopenharmony_ci        if (hasCjsFiled || hasJsonFiled) {
2184514f5e3Sopenharmony_ci            jsRecordInfo_.emplace(recordName, info);
2194514f5e3Sopenharmony_ci        } else {
2204514f5e3Sopenharmony_ci            delete info;
2214514f5e3Sopenharmony_ci        }
2224514f5e3Sopenharmony_ci    }
2234514f5e3Sopenharmony_ci    methodLiterals_ =
2244514f5e3Sopenharmony_ci        static_cast<MethodLiteral *>(JSPandaFileManager::AllocateBuffer(sizeof(MethodLiteral) * numMethods_));
2254514f5e3Sopenharmony_ci    methodLiteralMap_.reserve(numMethods_);
2264514f5e3Sopenharmony_ci}
2274514f5e3Sopenharmony_ci
2284514f5e3Sopenharmony_ciMethodLiteral *JSPandaFile::FindMethodLiteral(uint32_t offset) const
2294514f5e3Sopenharmony_ci{
2304514f5e3Sopenharmony_ci    auto iter = methodLiteralMap_.find(offset);
2314514f5e3Sopenharmony_ci    if (iter == methodLiteralMap_.end()) {
2324514f5e3Sopenharmony_ci        return nullptr;
2334514f5e3Sopenharmony_ci    }
2344514f5e3Sopenharmony_ci    return iter->second;
2354514f5e3Sopenharmony_ci}
2364514f5e3Sopenharmony_ci
2374514f5e3Sopenharmony_cibool JSPandaFile::IsFirstMergedAbc() const
2384514f5e3Sopenharmony_ci{
2394514f5e3Sopenharmony_ci    if (isFirstPandafile_ && !IsBundlePack()) {
2404514f5e3Sopenharmony_ci        return true;
2414514f5e3Sopenharmony_ci    }
2424514f5e3Sopenharmony_ci    return false;
2434514f5e3Sopenharmony_ci}
2444514f5e3Sopenharmony_ci
2454514f5e3Sopenharmony_cibool JSPandaFile::CheckAndGetRecordInfo(const CString &recordName, [[maybe_unused]] JSRecordInfo **recordInfo) const
2464514f5e3Sopenharmony_ci{
2474514f5e3Sopenharmony_ci    if (IsBundlePack()) {
2484514f5e3Sopenharmony_ci        *recordInfo = jsRecordInfo_.begin()->second;
2494514f5e3Sopenharmony_ci        return true;
2504514f5e3Sopenharmony_ci    }
2514514f5e3Sopenharmony_ci    auto info = jsRecordInfo_.find(recordName);
2524514f5e3Sopenharmony_ci    if (info != jsRecordInfo_.end()) {
2534514f5e3Sopenharmony_ci        *recordInfo = info->second;
2544514f5e3Sopenharmony_ci        return true;
2554514f5e3Sopenharmony_ci    }
2564514f5e3Sopenharmony_ci    return false;
2574514f5e3Sopenharmony_ci}
2584514f5e3Sopenharmony_ci
2594514f5e3Sopenharmony_ciconst JSRecordInfo* JSPandaFile::GetRecordInfo(const CString &recordName)
2604514f5e3Sopenharmony_ci{
2614514f5e3Sopenharmony_ci    if (IsBundlePack()) {
2624514f5e3Sopenharmony_ci        return jsRecordInfo_.begin()->second;
2634514f5e3Sopenharmony_ci    }
2644514f5e3Sopenharmony_ci    auto info = jsRecordInfo_.find(recordName);
2654514f5e3Sopenharmony_ci    if (info != jsRecordInfo_.end()) {
2664514f5e3Sopenharmony_ci        return info->second;
2674514f5e3Sopenharmony_ci    }
2684514f5e3Sopenharmony_ci    LOG_FULL(FATAL) << "Get record info failed";
2694514f5e3Sopenharmony_ci    UNREACHABLE();
2704514f5e3Sopenharmony_ci}
2714514f5e3Sopenharmony_ci
2724514f5e3Sopenharmony_ciCString JSPandaFile::GetEntryPoint(const CString &recordName) const
2734514f5e3Sopenharmony_ci{
2744514f5e3Sopenharmony_ci    CString entryPoint;
2754514f5e3Sopenharmony_ci    if (FindOhmUrlInPF(recordName, entryPoint) && HasRecord(entryPoint)) {
2764514f5e3Sopenharmony_ci        return entryPoint;
2774514f5e3Sopenharmony_ci    }
2784514f5e3Sopenharmony_ci    return CString();
2794514f5e3Sopenharmony_ci}
2804514f5e3Sopenharmony_ci
2814514f5e3Sopenharmony_ciCString JSPandaFile::GetRecordName(const CString &entryPoint) const
2824514f5e3Sopenharmony_ci{
2834514f5e3Sopenharmony_ci    if (entryPoint.empty() || entryPoint == JSPandaFile::ENTRY_FUNCTION_NAME) {
2844514f5e3Sopenharmony_ci        return GetJSPandaFileDesc();
2854514f5e3Sopenharmony_ci    }
2864514f5e3Sopenharmony_ci    return entryPoint;
2874514f5e3Sopenharmony_ci}
2884514f5e3Sopenharmony_ci
2894514f5e3Sopenharmony_cibool JSPandaFile::FindOhmUrlInPF(const CString &recordName, CString &entryPoint) const
2904514f5e3Sopenharmony_ci{
2914514f5e3Sopenharmony_ci    auto info = npmEntries_.find(recordName);
2924514f5e3Sopenharmony_ci    if (info != npmEntries_.end()) {
2934514f5e3Sopenharmony_ci        entryPoint = info->second;
2944514f5e3Sopenharmony_ci        return true;
2954514f5e3Sopenharmony_ci    }
2964514f5e3Sopenharmony_ci    return false;
2974514f5e3Sopenharmony_ci}
2984514f5e3Sopenharmony_ci
2994514f5e3Sopenharmony_ciFunctionKind JSPandaFile::GetFunctionKind(panda_file::FunctionKind funcKind)
3004514f5e3Sopenharmony_ci{
3014514f5e3Sopenharmony_ci    FunctionKind kind;
3024514f5e3Sopenharmony_ci    if ((static_cast<uint32_t>(funcKind) & SENDABLE_FUNCTION_MASK) != 0) {
3034514f5e3Sopenharmony_ci        funcKind = static_cast<panda_file::FunctionKind>(static_cast<uint32_t>(funcKind) & (~SENDABLE_FUNCTION_MASK));
3044514f5e3Sopenharmony_ci    }
3054514f5e3Sopenharmony_ci    switch (funcKind) {
3064514f5e3Sopenharmony_ci        case panda_file::FunctionKind::NONE:
3074514f5e3Sopenharmony_ci            kind = FunctionKind::NONE_FUNCTION;
3084514f5e3Sopenharmony_ci            break;
3094514f5e3Sopenharmony_ci        case panda_file::FunctionKind::FUNCTION:
3104514f5e3Sopenharmony_ci            kind = FunctionKind::BASE_CONSTRUCTOR;
3114514f5e3Sopenharmony_ci            break;
3124514f5e3Sopenharmony_ci        case panda_file::FunctionKind::NC_FUNCTION:
3134514f5e3Sopenharmony_ci            kind = FunctionKind::ARROW_FUNCTION;
3144514f5e3Sopenharmony_ci            break;
3154514f5e3Sopenharmony_ci        case panda_file::FunctionKind::GENERATOR_FUNCTION:
3164514f5e3Sopenharmony_ci            kind = FunctionKind::GENERATOR_FUNCTION;
3174514f5e3Sopenharmony_ci            break;
3184514f5e3Sopenharmony_ci        case panda_file::FunctionKind::ASYNC_FUNCTION:
3194514f5e3Sopenharmony_ci            kind = FunctionKind::ASYNC_FUNCTION;
3204514f5e3Sopenharmony_ci            break;
3214514f5e3Sopenharmony_ci        case panda_file::FunctionKind::ASYNC_GENERATOR_FUNCTION:
3224514f5e3Sopenharmony_ci            kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
3234514f5e3Sopenharmony_ci            break;
3244514f5e3Sopenharmony_ci        case panda_file::FunctionKind::ASYNC_NC_FUNCTION:
3254514f5e3Sopenharmony_ci            kind = FunctionKind::ASYNC_ARROW_FUNCTION;
3264514f5e3Sopenharmony_ci            break;
3274514f5e3Sopenharmony_ci        case panda_file::FunctionKind::CONCURRENT_FUNCTION:
3284514f5e3Sopenharmony_ci            kind = FunctionKind::CONCURRENT_FUNCTION;
3294514f5e3Sopenharmony_ci            break;
3304514f5e3Sopenharmony_ci        default:
3314514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "this branch is unreachable";
3324514f5e3Sopenharmony_ci            UNREACHABLE();
3334514f5e3Sopenharmony_ci    }
3344514f5e3Sopenharmony_ci    return kind;
3354514f5e3Sopenharmony_ci}
3364514f5e3Sopenharmony_ci
3374514f5e3Sopenharmony_ciFunctionKind JSPandaFile::GetFunctionKind(ConstPoolType type)
3384514f5e3Sopenharmony_ci{
3394514f5e3Sopenharmony_ci    FunctionKind kind;
3404514f5e3Sopenharmony_ci    switch (type) {
3414514f5e3Sopenharmony_ci        case ConstPoolType::BASE_FUNCTION:
3424514f5e3Sopenharmony_ci            kind = FunctionKind::BASE_CONSTRUCTOR;
3434514f5e3Sopenharmony_ci            break;
3444514f5e3Sopenharmony_ci        case ConstPoolType::NC_FUNCTION:
3454514f5e3Sopenharmony_ci            kind = FunctionKind::ARROW_FUNCTION;
3464514f5e3Sopenharmony_ci            break;
3474514f5e3Sopenharmony_ci        case ConstPoolType::GENERATOR_FUNCTION:
3484514f5e3Sopenharmony_ci            kind = FunctionKind::GENERATOR_FUNCTION;
3494514f5e3Sopenharmony_ci            break;
3504514f5e3Sopenharmony_ci        case ConstPoolType::ASYNC_FUNCTION:
3514514f5e3Sopenharmony_ci            kind = FunctionKind::ASYNC_FUNCTION;
3524514f5e3Sopenharmony_ci            break;
3534514f5e3Sopenharmony_ci        case ConstPoolType::CLASS_FUNCTION:
3544514f5e3Sopenharmony_ci            kind = FunctionKind::CLASS_CONSTRUCTOR;
3554514f5e3Sopenharmony_ci            break;
3564514f5e3Sopenharmony_ci        case ConstPoolType::METHOD:
3574514f5e3Sopenharmony_ci            kind = FunctionKind::NORMAL_FUNCTION;
3584514f5e3Sopenharmony_ci            break;
3594514f5e3Sopenharmony_ci        case ConstPoolType::ASYNC_GENERATOR_FUNCTION:
3604514f5e3Sopenharmony_ci            kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
3614514f5e3Sopenharmony_ci            break;
3624514f5e3Sopenharmony_ci        default:
3634514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "this branch is unreachable";
3644514f5e3Sopenharmony_ci            UNREACHABLE();
3654514f5e3Sopenharmony_ci    }
3664514f5e3Sopenharmony_ci    return kind;
3674514f5e3Sopenharmony_ci}
3684514f5e3Sopenharmony_ci
3694514f5e3Sopenharmony_ci/*
3704514f5e3Sopenharmony_ci handle desc like: case1: /data/storage/el1/bundle/entry/ets/modules.abc -> entry/ets/modules.abc
3714514f5e3Sopenharmony_ci case2: /data/storage/el1/bundle/entry/ets/widgets.abc -> entry/ets/widgets.abc
3724514f5e3Sopenharmony_ci case3: /data/app/el1/bundle/public/com.xx.xx/entry/ets/modules.abc -> entry/ets/modules.abc
3734514f5e3Sopenharmony_ci case4: /data/app/el1/bundle/public/com.xx.xx/entry/ets/widgets.abc -> entry/ets/widgets.abc
3744514f5e3Sopenharmony_ci*/
3754514f5e3Sopenharmony_ciCString JSPandaFile::GetNormalizedFileDesc(const CString &desc)
3764514f5e3Sopenharmony_ci{
3774514f5e3Sopenharmony_ci    auto etsTokenPos = desc.rfind(OHOS_PKG_ABC_PATH_ROOT);
3784514f5e3Sopenharmony_ci    if (etsTokenPos == std::string::npos) {
3794514f5e3Sopenharmony_ci        // file not in OHOS package.
3804514f5e3Sopenharmony_ci        return desc;
3814514f5e3Sopenharmony_ci    }
3824514f5e3Sopenharmony_ci    auto ohosModulePos = desc.rfind('/', etsTokenPos - 1);
3834514f5e3Sopenharmony_ci    if (ohosModulePos == std::string::npos) {
3844514f5e3Sopenharmony_ci        LOG_ECMA(ERROR) << "Get abcPath from desc failed. desc: " << desc;
3854514f5e3Sopenharmony_ci        return desc;
3864514f5e3Sopenharmony_ci    }
3874514f5e3Sopenharmony_ci    // substring likes {ohosModuleName}/ets/modules.abc or {ohosModuleName}/ets/widgets.abc
3884514f5e3Sopenharmony_ci    return desc.substr(ohosModulePos + 1);
3894514f5e3Sopenharmony_ci}
3904514f5e3Sopenharmony_ci
3914514f5e3Sopenharmony_ciCString JSPandaFile::GetNormalizedFileDesc() const
3924514f5e3Sopenharmony_ci{
3934514f5e3Sopenharmony_ci    return GetNormalizedFileDesc(desc_);
3944514f5e3Sopenharmony_ci}
3954514f5e3Sopenharmony_ci
3964514f5e3Sopenharmony_cistd::pair<std::string_view, bool> JSPandaFile::GetMethodName(EntityId methodId)
3974514f5e3Sopenharmony_ci{
3984514f5e3Sopenharmony_ci    LockHolder lock(methodNameMapMutex_);
3994514f5e3Sopenharmony_ci    uint32_t id = methodId.GetOffset();
4004514f5e3Sopenharmony_ci    auto iter = methodNameMap_.find(id);
4014514f5e3Sopenharmony_ci    if (iter != methodNameMap_.end()) {
4024514f5e3Sopenharmony_ci        panda_file::StringData sd = iter->second;
4034514f5e3Sopenharmony_ci        return {std::string_view(utf::Mutf8AsCString(sd.data), sd.utf16_length), sd.is_ascii};
4044514f5e3Sopenharmony_ci    }
4054514f5e3Sopenharmony_ci
4064514f5e3Sopenharmony_ci    panda_file::MethodDataAccessor mda(*pf_, methodId);
4074514f5e3Sopenharmony_ci    auto sd = GetStringData(mda.GetNameId());
4084514f5e3Sopenharmony_ci    methodNameMap_.emplace(id, sd);
4094514f5e3Sopenharmony_ci    return {std::string_view(utf::Mutf8AsCString(sd.data), sd.utf16_length), sd.is_ascii};
4104514f5e3Sopenharmony_ci}
4114514f5e3Sopenharmony_ci
4124514f5e3Sopenharmony_cistd::pair<std::string_view, bool> JSPandaFile::GetCpuProfilerMethodName(EntityId methodId) const
4134514f5e3Sopenharmony_ci{
4144514f5e3Sopenharmony_ci    panda_file::MethodDataAccessor mda(*pf_, methodId);
4154514f5e3Sopenharmony_ci    auto sd = GetStringData(mda.GetNameId());
4164514f5e3Sopenharmony_ci    std::string_view strView(utf::Mutf8AsCString(sd.data), sd.utf16_length);
4174514f5e3Sopenharmony_ci    return {strView, sd.is_ascii};
4184514f5e3Sopenharmony_ci}
4194514f5e3Sopenharmony_ci
4204514f5e3Sopenharmony_ciCString JSPandaFile::GetRecordName(EntityId methodId)
4214514f5e3Sopenharmony_ci{
4224514f5e3Sopenharmony_ci    LockHolder lock(recordNameMapMutex_);
4234514f5e3Sopenharmony_ci    uint32_t id = methodId.GetOffset();
4244514f5e3Sopenharmony_ci    auto iter = recordNameMap_.find(id);
4254514f5e3Sopenharmony_ci    if (iter != recordNameMap_.end()) {
4264514f5e3Sopenharmony_ci        return iter->second;
4274514f5e3Sopenharmony_ci    }
4284514f5e3Sopenharmony_ci
4294514f5e3Sopenharmony_ci    panda_file::MethodDataAccessor mda(*pf_, methodId);
4304514f5e3Sopenharmony_ci    panda_file::ClassDataAccessor cda(*pf_, mda.GetClassId());
4314514f5e3Sopenharmony_ci    CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
4324514f5e3Sopenharmony_ci    auto name =  JSPandaFile::ParseEntryPoint(desc);
4334514f5e3Sopenharmony_ci    recordNameMap_.emplace(id, name);
4344514f5e3Sopenharmony_ci    return name;
4354514f5e3Sopenharmony_ci}
4364514f5e3Sopenharmony_ci
4374514f5e3Sopenharmony_ciCString JSPandaFile::GetRecordNameWithBundlePack(EntityId methodIdx)
4384514f5e3Sopenharmony_ci{
4394514f5e3Sopenharmony_ci    CString recordName = IsBundlePack() ? ENTRY_FUNCTION_NAME : GetRecordName(methodIdx);
4404514f5e3Sopenharmony_ci    ASSERT(HasRecord(recordName));
4414514f5e3Sopenharmony_ci    return recordName;
4424514f5e3Sopenharmony_ci}
4434514f5e3Sopenharmony_ci
4444514f5e3Sopenharmony_ci
4454514f5e3Sopenharmony_civoid JSPandaFile::ClearNameMap()
4464514f5e3Sopenharmony_ci{
4474514f5e3Sopenharmony_ci    {
4484514f5e3Sopenharmony_ci        LockHolder lock(methodNameMapMutex_);
4494514f5e3Sopenharmony_ci        methodNameMap_.clear();
4504514f5e3Sopenharmony_ci    }
4514514f5e3Sopenharmony_ci    {
4524514f5e3Sopenharmony_ci        LockHolder lock(recordNameMapMutex_);
4534514f5e3Sopenharmony_ci        recordNameMap_.clear();
4544514f5e3Sopenharmony_ci    }
4554514f5e3Sopenharmony_ci}
4564514f5e3Sopenharmony_ci
4574514f5e3Sopenharmony_cisize_t JSPandaFile::GetClassAndMethodIndex(size_t *methodIdx)
4584514f5e3Sopenharmony_ci{
4594514f5e3Sopenharmony_ci    LockHolder lock(classIndexMutex_);
4604514f5e3Sopenharmony_ci    size_t result = 0;
4614514f5e3Sopenharmony_ci    Span<const uint32_t> classIndexes = GetClasses();
4624514f5e3Sopenharmony_ci    uint32_t index = 0;
4634514f5e3Sopenharmony_ci    do {
4644514f5e3Sopenharmony_ci        result = classIndex_++;
4654514f5e3Sopenharmony_ci        if (result >= numClasses_) {
4664514f5e3Sopenharmony_ci            return result;
4674514f5e3Sopenharmony_ci        }
4684514f5e3Sopenharmony_ci        index = classIndexes[result];
4694514f5e3Sopenharmony_ci    } while (IsExternal(panda_file::File::EntityId(index)));
4704514f5e3Sopenharmony_ci
4714514f5e3Sopenharmony_ci    *methodIdx = methodIndex_;
4724514f5e3Sopenharmony_ci    panda_file::File::EntityId classId(classIndexes[result]);
4734514f5e3Sopenharmony_ci    panda_file::ClassDataAccessor cda(*pf_, classId);
4744514f5e3Sopenharmony_ci    methodIndex_ += cda.GetMethodsNumber();
4754514f5e3Sopenharmony_ci    return result;
4764514f5e3Sopenharmony_ci}
4774514f5e3Sopenharmony_ci
4784514f5e3Sopenharmony_cibool JSPandaFile::TranslateClassesTask::Run([[maybe_unused]] uint32_t threadIndex)
4794514f5e3Sopenharmony_ci{
4804514f5e3Sopenharmony_ci    ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "TranslateClassesTask::Run");
4814514f5e3Sopenharmony_ci    jsPandaFile_->TranslateClass(thread_, *methodNamePtr_);
4824514f5e3Sopenharmony_ci    jsPandaFile_->ReduceTaskCount();
4834514f5e3Sopenharmony_ci    return true;
4844514f5e3Sopenharmony_ci}
4854514f5e3Sopenharmony_ci
4864514f5e3Sopenharmony_civoid JSPandaFile::TranslateClass(JSThread *thread, const CString &methodName)
4874514f5e3Sopenharmony_ci{
4884514f5e3Sopenharmony_ci    size_t methodIdx = 0;
4894514f5e3Sopenharmony_ci    size_t classIdx = GetClassAndMethodIndex(&methodIdx);
4904514f5e3Sopenharmony_ci    while (classIdx < numClasses_) {
4914514f5e3Sopenharmony_ci        PandaFileTranslator::TranslateClass(thread, this, methodName, methodIdx, classIdx);
4924514f5e3Sopenharmony_ci        classIdx = GetClassAndMethodIndex(&methodIdx);
4934514f5e3Sopenharmony_ci    }
4944514f5e3Sopenharmony_ci}
4954514f5e3Sopenharmony_ci
4964514f5e3Sopenharmony_civoid JSPandaFile::PostInitializeMethodTask(JSThread *thread, const std::shared_ptr<CString> &methodNamePtr)
4974514f5e3Sopenharmony_ci{
4984514f5e3Sopenharmony_ci    IncreaseTaskCount();
4994514f5e3Sopenharmony_ci    Taskpool::GetCurrentTaskpool()->PostTask(
5004514f5e3Sopenharmony_ci        std::make_unique<TranslateClassesTask>(thread->GetThreadId(), thread, this, methodNamePtr));
5014514f5e3Sopenharmony_ci}
5024514f5e3Sopenharmony_ci
5034514f5e3Sopenharmony_civoid JSPandaFile::IncreaseTaskCount()
5044514f5e3Sopenharmony_ci{
5054514f5e3Sopenharmony_ci    LockHolder holder(waitTranslateClassFinishedMutex_);
5064514f5e3Sopenharmony_ci    runningTaskCount_++;
5074514f5e3Sopenharmony_ci}
5084514f5e3Sopenharmony_ci
5094514f5e3Sopenharmony_civoid JSPandaFile::WaitTranslateClassTaskFinished()
5104514f5e3Sopenharmony_ci{
5114514f5e3Sopenharmony_ci    LockHolder holder(waitTranslateClassFinishedMutex_);
5124514f5e3Sopenharmony_ci    while (runningTaskCount_ > 0) {
5134514f5e3Sopenharmony_ci        waitTranslateClassFinishedCV_.Wait(&waitTranslateClassFinishedMutex_);
5144514f5e3Sopenharmony_ci    }
5154514f5e3Sopenharmony_ci}
5164514f5e3Sopenharmony_ci
5174514f5e3Sopenharmony_civoid JSPandaFile::ReduceTaskCount()
5184514f5e3Sopenharmony_ci{
5194514f5e3Sopenharmony_ci    LockHolder holder(waitTranslateClassFinishedMutex_);
5204514f5e3Sopenharmony_ci    runningTaskCount_--;
5214514f5e3Sopenharmony_ci    if (runningTaskCount_ == 0) {
5224514f5e3Sopenharmony_ci        waitTranslateClassFinishedCV_.SignalAll();
5234514f5e3Sopenharmony_ci    }
5244514f5e3Sopenharmony_ci}
5254514f5e3Sopenharmony_ci
5264514f5e3Sopenharmony_civoid JSPandaFile::SetAllMethodLiteralToMap()
5274514f5e3Sopenharmony_ci{
5284514f5e3Sopenharmony_ci    // async to optimize SetAllMethodLiteralToMap later
5294514f5e3Sopenharmony_ci    MethodLiteral *methodLiterals = GetMethodLiterals();
5304514f5e3Sopenharmony_ci    size_t methodIdx = 0;
5314514f5e3Sopenharmony_ci    while (methodIdx < numMethods_) {
5324514f5e3Sopenharmony_ci        MethodLiteral *methodLiteral = methodLiterals + (methodIdx++);
5334514f5e3Sopenharmony_ci        SetMethodLiteralToMap(methodLiteral);
5344514f5e3Sopenharmony_ci    }
5354514f5e3Sopenharmony_ci}
5364514f5e3Sopenharmony_ci
5374514f5e3Sopenharmony_civoid JSPandaFile::TranslateClasses(JSThread *thread, const CString &methodName)
5384514f5e3Sopenharmony_ci{
5394514f5e3Sopenharmony_ci    const std::shared_ptr<CString> methodNamePtr = std::make_shared<CString>(methodName);
5404514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); i++) {
5414514f5e3Sopenharmony_ci        PostInitializeMethodTask(thread, methodNamePtr);
5424514f5e3Sopenharmony_ci    }
5434514f5e3Sopenharmony_ci    TranslateClass(thread, methodName);
5444514f5e3Sopenharmony_ci    WaitTranslateClassTaskFinished();
5454514f5e3Sopenharmony_ci    SetAllMethodLiteralToMap();
5464514f5e3Sopenharmony_ci}
5474514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
548