!7742 冗余ets文件打印

Merge pull request !7742 from yaochaonan/logtools
This commit is contained in:
openharmony_ci 2024-07-24 11:55:29 +00:00 committed by Gitee
commit 88e4f5ae42
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 636 additions and 16 deletions

View File

@ -860,8 +860,10 @@ ecma_source = [
"ecmascript/module/js_shared_module.cpp",
"ecmascript/module/js_shared_module_manager.cpp",
"ecmascript/module/module_data_extractor.cpp",
"ecmascript/module/module_logger.cpp",
"ecmascript/module/module_manager_helper.cpp",
"ecmascript/module/module_path_helper.cpp",
"ecmascript/module/module_tools.cpp",
"ecmascript/module/napi_module_loader.cpp",
"ecmascript/mutator_lock.cpp",
"ecmascript/napi/jsnapi.cpp",

View File

@ -1254,4 +1254,4 @@ JSTaggedValue BuiltinsArkTools::StopRuntimeStat(EcmaRuntimeCallInfo *msg)
thread->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
return JSTaggedValue::Undefined();
}
} // namespace panda::ecmascript::builtins
} // namespace panda::ecmascript::builtins

View File

@ -40,8 +40,9 @@
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/module/js_shared_module.h"
#include "ecmascript/module/module_logger.h"
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/patch/patch_loader.h"
#include "ecmascript/platform/aot_crash_info.h"
@ -129,6 +130,9 @@ bool EcmaContext::Initialize()
if (vm_->GetJSOptions().GetTypedOpProfiler()) {
typedOpProfiler_ = new TypedOpProfiler();
}
if (vm_->GetJSOptions().EnableModuleLog() && !vm_->GetJSOptions().IsWorker()) {
moduleLogger_ = new ModuleLogger(vm_);
}
functionProtoTransitionTable_ = new FunctionProtoTransitionTable(thread_);
sustainingJSHandleList_ = new SustainingJSHandleList();
initialized_ = true;
@ -244,6 +248,10 @@ EcmaContext::~EcmaContext()
delete moduleManager_;
moduleManager_ = nullptr;
}
if (moduleLogger_ != nullptr) {
delete moduleLogger_;
moduleLogger_ = nullptr;
}
if (ptManager_ != nullptr) {
delete ptManager_;
ptManager_ = nullptr;
@ -383,6 +391,10 @@ Expected<JSTaggedValue, bool> EcmaContext::InvokeEcmaEntrypoint(const JSPandaFil
if (options.EnableModuleLog()) {
LOG_FULL(INFO) << "current executing file's name " << entryPoint.data();
}
ModuleLogger *moduleLogger = GetModuleLogger();
if (moduleLogger != nullptr) {
moduleLogger->SetStartTime(CString(entryPoint));
}
JSHandle<Program> program = JSPandaFileManager::GetInstance()->GenerateProgram(vm_, jsPandaFile, entryPoint);
if (program.IsEmpty()) {
LOG_ECMA(ERROR) << "program is empty, invoke entrypoint failed";
@ -401,6 +413,9 @@ Expected<JSTaggedValue, bool> EcmaContext::InvokeEcmaEntrypoint(const JSPandaFil
}
#endif
if (moduleLogger != nullptr) {
moduleLogger->SetEndTime(CString(entryPoint));
}
return result;
}

View File

@ -67,6 +67,7 @@ class QuickFixManager;
class OptCodeProfiler;
struct CJSInfo;
class FunctionProtoTransitionTable;
class ModuleLogger;
namespace job {
class MicroJobQueue;
@ -312,6 +313,11 @@ public:
return typedOpProfiler_;
}
ModuleLogger *GetModuleLogger() const
{
return moduleLogger_;
}
void SetDefaultLocale(const std::string& locale)
{
defaultLocale_ = locale;
@ -708,6 +714,8 @@ private:
// opt code loop hoist
TypedOpProfiler *typedOpProfiler_ {nullptr};
ModuleLogger *moduleLogger_ {nullptr};
std::string defaultLocale_;
std::optional<CompareStringsOption> defaultComapreStringsOption_;

View File

@ -77,6 +77,7 @@
#include "ecmascript/module/js_module_manager.h"
#include "ecmascript/module/module_data_extractor.h"
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/module/module_logger.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/patch/quick_fix_manager.h"
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
@ -184,6 +185,10 @@ void EcmaVM::PostFork()
heap_->NotifyPostFork();
heap_->NotifyFinishColdStartSoon();
#endif
ModuleLogger *moduleLogger = thread_->GetCurrentEcmaContext()->GetModuleLogger();
if (moduleLogger != nullptr) {
moduleLogger->PostModuleLoggerTask(thread_->GetThreadId(), this);
}
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
int arkProperties = OHOS::system::GetIntParameter<int>("persist.ark.properties", -1);
GetJSOptions().SetArkProperties(arkProperties);

View File

@ -29,8 +29,10 @@
#include "ecmascript/module/js_shared_module.h"
#include "ecmascript/module/js_shared_module_manager.h"
#include "ecmascript/module/module_data_extractor.h"
#include "ecmascript/module/module_logger.h"
#include "ecmascript/module/module_manager_helper.h"
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/module/module_tools.h"
#include "ecmascript/require/js_cjs_module.h"
#include "ecmascript/tagged_dictionary.h"
#ifdef PANDA_TARGET_WINDOWS
@ -119,6 +121,10 @@ JSTaggedValue ModuleManager::GetModuleValueOutterInternal(int32_t index, JSTagge
}
ASSERT(moduleEnvironment.IsTaggedArray());
JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(index);
ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
if (moduleLogger != nullptr) {
return ModuleTools::ProcessModuleLoadInfo(thread, currentModuleHdl, resolvedBinding, index);
}
if (resolvedBinding.IsResolvedIndexBinding()) {
ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
JSTaggedValue resolvedModule = binding->GetModule();
@ -613,6 +619,11 @@ JSTaggedValue ModuleManager::GetModuleNamespaceInternal(int32_t index, JSTaggedV
}
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
JSHandle<SourceTextModule> requiredModuleST = JSHandle<SourceTextModule>::Cast(requiredModule);
ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
if (moduleLogger != nullptr) {
return ModuleTools::ProcessModuleNameSpaceLoadInfo(thread,
JSHandle<SourceTextModule>(thread, module), requiredModuleST);
}
ModuleTypes moduleType = requiredModuleST->GetTypes();
// if requiredModuleST is Native module
if (SourceTextModule::IsNativeModule(moduleType)) {

View File

@ -25,6 +25,7 @@
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/js_promise.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/module/module_logger.h"
#include "ecmascript/module/js_module_deregister.h"
#include "ecmascript/module/js_module_manager.h"
#include "ecmascript/module/js_module_namespace.h"
@ -388,6 +389,10 @@ Local<JSValueRef> SourceTextModule::LoadNativeModuleImpl(EcmaVM *vm, JSThread *t
CString traceInfo = "LoadNativeModule: " + moduleRequestName;
ECMA_BYTRACE_START_TRACE(HITRACE_TAG_ARK, traceInfo.c_str());
}
ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
if (moduleLogger != nullptr) {
moduleLogger->SetStartTime(moduleRequestName);
}
CString soName = PathHelper::GetStrippedModuleName(moduleRequestName);
CString fileName = requiredModule->GetEcmaModuleFilenameString();
@ -405,11 +410,23 @@ Local<JSValueRef> SourceTextModule::LoadNativeModuleImpl(EcmaVM *vm, JSThread *t
// some function(s) may not registered in global object for non-main thread
if (!maybeFuncRef->IsFunction(vm)) {
LOG_FULL(WARN) << "Not found require func";
if (enableESMTrace) {
ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
}
if (moduleLogger != nullptr) {
moduleLogger->SetEndTime(moduleRequestName);
}
return JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
}
Local<FunctionRef> funcRef = maybeFuncRef;
auto exportObject = funcRef->Call(vm, JSValueRef::Undefined(vm), arguments.data(), arguments.size());
if (enableESMTrace) {
ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
}
if (moduleLogger != nullptr) {
moduleLogger->SetEndTime(moduleRequestName);
}
return exportObject;
}
@ -962,6 +979,10 @@ JSTaggedValue SourceTextModule::Evaluate(JSThread *thread, const JSHandle<Source
if (!thread->HasPendingException() && !executeFromJob) {
job::MicroJobQueue::ExecutePendingJob(thread, thread->GetCurrentEcmaContext()->GetMicroJobQueue());
}
ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
if ((moduleLogger != nullptr) && !executeFromJob) {
moduleLogger->InsertEntryPointModule(module);
}
// Return capability.[[Promise]].
return capability->GetPromise();
}
@ -1023,6 +1044,7 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand
module->SetPendingAsyncDependencies(0);
index++;
stack.emplace_back(module);
ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
if (!module->GetRequestedModules().IsUndefined()) {
JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
size_t requestedModulesLen = requestedModules->GetLength();
@ -1043,6 +1065,9 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand
SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
}
if (moduleLogger != nullptr) {
moduleLogger->InsertParentModule(module, requiredModule);
}
ModuleTypes moduleType = requiredModule->GetTypes();
if (SourceTextModule::IsNativeModule(moduleType)) {
EvaluateNativeModule(thread, requiredModule, moduleType);

View File

@ -0,0 +1,275 @@
/*
* Copyright (c) 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.
*/
#include "ecmascript/module/module_logger.h"
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/runtime_lock.h"
#include <fstream>
namespace panda::ecmascript {
ModuleLogger::ModuleLogger(EcmaVM *vm) : vm_(vm) {}
void ModuleLogger::PrintModuleLoadInfo()
{
ProcessModuleExecuteTime();
PrintSummary();
PrintUsedFileInfo();
PrintUnusedFileInfo();
}
bool ModuleLogger::CreateResultFile(std::string &path) const
{
path = FILEDIR + std::string(vm_->GetBundleName().c_str()) + SUFFIX;
const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IRGRP; // -rw-r--
int fd = creat(path.c_str(), defaultMode);
if (fd == -1) {
LOG_ECMA(ERROR) << "file create failed, errno = "<< errno;
return false;
}
close(fd);
return true;
}
bool ModuleLogger::OpenResultFile(std::string &path) const
{
path = FILEDIR + std::string(vm_->GetBundleName().c_str()) + SUFFIX;
if (access(path.c_str(), F_OK) == 0) {
if (access(path.c_str(), W_OK) == 0) {
LOG_ECMA(DEBUG) << "file open success";
return true;
}
LOG_ECMA(ERROR) << "file create failed, W_OK false";
return false;
}
return CreateResultFile(path);
}
void ModuleLogger::InsertModuleLoadInfo(JSHandle<SourceTextModule> currentModule,
JSHandle<SourceTextModule> exportModule, int32_t index)
{
JSThread *thread = vm_->GetJSThread();
RuntimeLockHolder locker(thread, mutex_);
CString curName = SourceTextModule::GetModuleName(currentModule.GetTaggedValue());
CString sonName = SourceTextModule::GetModuleName(exportModule.GetTaggedValue());
ModuleLoadInfo *sonModule = GetModuleLoadInfo(sonName);
sonModule->isUsed = true;
// get importName
CString exportNameStr;
if (index < 0) {
exportNameStr = "*";
} else {
JSHandle<TaggedArray> importArray(thread, currentModule->GetImportEntries());
JSHandle<ImportEntry> importEntry(thread, importArray->Get(index));
JSHandle<JSTaggedValue> importName(thread, importEntry->GetImportName());
exportNameStr = ModulePathHelper::Utf8ConvertToString(importName.GetTaggedValue());
}
auto &upLevelInfo = sonModule->upLevel;
auto ulModule = upLevelInfo.find(curName);
if (ulModule == upLevelInfo.end()) {
CSet<CString> tmp;
tmp.insert(exportNameStr);
upLevelInfo.emplace(curName, std::move(tmp));
return;
}
ulModule->second.insert(exportNameStr);
}
void ModuleLogger::InsertParentModule(JSHandle<SourceTextModule> currentModule,
JSHandle<SourceTextModule> requiredModule)
{
RuntimeLockHolder locker(vm_->GetJSThread(), mutex_);
CString curName = currentModule->GetEcmaModuleRecordNameString();
CString sonName = requiredModule->GetEcmaModuleRecordNameString();
ModuleLoadInfo *sonModule = GetModuleLoadInfo(sonName);
sonModule->parentModules.insert(std::move(curName));
}
void ModuleLogger::InsertEntryPointModule(JSHandle<SourceTextModule> currentModule)
{
RuntimeLockHolder locker(vm_->GetJSThread(), mutex_);
CString curName = currentModule->GetEcmaModuleRecordNameString();
ModuleLoadInfo *curModule = GetModuleLoadInfo(curName);
curModule->isUsed = true;
auto &upLevelInfo = curModule->upLevel;
CSet<CString> tmp;
upLevelInfo.emplace("EntryPoint", tmp);
}
void ModuleLogger::PrintSummary() const
{
std::string path;
if (!CreateResultFile(path)) {
LOG_ECMA(ERROR) << "open file fail, no log anymore";
}
std::ofstream fileHandle;
fileHandle.open(path, std::ios_base::app);
std::string start = "<----Summary----> Total file number: " + std::to_string(totalFileNumber_) + ", total time: " +
std::to_string(totalTime_) + "ms, including used file:" + std::to_string(usedFileNumber_) +
", cost time: " + std::to_string(usedFileTime_) + "ms, and unused file: " +
std::to_string(unusedFileNumber_) +", cost time: " + std::to_string(unusedFileTime_) + "ms\n";
fileHandle << start;
fileHandle.close();
}
void ModuleLogger::PrintUsedFileInfo() const
{
std::string path;
if (!OpenResultFile(path)) {
LOG_ECMA(ERROR) << "open file fail, no log anymore";
}
std::ofstream fileHandle;
fileHandle.open(path, std::ios_base::app);
std::string start = "<----used file start----> used file: " + std::to_string(usedFileNumber_) + ", cost time: "
+ std::to_string(usedFileTime_) + "ms\n";
fileHandle << start;
int32_t fileNumber = 1;
for (auto &i : jsModuleLoadInfo_) {
ModuleLoadInfo *info = i.second;
if (info->isUsed) {
std::string content = "used file " + std::to_string(fileNumber++) + ": " + i.first.c_str() +
", cost time: " + ToStringWithPrecision(info->time, THREE) + "ms\n";
fileHandle << content;
auto &upInfo = info->upLevel;
int32_t parentModuleCount = 1;
for (auto &k : upInfo) {
std::string parentInfoStr = " parentModule " + std::to_string(parentModuleCount++) +
": " + k.first.c_str() + " ";
for (auto &exportN : k.second) {
parentInfoStr += exportN + " ";
}
parentInfoStr += "\n";
fileHandle << parentInfoStr;
}
}
}
std::string end = "<----------used file end----------> \n";
fileHandle << end;
fileHandle.close();
}
void ModuleLogger::PrintUnusedFileInfo() const
{
std::string path;
if (!OpenResultFile(path)) {
LOG_ECMA(ERROR) << "open file fail, no log anymore";
}
std::ofstream fileHandle;
fileHandle.open(path, std::ios_base::app);
std::string start = "<----unused file start----> unused file: " + std::to_string(unusedFileNumber_) +
", cost time: " + std::to_string(unusedFileTime_) + "ms\n";
fileHandle << start;
int32_t fileNumber = 1;
for (auto &i : jsModuleLoadInfo_) {
ModuleLoadInfo *info = i.second;
if (!info->isUsed) {
std::string content = "unused file " + std::to_string(fileNumber++) + ": " + i.first.c_str() +
", cost time: " + ToStringWithPrecision(info->time, THREE) + "ms\n";
fileHandle << content;
int32_t parentNumber = 1;
CSet<CString> parents = info->parentModules;
for (auto &k : parents) {
std::string parent = " parentModule " + std::to_string(parentNumber++) +
": " + k.c_str() + "\n";
fileHandle << parent;
}
}
}
std::string end = "<----------unused file end----------> \n";
fileHandle << end;
fileHandle.close();
}
void ModuleLogger::ProcessModuleExecuteTime()
{
RuntimeLockHolder locker(vm_->GetJSThread(), mutex_);
totalFileNumber_ = jsModuleLoadInfo_.size();
double totalTime = 0;
double usedFileTime = 0;
double unusedFileTime = 0;
for (auto &i : jsModuleLoadInfo_) {
ModuleLoadInfo *info = i.second;
double time = info->time;
if (time > TWO_SECONDS) {
time = 0;
}
if (info->isUsed) {
usedFileNumber_++;
usedFileTime += time;
} else {
unusedFileNumber_++;
unusedFileTime += time;
}
totalTime += time;
}
totalTime_ = static_cast<int64_t>(totalTime);
usedFileTime_ = static_cast<int64_t>(usedFileTime);
unusedFileTime_ = static_cast<int64_t>(unusedFileTime);
}
ModuleLoadInfo *ModuleLogger::GetModuleLoadInfo(const CString &recordName)
{
auto info = jsModuleLoadInfo_.find(recordName);
if (info != jsModuleLoadInfo_.end()) {
return info->second;
}
ModuleLoadInfo *newInfo = new ModuleLoadInfo();
jsModuleLoadInfo_.emplace(recordName, newInfo);
return newInfo;
}
void ModuleLogger::SetStartTime(const CString &recordName)
{
RuntimeLockHolder locker(vm_->GetJSThread(), mutex_);
ModuleLoadInfo *info = GetModuleLoadInfo(recordName);
info->time = std::chrono::duration_cast<std::chrono::microseconds>
(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}
void ModuleLogger::SetEndTime(const CString &recordName)
{
RuntimeLockHolder locker(vm_->GetJSThread(), mutex_);
ModuleLoadInfo *info = GetModuleLoadInfo(recordName);
double time = info->time;
info->time = (std::chrono::duration_cast<std::chrono::microseconds>
(std::chrono::high_resolution_clock::now().time_since_epoch())
.count() - time) / DOUBLE_MILLISECONDS_PER_SEC;
}
std::string ModuleLogger::ToStringWithPrecision(const double num, const uint8_t n)
{
std::ostringstream out;
out << std::setprecision(n) << num;
return out.str();
}
void ModuleLogger::PostModuleLoggerTask(int32_t id, EcmaVM *vm)
{
Taskpool::GetCurrentTaskpool()->PostTask(
std::make_unique<ModuleLoggerTask>(id, vm));
}
bool ModuleLogger::ModuleLoggerTask::Run([[maybe_unused]]uint32_t threadIndex)
{
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "ModuleLoggerTask::Run");
std::this_thread::sleep_for(
std::chrono::microseconds(static_cast<int64_t>(TWO_SECONDS))); // 2s
ModuleLogger *moduleLogger =
vm_->GetJSThread()->GetCurrentEcmaContext()->GetModuleLogger();
moduleLogger->PrintModuleLoadInfo();
return true;
}
} // namespace panda::ecmascript

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 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_MODULE_MODULE_LOGGER_H
#define ECMASCRIPT_MODULE_MODULE_LOGGER_H
#include "ecmascript/module/js_module_source_text.h"
#include <fstream>
namespace panda::ecmascript {
struct ModuleLoadInfo {
bool isUsed {false};
CSet<CString> parentModules {};
CMap<CString, CSet<CString>> upLevel {}; // parent module and importName
double time {0};
};
class ModuleLogger {
public:
explicit ModuleLogger(EcmaVM *vm);
~ModuleLogger()
{
for (auto &info : jsModuleLoadInfo_) {
delete info.second;
}
jsModuleLoadInfo_.clear();
}
void SetStartTime(const CString &recordName);
void SetEndTime(const CString &recordName);
void PostModuleLoggerTask(int32_t id, EcmaVM *vm);
void InsertModuleLoadInfo(JSHandle<SourceTextModule> currentModule,
JSHandle<SourceTextModule> exportModule,
int32_t index);
void InsertParentModule(JSHandle<SourceTextModule> currentModule, JSHandle<SourceTextModule> requiredModule);
void InsertEntryPointModule(JSHandle<SourceTextModule> currentModule);
private:
static constexpr const int MILLISECONDS_PER_SEC = 1000;
static constexpr const double DOUBLE_MILLISECONDS_PER_SEC = 1000.0;
static constexpr const int TWO = 2;
static constexpr const int THREE = 3;
static constexpr const double TWO_SECONDS = TWO * MILLISECONDS_PER_SEC * MILLISECONDS_PER_SEC;
static constexpr const char FILEDIR[] = "/data/storage/el2/base/files/";
static constexpr const char SUFFIX[] = "_redundant_file.txt";
NO_COPY_SEMANTIC(ModuleLogger);
NO_MOVE_SEMANTIC(ModuleLogger);
bool CreateResultFile(std::string &path) const; // first time
bool OpenResultFile(std::string &path) const;
ModuleLoadInfo *GetModuleLoadInfo(const CString &recordName);
void PrintModuleLoadInfo();
void PrintSummary() const;
void PrintUsedFileInfo() const;
void PrintUnusedFileInfo() const;
void ProcessModuleExecuteTime();
static std::string ToStringWithPrecision(const double num, const uint8_t n);
EcmaVM *vm_ {nullptr};
CUnorderedMap<CString, ModuleLoadInfo*> jsModuleLoadInfo_ {};
uint32_t totalFileNumber_ {0};
uint32_t unusedFileNumber_ {0};
uint32_t usedFileNumber_ {0};
int64_t totalTime_ {0};
int64_t usedFileTime_ {0};
int64_t unusedFileTime_ {0};
Mutex mutex_;
class ModuleLoggerTask : public Task {
public:
ModuleLoggerTask(int32_t id, EcmaVM *vm)
: Task(id), vm_(vm) {}
~ModuleLoggerTask() override = default;
bool Run([[maybe_unused]]uint32_t threadIndex) override;
NO_COPY_SEMANTIC(ModuleLoggerTask);
NO_MOVE_SEMANTIC(ModuleLoggerTask);
private:
EcmaVM *vm_ {nullptr};
};
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_MODULE_MODULE_LOGGER_H

View File

@ -18,6 +18,7 @@
#include "ecmascript/jspandafile/js_pandafile_executor.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/module/js_shared_module.h"
#include "ecmascript/module/module_logger.h"
#include "ecmascript/require/js_cjs_module.h"
#include "ecmascript/module/module_path_helper.h"
#include "ecmascript/tagged_array-inl.h"
@ -87,50 +88,59 @@ JSTaggedValue ModuleManagerHelper::GetModuleValue(JSThread *thread, JSHandle<Sou
JSTaggedValue::Undefined())).GetTaggedValue();
}
JSTaggedValue ModuleManagerHelper::GetModuleValueFromIndexBinding(JSThread *thread, JSHandle<SourceTextModule> module,
JSTaggedValue ModuleManagerHelper::GetModuleValueFromIndexBinding(JSThread *thread,
JSHandle<SourceTextModule> module,
JSTaggedValue resolvedBinding)
{
JSHandle<ResolvedRecordIndexBinding> binding(thread, resolvedBinding);
JSHandle<SourceTextModule> resolvedModule = GetResolvedRecordIndexBindingModule(thread, module, binding);
return GetModuleValue(thread, resolvedModule, binding->GetIndex());
}
JSHandle<SourceTextModule> ModuleManagerHelper::GetResolvedRecordIndexBindingModule(
JSThread *thread, JSHandle<SourceTextModule> module, JSHandle<ResolvedRecordIndexBinding> binding)
{
JSHandle<JSTaggedValue> recordName(thread, binding->GetModuleRecord());
ASSERT(recordName->IsString());
// recordName is string, find at current vm
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
CString recordNameStr = ModulePathHelper::Utf8ConvertToString(recordName.GetTaggedValue());
JSHandle<SourceTextModule> resolvedModule;
if (moduleManager->IsEvaluatedModule(recordNameStr)) {
resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
} else {
if (!moduleManager->IsEvaluatedModule(recordNameStr)) {
auto isMergedAbc = !module->GetEcmaModuleRecordNameString().empty();
CString fileName = ModulePathHelper::Utf8ConvertToString((binding->GetAbcFileName()));
if (!JSPandaFileExecutor::LazyExecuteModule(thread, recordNameStr, fileName, isMergedAbc)) {
LOG_ECMA(FATAL) << "LazyExecuteModule failed";
}
resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
}
return GetModuleValue(thread, resolvedModule, binding->GetIndex());
return moduleManager->HostGetImportedModule(recordNameStr);
}
JSTaggedValue ModuleManagerHelper::GetModuleValueFromRecordBinding(JSThread *thread, JSHandle<SourceTextModule> module,
JSTaggedValue ModuleManagerHelper::GetModuleValueFromRecordBinding(JSThread *thread,
JSHandle<SourceTextModule> module,
JSTaggedValue resolvedBinding)
{
JSHandle<ResolvedRecordBinding> binding(thread, resolvedBinding);
JSHandle<SourceTextModule> resolvedModule = GetResolvedRecordBindingModule(thread, module, binding);
return GetModuleValue(thread, resolvedModule, binding->GetBindingName());
}
JSHandle<SourceTextModule> ModuleManagerHelper::GetResolvedRecordBindingModule(JSThread *thread,
JSHandle<SourceTextModule> module,
JSHandle<ResolvedRecordBinding> binding)
{
JSHandle<JSTaggedValue> recordName(thread, binding->GetModuleRecord());
ASSERT(recordName->IsString());
CString recordNameStr = ModulePathHelper::Utf8ConvertToString(recordName.GetTaggedValue());
// moduleRecord is string, find at current vm
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSHandle<SourceTextModule> resolvedModule;
if (moduleManager->IsEvaluatedModule(recordNameStr)) {
resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
} else {
if (!moduleManager->IsEvaluatedModule(recordNameStr)) {
auto isMergedAbc = !module->GetEcmaModuleRecordNameString().empty();
CString fileName = module->GetEcmaModuleFilenameString();
if (!JSPandaFileExecutor::LazyExecuteModule(thread, recordNameStr, fileName, isMergedAbc)) {
LOG_ECMA(FATAL) << "LazyExecuteModule failed";
}
resolvedModule = moduleManager->HostGetImportedModule(recordNameStr);
}
return GetModuleValue(thread, resolvedModule, binding->GetBindingName());
return moduleManager->HostGetImportedModule(recordNameStr);
}
JSTaggedValue ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(JSThread *thread,

View File

@ -42,6 +42,12 @@ public:
static JSTaggedValue PUBLIC_API GetModuleValueFromRecordBinding(JSThread *thread,
JSHandle<SourceTextModule> module,
JSTaggedValue resolvedBinding);
static JSHandle<SourceTextModule> GetResolvedRecordIndexBindingModule(
JSThread *thread, JSHandle<SourceTextModule> module, JSHandle<ResolvedRecordIndexBinding> binding);
static JSHandle<SourceTextModule> GetResolvedRecordBindingModule(
JSThread *thread, JSHandle<SourceTextModule> module, JSHandle<ResolvedRecordBinding> binding);
static JSTaggedValue GetLazyModuleValueFromIndexBinding(JSThread *thread,
JSHandle<SourceTextModule> module,

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 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.
*/
#include "ecmascript/module/module_tools.h"
#include "ecmascript/global_env.h"
#include "ecmascript/module/js_shared_module.h"
#include "ecmascript/module/module_logger.h"
#include "ecmascript/module/module_manager_helper.h"
#include "ecmascript/require/js_cjs_module.h"
namespace panda::ecmascript {
JSTaggedValue ModuleTools::GetModuleValueFromIndexBindingForLog(
JSThread *thread, JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index)
{
JSHandle<ResolvedRecordIndexBinding> binding(thread, resolvedBinding);
JSHandle<SourceTextModule> resolvedModule =
ModuleManagerHelper::GetResolvedRecordIndexBindingModule(thread, module, binding);
ModuleLogger *moduleLogger =
thread->GetCurrentEcmaContext()->GetModuleLogger();
moduleLogger->InsertModuleLoadInfo(module, resolvedModule, index);
return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetIndex());
}
// use for moduleLogger is not nullptr
JSTaggedValue ModuleTools::GetModuleValueFromRecordBindingForLog(
JSThread *thread, JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index)
{
JSHandle<ResolvedRecordBinding> binding(thread, resolvedBinding);
JSHandle<SourceTextModule> resolvedModule =
ModuleManagerHelper::GetResolvedRecordBindingModule(thread, module, binding);
ModuleLogger *moduleLogger =
thread->GetCurrentEcmaContext()->GetModuleLogger();
moduleLogger->InsertModuleLoadInfo(module, resolvedModule, index);
return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetBindingName());
}
// use for moduleLogger is not nullptr
JSTaggedValue ModuleTools::ProcessModuleLoadInfo(JSThread *thread, JSHandle<SourceTextModule> currentModule,
JSTaggedValue resolvedBinding, int32_t index)
{
ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
JSMutableHandle<JSTaggedValue> res(thread, thread->GlobalConstants()->GetUndefined());
if (resolvedBinding.IsResolvedIndexBinding()) {
ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
JSTaggedValue resolvedModule = binding->GetModule();
JSHandle<SourceTextModule> module(thread, resolvedModule);
ASSERT(resolvedModule.IsSourceTextModule());
// Support for only modifying var value of HotReload.
// Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord.
EcmaContext *context = thread->GetCurrentEcmaContext();
if (context->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
const JSHandle<JSTaggedValue> resolvedModuleOfHotReload =
context->FindPatchModule(module->GetEcmaModuleRecordNameString());
if (!resolvedModuleOfHotReload->IsHole()) {
resolvedModule = resolvedModuleOfHotReload.GetTaggedValue();
JSHandle<SourceTextModule> moduleOfHotReload(thread, resolvedModule);
moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
return ModuleManagerHelper::GetModuleValue(thread, moduleOfHotReload, binding->GetIndex());
}
}
moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex());
}
if (resolvedBinding.IsResolvedBinding()) {
ResolvedBinding *binding = ResolvedBinding::Cast(resolvedBinding.GetTaggedObject());
JSTaggedValue resolvedModule = binding->GetModule();
JSHandle<SourceTextModule> module(thread, resolvedModule);
if (SourceTextModule::IsNativeModule(module->GetTypes())) {
moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
thread, currentModule, module, index, binding->GetBindingName());
}
if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
moduleLogger->InsertModuleLoadInfo(currentModule, module, index);
return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
thread, currentModule, module, index, binding->GetBindingName());
}
}
if (resolvedBinding.IsResolvedRecordIndexBinding()) {
return GetModuleValueFromIndexBindingForLog(thread, currentModule, resolvedBinding, index);
}
if (resolvedBinding.IsResolvedRecordBinding()) {
return GetModuleValueFromRecordBindingForLog(thread, currentModule, resolvedBinding, index);
}
LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding";
UNREACHABLE();
}
JSTaggedValue ModuleTools::ProcessModuleNameSpaceLoadInfo(
JSThread *thread, JSHandle<SourceTextModule> currentModule, JSHandle<SourceTextModule> requiredModule)
{
ModuleTypes moduleType = requiredModule->GetTypes();
ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
// if requiredModule is Native module
if (SourceTextModule::IsNativeModule(moduleType)) {
moduleLogger->InsertModuleLoadInfo(currentModule, requiredModule, -1);
return SourceTextModule::Cast(requiredModule.GetTaggedValue())->GetModuleValue(thread, 0, false);
}
// if requiredModule is CommonJS
if (moduleType == ModuleTypes::CJS_MODULE) {
moduleLogger->InsertModuleLoadInfo(currentModule, requiredModule, -1);
CString cjsModuleName = SourceTextModule::GetModuleName(requiredModule.GetTaggedValue());
JSHandle<JSTaggedValue> moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName));
return CjsModule::SearchFromModuleCache(thread, moduleNameHandle).GetTaggedValue();
}
// if requiredModule is ESM
moduleLogger->InsertModuleLoadInfo(currentModule, requiredModule, -1);
JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModule);
ASSERT(moduleNamespace->IsModuleNamespace());
return moduleNamespace.GetTaggedValue();
}
} // namespace panda::ecmascript

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 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_MODULE_TOOLS_H
#define ECMASCRIPT_MODULE_TOOLS_H
#include "ecmascript/module/js_module_source_text.h"
namespace panda::ecmascript {
class ModuleTools {
public:
static JSTaggedValue GetModuleValueFromIndexBindingForLog(JSThread *thread,
JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index);
static JSTaggedValue GetModuleValueFromRecordBindingForLog(JSThread *thread,
JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding, int32_t index);
static JSTaggedValue ProcessModuleLoadInfo(JSThread *thread, JSHandle<SourceTextModule> currentModule,
JSTaggedValue resolvedBinding, int32_t index);
static JSTaggedValue ProcessModuleNameSpaceLoadInfo(JSThread *thread,
JSHandle<SourceTextModule> currentModule,
JSHandle<SourceTextModule> requiredModule);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_MODULE_MODULE_TOOLS_H