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