diff --git a/BUILD.gn b/BUILD.gn index 7a00f3610d603f6fc8d0156a6d2a75cbb42d1f84..55d9cf0cadd4988c61c7cda2d69d44b97dbba3c8 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -158,7 +158,7 @@ group("common_components_js_unittest") { if (ets_runtime_enable_cmc_gc) { deps += [ "common_components/base/tests:unittest", - "common_components/base_runtime/tests:unittest", + "common_components/common_runtime/tests:unittest", #"common_components/heap/allocator/tests:unittest", "common_components/heap/barrier/tests:unittest", @@ -180,7 +180,7 @@ group("common_components_unittest") { if (ets_runtime_enable_cmc_gc) { deps += [ "common_components/base/tests:host_unittest", - "common_components/base_runtime/tests:host_unittest", + "common_components/common_runtime/tests:host_unittest", #"common_components/heap/allocator/tests:host_unittest", "common_components/heap/barrier/tests:host_unittest", @@ -1428,8 +1428,8 @@ if (enable_target_compilation) { # Only use when cmc-gc enable ohos_source_set("libcommon_components_set") { sources = [ - "common_components/base_runtime/base_runtime.cpp", - "common_components/base_runtime/base_runtime_param.cpp", + "common_components/common_runtime/base_runtime.cpp", + "common_components/common_runtime/base_runtime_param.cpp", "common_components/heap/heap_allocator.cpp", "common_components/heap/heap_visitor.cpp", "common_components/profiler/heap_profiler_listener.cpp", diff --git a/common_components/BUILD.gn b/common_components/BUILD.gn index 4361398f53c2a5512d7fd8ea935080cb22dc01e9..9c5af8e92ed08a161ccd0e55956903847117337f 100755 --- a/common_components/BUILD.gn +++ b/common_components/BUILD.gn @@ -362,8 +362,8 @@ ohos_shared_library("libark_common_components_test") { configs = [ ":common_components_test_config" ] sources = [ - "base_runtime/base_runtime.cpp", - "base_runtime/base_runtime_param.cpp", + "common_runtime/base_runtime.cpp", + "common_runtime/base_runtime_param.cpp", "base/utf_helper.cpp", "heap/heap_allocator.cpp", "log/log.cpp", diff --git a/common_components/common_runtime/src/base/log_file.cpp b/common_components/common_runtime/base/log_file.cpp similarity index 99% rename from common_components/common_runtime/src/base/log_file.cpp rename to common_components/common_runtime/base/log_file.cpp index a64eca43557c46d5dbf7834f971149bbb596fb3d..db7d1033c74cfd1cba6c912ef53b62e18d66fd63 100644 --- a/common_components/common_runtime/src/base/log_file.cpp +++ b/common_components/common_runtime/base/log_file.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "common_components/common_runtime/src/base/log_file.h" +#include "common_components/common_runtime/base/log_file.h" #include diff --git a/common_components/common_runtime/src/base/log_file.h b/common_components/common_runtime/base/log_file.h similarity index 100% rename from common_components/common_runtime/src/base/log_file.h rename to common_components/common_runtime/base/log_file.h diff --git a/common_components/base_runtime/base_runtime.cpp b/common_components/common_runtime/base_runtime.cpp similarity index 98% rename from common_components/base_runtime/base_runtime.cpp rename to common_components/common_runtime/base_runtime.cpp index 677a06f353f5433abe7e07f96f6aae78ca9b622a..99c2793fe2d5ef624bed744b4c77b31594acfb3c 100755 --- a/common_components/base_runtime/base_runtime.cpp +++ b/common_components/common_runtime/base_runtime.cpp @@ -15,8 +15,8 @@ #include "common_interfaces/base_runtime.h" -#include "common_components/base_runtime/base_runtime_param.h" -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/base_runtime_param.h" +#include "common_components/common_runtime/hooks.h" #include "common_components/common/page_pool.h" #include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/collector/heuristic_gc_policy.h" diff --git a/common_components/base_runtime/base_runtime_param.cpp b/common_components/common_runtime/base_runtime_param.cpp similarity index 96% rename from common_components/base_runtime/base_runtime_param.cpp rename to common_components/common_runtime/base_runtime_param.cpp index e87e6473eef5e60248e00cb73525bad653172bff..51db0d92b07057e4134671362e81da84e8b5b458 100755 --- a/common_components/base_runtime/base_runtime_param.cpp +++ b/common_components/common_runtime/base_runtime_param.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "common_components/base_runtime/base_runtime_param.h" +#include "common_components/common_runtime/base_runtime_param.h" #include "common_components/platform/cpu.h" diff --git a/common_components/base_runtime/base_runtime_param.h b/common_components/common_runtime/base_runtime_param.h similarity index 100% rename from common_components/base_runtime/base_runtime_param.h rename to common_components/common_runtime/base_runtime_param.h diff --git a/common_components/base_runtime/hooks.h b/common_components/common_runtime/hooks.h similarity index 100% rename from common_components/base_runtime/hooks.h rename to common_components/common_runtime/hooks.h diff --git a/common_components/common_runtime/src/cpu_profiler/cpu_profiler.cpp b/common_components/common_runtime/src/cpu_profiler/cpu_profiler.cpp deleted file mode 100755 index d638ba98c4821777328dae74829bcabbbb6e1b1c..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/cpu_profiler/cpu_profiler.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2025 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 "common_components/common_runtime/src/cpu_profiler/cpu_profiler.h" - -#include "common_components/common_runtime/src/mutator/mutator_manager.h" - -namespace panda { -CpuProfiler::~CpuProfiler() -{ - TryStopSampling(); -} - -bool CpuProfiler::StartCpuProfilerForFile() -{ - if (generator_.GetIsStart()) { - LOG_COMMON(ERROR) << "Start CpuProfiler repeatedly."; - return false; - } - generator_.SetIsStart(true); - tid_ = std::thread(CpuProfiler::SamplingThread, std::ref(generator_)); - if (!tid_.joinable()) { - LOG_COMMON(ERROR) << "Failed to create sampling thread."; - return false; - } - return true; -} - -bool CpuProfiler::StopCpuProfilerForFile(const int fd) -{ - if (!generator_.GetIsStart()) { - LOG_COMMON(ERROR) << "CpuProfiler is not in profiling"; - return false; - } - bool ret = generator_.OpenFile(fd); - if (!ret) { - LOG_COMMON(ERROR) << "Open file failed"; - } - TryStopSampling(); - return ret; -} - -void CpuProfiler::TryStopSampling() -{ - if (!generator_.GetIsStart()) { - return; - } - generator_.SetIsStart(false); - if (tid_.joinable()) { - tid_.join(); - } -} - -void CpuProfiler::SamplingThread(SamplesRecord& generator) -{ - generator.InitProfileInfo(); - uint32_t interval = generator.GetSamplingInterval(); - uint64_t startTime = SamplesRecord::GetMicrosecondsTimeStamp(); - generator.SetThreadStartTime(startTime); - uint64_t endTime = startTime; - while (generator.GetIsStart()) { - startTime = SamplesRecord::GetMicrosecondsTimeStamp(); - int64_t ts = static_cast(interval) - static_cast(startTime - endTime); - endTime = startTime; - if (ts > 0) { - usleep(ts); - endTime = SamplesRecord::GetMicrosecondsTimeStamp(); - } - DoSampleStack(); - generator.ParseSampleData(endTime); - generator.DoSingleTask(endTime); - } - generator.RunTaskLoop(); - generator.SetSampleStopTime(SamplesRecord::GetMicrosecondsTimeStamp()); - generator.DumpProfileInfo(); - generator.ReleaseProfileInfo(); -} - -void CpuProfiler::DoSampleStack() -{ - MutatorManager::Instance().TransitionAllMutatorsToCpuProfile(); -} -} diff --git a/common_components/common_runtime/src/cpu_profiler/samples_record.cpp b/common_components/common_runtime/src/cpu_profiler/samples_record.cpp deleted file mode 100755 index aeafcb491dd779589cd49d7eb73f55910fab96e0..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/cpu_profiler/samples_record.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (c) 2025 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 "common_components/common_runtime/src/cpu_profiler/samples_record.h" -#include -#include "common_components/common_runtime/src/base/time_utils.h" - -namespace panda { -const int USEC_PER_SEC = 1000 * 1000; -const int NSEC_PER_USEC = 1000; -uint64_t SamplesRecord::GetMicrosecondsTimeStamp() -{ - struct timespec time; - clock_gettime(CLOCK_MONOTONIC, &time); - return time.tv_sec * USEC_PER_SEC + time.tv_nsec / NSEC_PER_USEC; -} - -SamplesRecord::~SamplesRecord() -{ - ReleaseProfileInfo(); -} - -void SamplesRecord::InitProfileInfo() -{ - profileInfo_ = new ProfileInfo(); - LOGF_CHECK(profileInfo_ != nullptr) << "new profileInfo fail"; - NodeInit(); -} - -void SamplesRecord::ReleaseProfileInfo() -{ - if (profileInfo_ != nullptr) { - delete profileInfo_; - profileInfo_ = nullptr; - } -} - -void SamplesRecord::NodeInit() -{ - CpuProfileNode methodNode; - - methodNode.id = ROOT_NODE_ID; - methodNode.parentId = UNKNOWN_NODE_ID; - methodNode.codeEntry.functionName = "(root)"; - profileInfo_->nodes[profileInfo_->nodeCount++] = methodNode; - profileInfo_->nodeSet.insert(methodNode); - - methodNode.id = PROGRAM_NODE_ID; - methodNode.parentId = ROOT_NODE_ID; - methodNode.codeEntry.functionName = "(program)"; - profileInfo_->nodes[profileInfo_->nodeCount++] = methodNode; - profileInfo_->nodes[ROOT_NODE_ID - 1].children.emplace_back(methodNode.id); - profileInfo_->nodeSet.insert(methodNode); - - methodNode.id = IDLE_NODE_ID; - methodNode.parentId = ROOT_NODE_ID; - methodNode.codeEntry.functionName = "(idle)"; - profileInfo_->nodes[profileInfo_->nodeCount++] = methodNode; - profileInfo_->nodes[ROOT_NODE_ID - 1].children.emplace_back(methodNode.id); - profileInfo_->nodeSet.insert(methodNode); -} - -uint64_t SamplesRecord::UpdateScriptIdMap(CString& url) -{ - auto iter = scriptIdMap_.find(url); - if (iter == scriptIdMap_.end()) { - scriptIdMap_.emplace(url, scriptIdMap_.size() + 1); - return static_cast(scriptIdMap_.size()); - } else { - return iter->second; - } -} - -bool SamplesRecord::UpdateNodeMap(ProfileInfo* info, CpuProfileNode& methodNode) -{ - auto& nodSet = info->nodeSet; - auto result = nodSet.find(methodNode); - if (result == nodSet.end()) { - info->previousId = methodNode.id = nodSet.size() + 1; - nodSet.insert(methodNode); - return true; - } else { - info->previousId = methodNode.id = result->id; - return false; - } -} - -void SamplesRecord::AddNodes(ProfileInfo* info, CpuProfileNode& methodNode) -{ - info->nodes[info->nodeCount++] = methodNode; - if (methodNode.parentId > 0 && methodNode.parentId <= info->nodeCount) { - info->nodes[methodNode.parentId - 1].children.emplace_back(methodNode.id); - } -} - -int SamplesRecord::GetSampleNodeId(uint64_t previousId, uint64_t topFrameNodeId) -{ - return previousId == 0 ? ROOT_NODE_ID : topFrameNodeId; -} - -uint64_t SamplesRecord::GetPreviousTimeStamp(uint64_t previousTimeStamp, uint64_t startTime) -{ - return previousTimeStamp == 0 ? startTime : previousTimeStamp; -} - -void SamplesRecord::DeleteAbnormalSample(ProfileInfo* info, int timeDelta) -{ - if (timeDelta > static_cast(timeDeltaThreshold_)) { - uint32_t size = info->samples.size(); - if (size > 0) { - info->samples[size - 1] = PROGRAM_NODE_ID; - } - info->previousState = FrameType::UNKNOWN; - } -} - -void SamplesRecord::SetPreviousState(ProfileInfo* info, FrameType frameType) -{ - info->previousState = frameType; -} - -void SamplesRecord::IncreaseNodeHitCount(ProfileInfo* info, int sampleNodeId) -{ - info->nodes[sampleNodeId - 1].hitCount++; -} - -void SamplesRecord::AddSampleNodeId(ProfileInfo* info, int sampleNodeId) -{ - info->samples.emplace_back(sampleNodeId); -} - -void SamplesRecord::AddTimeDelta(ProfileInfo* info, int timeDelta) -{ - info->timeDeltas.emplace_back(timeDelta); -} - -void SamplesRecord::SetPreviousTimeStamp(ProfileInfo* info, uint64_t timeStamp) -{ - info->previousTimeStamp = timeStamp; -} - -ProfileInfo* SamplesRecord::GetProfileInfo(uint64_t mutatorId) -{ - if (profileInfo_->mutatorId != mutatorId) { - profileInfo_->mutatorId = mutatorId; - } - return profileInfo_; -} - -void SamplesRecord::AddSample(SampleTask& task) -{ - ProfileInfo* info = GetProfileInfo(task.mutatorId); - if (info->nodeCount >= MAX_NODE_COUNT) { - LOG_COMMON(WARN) << "CpuProfileNode counts over 20000."; - return; - } - std::vector codeInfos = GetCodeInfos(task); - int frameSize = codeInfos.size(); - CpuProfileNode methodNode; - methodNode.id = 1; - for (; frameSize >= 1; frameSize--) { - methodNode.codeEntry = codeInfos[frameSize - 1]; - methodNode.parentId = methodNode.id; - if (UpdateNodeMap(info, methodNode)) { - AddNodes(info, methodNode); - } - } - int sampleNodeId = GetSampleNodeId(info->previousId, methodNode.id); - uint64_t previousTimeStamp = GetPreviousTimeStamp(info->previousTimeStamp, info->startTime); - int timeDelta = static_cast(task.timeStamp - previousTimeStamp); - - DeleteAbnormalSample(info, timeDelta); - - StatisticStateTime(info, timeDelta); - - SetPreviousState(info, codeInfos.front().frameType); - - IncreaseNodeHitCount(info, sampleNodeId); - - AddSampleNodeId(info, sampleNodeId); - - AddTimeDelta(info, timeDelta); - - SetPreviousTimeStamp(info, task.timeStamp); -} - -void SamplesRecord::AddEmptySample(SampleTask& task) -{ - ProfileInfo* info = GetProfileInfo(task.mutatorId); - uint64_t previousTimeStamp = GetPreviousTimeStamp(info->previousTimeStamp, info->startTime); - int timeDelta = static_cast(task.timeStamp - previousTimeStamp); - - DeleteAbnormalSample(info, timeDelta); - - StatisticStateTime(info, timeDelta); - - SetPreviousState(info, FrameType::UNKNOWN); - - IncreaseNodeHitCount(info, ROOT_NODE_ID); - - AddSampleNodeId(info, IDLE_NODE_ID); - - AddTimeDelta(info, timeDelta); - - SetPreviousTimeStamp(info, task.timeStamp); -} - -void SamplesRecord::StatisticStateTime(ProfileInfo* info, int timeDelta) -{ - FrameType state = info->previousState; - switch (state) { - case FrameType::MANAGED: { - info->managedTime += static_cast(timeDelta); - break; - } - default: { - info->unknownTime += static_cast(timeDelta); - } - } -} - -void SamplesRecord::StringifySampleData(ProfileInfo* info) -{ - sampleData_ = ""; - sampleData_.Append(CString::FormatString("{\"mutatorId\":%d,", info->mutatorId)); - sampleData_.Append(CString::FormatString("\"startTime\":%llu,", info->startTime)); - sampleData_.Append(CString::FormatString("\"endTime\":%llu,", info->stopTime)); - - StringifyStateTimeStatistic(info); - StringifyNodes(info); - StringifySamples(info); -} - -void SamplesRecord::StringifyStateTimeStatistic(ProfileInfo* info) -{ - sampleData_.Append(CString::FormatString("\"managedTime\":%llu,", info->managedTime)); - sampleData_.Append(CString::FormatString("\"unknownTime\":%llu,", info->unknownTime)); -} - -void SamplesRecord::StringifyNodes(ProfileInfo* info) -{ - sampleData_.Append("\"nodes\":["); - size_t nodeCount = static_cast(info->nodeCount); - - for (size_t i = 0; i < nodeCount; i++) { - struct CpuProfileNode& node = info->nodes[i]; - struct CodeInfo& codeEntry = node.codeEntry; - sampleData_.Append(CString::FormatString("{\"id\":%d,", node.id)); - sampleData_.Append("\"callFrame\":{\"functionName\":\""); - sampleData_.Append(codeEntry.functionName); - sampleData_.Append(CString::FormatString("\",\"scriptId\":\"%d\",", codeEntry.scriptId)); - sampleData_.Append("\"url\":\""); - sampleData_.Append(codeEntry.url); - sampleData_.Append(CString::FormatString("\",\"lineNumber\":%d},", codeEntry.lineNumber)); - sampleData_.Append(CString::FormatString("\"hitCount\":%d,\"children\":[", node.hitCount)); - - std::vector children = node.children; - size_t childrenCount = children.size(); - for (size_t j = 0; j < childrenCount; j++) { - sampleData_.Append(CString::FormatString("%d,", children[j])); - } - if (childrenCount > 0) { - sampleData_ = sampleData_.SubStr(0, sampleData_.Length() - 1); - } - sampleData_ += "]},"; - } - sampleData_ = sampleData_.SubStr(0, sampleData_.Length() - 1); - sampleData_ += "],"; -} - -void SamplesRecord::StringifySamples(ProfileInfo* info) -{ - std::vector& samples = info->samples; - std::vector& timeDeltas = info->timeDeltas; - - size_t samplesCount = samples.size(); - if (samplesCount == 0) { - sampleData_.Append("\"samples\":[],\"timeDeltas\":[]}"); - return; - } - CString samplesIdStr = ""; - CString timeDeltasStr = ""; - for (size_t i = 0; i < samplesCount; i++) { - samplesIdStr.Append(CString::FormatString("%d,", samples[i])); - timeDeltasStr.Append(CString::FormatString("%d,", timeDeltas[i])); - } - - samplesIdStr = samplesIdStr.SubStr(0, samplesIdStr.Length() - 1); - timeDeltasStr = timeDeltasStr.SubStr(0, timeDeltasStr.Length() - 1); - - sampleData_.Append("\"samples\":["); - sampleData_.Append(samplesIdStr); - sampleData_.Append("],\"timeDeltas\":["); - sampleData_.Append(timeDeltasStr); - sampleData_.Append("]}"); -} - -void SamplesRecord::DumpProfileInfo() -{ - StringifySampleData(profileInfo_); - WriteFile(); -} - -bool SamplesRecord::OpenFile(int fd) -{ - if (fd == -1) { - return false; - } - - if (ftruncate(fd, 0) == -1) { - return false; - } - fileDesc_ = fd; - return true; -} - -void SamplesRecord::WriteFile() -{ - int err = write(fileDesc_, sampleData_.Str(), sampleData_.Length()); - if (err == -1) { - LOG_COMMON(ERROR) << "Write file failed. msg: " << strerror(errno); - } -} - -void SamplesRecord::RunTaskLoop() -{ - while (!taskQueue_.empty()) { - auto task = taskQueue_.front(); - taskQueue_.pop_front(); - if (task.frameCnt == 0) { - AddEmptySample(task); - } else { - AddSample(task); - } - } -} - -void SamplesRecord::DoSingleTask(uint64_t previousTimeStemp) -{ - if (IsTimeout(previousTimeStemp)) { - return; - } - if (taskQueue_.empty()) { - return; - } - auto task = taskQueue_.front(); - if (!task.finishParsed) { - return; - } - taskQueue_.pop_front(); - if (task.frameCnt == 0) { - AddEmptySample(task); - } else { - AddSample(task); - } -} - -void SamplesRecord::ParseSampleData(uint64_t previousTimeStemp) -{ - if (taskQueue_.empty()) { - return; - } - for (auto& task : taskQueue_) { - if (task.finishParsed) { - continue; - } - for (int i = task.checkPoint; i < task.frameCnt; ++i) { - GetDemangleName(task.funcDescRefs[i]); - GetUrl(task.funcDescRefs[i]); - if (IsTimeout(previousTimeStemp)) { - task.checkPoint = i + 1; - return; - } - } - task.finishParsed = true; - } -} - -bool SamplesRecord::IsTimeout(uint64_t previousTimeStemp) -{ - uint64_t currentTimeStamp = SamplesRecord::GetMicrosecondsTimeStamp(); - int64_t ts = static_cast(interval_) - - static_cast(currentTimeStamp - previousTimeStemp); - if (ts < 0) { - return true; - } - return false; -} - -void SamplesRecord::Post(uint64_t mutatorId, std::vector& FuncDescRefs, - std::vector& FrameTypes, std::vector& LineNumbers) -{ - uint64_t timeStamp = SamplesRecord::GetMicrosecondsTimeStamp(); - SampleTask task(timeStamp, mutatorId, FuncDescRefs, FrameTypes, LineNumbers); - taskQueue_.push_back(task); -} - -std::vector SamplesRecord::GetCodeInfos(SampleTask& task) -{ - std::vector codeInfos; - for (int i = 0; i < task.frameCnt; ++i) { - CodeInfo codeInfo; - codeInfo.lineNumber = task.lineNumbers[i]; - codeInfo.frameType = task.frameTypes[i]; - codeInfo.funcIdentifier = task.funcDescRefs[i]; - codeInfo.functionName = GetDemangleName(codeInfo.funcIdentifier); - codeInfo.url = GetUrl(codeInfo.funcIdentifier); - codeInfo.scriptId = UpdateScriptIdMap(codeInfo.url); - codeInfos.emplace_back(codeInfo); - } - return codeInfos; -} - -CString SamplesRecord::GetUrl(uint64_t funcIdentifier) -{ - if (identifierUrlMap_.find(funcIdentifier) != identifierUrlMap_.end()) { - return identifierUrlMap_[funcIdentifier]; - } - return ParseUrl(funcIdentifier); -} - -CString SamplesRecord::ParseUrl(uint64_t funcIdentifier) { return CString(); } - -CString SamplesRecord::GetDemangleName(uint64_t funcIdentifier) -{ - if (identifierFuncnameMap_.find(funcIdentifier) != identifierFuncnameMap_.end()) { - return identifierFuncnameMap_[funcIdentifier]; - } - return ParseDemangleName(funcIdentifier); -} - -CString SamplesRecord::ParseDemangleName(uint64_t funcIdentifier) -{ - LOG_COMMON(FATAL) << "Unresolved fatal"; - UNREACHABLE_CC(); -} -} diff --git a/common_components/common_runtime/src/cpu_profiler/samples_record.h b/common_components/common_runtime/src/cpu_profiler/samples_record.h deleted file mode 100755 index 8c71d5d6d041b10075b4ca9f0572402606351689..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/cpu_profiler/samples_record.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2025 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 ARK_COMMON_SAMPLES_RECORD_H -#define ARK_COMMON_SAMPLES_RECORD_H - -#include -#include -#include -#include -#include - -#include "common_components/common_runtime/src/base/c_string.h" - -namespace panda { -constexpr int MAX_NODE_COUNT = 20000; // 20000:the maximum size of the array -constexpr int UNKNOWN_NODE_ID = 0; // 0: the (root) node parent id -constexpr int ROOT_NODE_ID = 1; // 1: the (root) node id -constexpr int PROGRAM_NODE_ID = 2; // 2: the (program) node id -constexpr int IDLE_NODE_ID = 3; // 3: the (idel) node id - -struct CodeInfo { - uint64_t funcIdentifier = 0; - uint64_t scriptId = 0; - uint32_t lineNumber = 0; - CString functionName = ""; - CString url = ""; -}; - -struct CpuProfileNode { - uint64_t id = 0; - uint64_t parentId = 0; - uint64_t hitCount = 0; - struct CodeInfo codeEntry; - std::vector children; - - bool operator < (const CpuProfileNode& node) const - { - return parentId < node.parentId || (parentId == node.parentId && codeEntry < node.codeEntry); - } -}; - -struct ProfileInfo { - uint64_t mutatorId = 0; - uint64_t startTime = 0; - uint64_t stopTime = 0; - uint64_t nodeCount = 0; - - CpuProfileNode nodes[MAX_NODE_COUNT]; - std::vector samples; - std::vector timeDeltas; - - std::set nodeSet; - uint64_t previousTimeStamp = 0; - uint64_t previousId = 0; - - // state time statistic - uint64_t managedTime = 0; - uint64_t unknownTime = 0; -}; - -class SampleTask { -public: - uint64_t timeStamp; - uint64_t mutatorId; - std::vector funcDescRefs; - std::vector lineNumbers; - uint64_t frameCnt; - bool finishParsed {false}; - int checkPoint {0}; -}; - -class SamplesRecord { -public: - SamplesRecord() {} - ~SamplesRecord(); - void InitProfileInfo(); - void ReleaseProfileInfo(); - void SetIsStart(bool started) { isStart_.store(started); } - bool GetIsStart() const { return isStart_.load(); } - void SetThreadStartTime(uint64_t threadStartTime) { profileInfo_->startTime = threadStartTime; } - void SetSampleStopTime(uint64_t threadStopTime) { profileInfo_->stopTime = threadStopTime; } - void AddSample(SampleTask& task); - void AddEmptySample(SampleTask& task); - void StringifySampleData(ProfileInfo* info); - void DumpProfileInfo(); - void RunTaskLoop(); - void DoSingleTask(uint64_t previousTimeStemp); - void ParseSampleData(uint64_t previousTimeStemp); - std::vector BuildCodeInfos(SampleTask* task); - int GetSamplingInterval() { return interval_; } - bool OpenFile(int fd); - static uint64_t GetMicrosecondsTimeStamp(); - -private: - void StatisticStateTime(ProfileInfo* info, int timeDelta); - void NodeInit(); - void StringifyStateTimeStatistic(ProfileInfo* info); - void StringifyNodes(ProfileInfo* info); - void StringifySamples(ProfileInfo* info); - uint64_t UpdateScriptIdMap(CString& url); - bool UpdateNodeMap(ProfileInfo* info, CpuProfileNode& methodNode); - void AddNodes(ProfileInfo* info, CpuProfileNode& methodNode); - int GetSampleNodeId(uint64_t previousId, uint64_t topFrameNodeId); - uint64_t GetPreviousTimeStamp(uint64_t previousTimeStamp, uint64_t startTime); - void DeleteAbnormalSample(ProfileInfo* info, int timeDelta); - void IncreaseNodeHitCount(ProfileInfo* info, int sampleNodeId); - void AddSampleNodeId(ProfileInfo* info, int sampleNodeId); - void AddTimeDelta(ProfileInfo* info, int timeDelta); - void SetPreviousTimeStamp(ProfileInfo* info, uint64_t timeStamp); - std::vector GetCodeInfos(SampleTask& task); - CString GetUrl(uint64_t funcIdentifier); - CString ParseUrl(uint64_t funcIdentifier); - CString GetDemangleName(uint64_t funcIdentifier); - CString ParseDemangleName(uint64_t funcIdentifier); - void WriteFile(); - bool IsTimeout(uint64_t previousTimeStemp); - ProfileInfo* GetProfileInfo(uint64_t mutatorId); - - int fileDesc_{ -1 }; - uint32_t timeDeltaThreshold_{ 2000 }; // 2000 : default timeDeltaThreshold 2000us - std::atomic_bool isStart_{ false }; - CString sampleData_{ "" }; - std::list taskQueue_; - ProfileInfo* profileInfo_{ nullptr }; - std::map scriptIdMap_{ { "", 0 } }; - int interval_{ 500 }; // 500 : default interval 500us - std::map identifierFuncnameMap_; - std::map identifierUrlMap_; -}; -} // namespace panda -#endif diff --git a/common_components/common_runtime/src/inspector/alloc_data.cpp b/common_components/common_runtime/src/inspector/alloc_data.cpp deleted file mode 100755 index b2242d15ab03761db9b019ff61e6d3dff0dacc55..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/alloc_data.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (c) 2025 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 "common_components/common_runtime/src/inspector/alloc_data.h" -#include -#include -#include -#include -#include "common_components/common_runtime/src/common/stack_type.h" -#include "common_components/common_runtime/src/unwind_stack/print_stack_info.h" -#include "common_components/common_runtime/src/unwind_stack/stack_info.h" -#include "common_components/common_runtime/src/unwind_stack/stack_metadata_helper.h" -#include "common_components/common_runtime/src/inspector/file_stream.h" - -namespace panda { -static ArkAllocData* g_allocInfo; -ArkAllocData* ArkAllocData::GetArkAllocData() -{ - if (g_allocInfo == nullptr) { - g_allocInfo = new ArkAllocData(); - } - return g_allocInfo; -} - -void ArkAllocData::SetArkAllocData() -{ - g_allocInfo -> InitAllocParam(); -} - -TraceNodeField* ArkAllocData::FindNode(const FrameAddress* ptr, const char* str) -{ - if (str == nullptr) { - return nullptr; - }; - size_t key = FindKey(ptr, str); - auto iter = traceNodeMap_.find(key); - if (iter != traceNodeMap_.end()) { - return iter->second; - } else { - return nullptr; - } -} - -int32_t ArkAllocData::FindKey(const FrameAddress* ptr, const char* str) -{ - // The identifier of a stack frame depends on the FA of the frame and the name of the frame. - std::size_t hash1 = std::hash{}(ptr); - std::size_t hash2 = std::hash{}(str); - return hash1 ^ hash2; -} - -void ArkAllocData::DeleteArkAllocData() -{ - std::unique_lock lock(sharedMtx_); - SetRecording(false); - HeapProfilerStream* stream = &panda::HeapProfilerStream::GetInstance(); - stream->SetContext(ALLOCATION); - g_allocInfo->SerializeArkAllocData(); - for (auto sample : g_allocInfo->samples_) { - delete sample; - sample = nullptr; - } - samples_.clear(); - for (auto traceInfo : g_allocInfo->traceFunctionInfo_) { - delete traceInfo; - traceInfo = nullptr; - } - traceFunctionInfo_.clear(); - g_allocInfo->DeleteAllNode(g_allocInfo->traceNodeHead_); - delete g_allocInfo->writer_; -} - -void ArkAllocData::DeleteAllNode(TraceNodeField* node) -{ - for (size_t i = 0; i < node->children.size(); i++) { - DeleteAllNode(node->children[i]); - } - delete node; -} - -void ArkAllocData::SerializeArkAllocData() -{ - writer_->WriteString("{\\\"head\\\":"); - // 1. dump callFrame - SerializeCallFrames(); - writer_->WriteString(","); - // 2. dump samples - SerializeSamples(); - writer_->WriteChar('}'); - writer_->End(); -} - -void ArkAllocData::SerializeCallFrames() { SerializeEachFrame(traceNodeHead_); } - -void ArkAllocData::SerializeFunctionInfo(int32_t idx) -{ - writer_->WriteString("{\\\"functionName\\\":\\\""); - writer_->WriteString(traceFunctionInfo_[idx]->functionName); - writer_->WriteString("\\\",\\\"scriptName\\\":\\\""); - writer_->WriteString(traceFunctionInfo_[idx]->scriptName); - writer_->WriteString("\\\",\\\"lineNumber\\\":"); - writer_->WriteNumber(traceFunctionInfo_[idx]->line); - writer_->WriteString(",\\\"columnNumber\\\":"); - writer_->WriteNumber(traceFunctionInfo_[idx]->column); - writer_->WriteChar('}'); -} - -void ArkAllocData::SerializeEachFrame(TraceNodeField* node) -{ - writer_->WriteString("{\\\"callFrame\\\":"); - SerializeFunctionInfo(node->functionInfoIndex); - writer_->WriteChar(','); - writer_->WriteString("\\\"selfSize\\\":"); - writer_->WriteNumber(node->selfSize); - writer_->WriteString(",\\\"id\\\":"); - writer_->WriteNumber(node->id); - writer_->WriteString(",\\\"children\\\":["); - if (node->children.size() != 0) { - for (size_t i = 0; i < node->children.size(); i++) { - SerializeEachFrame(node->children[i]); - if (i < node->children.size() - 1) { - writer_->WriteChar(','); - } - } - } - writer_->WriteChar(']'); - writer_->WriteChar('}'); -} - -void ArkAllocData::SerializeSamples() -{ - writer_->WriteString("\\\"samples\\\":["); - // for each sample - for (size_t i = 0; i < samples_.size(); i++) { - if (i != 0) { - writer->WriteChar(','); - } - writer->WriteString("{\\\"size\\\":"); - writer->WriteNumber(samples_[i]->size); - writer->WriteChar(','); - writer->WriteString("\\\"nodeId\\\":"); - writer->WriteNumber(samples_[i]->nodeId); - writer->WriteChar(','); - writer->WriteString("\\\"ordinal\\\":"); - writer->WriteNumber(samples_[i]->orinal); - writer->WriteChar('}'); - } - writer_->WriteChar(']'); -} -void ArkAllocData::InitRoot() -{ - TraceNodeField* traceNode = new TraceNodeField(); - if (traceNode == nullptr) { - LOG_COMMON(ERROR) << "init traceNode failed"; - return; - } - traceNode->id = 0; - traceNode->functionInfoIndex = 0; - traceNode->selfSize = 0; - traceNodeHead_ = traceNode; - TraceFunctionInfo* traceFunction = new TraceFunctionInfo(); - if (traceFunction == nullptr) { - LOG_COMMON(ERROR) << "init traceFunction failed"; - return; - } - traceFunction->functionName = "{root}"; - traceFunction->scriptName = ""; - traceFunction->line = -1; - ArkAllocData::GetArkAllocData()->traceFunctionInfo_.push_back(traceFunction); -} - -void ArkAllocData::InitAllocParam() -{ - sampSize_ = 1 * 1024; // default 1 * 1024 b - InitRoot(); - HeapProfilerStream* stream = &panda::HeapProfilerStream::GetInstance(); - writer_ = new StreamWriter(stream); -} - -void ArkAllocData::SerializeStats() -{ - HeapProfilerStream* stream = &panda::HeapProfilerStream::GetInstance(); - stream->SetContext(STATSUPDATE); - writer_->WriteString("["); - writer_->WriteNumber(traceNodeID_); - writer_->WriteChar(','); - writer_->WriteNumber(0); - writer_->WriteChar(','); - ssize_t allocatedSize = panda::Heap::GetHeap().GetAllocatedSize(); - writer_->WriteNumber(allocatedSize); - writer_->WriteString("]"); - writer_->End(); -} - -void ArkAllocData::RecordAllocNodes(const TypeInfo* klass, uint32_t size) -{ - std::unique_lock lock(sharedMtx_); - if (!IsRecording()) { // avoid delete func was called at this time - return; - } - allocSize_ += size; - if (allocSize < sampSize_) { - return; - } else { - AllocStackInfo* allocStackInfo = new AllocStackInfo(); - allocStackInfo->ProcessStackTrace(size); - delete allocStackInfo; - allocSize_ = 0; - SerializeStats(); - } -} - -int32_t AllocStackInfo::ProcessTraceInfo(FrameInfo &frame) -{ - if (frame.GetFrameType() == FrameType::NATIVE) { - return -1; - } - TraceFunctionInfo* traceFunction = new TraceFunctionInfo(); - if (frame.GetFrameType() == FrameType::MANAGED) { - StackMetadataHelper stackMetadataHelper(frame); - traceFunction->scriptName = frame.GetFileName(); - traceFunction->scriptName.ReplaceAll("/", "\\"); - traceFunction->functionName = frame.GetFuncName(); - traceFunction->line = stackMetadataHelper.GetLineNumber(); - } else { - delete traceFunction; - return -1; - } - - ArkAllocData::GetArkAllocData()->traceFunctionInfo_.push_back(traceFunction); - int32_t functionInfoIndex = ArkAllocData::GetArkAllocData()->traceFunctionInfo_.size() - 1; - return functionInfoIndex; -} - -void AllocStackInfo::ProcessTraceNode(TraceNodeField* head, uint32_t allocSize) -{ - // Initialize nodes and fill nodes in head in sequence. - if (frames_.empty()) { - // This node is the root node. - head->selfSize += allocSize; - return; - } - while (!frames_.empty()) { - FrameInfo* f = frames_.top(); - frames_.pop(); - TraceNodeField* traceNode = new TraceNodeField(); - traceNode->id = ArkAllocData::GetArkAllocData()->SetNodeID(); - traceNode->functionInfoIndex = ProcessTraceInfo(*f); - if (traceNode->functionInfoIndex == -1) { - delete traceNode; - continue; - } - traceNode->selfSize = 0; - // Add the children node of the upper-level node. - head->children.push_back(traceNode); - // In this case, head becomes a child node. Used to insert a child node next time. - head = traceNode; - // Add to the map for next search. - FrameAddress* FA = f->mFrame.GetFA(); - size_t key = ArkAllocData::GetArkAllocData()->FindKey(FA, f->GetFuncName().Str()); - ArkAllocData::GetArkAllocData()->traceNodeMap_.insert(std::pair(key, traceNode)); - delete f; - f = nullptr; - } - head->selfSize += allocSize; -} -void AllocStackInfo::ProcessStackTrace(uint32_t size) -{ - UnwindContext uwContext; - // Top unwind context can only be runtime or Arkcommon context. - CheckTopUnwindContextAndInit(uwContext); - while (!uwContext.frameInfo.mFrame.IsAnchorFrame(anchorFA)) { - AnalyseAndSetFrameType(uwContext); - FrameInfo* f = new FrameInfo(uwContext.frameInfo); - // 1. If the node has been recorded, add the content in the stack to the end of the node. - FrameAddress* FA = f->mFrame.GetFA(); - TraceNodeField* node = ArkAllocData::GetArkAllocData()->FindNode(FA, f->GetFuncName().Str()); - if (node != nullptr) { - delete f; - ProcessTraceNode(node, size); - return; - } - frames_.push(f); - UnwindContext caller; - lastFrameType = uwContext.frameInfo.GetFrameType(); -#ifndef _WIN64 - if (uwContext.UnwindToCallerContext(caller) == false) { -#else - if (uwContext.UnwindToCallerContext(caller, uwCtxStatus_) == false) { -#endif - return; - } - uwContext = caller; - } - // 2. If the stack back is not recorded, the call chain is a new call chain and the root node is the root node. - ProcessTraceNode(ArkAllocData::GetArkAllocData()->traceNodeHead_, size); - - // 3. Record the samples at this time. - Sample* sample = new Sample(); - sample->size = size; - sample->nodeId = ArkAllocData::GetArkAllocData()->traceFunctionInfo_.size(); - auto now = std::chrono::system_clock::now(); - auto timestamp = std::chrono::duration_cast(now.time_since_epoch()).count(); - sample->orinal = static_cast(timestamp); - ArkAllocData::GetArkAllocData()->samples_.push_back(sample); -} -} diff --git a/common_components/common_runtime/src/inspector/alloc_data.h b/common_components/common_runtime/src/inspector/alloc_data.h deleted file mode 100755 index ded843e6576bedbdbcaba956221707217923f309..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/alloc_data.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2025 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 ARK_COMMON_ALLOC_DATA_H -#define ARK_COMMON_ALLOC_DATA_H -#include "common_components/common_runtime/src/unwind_stack/gc_stack_info.h" -#include "common_components/common_runtime/src/inspector/heap_data.h" -#include "common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.h" -namespace panda { -struct TraceFunctionInfo { - CString functionName; - CString scriptName; - CString url = ""; - int32_t line; - int32_t column = -1; -}; - -struct TraceNodeField { - int32_t id = 0; // Unique ID - int32_t functionInfoIndex; - int32_t selfSize; - std::vector children; -}; - -struct Sample { - int32_t size; - int32_t nodeId; - int32_t orinal; -}; - -class ArkAllocData { -public: - static ArkAllocData* GetArkAllocData(); - static void SetArkAllocData(); - TraceNodeField* FindNode(const FrameAddress*, const char*); - int32_t FindKey(const FrameAddress*, const char*); - void DeleteArkAllocData(); - bool IsRecording() { return recording_.load(); }; - void SetRecording(bool isRecording) { recording_.store(isRecording, std::memory_order_release); }; - void DeleteAllNode(TraceNodeField* node); - void SerializeArkAllocData(); - void SerializeSamples(); - void SerializeCallFrames(); - void SerializeStats(); - void SerializeFunctionInfo(int32_t idx); - void SerializeEachFrame(TraceNodeField* node); - void InitAllocParam(); - void InitRoot(); - void RecordAllocNodes(const TypeInfo* klass, uint32_t size); - int32_t SetNodeID() { return ++traceNodeID_; }; - friend class AllocStackInfo; -private: - std::unordered_map traceNodeMap_; - TraceNodeField* traceNodeHead_; // ROOT node - std::vector samples_; - std::vector traceFunctionInfo_; - int32_t sampSize_; - int32_t allocSize_; - int32_t traceNodeID_ = 0; - StreamWriter* writer_ = nullptr; - std::atomic recording_{ false }; - std::mutex sharedMtx_; -}; - -class AllocStackInfo : public GCStackInfo { -public: - int32_t ProcessTraceInfo(FrameInfo &frame); - void ProcessTraceNode(TraceNodeField* head, uint32_t allocSize); - void ProcessStackTrace(uint32_t size); -private: - std::stack frames_; -}; - -} // namespace panda -#endif diff --git a/common_components/common_runtime/src/inspector/file_stream.cpp b/common_components/common_runtime/src/inspector/file_stream.cpp deleted file mode 100755 index be1cbd252ce0772400f75a5af66e5511ed795a22..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/file_stream.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include -#include -#include -#include -#include -#include "common_components/common_runtime/src/base/log_file.h" -#include "common_components/common_runtime/src/inspector/file_stream.h" - -namespace panda { -void HeapProfilerStream::SetHandler(SendMsgCB sendMsgInit) -{ - if (sendMsg_ != nullptr) { - return; - } - sendMsg_ = sendMsgInit; -} -bool HeapProfilerStream::SetMessageID(const std::string &message) -{ - std::string key = "\"id\":"; - size_t startPos = message.find(key); - if (startPos == std::string::npos) { - return false; - } - startPos += key.length(); - - while (startPos < message.length() && std::isspace(message[startPos])) { - ++startPos; - } - - if (message[startPos] == '"') { - size_t endPos = message.find('"', startPos + 1); - if (endPos == std::string::npos) { - return false; - } - messageId_ = CString(message.substr(startPos + 1, endPos - startPos - 1).c_str()); - } else { - size_t endPos = message.find(',', startPos); - if (endPos == std::string::npos) { - endPos = message.find('}', startPos); - } - if (endPos == std::string::npos) { - return false; - } - messageId_ = CString(message.substr(startPos, endPos - startPos).c_str()); - } - return true; -} - -CString HeapProfilerStream::GetMessageID() -{ - return messageId_; -} - -void HeapProfilerStream::SetContext(MsgType type) -{ - if (type == DUMPHEAPSNAPSHOT || type == ALLOCATION) { - start_ = "{\"method\":\"HeapProfiler.addHeapSnapshotChunk\",\"params\":{\"chunk\":\""; - end_ = "\"},\"profiler\":\"arkcommon profiler\"}"; - return; - } else if (type == STATSUPDATE) { - start_ = "{\"method\":\"HeapProfiler.heapStatsUpdate\",\"params\":{\"statsUpdate\":"; - end_ = "},\"profiler\":\"arkcommon profiler\"}"; - return; - } else { - start_ = ""; - } - end_ = ",\"profiler\":\"arkcommon profiler\"}"; -} -int HeapProfilerStream::GetSize() -{ - static const int heapProfilerChunkSise = static_cast(20 * 1024); - return heapProfilerChunkSise; -} -bool HeapProfilerStream::WriteChunk(char* data, int32_t size) -{ - std::string chunk(data, size); - std::string msg = start_ + chunk + end_; - sendMsg_(msg); - return true; -} -} diff --git a/common_components/common_runtime/src/inspector/file_stream.h b/common_components/common_runtime/src/inspector/file_stream.h deleted file mode 100755 index 6a3105fc7caa1dc1f3dce5da30585550a1afaaa7..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/file_stream.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2025 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 ARK_COMMON_FILE_STREAM_H -#define ARK_COMMON_FILE_STREAM_H - -#include -#include -#include -#include - -#include "common_components/common_runtime/src/inspector/stream.h" -#include "common_components/log/log.h" - -namespace panda { -class StreamWriter { -public: - explicit StreamWriter(Stream* stream) - : stream_(stream), chunkSize_(stream->GetSize()), chunk_(chunkSize_), current_(0) - { - } - - void WriteString(const CString &str) - { - auto len = str.Length(); - DCHECK_CC(len <= static_cast(INT_MAX)); - if (len == 0) { - return; - } - const char* cur = str.Str(); - const char* end = cur + len; - while (cur < end) { - int dstSize = chunkSize_ - current_; - int writeSize = std::min(static_cast(end - cur), dstSize); - DCHECK_CC(writeSize > 0); - if (memcpy_s(chunk_.data() + current_, dstSize, cur, writeSize) != EOK) { - LOG_COMMON(ERROR) << "memcpy_s failed"; - } - cur += writeSize; - current_ += writeSize; - MaybeWriteChunk(); - } - } - - void WriteChar(char c) - { - DCHECK_CC(c != '\0'); - DCHECK_CC(current_ < chunkSize_); - chunk_[current_++] = c; - MaybeWriteChunk(); - } - - void WriteNumber(int32_t num) - { - WriteString(CString(num)); - } - - void End() - { - if (current_ > 0) { - WriteChunk(); - } - stream_->EndOfStream(); - } - -private: - void MaybeWriteChunk() - { - DCHECK_CC(current_ <= chunkSize_); - if (current_ >= chunkSize_) { - WriteChunk(); - } - } - - void WriteChunk() - { - stream_->WriteChunk(chunk_.data(), current_); - current_ = 0; - } - - Stream* stream_ {nullptr}; - int chunkSize_ {0}; - std::vector chunk_; - int current_ {0}; -}; - -enum MsgType : uint32_t { - DUMPHEAPSNAPSHOT = 0, - ALLOCATION = 1, - HEAPUSAGE = 2, - DISABLE = 3, - END = 4, - STATSUPDATE = 5, -}; - -class HeapProfilerStream : public Stream { -public: - static HeapProfilerStream& GetInstance() - { - static HeapProfilerStream instance; - return instance; - } - using SendMsgCB = std::function; - HeapProfilerStream() : sendMsg_(nullptr) {} - void SetHandler(SendMsgCB sendMsgInit); - bool SetMessageID(const std::string &message); - CString GetMessageID(); - void SetContext(MsgType type); - void EndOfStream() override {} - int GetSize() override; - bool WriteChunk(char* data, int32_t size) override; - -private: - std::string start_; - std::string end_; - SendMsgCB sendMsg_; - CString messageId_; -}; -} -#endif diff --git a/common_components/common_runtime/src/inspector/heap_data.cpp b/common_components/common_runtime/src/inspector/heap_data.cpp deleted file mode 100755 index 93ef35a65058214d88ffb3b57a4ddf734aa89867..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/heap_data.cpp +++ /dev/null @@ -1,826 +0,0 @@ -/* - * Copyright (c) 2025 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 "common_components/common_runtime/src/inspector/heap_data.h" - -#include - -#include "common_components/common_runtime/src/common/base_object.h" -#include "common_components/common_runtime/src/common/scoped_object_access.h" -#include "common_components/common_runtime/src/heap/collector/task_queue.h" -#include "common_components/common_runtime/src/heap/collector/trace_collector.h" -#include "common_components/common_runtime/src/heap/heap.h" - -namespace panda { -static bool g_oomIsTrigged = false; - -void ArkHeapData::WriteHeap() -{ - WriteFixedHeader(); - WriteString(); - WriteAllClassLoad(); - WriteAllStructClassLoad(); - WriteStackTrace(); - WriteStartThread(); - WriteHeapDump(); -} - -void ArkHeapData::ProcessHeap() -{ - ProcessRootGlobal(); - ProcessRootLocal(); - ProcessRootFinalizer(); - (void)LookupStringId("reserved"); - (void)LookupStringId("RefFields"); - (void)LookupStringId("ValueField"); - // dump object contents - auto dumpVisitor = [this](BaseObject* obj) { ProcessHeapObject(obj); }; - bool ret = Heap::GetHeap().ForEachObject(dumpVisitor, false); - LOGE_IF(UNLIKELY_CC(!ret)) << "theAllocator.ForEachObject() in DumpHeap() return false."; -} - -void ArkHeapData::DumpHeap() -{ - // step1 - open file - CString specifiedPath; - if (dumpAfterOOM && !g_oomIsTrigged) { - g_oomIsTrigged = true; - specifiedPath = ""; - auto pid = GetPid(); - CString dumpFile = CString("ark_OOM_pid") + CString(pid) + CString(".dat"); -#if defined(_WIN64) - const char* separator = "\\"; -#else - const char* separator = "/"; -#endif - if (specifiedPath.IsEmpty()) { - // dump to current path - fp = fopen(dumpFile.Str(), "wb"); - VLOG(INFO, "Heap dump log is writing into %s%s", separator, dumpFile.Str()); - } else { - // dump to specified path - dumpFile = specifiedPath + separator + dumpFile; - fp = fopen(dumpFile.Str(), "wb"); - VLOG(INFO, "Heap dump log is writing into %s", dumpFile.Str()); - } - } else { - // dump for prof - fp = fopen("item_data.dat.cache", "wb"); - } - - if (!fp) { - LOG_COMMON(ERROR) << "Failed to open heap dump file, stop dumping heap info, errno type is %d", errno); - return; - } - - // step2 - write file - STWParam stwParam{"dump-heap"}; - ScopedStopTheWorld stw(stwParam); - ProcessHeap(); - WriteHeap(); - - // step3 - close file - int ret = fclose(fp); - if (ret) { - LOG_COMMON(ERROR) << "Fail to close file when dump heap data finished"; - } - if (!dumpAfterOOM) { - ret = rename("item_data.dat.cache", "item_data.dat"); - if (ret) { - LOG_COMMON(ERROR) << "Fail to rename file when dump heap data finished"; - } - } -} - -void ArkHeapData::ProcessHeapObject(BaseObject* obj) -{ - if (obj == nullptr) { - return; - } - - if (obj->IsRawArray()) { - MArray* mArray = reinterpret_cast(obj); - TypeInfo* componentTypeInfo = mArray->GetComponentTypeInfo(); - if (componentTypeInfo->IsPrimitiveType()) { - DumpObject dumpObject = { obj, TAG_PRIMITIVE_ARRAY_DUMP, 0, 0, - LookupStringId(obj->GetTypeInfo()->GetName() == nullptr ? - "anonymousPrimitiveArray" : - obj->GetTypeInfo()->GetName()) }; - dumpObjects.push_back(dumpObject); - } else if (componentTypeInfo->IsStructType()) { - DumpObject dumpObject = { obj, TAG_STRUCT_ARRAY_DUMP, 0, 0, - LookupStringId(obj->GetTypeInfo()->GetName() == nullptr ? - "anonymousStructArray" : - obj->GetTypeInfo()->GetName()) }; - dumpObjects.push_back(dumpObject); - ProcessStructClass(obj->GetTypeInfo()); - return; - } else if (componentTypeInfo->IsObjectType() || - componentTypeInfo->IsArrayType() || - componentTypeInfo->IsInterface()) { - DumpObject dumpObject = { obj, TAG_OBJECT_ARRAY_DUMP, 0, 0, - LookupStringId(obj->GetTypeInfo()->GetName() == nullptr ? - "anonymousObjectArray" : - obj->GetTypeInfo()->GetName()) }; - dumpObjects.push_back(dumpObject); - } else { - LOG_COMMON(ERROR) << "array object %p has wrong component type", mArray); - } - } else if (obj->GetTypeInfo()->IsVaildType()) { - DumpObject dumpObject = { - obj, TAG_INSTANCE_DUMP, 0, 0, - LookupStringId(obj->GetTypeInfo()->GetName() == nullptr ? "defaultLambda" : obj->GetTypeInfo()->GetName()) - }; - dumpObjects.push_back(dumpObject); - } else { - LOG_COMMON(ERROR) << "object %p has wrong component type", obj); - return; - } - ProcessRootClass(obj->GetTypeInfo()); -} - -void ArkHeapData::ProcessRootClass(TypeInfo* klass) -{ - if (dumpClassMap.find(klass) == dumpClassMap.end()) { - dumpClassMap.insert(std::pair( - klass, - LookupStringId(klass->GetName() == nullptr ? "defaultLambda" : - klass->GetName()))); // lamda obj has null name - } -} - -void ArkHeapData::ProcessStructClass(TypeInfo* klass) -{ - if (dumpStructClassMap.find(klass) == dumpStructClassMap.end()) { - dumpStructClassMap.insert(std::pair( - klass, - LookupStringId(klass->GetName() == nullptr ? "defaultStructLamda" : - klass->GetName()))); // lamda obj has null name - } -} -void ArkHeapData::ProcessStacktrace(RecordStackInfo* recordStackInfo) -{ - std::vector framesInStack = recordStackInfo->stacks; - if (stacktraces.find(recordStackInfo) == stacktraces.end()) { - stacktraces.insert( - std::pair(recordStackInfo, traceSerialNum++)); - CString threadIdx = CString(threadId); - LookupStringId(threadName); - for (size_t i = 0; i < framesInStack.size(); ++i) { - FrameInfo* frame = framesInStack[i]; - if (frame->GetFrameType() == FrameType::MANAGED) { - LookupStringId(frame->GetFuncName().Str()); - LookupStringId(frame->GetFileName().Str()); - } else { - Os::Loader::BinaryInfo binInfo; - (void)Os::Loader::GetBinaryInfoFromAddress(frame->mFrame.GetIP(), &binInfo); - LookupStringId(CString(binInfo.filePathName).Str()); - LookupStringId(CString(binInfo.symbolName).Str()); - } - frames.insert(std::pair(frame, frameId++)); - } - } -} - -void ArkHeapData::ProcessRootLocal() -{ - LOG_COMMON(FATAL) << "Unresolved fatal"; - UNREACHABLE_CC(); -} - -void ArkHeapData::ProcessRootGlobal() -{ - RefFieldVisitor visitor = [this](RefField<>& refField) { - BaseObject* obj = Heap::GetBarrier().ReadStaticRef(refField); - if (obj == nullptr || !Heap::IsHeapAddress(obj)) { - return; - } - DumpObject dumpObject = { - obj, TAG_ROOT_GLOBAL, 0, 0, - LookupStringId(obj->GetTypeInfo()->GetName() == nullptr ? "anonymous" : obj->GetTypeInfo()->GetName()) - }; - dumpObjects.push_back(dumpObject); - }; - Heap::GetHeap().VisitStaticRoots(visitor); -} - -void ArkHeapData::ProcessRootFinalizer() -{ - RootVisitor visitor = [this](ObjectRef& objRef) { - BaseObject* obj = objRef.object; - if (obj == nullptr || !Heap::IsHeapAddress(obj)) { - return; - } - DumpObject dumpObject = { - obj, TAG_ROOT_UNKNOWN, 0, 0, - LookupStringId(obj->GetTypeInfo()->GetName() == nullptr ? "anonymous" : obj->GetTypeInfo()->GetName()) - }; - dumpObjects.push_back(dumpObject); - }; - Heap::GetHeap().GetFinalizerProcessor().VisitGCRoots(visitor); -} - -void ArkHeapData::WriteHeapDump() -{ - WriteRecordHeader(TAG_HEAP_DUMP, kHeapDataTime); - WriteAllClass(); - WriteAllStructClass(); - WriteAllObjects(); - ModifyLength(); - EndRecord(); -} -/* - * Record thread info: - * RecordHeader header; - * u4 thread serial number - * ID thread object ID - * u4 stack trace serial number - * ID thread name string ID - */ -void ArkHeapData::WriteStartThread() -{ - for (auto trace = stacktraces.begin(); trace != stacktraces.end(); trace++) { - WriteRecordHeader(TAG_START_THREAD, kHeapDataTime); - AddU4(trace->first->GetStackTid()); - AddID(threadObjectId++); - AddU4(trace->second); - CString threadNameAll = trace->first->GetThreadName(); - AddID(LookupStringId(threadNameAll)); - ModifyLength(); - EndRecord(); - } -} - -void ArkHeapData::WriteAllClass() -{ - for (auto klassInfo : dumpClassMap) { - WriteClass(klassInfo.first, klassInfo.second, TAG_CLASS_DUMP); - } -} - -void ArkHeapData::WriteAllStructClass() -{ - for (auto klassInfo : dumpStructClassMap) { - WriteStructClass(klassInfo.first, klassInfo.second, TAG_CLASS_DUMP); - } -} - -void ArkHeapData::WriteAllObjects() -{ - for (auto objectInfo : dumpObjects) { - switch (objectInfo.tag) { - case TAG_ROOT_THREAD_OBJECT: - WriteThreadObjectRoot(objectInfo.obj, objectInfo.tag, objectInfo.threadId, 0); - break; - case TAG_ROOT_LOCAL: - WriteLocalRoot(objectInfo.obj, objectInfo.tag, objectInfo.threadId, objectInfo.frameNum); - break; - case TAG_ROOT_GLOBAL: - WriteGlobalRoot(objectInfo.obj, objectInfo.tag); - break; - case TAG_ROOT_UNKNOWN: - WriteUnknownRoot(objectInfo.obj, objectInfo.tag); - break; - case TAG_OBJECT_ARRAY_DUMP: - WriteObjectArray(objectInfo.obj, objectInfo.tag); - break; - case TAG_STRUCT_ARRAY_DUMP: - WriteStructArray(objectInfo.obj, objectInfo.tag); - break; - case TAG_PRIMITIVE_ARRAY_DUMP: - WritePrimitiveArray(objectInfo.obj, objectInfo.tag); - break; - case TAG_INSTANCE_DUMP: - WriteInstance(objectInfo.obj, objectInfo.tag); - break; - default: - break; - } - } -} -/* - * Record Global Root Info: - * u1 tag; //denoting the type of this sub-record - * ID objId; // object ID - */ -void ArkHeapData::WriteGlobalRoot(BaseObject*& obj, const u1 tag) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - CString name = obj->GetTypeInfo()->GetName(); - AddStringId(objId); -} - -/* - * Record Unknown Root Info: - * u1 tag; // denoting the type of this sub-record - * ID objId; // object ID - */ -void ArkHeapData::WriteUnknownRoot(BaseObject*& obj, const u1 tag) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - AddStringId(objId); -} - -/* - * Record Local Root Info: - * u1 tag; // denoting the type of this sub-record - * ID objId; // object ID - * u4 threadIdx; // thread serial number - * u4 frame; // frame number in stack trace (-1 for empty) - */ -void ArkHeapData::WriteLocalRoot(BaseObject*& obj, const u1 tag, const u4 tid, const u1 depth) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - AddStringId(objId); - AddU4(tid); - AddU4(depth); -} - -/* - * Record Thread Object Root Info: - * u1 tag; // denoting the type of this sub-record - * ID threadObjId; // thread object ID - * u4 threadIdx; // thread serial number - * u4 stackTraceIdx; // stack trace serial number - * - */ -void ArkHeapData::WriteThreadObjectRoot(BaseObject*& obj, const u1 tag, const u4 tid, const u4 stackTraceIdx) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - AddStringId(objId); - AddU4(tid); - AddU4(stackTraceIdx); -} - - -/* - * Record Object Array Info: - * u1 tag; // denoting the type of this sub-record - * ID arrObjId; // array object ID - * u4 num; // number of elements - * ID arrClassObjId; // array class object ID - * ID elements[num]; // elements - * - */ -void ArkHeapData::WriteObjectArray(BaseObject*& obj, const u1 tag) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - AddStringId(objId); - u4 num = 0; - std::stack VAL; - RefFieldVisitor visitor = [&VAL, &num](RefField<>& arrayContent) { - VAL.push(reinterpret_cast(arrayContent.GetTargetObject())); - num++; - }; - // take array length and content. - MArray* mArray = reinterpret_cast(obj); - MIndex arrayLengthVal = mArray->GetLength(); - RefField<>* arrayContent = reinterpret_cast*>(mArray->ConvertToCArray()); - // for each object in array. - for (MIndex i = 0; i < arrayLengthVal; ++i) { - visitor(arrayContent[i]); - } - AddU4(num); - AddStringId(reinterpret_cast(obj->GetTypeInfo())); - while (!VAL.empty()) { - u8 val = VAL.top(); - VAL.pop(); - AddU8(val); - } -} - -/* - * Record struct Array Info: - * u1 tag; // denoting the type of this sub-record - * ID arrObjId; // array object ID - * u4 componentNum; // component Num - * u4 num; // number of ref fields - * ID arrClassObjId; // array class object ID - * ID elements[num]; // elements - * - */ -void ArkHeapData::WriteStructArray(BaseObject*& obj, const u1 tag) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - AddStringId(objId); - u4 num = 0; - std::stack VAL; - RefFieldVisitor visitor = [&VAL, &num](RefField<>& arrayContent) { - VAL.push(reinterpret_cast(arrayContent.GetTargetObject())); - num++; - }; - // take array length and content. - MArray* mArray = reinterpret_cast(obj); - MIndex arrayLengthVal = mArray->GetLength(); - TypeInfo* componentTypeInfo = mArray->GetComponentTypeInfo(); - GCTib gcTib = componentTypeInfo->GetGCTib(); - HeapAddress contentAddr = reinterpret_cast(mArray) + MArray::GetContentOffset(); - for (MIndex i = 0; i < arrayLengthVal; ++i) { - gcTib.ForEachBitmapWord(contentAddr, visitor); - contentAddr += mArray->GetElementSize(); - } - AddU4(arrayLengthVal); - AddU4(num); - AddStringId(reinterpret_cast(obj->GetTypeInfo())); - while (!VAL.empty()) { - u8 val = VAL.top(); - VAL.pop(); - AddU8(val); - } -} - -/* - * Record Primitive Array Info: - * u1 tag; // denoting the type of this sub-record - * ID arrObjId; // array object - * u4 num; // number of elements - * u1 type; // element type - */ - -void ArkHeapData::WritePrimitiveArray(BaseObject*& obj, const u1 tag) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - AddStringId(objId); - MArray* mArray = reinterpret_cast(obj); - AddU4(mArray->GetLength()); - uint32_t ComponentSize = obj->GetTypeInfo()->GetComponentSize(); - switch (ComponentSize) { - // bool:1 bytes - case 1: - AddU1(BOOLEAN); - break; - // short:2 bytes - case 2: - AddU1(SHORT); - break; - // int:4 bytes - case 4: - AddU1(INT); - break; - // long:8 bytes - case 8: - AddU1(LONG); - break; - default: - break; - } -} - -/* - * Record Struct Class Info: - * u1 tag; // denoting the type of this sub-record - * ID classObjId; // class object ID - * u4 size; // instance size (in bytes) - */ -void ArkHeapData::WriteStructClass(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag) -{ - AddU1(tag); - AddStringId(reinterpret_cast(klass)); - TypeInfo* componentKlass = klass->GetComponentTypeInfo(); - // No alignment required - u4 size = componentKlass->GetInstanceSize(); - AddU4(size); -} - -/* - * Record Class Info: - * u1 tag; // denoting the type of this sub-record - * ID classObjId; // class object ID - * u4 size; // instance size (in bytes) - */ -void ArkHeapData::WriteClass(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag) -{ - AddU1(tag); - AddStringId(reinterpret_cast(klass)); - // 8-byte alignment - if (!klass->IsObjectType()) { - AddU4(0); - return; - } - u4 size = AlignUp((klass->GetInstanceSize() + sizeof(TypeInfo*)), alignment); - // 8 bytes for each field - AddU4(size); -} - -/* - * Record Instance Info: - * u1 tag; // denoting the type of this sub-record - * ID objId; // object ID - * ID classObjId; // class object ID - * u4 num; // number of ref fields - * VAL entry[]; // ref contents in instance field values (this class, followed by super class, etc) - */ -void ArkHeapData::WriteInstance(BaseObject*& obj, const u1 tag) -{ - AddU1(tag); - ArkHeapDataID objId = (reinterpret_cast(obj)); - AddStringId(objId); - AddStringId(reinterpret_cast(obj->GetTypeInfo())); - u4 num = 0; - std::stack VAL; - RefFieldVisitor visitor = [&VAL, &num](RefField<>& fieldAddr) { - VAL.push(reinterpret_cast(fieldAddr.GetTargetObject())); - num++; - }; - TypeInfo* currentClass = obj->GetTypeInfo(); - if (obj->HasRefField()) { - GCTib gcTib = currentClass->GetGCTib(); - HeapAddress objAddr = reinterpret_cast(obj) + sizeof(TypeInfo*); - gcTib.ForEachBitmapWord(objAddr, visitor); - } - AddU4(num); - while (!VAL.empty()) { - u8 val = VAL.top(); - VAL.pop(); - AddU8(val); - } -} - -/* - * Record String Info: - * RecordHeader header; - * ID id; // ID for this string - * u1 str[]; // UTF8 characters for string (NOT NULL terminated) - */ -void ArkHeapData::WriteString() -{ - for (auto string : strings) { - WriteRecordHeader(TAG_STRING_IN_UTF8, kHeapDataTime); - ArkHeapDataStringId id = string.second; - AddStringId(id); - const CString str = string.first; - AddU1List(reinterpret_cast(str.Str()), str.Length()); - ModifyLength(); - EndRecord(); - } -} - -/* - * Record Stack Frame Info: - * RecordHeader header; - * ID frameId; // stack frame ID - * ID methodNameId; // method name string ID - * ID srcFileNameId; // source file name string ID - * u4 line; // line number(>0: line number, 0: no line information available, -1: unknown - * location) - */ -void ArkHeapData::WriteStackFrame(FrameInfo& frame, uint32_t frameIdx) -{ - if (frameIdx > 0 && frame.GetFrameType() == FrameType::NATIVE) { - return; - } - if (frame.GetFrameType() == FrameType::MANAGED) { - StackMetadataHelper stackMetadataHelper(frame); - methodName = frame.GetFuncName(); - fileName = frame.GetFileName(); - lineNumber = stackMetadataHelper.GetLineNumber(); - } else { - Os::Loader::BinaryInfo binInfo; - (void)Os::Loader::GetBinaryInfoFromAddress(frame.mFrame.GetIP(), &binInfo); - fileName = CString(binInfo.filePathName); - methodName = CString(binInfo.symbolName); - } - WriteRecordHeader(TAG_STACK_FRAME, kHeapDataTime); - AddStringId(frames[&frame]); - AddStringId(LookupStringId(methodName.Str())); - AddStringId(LookupStringId(fileName.Str())); - AddU4(reinterpret_cast(lineNumber)); - ModifyLength(); - EndRecord(); -} - -/* - * Record Stack Trace Info: - * RecordHeader header; - * u4 stackTraceIdx; // stack trace serial number - * u4 threadIdx; // thread serial number - * u4 frameNum; // number of frames - * ID frames[]; // series of stack frame ID's - */ -void ArkHeapData::WriteStackTrace() -{ - for (auto trace = stacktraces.begin(); trace != stacktraces.end(); trace++) { - auto env = std::getenv("DumpStackDepth"); - // 10: Default Limit Max Dump Depth as 10 frames - size_t size = CString::ParseNumFromEnv(env) == 0 ? 10 : CString::ParseNumFromEnv(env); - size_t depth = trace->first->stacks.size() > size ? size : trace->first->stacks.size(); - std::vector stack = trace->first->stacks; - for (size_t i = 0; i < depth; ++i) { - WriteStackFrame(*stack[i], i); - } - WriteRecordHeader(TAG_STACK_TRACE, kHeapDataTime); - AddU4(trace->second); - AddU4(trace->first->GetStackTid()); - AddU4(depth); - for (size_t i = 0; i < depth; ++i) { - AddStringId(frames[stack[i]]); - } - ModifyLength(); - EndRecord(); - } -} - -/* - * Record Record Header Info: - * u1 tag; // denoting the type of the record - * u4 time; // number of microseconds since the time stamp in the header - * u4 length; // number of bytes that follow this u4 field and belong to this record - */ -void ArkHeapData::WriteRecordHeader(const u1 tag, const u4 time) -{ - AddU1(tag); - // DEADDEADEADDEAD: placeholder, the actual length is filled in Func modifyLength. - const u8 tmpLens = 0xDEADDEADEADDEAD; - AddU8(tmpLens); -} - -void ArkHeapData::AddU1(const u1 value) { AddU1List(&value, 1); } - -void ArkHeapData::AddU2(const u2 value) { AddU2List(&value, 1); } - -void ArkHeapData::AddU4(const u4 value) { AddU4List(&value, 1); } - -void ArkHeapData::AddU8(const u8 value) { AddU8List(&value, 1); } - -void ArkHeapData::AddID(const u8 value) { AddU8List(&value, 1); } - -void ArkHeapData::AddU1List(const u1* value, uint8_t count) -{ - HandleAddU1(value, count); - length += count; -} - -void ArkHeapData::AddU2List(const u2* value, uint8_t count) -{ - HandleAddU2(value, count); - length += count * sizeof(u2); - ; -} - -void ArkHeapData::AddU4List(const u4* value, uint8_t count) -{ - HandleAddU4(value, count); - length += count * sizeof(u4); -} -void ArkHeapData::AddU8List(const u8* value, uint8_t count) -{ - HandleAddU8(value, count); - length += count * sizeof(u8); -} - -enum ByteOffset { - FIRST_BYTE = 0 * 8, - SECOND_BYTE = 1 * 8, - THIRD_BYTE = 2 * 8, - FOURTH_BYTE = 3 * 8, - FIFTH_BYTE = 4 * 8, - SIXTH_BYTE = 5 * 8, - SEVENTH_BYTE = 6 * 8, - EIGHTH_BYTE = 7 * 8 -}; - -void ArkHeapData::HandleAddU1(const u1* value, uint8_t count) { buffer.insert(buffer.end(), value, value + count); } - -void ArkHeapData::HandleAddU2(const u2* value, uint8_t count) -{ - for (int i = 0; i < count; i++) { - buffer.push_back(static_cast((*value >> SECOND_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> FIRST_BYTE) & 0xFF)); - value++; - } -} - -void ArkHeapData::HandleAddU4(const u4* value, uint8_t count) -{ - for (int i = 0; i < count; i++) { - buffer.push_back(static_cast((*value >> FOURTH_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> THIRD_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> SECOND_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> FIRST_BYTE) & 0xFF)); - value++; - } -} - -void ArkHeapData::HandleAddU8(const u8* value, uint8_t count) -{ - // 0: offset for 1st byte - // 8: offset for 2nd byte - // 16: offset for 3st byte - // 24: offset for 4st byte - // 32: offset for 5st byte - // 40: offset for 6st byte - // 48: offset for 7st byte - // 56: offset for 8st byte - for (int i = 0; i < count; i++) { - buffer.push_back(static_cast((*value >> EIGHTH_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> SEVENTH_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> SIXTH_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> FIFTH_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> FOURTH_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> THIRD_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> SECOND_BYTE) & 0xFF)); - buffer.push_back(static_cast((*value >> FIRST_BYTE) & 0xFF)); - value++; - } -} - -void ArkHeapData::AddStringId(ArkHeapData::ArkHeapDataStringId value) { AddID(static_cast(value)); } - -void ArkHeapData::EndRecord() -{ - const char* ptr = reinterpret_cast(buffer.data()); - if (fwrite(ptr, length, 1, fp) < 1) { - LOG_COMMON(ERROR) << "Failed to write heap dump file."; - } - length = 0; - std::vector().swap(buffer); -} - -void ArkHeapData::WriteFixedHeader() -{ - const char ident[] = "ARKCOMMON PROFILE 1.0.1"; - AddU1List(reinterpret_cast(ident), sizeof(ident)); - const u4 idSize = sizeof(ArkHeapDataID); - AddU4(idSize); - struct timeval timeNow {}; - gettimeofday(&timeNow, nullptr); - const uint64_t msecsTime = (timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000); - const uint32_t timeHigh = static_cast(msecsTime >> 32); - const uint32_t timeLow = static_cast(msecsTime & 0xFFFFFFFF); - AddU4(timeHigh); - AddU4(timeLow); - EndRecord(); -} -void ArkHeapData::WriteAllClassLoad() -{ - for (auto klassInfo : dumpClassMap) { - WriteClassLoad(klassInfo.first, klassInfo.second, TAG_CLASS_LOAD); - } -} - -void ArkHeapData::WriteAllStructClassLoad() -{ - for (auto klassInfo : dumpStructClassMap) { - WriteClassLoad(klassInfo.first, klassInfo.second, TAG_CLASS_LOAD); - } -} - -/* - * Record Class Load Info: - * ID class object ID - * ID class name string ID - */ -void ArkHeapData::WriteClassLoad(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag) -{ - WriteRecordHeader(tag, kHeapDataTime); - AddID(reinterpret_cast(klass)); - AddStringId(klassId); - ModifyLength(); - EndRecord(); -} - -void ArkHeapData::ModifyLength() -{ - // 9: Subtract the length of the record header - constexpr uint8_t recordHeaderLength = 9; - uint64_t value = length - recordHeaderLength; - // 1,2,3,4,5,6,7,8: Stores 64 bits for length - buffer[1] = (static_cast((value >> EIGHTH_BYTE) & 0xFF)); // 1 : index of buffer - buffer[2] = (static_cast((value >> SEVENTH_BYTE) & 0xFF)); // 2 : index of buffer - buffer[3] = (static_cast((value >> SIXTH_BYTE) & 0xFF)); // 3 : index of buffer - buffer[4] = (static_cast((value >> FIFTH_BYTE) & 0xFF)); // 4 : index of buffer - buffer[5] = (static_cast((value >> FOURTH_BYTE) & 0xFF)); // 5 : index of buffer - buffer[6] = (static_cast((value >> THIRD_BYTE) & 0xFF)); // 6 : index of buffer - buffer[7] = (static_cast((value >> SECOND_BYTE) & 0xFF)); // 7 : index of buffer - buffer[8] = (static_cast((value >> FIRST_BYTE) & 0xFF)); // 8 : index of buffer -} - -ArkHeapData::ArkHeapDataStringId ArkHeapData::LookupStringId(const CString& string) -{ - auto it = strings.find(string); - if (it != strings.end()) { - return it->second; - } - ArkHeapData::ArkHeapDataStringId id = stringId++; - strings.insert(std::pair(string, id)); - return id; -} -} // namespace panda diff --git a/common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.cpp b/common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.cpp deleted file mode 100755 index 51e9869a08418a4c5263a8d4a94be06c458456e8..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include -#include -#include "common_components/common_runtime/src/mutator/mutator_manager.h" -#include "common_components/common_runtime/src/unwind_stack/stack_metadata_helper.h" -#include "common_components/common_runtime/src/object_model/m_array.inline.h" -#include "common_components/common_runtime/src/inspector/file_stream.h" -#include "common_components/common_runtime/src/inspector/heap_data.h" -#include "common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.h" - -namespace panda { - -bool ArkHeapDataForIDE::Serialize() -{ - STWParam stwParam{"serialize-heap-data"}; - ScopedStopTheWorld stw(stwParam); - ProcessHeap(); - HeapProfilerStream* stream = &panda::HeapProfilerStream::GetInstance(); - stream->SetContext(DUMPHEAPSNAPSHOT); - writer_ = new StreamWriter(stream); - writer_->WriteChar('{'); - SerializeFixedHeader(); - SerializeString(); - SerializeAllClassLoad(); - SerializeAllStructClassLoad(); - SerializeStackTrace(); - SerializeStartThread(); - SerializeHeapDump(); - writer_->WriteChar('}'); - writer_->End(); - stream->SetContext(END); - writer_->WriteString("{\"id\":"); - writer_->WriteString(stream->GetMessageID()); - writer_->WriteString(",\"result\":{}"); - writer_->End(); - delete writer_; - return true; -} - -void ArkHeapDataForIDE::SerializeFixedHeader() -{ - const u4 idSize = sizeof(u4); - struct timeval timeNow {}; - gettimeofday(&timeNow, nullptr); - const uint64_t msecsTime = (timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000); - const uint32_t timeHigh = static_cast(msecsTime >> 32); - const uint32_t timeLow = static_cast(msecsTime & 0xFFFFFFFF); - writer_->WriteString("\\\"HEADER\\\":["); - writer_->WriteNumber(idSize); - writer_->WriteChar(','); - writer_->WriteNumber(timeHigh); - writer_->WriteChar(','); - writer_->WriteNumber(timeLow); - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeString() -{ - writer_->WriteString("\\\"STRING\\\":["); - bool isFirstElement = true; - for (auto string : strings) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - writer_->WriteChar('['); - ArkHeapDataStringId id = string.second; - writer_->WriteNumber(GetId(id)); - writer_->WriteChar(','); - const CString str = string.first; - writer_->WriteString("\\\""); - writer_->WriteString(str); - writer_->WriteString("\\\""); - writer_->WriteChar(']'); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeAllClassLoad() -{ - writer_->WriteString("\\\"CLASSLOAD\\\":["); - bool isFirstElement = true; - for (auto klassInfo : dumpClassMap) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - SerializeClassLoad(klassInfo.first, klassInfo.second, TAG_CLASS_LOAD); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeAllClass() -{ - writer_->WriteString("\\\"CLASS\\\":["); - bool isFirstElement = true; - for (auto klassInfo : dumpClassMap) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - SerializeClass(klassInfo.first, klassInfo.second, TAG_CLASS_DUMP); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeAllStructClass() -{ - writer_->WriteString("\\\"STRUCTCLASS\\\":["); - bool isFirstElement = true; - for (auto klassInfo : dumpStructClassMap) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - SerializeStructClass(klassInfo.first, klassInfo.second, TAG_CLASS_DUMP); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeClassLoad(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(GetId(reinterpret_cast(klass))); - writer_->WriteChar(','); - writer_->WriteNumber(GetId(reinterpret_cast(klassId))); - writer_->WriteChar(']'); -} - -void ArkHeapDataForIDE::SerializeAllStructClassLoad() -{ - writer_->WriteString("\\\"STRUCTCLASSLOAD\\\":["); - bool isFirstElement = true; - for (auto klassInfo : dumpStructClassMap) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - SerializeClassLoad(klassInfo.first, klassInfo.second, TAG_CLASS_LOAD); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeStackFrame(FrameInfo& frame, uint32_t frameIdx) -{ - writer_->WriteChar('['); - if (frameIdx > 0 && frame.GetFrameType() == FrameType::NATIVE) { - return; - } - if (frame.GetFrameType() == FrameType::MANAGED) { - StackMetadataHelper stackMetadataHelper(frame); - methodName = frame.GetFuncName(); - fileName = frame.GetFileName(); - lineNumber = stackMetadataHelper.GetLineNumber(); - } else { - Os::Loader::BinaryInfo binInfo; - (void)Os::Loader::GetBinaryInfoFromAddress(frame.mFrame.GetIP(), &binInfo); - fileName = CString(binInfo.filePathName); - methodName = CString(binInfo.symbolName); - } - writer_->WriteNumber(frames[&frame]); - writer_->WriteChar(','); - writer_->WriteNumber(LookupStringId(methodName.Str())); - writer_->WriteChar(','); - writer_->WriteNumber(LookupStringId(fileName.Str())); - writer_->WriteChar(','); - writer_->WriteNumber(reinterpret_cast(lineNumber)); -} - - -void ArkHeapDataForIDE::SerializeStackTrace() -{ - for (auto trace = stacktraces.begin(); trace != stacktraces.end(); trace++) { - auto env = std::getenv("DumpStackDepth"); - // 10: Default Limit Max Dump Depth as 10 frames - size_t size = CString::ParseNumFromEnv(env) == 0 ? 10 : CString::ParseNumFromEnv(env); - size_t depth = trace->first->stacks.size() > size ? size : trace->first->stacks.size(); - std::vector stack = trace->first->stacks; - writer_->WriteString("\\\"STACKFRAME\\\":["); - for (size_t i = 0; i < depth; ++i) { - SerializeStackFrame(*stack[i], i); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); - writer_->WriteString("\\\"STACKTRACE\\\":["); - writer_->WriteNumber(trace->second); - writer_->WriteChar(','); - writer_->WriteNumber(trace->first->GetStackTid()); - writer_->WriteChar(','); - writer_->WriteNumber(depth); - writer_->WriteChar(','); - writer_->WriteChar('['); - for (size_t i = 0; i < depth; ++i) { - writer_->WriteNumber(frames[stack[i]]); - } - writer_->WriteChar(']'); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeStartThread() -{ - writer_->WriteString("\\\"STARTTHREAD\\\":["); - for (auto trace = stacktraces.begin(); trace != stacktraces.end(); trace++) { - writer_->WriteNumber(trace->first->GetStackTid()); - writer_->WriteChar(','); - writer_->WriteNumber(GetId(threadObjectId++)); - writer_->WriteChar(','); - writer_->WriteNumber(trace->second); - writer_->WriteChar(','); - CString threadNameAll = trace->first->GetThreadName(); - writer_->WriteNumber(GetId(LookupStringId(threadNameAll))); - } - writer_->WriteChar(']'); - writer_->WriteChar(','); -} - -void ArkHeapDataForIDE::SerializeHeapDump() -{ - SerializeAllClass(); - SerializeAllStructClass(); - SerializeAllObjects(); -} - -void ArkHeapDataForIDE::SerializeAllObjects() -{ - writer_->WriteString("\\\"OBJECTS\\\":["); - bool isFirstElement = true; - for (auto objectInfo : dumpObjects) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - switch (objectInfo.tag) { - case TAG_ROOT_THREAD_OBJECT: - SerializeThreadObjectRoot(objectInfo.obj, objectInfo.tag, objectInfo.threadId, 0); - break; - case TAG_ROOT_LOCAL: - SerializeLocalRoot(objectInfo.obj, objectInfo.tag, objectInfo.threadId, objectInfo.frameNum); - break; - case TAG_ROOT_GLOBAL: - SerializeGlobalRoot(objectInfo.obj, objectInfo.tag); - break; - case TAG_ROOT_UNKNOWN: - SerializeUnknownRoot(objectInfo.obj, objectInfo.tag); - break; - case TAG_OBJECT_ARRAY_DUMP: - SerializeObjectArray(objectInfo.obj, objectInfo.tag); - break; - case TAG_STRUCT_ARRAY_DUMP: - SerializeStructArray(objectInfo.obj, objectInfo.tag); - break; - case TAG_PRIMITIVE_ARRAY_DUMP: - SerializePrimitiveArray(objectInfo.obj, objectInfo.tag); - break; - case TAG_INSTANCE_DUMP: - SerializeInstance(objectInfo.obj, objectInfo.tag); - break; - default: - break; - } - } - writer_->WriteChar(']'); -} - -/* - * Record Global Root Info: - * u1 tag; //denoting the type of this sub-record - * ID objId; // object ID - */ -void ArkHeapDataForIDE::SerializeGlobalRoot(BaseObject*& obj, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - ArkHeapDataID objAddr = (reinterpret_cast(obj)); - u4 id = GetId(objAddr); - CString name = obj->GetTypeInfo()->GetName(); - writer_->WriteNumber(id); - writer_->WriteChar(']'); -} - -/* - * Record Unknown Root Info: - * u1 tag; // denoting the type of this sub-record - * ID objId; // object ID - */ -void ArkHeapDataForIDE::SerializeUnknownRoot(BaseObject*& obj, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - ArkHeapDataID objAddr = (reinterpret_cast(obj)); - u4 id = GetId(objAddr); - writer_->WriteNumber(id); - writer_->WriteChar(']'); -} - -/* - * Record Local Root Info: - * u1 tag; // denoting the type of this sub-record - * ID objId; // object ID - * u4 threadIdx; // thread serial number - * u4 frame; // frame number in stack trace (-1 for empty) - */ -void ArkHeapDataForIDE::SerializeLocalRoot(BaseObject*& obj, const u1 tag, const u4 tid, const u1 depth) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - ArkHeapDataID objAddr = (reinterpret_cast(obj)); - u4 id = GetId(objAddr); - writer_->WriteNumber(id); - writer_->WriteChar(','); - writer_->WriteNumber(tid); - writer_->WriteChar(','); - writer_->WriteNumber(depth); - writer_->WriteChar(']'); -} - -/* - * Record Thread Object Root Info: - * u1 tag; // denoting the type of this sub-record - * ID threadObjId; // thread object ID - * u4 threadIdx; // thread serial number - * u4 stackTraceIdx; // stack trace serial number - * - */ -void ArkHeapDataForIDE::SerializeThreadObjectRoot(BaseObject*& obj, const u1 tag, const u4 tid, const u4 stackTraceIdx) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - ArkHeapDataID objAddr = (reinterpret_cast(obj)); - u4 id = GetId(objAddr); - writer_->WriteNumber(id); - writer_->WriteChar(','); - writer_->WriteNumber(tid); - writer_->WriteChar(','); - writer_->WriteNumber(stackTraceIdx); - writer_->WriteChar(']'); -} - -/* - * Record Class Info: - * u1 tag; // denoting the type of this sub-record - * ID classObjId; // class object ID - * u4 size; // instance size (in bytes) - */ -void ArkHeapDataForIDE::SerializeClass(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - writer_->WriteNumber(GetId(reinterpret_cast(klass))); - writer_->WriteChar(','); - // 8-byte alignment - if (!klass->IsObjectType()) { - writer_->WriteNumber(0); - writer_->WriteChar(']'); - return; - } - u4 size = AlignUp((klass->GetInstanceSize() + sizeof(TypeInfo*)), alignment); - // 8 bytes for each field - writer_->WriteNumber(size); - writer_->WriteChar(']'); -} - -/* - * Record Object Array Info: - * u1 tag; // denoting the type of this sub-record - * ID arrObjId; // array object ID - * u4 num; // number of elements - * ID arrClassObjId; // array class object ID - * ID elements[num]; // elements - * - */ -void ArkHeapDataForIDE::SerializeObjectArray(BaseObject*& obj, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - ArkHeapDataID objAddr = (reinterpret_cast(obj)); - u4 id = GetId(objAddr); - writer_->WriteNumber(id); - writer_->WriteChar(','); - u4 num = 0; - std::stack VAL; - RefFieldVisitor visitor = [&VAL, &num, this](RefField<>& arrayContent) { - VAL.push(GetId(reinterpret_cast(arrayContent.GetTargetObject()))); - num++; - }; - // take array length and content. - MArray* mArray = reinterpret_cast(obj); - MIndex arrayLengthVal = mArray->GetLength(); - RefField<>* arrayContent = reinterpret_cast*>(mArray->ConvertToCArray()); - // for each object in array. - for (MIndex i = 0; i < arrayLengthVal; ++i) { - visitor(arrayContent[i]); - } - writer_->WriteNumber(num); - writer_->WriteChar(','); - writer_->WriteNumber(GetId(reinterpret_cast(obj->GetTypeInfo()))); - writer_->WriteChar(','); - writer_->WriteChar('['); - bool isFirstElement = true; - while (!VAL.empty()) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - u4 val = VAL.top(); - VAL.pop(); - writer_->WriteNumber(val); - } - writer_->WriteChar(']'); - writer_->WriteChar(']'); -} - -/* - * Record struct Array Info: - * u1 tag; // denoting the type of this sub-record - * ID arrObjId; // array object ID - * u4 componentNum; // component Num - * u4 num; // number of ref fields - * ID arrClassObjId; // array class object ID - * ID elements[num]; // elements - * - */ - -void ArkHeapDataForIDE::SerializeStructArray(BaseObject*& obj, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - ArkHeapDataID objAddr = (reinterpret_cast(obj)); - u4 id = GetId(objAddr); - writer_->WriteNumber(id); - writer_->WriteChar(','); - u4 num = 0; - std::stack VAL; - RefFieldVisitor visitor = [&VAL, &num, this](RefField<>& arrayContent) { - VAL.push(GetId(reinterpret_cast(arrayContent.GetTargetObject()))); - num++; - }; - // take array length and content. - MArray* mArray = reinterpret_cast(obj); - MIndex arrayLengthVal = mArray->GetLength(); - TypeInfo* componentTypeInfo = mArray->GetComponentTypeInfo(); - GCTib gcTib = componentTypeInfo->GetGCTib(); - HeapAddress contentAddr = reinterpret_cast(mArray) + MArray::GetContentOffset(); - for (MIndex i = 0; i < arrayLengthVal; ++i) { - gcTib.ForEachBitmapWord(contentAddr, visitor); - contentAddr += mArray->GetElementSize(); - } - writer_->WriteNumber(arrayLengthVal); - writer_->WriteChar(','); - writer_->WriteNumber(num); - writer_->WriteChar(','); - writer_->WriteNumber(GetId(reinterpret_cast(obj->GetTypeInfo()))); - writer_->WriteChar(','); - writer_->WriteChar('['); - bool isFirstElement = true; - while (!VAL.empty()) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - u4 val = VAL.top(); - VAL.pop(); - writer_->WriteNumber(val); - } - writer_->WriteChar(']'); - writer_->WriteChar(']'); -} - -/* - * Record Primitive Array Info: - * u1 tag; // denoting the type of this sub-record - * ID arrObjId; // array object - * u4 num; // number of elements - * u1 type; // element type - */ - -void ArkHeapDataForIDE::SerializePrimitiveArray(BaseObject*& obj, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - ArkHeapDataID objAddr = (reinterpret_cast(obj)); - u4 id = GetId(objAddr); - writer_->WriteNumber(id); - writer_->WriteChar(','); - MArray* mArray = reinterpret_cast(obj); - writer_->WriteNumber(mArray->GetLength()); - writer_->WriteChar(','); - uint32_t ComponentSize = obj->GetTypeInfo()->GetComponentSize(); - switch (ComponentSize) { - // bool:1 bytes - case 1: - writer_->WriteNumber(BOOLEAN); - break; - // short:2 bytes - case 2: - writer_->WriteNumber(SHORT); - break; - // int:4 bytes - case 4: - writer_->WriteNumber(INT); - break; - // long:8 bytes - case 8: - writer_->WriteNumber(LONG); - break; - default: - break; - } - writer_->WriteChar(']'); -} - -/* - * Record Struct Class Info: - * u1 tag; // denoting the type of this sub-record - * ID classObjId; // class object ID - * u4 size; // instance size (in bytes) - */ -void ArkHeapDataForIDE::SerializeStructClass(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - writer_->WriteNumber(GetId(reinterpret_cast(klass))); - TypeInfo* componentKlass = klass->GetComponentTypeInfo(); - // No alignment required - u4 size = componentKlass->GetInstanceSize(); - writer_->WriteChar(','); - writer_->WriteNumber(size); - writer_->WriteChar(']'); -} - -/* - * Record Instance Info: - * u1 tag; // denoting the type of this sub-record - * ID objId; // object ID - * ID classObjId; // class object ID - * u4 num; // number of ref fields - * VAL entry[]; // ref contents in instance field values (this class, followed by super class, etc) - */ -void ArkHeapDataForIDE::SerializeInstance(BaseObject*& obj, const u1 tag) -{ - writer_->WriteChar('['); - writer_->WriteNumber(tag); - writer_->WriteChar(','); - u4 id = GetId(reinterpret_cast(obj)); - writer_->WriteNumber(id); - writer_->WriteChar(','); - writer_->WriteNumber(GetId(reinterpret_cast(obj->GetTypeInfo()))); - writer_->WriteChar(','); - u4 num = 0; - std::stack VAL; - RefFieldVisitor visitor = [&VAL, &num, this](RefField<>& fieldAddr) { - VAL.push(GetId(reinterpret_cast(fieldAddr.GetTargetObject()))); - num++; - }; - TypeInfo* currentClass = obj->GetTypeInfo(); - if (obj->HasRefField()) { - GCTib gcTib = currentClass->GetGCTib(); - HeapAddress objAddr = reinterpret_cast(obj) + sizeof(TypeInfo*); - gcTib.ForEachBitmapWord(objAddr, visitor); - } - writer_->WriteNumber(num); - writer_->WriteChar(','); - writer_->WriteChar('['); - bool isFirstElement = true; - while (!VAL.empty()) { - if (!isFirstElement) { - writer_->WriteChar(','); - } else { - isFirstElement = false; - } - u4 val = VAL.top(); - VAL.pop(); - writer_->WriteNumber(val); - } - writer_->WriteChar(']'); - writer_->WriteChar(']'); -} - -ArkHeapData::u4 ArkHeapDataForIDE::GetId(ArkHeapDataStringId klassId) -{ - if (stringIdxMap_.find(klassId) == stringIdxMap_.end()) { - stringIdxMap_[klassId] = ++stringIdx; - } - return stringIdxMap_[klassId]; -} - -} diff --git a/common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.h b/common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.h deleted file mode 100755 index 774615954a2edb69c09fa987eb59b541b5230043..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/heap_snapshot_json_serializer.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2025 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 ARK_HEAP_SNAPSHOT_JSON_SERIALIZER_H -#define ARK_HEAP_SNAPSHOT_JSON_SERIALIZER_H -#include -#include -#include -#include "common_components/common_runtime/src/inspector/file_stream.h" -#include "common_components/common_runtime/src/base/c_string.h" -#include "common_components/common_runtime/src/inspector/heap_data.h" -#include "securec.h" - -namespace panda { -class ArkHeapDataForIDE : public ArkHeapData { -public: - using HeapDataIDForIDE = u4; - bool Serialize(); - void SerializeFixedHeader(); - void SerializeString(); - void SerializeRecordHeader(const u1 tag, const u4 time); - void SerializeAllClassLoad(); - void SerializeAllStructClassLoad(); - void SerializeAllClass(); - void SerializeAllStructClass(); - void SerializeStackTrace(); - void SerializeStartThread(); - void SerializeHeapDump(); - void SerializeClassLoad(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag); - void SerializeAllObjects(); - void SerializeGlobalRoot(BaseObject*& obj, const u1 tag); - void SerializeUnknownRoot(BaseObject*& obj, const u1 tag); - void SerializeLocalRoot(BaseObject*& obj, const u1 tag, const u4 tid, const u1 depth); - void SerializeThreadObjectRoot(BaseObject*& obj, const u1 tag, const u4 tid, const u4 stackTraceIdx); - void SerializeObjectArray(BaseObject*& obj, const u1 tag); - void SerializeStructArray(BaseObject*& obj, const u1 tag); - void SerializePrimitiveArray(BaseObject*& obj, const u1 tag); - void SerializeInstance(BaseObject*& obj, const u1 tag); - void SerializeClass(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag); - void SerializeStructClass(TypeInfo* klass, ArkHeapDataStringId klassId, const u1 tag); - u4 GetId(ArkHeapDataStringId klassId); -private: - StreamWriter* writer_ = nullptr; - std::unordered_map stringIdxMap_; - u4 stringIdx_ = 0; -}; -} -#endif diff --git a/common_components/common_runtime/src/inspector/profiler_agent_impl.cpp b/common_components/common_runtime/src/inspector/profiler_agent_impl.cpp deleted file mode 100755 index f683f392403718fdad56f3e338924ad4ff1a0cbf..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/profiler_agent_impl.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2025 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 "common_components/common_runtime/src/heap/heap.h" -#include "common_components/common_runtime/src/heap/collector/task_queue.h" -#include "common_components/common_runtime/src/heap/collector/collector_resources.h" -#include "common_components/common_runtime/src/heap/collector/gc_request.h" -#include "common_components/common_runtime/src/inspector/file_stream.h" -#include "common_components/common_runtime/src/inspector/alloc_data.h" -#include "common_components/common_runtime/src/heap/allocator/region_info.h" -#include "common_components/common_runtime/src/heap/allocator/alloc_buffer.h" -#include "common_components/common_runtime/src/inspector/profiler_agent_impl.h" -namespace panda { -int EnableAllocRecord(bool enable) -{ - panda::ArkAllocData::GetArkAllocData()->SetRecording(enable); - if (enable) { - panda::ArkAllocData::SetArkAllocData(); - } else { - panda::ArkAllocData::GetArkAllocData()->DeleteArkAllocData(); - } - return 0; -} -std::string ParseDomain(const std::string &message) -{ - std::string key = "\"id\":"; - size_t startPos = message.find(key); - if (startPos == std::string::npos) { - return ""; - } - startPos += key.length(); - - while (startPos < message.length() && std::isspace(message[startPos])) { - ++startPos; - } - - if (message[startPos] == '"') { - size_t endPos = message.find('"', startPos + 1); - if (endPos == std::string::npos) { - return ""; - } - return message.substr(startPos + 1, endPos - startPos - 1); - } else { - size_t endPos = message.find(',', startPos); - if (endPos == std::string::npos) { - endPos = message.find('}', startPos); - } - if (endPos == std::string::npos) { - return ""; - } - return message.substr(startPos, endPos - startPos); - } -} - -void SetEnd(const std::string &message, panda::MsgType type) -{ - panda::HeapProfilerStream* stream = &panda::HeapProfilerStream::GetInstance(); - stream->SetContext(type); - panda::StreamWriter* writer = new panda::StreamWriter(stream); - writer->WriteString("{\"id\":"); - writer->WriteString(panda::HeapProfilerStream::GetInstance().GetMessageID()); - writer->WriteString(",\"result\":{}"); - writer->End(); - delete writer; -} - -void DumpHeapSnapshot(SendMsgCB sendMsg) -{ - panda::Heap::GetHeap().GetCollectorResources().RequestHeapDump( - panda::GCTask::TaskType::GC_TASK_DUMP_HEAP_IDE); -} - -void StartTrackingHeapObjects(const std::string &message, SendMsgCB sendMsg) -{ - SetEnd(message, panda::MsgType::END); - EnableAllocRecord(true); -} - -void StopTrackingHeapObjects(const std::string &message, SendMsgCB sendMsg) -{ - EnableAllocRecord(false); - SetEnd(message, panda::MsgType::END); -} - -void CollectGarbage(const std::string &message, SendMsgCB sendMsg) -{ - panda::Heap::GetHeap().GetCollectorResources().RequestGC(panda::GC_REASON_HEU, false, GC_TYPE_FULL); - SetEnd(message, panda::MsgType::END); -} - -void DisableCollect(const std::string &message, SendMsgCB sendMsg) -{ - SetEnd(message, panda::MsgType::DISABLE); -} - -void GetHeapUsage(const std::string &message, SendMsgCB sendMsg) -{ - panda::HeapProfilerStream* stream = &panda::HeapProfilerStream::GetInstance(); - stream->SetContext(panda::MsgType::HEAPUSAGE); - panda::StreamWriter* writer = new panda::StreamWriter(stream); - writer->WriteString("{\"id\":"); - writer->WriteString(panda::HeapProfilerStream::GetInstance().GetMessageID()); - writer->WriteString(",\"result\":{\"usedSize\":"); - ssize_t allocatedSize = panda::Heap::GetHeap().GetAllocatedSize(); - writer->WriteNumber(allocatedSize); - writer->WriteString(",\"totalSize\":"); - ssize_t totalSize = panda::Heap::GetHeap().GetMaxCapacity(); - writer->WriteNumber(totalSize); - writer->WriteString("}"); - writer->End(); - delete writer; -} - -void ProfilerAgentImpl(const std::string &message, SendMsgCB sendMsg) -{ - panda::HeapProfilerStream::GetInstance().SetHandler(sendMsg); - panda::HeapProfilerStream::GetInstance().SetMessageID(message); - if (message.find("takeHeapSnapshot", 0) != std::string::npos) { - DumpHeapSnapshot(sendMsg); - } else if (message.find("startTrackingHeapObjects", 0) != std::string::npos) { - StartTrackingHeapObjects(message, sendMsg); - } else if (message.find("stopTrackingHeapObjects", 0) != std::string::npos) { - StopTrackingHeapObjects(message, sendMsg); - } else if (message.find("disable", 0) != std::string::npos) { - DisableCollect(message, sendMsg); - } else if (message.find("collectGarbage", 0) != std::string::npos) { - CollectGarbage(message, sendMsg); - } else if (message.find("getHeapUsage", 0) != std::string::npos) { - GetHeapUsage(message, sendMsg); - } else { - LOG_COMMON(ERROR) << "invaild request\n"; - } -} -} \ No newline at end of file diff --git a/common_components/common_runtime/src/inspector/profiler_agent_impl.h b/common_components/common_runtime/src/inspector/profiler_agent_impl.h deleted file mode 100755 index 2a7bf731846ebb59e6434d8a7078fd97346882b0..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/profiler_agent_impl.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2025 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 INSPECTOR_PROFILERAGENTIMPL_H -#define INSPECTOR_PROFILERAGENTIMPL_H -namespace panda { -using SendMsgCB = std::function; -void ProfilerAgentImpl(const std::string &message, SendMsgCB sendMsg); -} - -#endif diff --git a/common_components/common_runtime/src/inspector/stream.h b/common_components/common_runtime/src/inspector/stream.h deleted file mode 100755 index ec8d56ae21358c11d86f2c5897d80804f0f3608d..0000000000000000000000000000000000000000 --- a/common_components/common_runtime/src/inspector/stream.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2025 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 ARK_COMMON_STREAM_H -#define ARK_COMMON_STREAM_H -#include "common_components/common_runtime/src/base/log_file.h" -namespace panda { -class Stream { -public: - virtual ~Stream() = default; - - virtual void EndOfStream() = 0; - - // Get chunk's size - virtual int GetSize() = 0; - - // Writes the chunk of data into the stream - virtual bool WriteChunk(char* data, int32_t size) = 0; -}; -} // namespace panda - -#endif diff --git a/common_components/base_runtime/tests/BUILD.gn b/common_components/common_runtime/tests/BUILD.gn similarity index 100% rename from common_components/base_runtime/tests/BUILD.gn rename to common_components/common_runtime/tests/BUILD.gn diff --git a/common_components/base_runtime/tests/base_runtime_test.cpp b/common_components/common_runtime/tests/base_runtime_test.cpp similarity index 100% rename from common_components/base_runtime/tests/base_runtime_test.cpp rename to common_components/common_runtime/tests/base_runtime_test.cpp diff --git a/common_components/heap/allocator/memory_map.cpp b/common_components/heap/allocator/memory_map.cpp index 90420c26bf0ee0c8985de206ee929811910418d1..54ad8ea22c6a83cf5d6dd6c0aaf72c7cf03c87ba 100755 --- a/common_components/heap/allocator/memory_map.cpp +++ b/common_components/heap/allocator/memory_map.cpp @@ -23,7 +23,7 @@ #endif #include "common_components/platform/os.h" -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" #include "common_components/base/sys_call.h" #include "common_components/log/log.h" diff --git a/common_components/heap/allocator/region_manager.cpp b/common_components/heap/allocator/region_manager.cpp index 24e7ea0be7d547cc2986a248cb0fa43881cd741a..5f2d158d47da74f03e2e178a24d6106662cfbc1f 100755 --- a/common_components/heap/allocator/region_manager.cpp +++ b/common_components/heap/allocator/region_manager.cpp @@ -20,7 +20,7 @@ #include #include -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" #include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/allocator/region_space.h" #include "common_components/base/c_string.h" diff --git a/common_components/heap/allocator/tests/heap_allocator_test.cpp b/common_components/heap/allocator/tests/heap_allocator_test.cpp index 7f8c1372b245f9548dbb020a6d50287fa3e91d7a..f23fb161ee0de85b4495a7ea18221b3cc8ba43db 100644 --- a/common_components/heap/allocator/tests/heap_allocator_test.cpp +++ b/common_components/heap/allocator/tests/heap_allocator_test.cpp @@ -19,7 +19,7 @@ #include "common_components/heap/allocator/region_space.h" #include "common_components/heap/collector/trace_collector.h" #include "common_components/heap/heap.cpp" -#include "common_components/base_runtime/base_runtime_param.h" +#include "common_components/common_runtime/base_runtime_param.h" #include "common_components/heap/heap_manager.h" #include "common_components/tests/test_helper.h" diff --git a/common_components/heap/allocator/tests/region_manager_test.cpp b/common_components/heap/allocator/tests/region_manager_test.cpp index 07b15d7c6d6174ba979a0b44576822d17487d392..8fe0bece36eef744cc514973352a06faa14998c3 100755 --- a/common_components/heap/allocator/tests/region_manager_test.cpp +++ b/common_components/heap/allocator/tests/region_manager_test.cpp @@ -16,7 +16,7 @@ #include "common_components/heap/allocator/region_manager.h" #include "common_components/heap/collector/trace_collector.h" #include "common_components/heap/heap.cpp" -#include "common_components/base_runtime/base_runtime_param.h" +#include "common_components/common_runtime/base_runtime_param.h" #include "common_components/heap/heap_manager.h" #include "common_components/tests/test_helper.h" #include diff --git a/common_components/heap/allocator/tests/region_space_test.cpp b/common_components/heap/allocator/tests/region_space_test.cpp index f2db5516d6128e8087cbe86d4abd2f8b119cff1d..de7685e21a8b970f77108b60b084519a0d910acc 100755 --- a/common_components/heap/allocator/tests/region_space_test.cpp +++ b/common_components/heap/allocator/tests/region_space_test.cpp @@ -17,7 +17,7 @@ #include "common_components/heap/allocator/region_space.h" #include "common_components/heap/collector/trace_collector.h" #include "common_components/heap/heap.cpp" -#include "common_components/base_runtime/base_runtime_param.h" +#include "common_components/common_runtime/base_runtime_param.h" #include "common_components/heap/heap_manager.h" #include "common_components/tests/test_helper.h" #include diff --git a/common_components/heap/collector/collector_proxy.h b/common_components/heap/collector/collector_proxy.h index 6cc0ba2fabb58c2280123c0e4472ab847c03222d..27a9fea1964b381715d50372eb75bd1f147bc9cd 100755 --- a/common_components/heap/collector/collector_proxy.h +++ b/common_components/heap/collector/collector_proxy.h @@ -25,7 +25,7 @@ namespace common { // collector. However, it actually manages a set of collectors implemented yet, and delegate garbage-collecting to // one of these collectors. // CollectorProxy should inherit collector interfaces, but no datas -class CollectorProxy : public Collector { +class CollectorProxy final : public Collector { public: explicit CollectorProxy(Allocator& allocator, CollectorResources& resources) : wCollector_(allocator, resources) @@ -87,7 +87,7 @@ public: private: // supported collector set - TraceCollector* currentCollector_ = nullptr; + WCollector* currentCollector_ = nullptr; WCollector wCollector_; }; } // namespace common diff --git a/common_components/heap/heap_visitor.cpp b/common_components/heap/heap_visitor.cpp index c95c25aee1bac33de8db9f1ba4d11b175fbf5eb8..6b9545a87c9604a2c8a54497f08e0064f02694aa 100755 --- a/common_components/heap/heap_visitor.cpp +++ b/common_components/heap/heap_visitor.cpp @@ -15,7 +15,7 @@ #include "common_interfaces/heap/heap_visitor.h" -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" #include "common_components/mutator/mutator.h" namespace common { diff --git a/common_components/heap/w_collector/copy_barrier.cpp b/common_components/heap/w_collector/copy_barrier.cpp index 9feda8c10877c48b3ab83f8c8ce064509f6374c1..4647c687ac90b331dae09deedd6dc032d742ceae 100755 --- a/common_components/heap/w_collector/copy_barrier.cpp +++ b/common_components/heap/w_collector/copy_barrier.cpp @@ -17,6 +17,7 @@ #include "common_components/base/sys_call.h" #include "common_components/common/scoped_object_lock.h" #include "common_components/mutator/mutator.h" +#include "heap/collector/collector_proxy.h" #if defined(COMMON_TSAN_SUPPORT) #include "common_components/sanitizer/sanitizer_interface.h" #endif @@ -26,28 +27,16 @@ BaseObject* CopyBarrier::ReadRefField(BaseObject* obj, RefField& field) c { do { RefField<> tmpField(field); - bool isWeak = tmpField.IsWeak(); - BaseObject* oldRef = tmpField.GetTargetObject(); - if (LIKELY_CC(!theCollector.IsFromObject(oldRef))) { - if (isWeak) { - return (BaseObject*)((uintptr_t)oldRef | TAG_WEAK); - } else { - return oldRef; - } + BaseObject* oldRef = reinterpret_cast(tmpField.GetAddress()); + if (LIKELY_CC(!static_cast(&theCollector)->IsFromObject(oldRef))) { + return oldRef; } + + auto weakMask = reinterpret_cast(oldRef) & TAG_WEAK; + oldRef = reinterpret_cast(reinterpret_cast(oldRef) & (~TAG_WEAK)); BaseObject* toObj = nullptr; - if (theCollector.IsUnmovableFromObject(oldRef)) { - if (isWeak) { - return (BaseObject*)((uintptr_t)oldRef | TAG_WEAK); - } else { - return oldRef; - } - } else if (theCollector.TryForwardRefField(obj, field, toObj)) { - if (isWeak) { - return (BaseObject*)((uintptr_t)toObj | TAG_WEAK); - } else { - return toObj; - } + if (static_cast(&theCollector)->TryForwardRefField(obj, field, toObj)) { + return (BaseObject*)((uintptr_t)toObj | weakMask); } } while (true); // unreachable path. diff --git a/common_components/heap/w_collector/preforward_barrier.cpp b/common_components/heap/w_collector/preforward_barrier.cpp index bd4fda3f3c499c7f1163cb64d73b667a05db961a..4f73e391148f5cfc8cd04e8830e269c08b804481 100755 --- a/common_components/heap/w_collector/preforward_barrier.cpp +++ b/common_components/heap/w_collector/preforward_barrier.cpp @@ -18,6 +18,7 @@ #include "common_components/base/sys_call.h" #include "common_components/common/scoped_object_lock.h" #include "common_components/mutator/mutator.h" +#include "heap/collector/collector_proxy.h" #if defined(COMMON_TSAN_SUPPORT) #include "common_components/sanitizer/sanitizer_interface.h" #endif @@ -27,28 +28,16 @@ BaseObject* PreforwardBarrier::ReadRefField(BaseObject* obj, RefField& fi { do { RefField<> tmpField(field); - bool isWeak = tmpField.IsWeak(); - BaseObject* oldRef = tmpField.GetTargetObject(); - if (LIKELY_CC(!theCollector.IsFromObject(oldRef))) { - if (isWeak) { - return (BaseObject*)((uintptr_t)oldRef | TAG_WEAK); - } else { - return oldRef; - } + BaseObject* oldRef = reinterpret_cast(tmpField.GetAddress()); + if (LIKELY_CC(!static_cast(&theCollector)->IsFromObject(oldRef))) { + return oldRef; } + + auto weakMask = reinterpret_cast(oldRef) & TAG_WEAK; + oldRef = reinterpret_cast(reinterpret_cast(oldRef) & (~TAG_WEAK)); BaseObject* toObj = nullptr; - if (theCollector.IsUnmovableFromObject(oldRef)) { - if (isWeak) { - return (BaseObject*)((uintptr_t)oldRef | TAG_WEAK); - } else { - return oldRef; - } - } else if (theCollector.TryForwardRefField(obj, field, toObj)) { - if (isWeak) { - return (BaseObject*)((uintptr_t)toObj | TAG_WEAK); - } else { - return toObj; - } + if (static_cast(&theCollector)->TryForwardRefField(obj, field, toObj)) { + return (BaseObject*)((uintptr_t)toObj | weakMask); } } while (true); // unreachable path. diff --git a/common_components/heap/w_collector/tests/copy_barrier_test.cpp b/common_components/heap/w_collector/tests/copy_barrier_test.cpp index 6d5d329e697b6267cb67b2235d1a1d2dd090f6b4..178108f97715fde11b613e8593f94a22b3383ffc 100755 --- a/common_components/heap/w_collector/tests/copy_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/copy_barrier_test.cpp @@ -134,7 +134,7 @@ HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST6) RefField field(obj); BaseObject* resultObj = copyBarrier->ReadRefField(obj, field); - ASSERT_TRUE(resultObj == nullptr); + ASSERT_TRUE(resultObj != nullptr); } HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST7) diff --git a/common_components/heap/w_collector/tests/preforward_barrier_test.cpp b/common_components/heap/w_collector/tests/preforward_barrier_test.cpp index 16c429e54e6d84c4f427e019cac482c52cb3543f..559e5938223d4cf059f23aec3b179d8832fc4a85 100755 --- a/common_components/heap/w_collector/tests/preforward_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/preforward_barrier_test.cpp @@ -134,7 +134,7 @@ HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST6) RefField field(obj); BaseObject* resultObj = preforwardBarrier->ReadRefField(obj, field); - ASSERT_TRUE(resultObj == nullptr); + ASSERT_TRUE(resultObj != nullptr); } HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST7) @@ -358,4 +358,3 @@ HWTEST_F_L0(PreforwardBarrierTest, CompareAndSwapRefField_TEST3) ASSERT_FALSE(result); } } // namespace common::test - diff --git a/common_components/heap/w_collector/w_collector.cpp b/common_components/heap/w_collector/w_collector.cpp index d1206c13018cfe058b24cda1e384535a025a51f9..86876bcc92495a5664da85094638aa625e5dcad2 100755 --- a/common_components/heap/w_collector/w_collector.cpp +++ b/common_components/heap/w_collector/w_collector.cpp @@ -14,7 +14,7 @@ */ #include "common_components/heap/w_collector/w_collector.h" -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" #include "common_components/log/log.h" #include "common_components/mutator/mutator_manager-inl.h" #include "common_components/heap/verification.h" diff --git a/common_components/heap/w_collector/w_collector.h b/common_components/heap/w_collector/w_collector.h index 6e318d550f52d5381589a01ef21668d0ef0795bc..627a9d71c825fa18c4c66fc0c1fed8b4c10f6508 100755 --- a/common_components/heap/w_collector/w_collector.h +++ b/common_components/heap/w_collector/w_collector.h @@ -49,7 +49,7 @@ enum class GCMode: uint8_t { STW = 2 }; -class WCollector : public TraceCollector { +class WCollector final : public TraceCollector { public: explicit WCollector(Allocator& allocator, CollectorResources& resources) : TraceCollector(allocator, resources), fwdTable_(reinterpret_cast(allocator)) @@ -135,7 +135,6 @@ public: void SetGCThreadRssPriority(common::RssPriorityType type); void SetGCThreadQosPriority(common::PriorityMode mode); -protected: BaseObject* CopyObjectImpl(BaseObject* obj); BaseObject* CopyObjectAfterExclusive(BaseObject* obj) override; @@ -154,6 +153,7 @@ protected: } } +protected: void CollectLargeGarbage() { COMMON_PHASE_TIMER("Collect large garbage"); diff --git a/common_components/mutator/mutator.cpp b/common_components/mutator/mutator.cpp index 0de940d1bf7257a4926ff4d1b3956e733e76f59b..3f87ed71c7a4de1d1a12b040865fad9585089ed6 100755 --- a/common_components/mutator/mutator.cpp +++ b/common_components/mutator/mutator.cpp @@ -17,7 +17,7 @@ #include #include -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" #include "common_components/common/type_def.h" #if defined(_WIN64) #define NOGDI diff --git a/common_components/mutator/mutator_manager.cpp b/common_components/mutator/mutator_manager.cpp index c01f2617888cc1c8f0b0bc0411d90e58d2a7be5a..d0a9a7c5973c97295c917590493bc8a03e36f742 100755 --- a/common_components/mutator/mutator_manager.cpp +++ b/common_components/mutator/mutator_manager.cpp @@ -23,6 +23,8 @@ #include "common_components/mutator/mutator.inline.h" namespace common { +bool g_enableGCTimeoutCheck = true; + bool IsRuntimeThread() { if (static_cast(ThreadLocal::GetThreadType()) >= static_cast(ThreadType::GC_THREAD)) { @@ -342,6 +344,13 @@ void MutatorManager::WaitUntilAllStopped() return; } + if (UNLIKELY_CC(common::g_enableGCTimeoutCheck && TimeUtil::MilliSeconds() - beginTime > + (((remainMutatorsSize / STW_TIMEOUTS_THREADS_BASE_COUNT) * STW_TIMEOUTS_BASE_MS) + STW_TIMEOUTS_BASE_MS))) { + timeoutTimes++; + beginTime = TimeUtil::MilliSeconds(); + DumpMutators(timeoutTimes); + } + (void)sched_yield(); } } diff --git a/common_components/mutator/mutator_manager.h b/common_components/mutator/mutator_manager.h index d07947c83d82f5fa423ce7eb9ee088ccd4017deb..9db1fb5b06bb7575c204e5d45773ff782129db6d 100755 --- a/common_components/mutator/mutator_manager.h +++ b/common_components/mutator/mutator_manager.h @@ -43,6 +43,8 @@ const uint32_t LOCK_OWNER_NONE = 0; const uint32_t LOCK_OWNER_GC = LOCK_OWNER_NONE + 1; const uint32_t LOCK_OWNER_MUTATOR = LOCK_OWNER_GC + 1; +extern bool g_enableGCTimeoutCheck; + bool IsRuntimeThread(); bool IsGcThread(); diff --git a/common_components/mutator/tests/mutator_manager_test.cpp b/common_components/mutator/tests/mutator_manager_test.cpp index d6a6f79fc2f0f753a093559f256b085ff2ab88c4..87a1649f9575c53c2b573045f68f429f363db7a6 100755 --- a/common_components/mutator/tests/mutator_manager_test.cpp +++ b/common_components/mutator/tests/mutator_manager_test.cpp @@ -15,7 +15,7 @@ #include "common_components/tests/test_helper.h" #include "common_components/mutator/mutator_manager.h" -#include "common_components/base_runtime/base_runtime.cpp" +#include "common_components/common_runtime/base_runtime.cpp" #include "common_components/heap/w_collector/w_collector.h" using namespace common; diff --git a/common_components/mutator/tests/satb_buffer_test.cpp b/common_components/mutator/tests/satb_buffer_test.cpp index 1236bb44fd7afa260dc2a7cd9552a39c40ff069c..41d209d5b72d7ed1e6faeee2a26cdcf40cea7d79 100755 --- a/common_components/mutator/tests/satb_buffer_test.cpp +++ b/common_components/mutator/tests/satb_buffer_test.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "common_components/base_runtime/base_runtime_param.h" +#include "common_components/common_runtime/base_runtime_param.h" #include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/allocator/region_space.h" #include "common_components/mutator/satb_buffer.h" diff --git a/common_components/tests/test_hooks.cpp b/common_components/tests/test_hooks.cpp index bd47af44649bb07e184413475b3d492d237f2131..c7015e5f37f69adeff1e779fe8ac72da64b0af5d 100755 --- a/common_components/tests/test_hooks.cpp +++ b/common_components/tests/test_hooks.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" namespace common { void SetBaseAddress(uintptr_t base) {} diff --git a/common_components/thread/thread_holder.cpp b/common_components/thread/thread_holder.cpp index f6eb026c17f120e1008747895f32525f87e34bff..6d4e89b7326fbea1eb18f57337d39393b61a4a3d 100755 --- a/common_components/thread/thread_holder.cpp +++ b/common_components/thread/thread_holder.cpp @@ -15,7 +15,7 @@ #include "common_interfaces/thread/thread_holder-inl.h" -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" #include "common_components/mutator/mutator.h" #include "common_components/mutator/thread_local.h" #include "common_interfaces/base_runtime.h" diff --git a/ecmascript/compiler/aot_compiler.cpp b/ecmascript/compiler/aot_compiler.cpp index e7723ab847589bdfc73a6b8f0df942d52714accc..7cc17b50087c2cac2004f172c27f9ce0efb5089f 100644 --- a/ecmascript/compiler/aot_compiler.cpp +++ b/ecmascript/compiler/aot_compiler.cpp @@ -75,6 +75,7 @@ int Main(const int argc, const char **argv) // ark_aot_compiler running need disable asm interpreter to disable the loading of AOT files. runtimeOptions.SetEnableAsmInterpreter(false); runtimeOptions.SetOptionsForTargetCompilation(); + runtimeOptions.DisableGCTimeoutCheck(); EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions); if (vm == nullptr) { LOG_COMPILER(ERROR) << "Cannot Create vm"; diff --git a/ecmascript/compiler/barrier_stub_builder.cpp b/ecmascript/compiler/barrier_stub_builder.cpp index 7334e0a957c2074e6524a012c3a6c642aa4f1b88..ab694ba8fcf5c98f275802d3a342d6acc9f24a6f 100644 --- a/ecmascript/compiler/barrier_stub_builder.cpp +++ b/ecmascript/compiler/barrier_stub_builder.cpp @@ -744,27 +744,103 @@ void BarrierStubBuilder::DoReverseBarrier() { auto env = GetEnvironment(); Label entry(env); - env->SubCfgEntry(&entry); Label exit(env); Label checkNext(env); + Label needMarking(env); + Label notMarkRSet(env); + Label markInBuffer(env); + Label continueProcessing(env); + Label isTaggedObject(env); + Label RefisTaggedObject(env); + Label markRSet(env); + Label continueLoopHead(env); + Label continueLoopEnd(env); + Label notMarkRSetLoopHead(env); + Label notMarkRSetLoopEnd(env); + Label iLessLength(env); + Label indexLessLength(env); + env->SubCfgEntry(&entry); + BRANCH_UNLIKELY(LoadPrimitive( VariableType::BOOL(), glue_, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))), - &exit, &checkNext); + &needMarking, &checkNext); + Bind(&needMarking); + { + GateRef objRegionType = GetCMCRegionType(dstObj_); + GateRef gcPhase = GetGCPhase(glue_); + GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase); + BRANCH(CMCIsInYoungSpace(objRegionType), ¬MarkRSet, &continueProcessing); + Bind(&continueProcessing); + { + DEFVARIABLE(i, VariableType::INT32(), Int32(0)); + Label checkOldToYoung(env); + BRANCH(ShouldUpdateRememberSet(glue_, gcPhase), &checkOldToYoung, ¬MarkRSet); + Bind(&checkOldToYoung); + Jump(&continueLoopHead); + LoopBegin(&continueLoopHead); + { + BRANCH(Int32UnsignedLessThan(*i, slotCount_), &iLessLength, ¬MarkRSet); + Bind(&iLessLength); + { + //GateRef offset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(sizeof(uintptr_t))); + GateRef offset = PtrMul(ZExtInt32ToPtr(*i), IntPtr(JSTaggedValue::TaggedTypeSize())); + GateRef ref = LoadPrimitive(VariableType::JS_ANY(), dstAddr_, offset); + BRANCH(TaggedIsHeapObject(ref), &isTaggedObject, &continueLoopEnd); + } + Bind(&isTaggedObject); + MarkRSetCardTable(dstObj_, ¬MarkRSet); + Bind(&continueLoopEnd); + i = Int32Add(*i, Int32(1)); + LoopEnd(&continueLoopHead); + } + } + Bind(¬MarkRSet); + { + DEFVARIABLE(index, VariableType::INT32(), Int32(0)); + GateRef gcPhase = GetGCPhase(glue_); + GateRef shouldProcessSATB = ShouldProcessSATB(gcPhase); + Jump(¬MarkRSetLoopHead); + LoopBegin(¬MarkRSetLoopHead); + { + BRANCH_LIKELY(Int32UnsignedLessThan(*index, slotCount_), &indexLessLength, &exit); + Bind(&indexLessLength); + GateRef offset = PtrMul(ZExtInt32ToPtr(*index), IntPtr(JSTaggedValue::TaggedTypeSize())); + GateRef ref = LoadPrimitive(VariableType::JS_ANY(), dstAddr_, offset); + + BRANCH(TaggedIsHeapObject(ref), &RefisTaggedObject, ¬MarkRSetLoopEnd); + Bind(&RefisTaggedObject); + + BRANCH_UNLIKELY(shouldProcessSATB, &markInBuffer, &exit); + Bind(&markInBuffer); + { + ASSERT(RuntimeStubCSigns::Get(RTSTUB_ID(MarkInBuffer))->IsNoTailCall()); + CallNGCRuntime(glue_, RTSTUB_ID(MarkInBuffer), {ref}); + Jump(¬MarkRSetLoopEnd); + } + + Bind(¬MarkRSetLoopEnd); + index = Int32Add(*index, Int32(1)); + LoopEnd(¬MarkRSetLoopHead); + } + } + } Bind(&checkNext); - Label handleMark(env); - Label handleBitSet(env); - Label doReverse(env); - BRANCH_NO_WEIGHT(Int32Equal(slotCount_, Int32(0)), &exit, &doReverse); - Bind(&doReverse); - BRANCH_NO_WEIGHT(InSharedHeap(objectRegion_), &handleMark, &handleBitSet); - Bind(&handleBitSet); { - DoReverseBarrierInternal(); - Jump(&handleMark); + Label handleMark(env); + Label handleBitSet(env); + Label doReverse(env); + BRANCH_NO_WEIGHT(Int32Equal(slotCount_, Int32(0)), &exit, &doReverse); + Bind(&doReverse); + BRANCH_NO_WEIGHT(InSharedHeap(objectRegion_), &handleMark, &handleBitSet); + Bind(&handleBitSet); + { + DoReverseBarrierInternal(); + Jump(&handleMark); + } + Bind(&handleMark); + HandleMark(); + Jump(&exit); } - Bind(&handleMark); - HandleMark(); - Jump(&exit); Bind(&exit); env->SubCfgExit(); } diff --git a/ecmascript/compiler/barrier_stub_builder.h b/ecmascript/compiler/barrier_stub_builder.h index 0fdc1bf71ad7e03d9fb412825bf13f1d8a8a1ae7..7a540f2f593988c9495f0e29ec874c4436bb9f83 100644 --- a/ecmascript/compiler/barrier_stub_builder.h +++ b/ecmascript/compiler/barrier_stub_builder.h @@ -24,6 +24,7 @@ public: BarrierStubBuilder(StubBuilder *parent, GateRef glue, GateRef obj, GateRef startAddr, GateRef slotCount) : StubBuilder(parent), glue_(glue), + dstObj_(obj), dstAddr_(startAddr), slotCount_(slotCount), objectRegion_(ObjectAddressToRange(obj)) {} @@ -69,6 +70,7 @@ private: void BitSetRangeReverse(GateRef bitSet, GateRef startIdx, GateRef length); void DoMoveBarrierSameRegionKind(GateRef srcAddr, GateRef srcRegion, RegionKind regionKind); const GateRef glue_; + const GateRef dstObj_; const GateRef dstAddr_; const GateRef slotCount_; const GateRef objectRegion_; diff --git a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp index ff49664ed77df2e57bd90d71c46572fa80664452..ac7b074a21feeeeb83fb75ac3222bad5656f8331 100644 --- a/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_array_stub_builder.cpp @@ -2039,15 +2039,9 @@ void BuiltinsArrayStubBuilder::Reverse(GateRef glue, GateRef thisValue, [[maybe_ Bind(¬COWArray); GateRef thisLen = GetArrayLength(thisValue); GateRef thisArrLen = ZExtInt32ToInt64(thisLen); -// CMC-GC may need to fix it later #if ENABLE_NEXT_OPTIMIZATION Label useReversBarrier(env); Label noReverseBarrier(env); - Label checkNext(env); - BRANCH_UNLIKELY( - LoadPrimitive(VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))), - &noReverseBarrier, &checkNext); - Bind(&checkNext); // 10 : length < 10 reverse item by item BRANCH(Int32LessThan(thisLen, Int32(10)), &noReverseBarrier, &useReversBarrier); Bind(&useReversBarrier); diff --git a/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp index 92dba9d4c8a392a5a91d578cb5118690c65e50c1..fab81a91d8e9ea7fd2253368ccda48539a25c2e3 100644 --- a/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_proxy_stub_builder.cpp @@ -180,7 +180,7 @@ GateRef BuiltinsProxyStubBuilder::GetProperty(GateRef proxy, GateRef key, GateRe Label handlerIsNotNull(env); Label slowPath(env); Label trapIsCallable(env); - Label trapIsNotUndefinedOrNullOrHole(env); + Label trapFastPath(env); GateRef handler = GetHandler(glue_, proxy); BRANCH(TaggedIsNull(handler), &handlerIsNull, &handlerIsNotNull); Bind(&handlerIsNull); @@ -196,8 +196,8 @@ GateRef BuiltinsProxyStubBuilder::GetProperty(GateRef proxy, GateRef key, GateRe GateRef name = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::GET_STRING_INDEX); GateRef trap = GetPropertyByName(glue_, handler, name); - BRANCH(TaggedIsUndefinedOrNullOrHole(trap), &slowPath, &trapIsNotUndefinedOrNullOrHole); - Bind(&trapIsNotUndefinedOrNullOrHole); + BRANCH(TaggedIsHeapObject(trap), &trapFastPath, &slowPath); + Bind(&trapFastPath); { BRANCH(IsCallable(glue_, trap), &trapIsCallable, &slowPath); Bind(&trapIsCallable); @@ -238,7 +238,7 @@ GateRef BuiltinsProxyStubBuilder::SetProperty(GateRef proxy, GateRef key, GateRe Label handlerIsNotNull(env); Label slowPath(env); Label trapIsCallable(env); - Label trapIsNotUndefinedOrNullOrHole(env); + Label trapFastPath(env); GateRef handler = GetHandler(glue_, proxy); BRANCH(TaggedIsNull(handler), &handlerIsNull, &handlerIsNotNull); Bind(&handlerIsNull); @@ -254,8 +254,8 @@ GateRef BuiltinsProxyStubBuilder::SetProperty(GateRef proxy, GateRef key, GateRe GateRef name = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::SET_STRING_INDEX); GateRef trap = GetPropertyByName(glue_, handler, name); - BRANCH(TaggedIsUndefinedOrNullOrHole(trap), &slowPath, &trapIsNotUndefinedOrNullOrHole); - Bind(&trapIsNotUndefinedOrNullOrHole); + BRANCH(TaggedIsHeapObject(trap), &trapFastPath, &slowPath); + Bind(&trapFastPath); { BRANCH(IsCallable(glue_, trap), &trapIsCallable, &slowPath); Bind(&trapIsCallable); diff --git a/ecmascript/compiler/mcr_lowering.cpp b/ecmascript/compiler/mcr_lowering.cpp index 13051b6776fd517dd3f86b641e875e8d8ba5b0b0..c3f4057a062a66a653eb8a3062ca41b8d7b8ff28 100644 --- a/ecmascript/compiler/mcr_lowering.cpp +++ b/ecmascript/compiler/mcr_lowering.cpp @@ -878,7 +878,7 @@ void MCRLowering::LowerRemainderIsNegativeZero(GateRef gate) GateRef left = acc_.GetValueIn(gate, 0); GateRef right = acc_.GetValueIn(gate, 1); GateRef remainderIsNegative = LogicAndBuilder(&env) - .And(builder_.Int32LessThan(left, builder_.Int32(0))) + .And(builder_.Int32LessThanOrEqual(left, builder_.Int32(0))) .And(builder_.Int32Equal(builder_.Int32(0), builder_.BinaryArithmetic(circuit_->Smod(), MachineType::I32, left, right, GateType::NJSValue()))) .Done(); diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index 8b1de65d3fb682e0adb0b67649822649cb6c2564..2a39f1a1177aad487a1bb20e89b87b1d252f851d 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -32,6 +32,7 @@ #include "ecmascript/require/js_cjs_module_cache.h" #include "ecmascript/transitions_dictionary.h" #include "common_components/heap/allocator/region_desc.h" +#include "objects/base_state_word.h" namespace panda::ecmascript::kungfu { void StubBuilder::Jump(Label *label) @@ -1059,7 +1060,7 @@ GateRef StubBuilder::JSObjectHasProperty(GateRef glue, GateRef obj, GateRef key, opStubBuilder.StartLookup( glue, key, &checkHolder, opOptions, opResult, hir); - // if holder is JSProxy, op's lookup will return. This will be handled by CallRuntime. + // if holder is JSProxy, op's lookup will return. This will be handled by CallRuntime. Bind(&checkHolder); { Label isJSProxy(env); @@ -1923,7 +1924,7 @@ GateRef StubBuilder::GetCMCRegionType(GateRef obj) return regionDescAddr; } -GateRef StubBuilder::IsInYoungSpace(GateRef regionType) +GateRef StubBuilder::CMCIsInYoungSpace(GateRef regionType) { auto env = GetEnvironment(); GateRef ret = LogicOrBuilder(env) @@ -1938,8 +1939,8 @@ GateRef StubBuilder::IsOldToYoung(GateRef objRegionType, GateRef valueRegionType { auto env = GetEnvironment(); GateRef isOldToYoung = LogicAndBuilder(env) - .And(BoolNot(IsInYoungSpace(objRegionType))) - .And(IsInYoungSpace(valueRegionType)).Done(); + .And(BoolNot(CMCIsInYoungSpace(objRegionType))) + .And(CMCIsInYoungSpace(valueRegionType)).Done(); return isOldToYoung; } @@ -2353,8 +2354,62 @@ GateRef StubBuilder::GetValueWithBarrier(GateRef glue, GateRef addr) } Bind(&isHeapObject); { - result = CallNGCRuntime(glue, RTSTUB_ID(ReadBarrier), { glue, addr }); - Jump(&exit); + Label isHeapAddress(env); + Label notHeapAddress(env); + BRANCH(IsHeapAddress(glue, value), &isHeapAddress, ¬HeapAddress); + Bind(¬HeapAddress); + { + result = value; + Jump(&exit); + } + Bind(&isHeapAddress); + { + result = FastReadBarrier(glue, addr, value); + Jump(&exit); + } + } + + Bind(&exit); + auto ret = *result; + env->SubCfgExit(); + return ret; +} + +GateRef StubBuilder::FastReadBarrier(GateRef glue, GateRef addr, GateRef value) +{ + auto env = GetEnvironment(); + Label entry(env); + env->SubCfgEntry(&entry); + Label exit(env); + DEFVARIABLE(result, VariableType::JS_ANY(), value); + + GateRef intValue = ChangeTaggedPointerToInt64(value); + GateRef regionType = GetCMCRegionType(value); + Label isFromeSpace(env); + GateRef fromType = Int8(static_cast(common::RegionDesc::RegionType::FROM_REGION)); + Branch(Int8Equal(regionType, fromType), &isFromeSpace, &exit); + Bind(&isFromeSpace); + { + GateRef weakMask = Int64And(intValue, Int64(JSTaggedValue::TAG_WEAK)); + GateRef obj = Int64And(intValue, Int64(~JSTaggedValue::TAG_WEAK)); + + GateRef forwardedAddr = LoadPrimitive(VariableType::INT64(), obj, IntPtr(0)); + GateRef forwardState = + Int64LSR(forwardedAddr, Int64(common::BaseStateWord::PADDING_WIDTH + common::BaseStateWord::FORWARD_WIDTH)); + Label forwarded(env); + Label notForwarded(env); + Branch(Int64Equal(forwardState, Int64(static_cast(common::BaseStateWord::ForwardState::FORWARDED))), + &forwarded, ¬Forwarded); + Bind(&forwarded); + { + result = Int64ToTaggedPtr(Int64Or(Int64And(forwardedAddr, Int64(TaggedStateWord::ADDRESS_MASK)), weakMask)); + Jump(&exit); + } + Bind(¬Forwarded); + { + result = CallNGCRuntime(glue, RTSTUB_ID(ReadBarrier), { glue, addr }); + Jump(&exit); + } } Bind(&exit); @@ -2363,6 +2418,17 @@ GateRef StubBuilder::GetValueWithBarrier(GateRef glue, GateRef addr) return ret; } +GateRef StubBuilder::IsHeapAddress(GateRef glue, GateRef value) +{ + bool isArch32 = GetEnvironment()->Is32Bit(); + GateRef heapStartAddr = LoadPrimitive( + VariableType::NATIVE_POINTER(), glue, IntPtr(JSThread::GlueData::GetHeapStartAddrOffset(isArch32))); + GateRef heapCurrentEnd = LoadPrimitive( + VariableType::NATIVE_POINTER(), glue, IntPtr(JSThread::GlueData::GetHeapCurrentEndOffset(isArch32))); + auto IntPtrValue = ChangeTaggedPointerToInt64(value); + return BitAnd(IntPtrGreaterThanOrEqual(IntPtrValue, heapStartAddr), IntPtrLessThan(IntPtrValue, heapCurrentEnd)); +} + GateRef StubBuilder::TaggedIsBigInt(GateRef glue, GateRef obj) { auto env = GetEnvironment(); @@ -12661,7 +12727,7 @@ void StubBuilder::EndTraceLoadValue([[maybe_unused]]GateRef glue) #endif } -void StubBuilder::StartTraceCallDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef profileTypeInfo, +void StubBuilder::StartTraceCallDetail([[maybe_unused]] GateRef glue, [[maybe_unused]] GateRef profileTypeInfo, [[maybe_unused]] GateRef slotId) { #if ECMASCRIPT_ENABLE_TRACE_CALL diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index 54f2380af45ffa496b7542b68d4aa08d3a870808..6522764427ed2487f3d6480dae0ccde54f5e030e 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -188,7 +188,7 @@ public: GateRef CallRuntimeWithGlobalEnv(GateRef glue, GateRef globalEnv, int index, const std::vector& args); GateRef CallRuntimeWithGlobalEnv(GateRef glue, GateRef globalEnv, int index, GateRef argc, GateRef argv); GateRef CallRuntimeWithCurrentEnv(GateRef glue, GateRef currentEnv, int index, const std::vector& args); - + GateRef CallNGCRuntime(GateRef glue, int index, const std::vector& args, GateRef hir = Circuit::NullGate()); GateRef FastCallOptimized(GateRef glue, GateRef code, @@ -823,7 +823,7 @@ public: GateRef GetCMCRegionType(GateRef obj); GateRef GetGCPhase(GateRef glue); GateRef GetGCReason(GateRef glue); - GateRef IsInYoungSpace(GateRef regionType); + GateRef CMCIsInYoungSpace(GateRef regionType); GateRef IsOldToYoung(GateRef objRegionType, GateRef valueRegionType); void MarkRSetCardTable(GateRef obj, Label *exit); GateRef ShouldGetGCReason(GateRef gcPhase); @@ -834,6 +834,8 @@ public: void SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, MemoryAttribute::ShareFlag share = MemoryAttribute::UNKNOWN); GateRef GetValueWithBarrier(GateRef glue, GateRef addr); + GateRef FastReadBarrier(GateRef glue, GateRef addr, GateRef value); + GateRef IsHeapAddress(GateRef glue, GateRef value); GateRef GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, ProfileOperation callback, GateRef hir = Circuit::NullGate()); GateRef GetPropertyByName(GateRef glue, diff --git a/ecmascript/js_runtime_options.cpp b/ecmascript/js_runtime_options.cpp index 2083f21e56c00151fbbd5390763e549ca8da9467..5ee5fdccf6e3f5dafb4c7df10484693705ce29ae 100644 --- a/ecmascript/js_runtime_options.cpp +++ b/ecmascript/js_runtime_options.cpp @@ -18,7 +18,7 @@ #include #include -#include "common_components/base_runtime/base_runtime_param.h" +#include "common_components/common_runtime/base_runtime_param.h" #include "ecmascript/compiler/aot_file/an_file_data_manager.h" #include "ecmascript/compiler/assembler/assembler.h" #include "ecmascript/compiler/bc_call_signature.h" diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index f29b0abf7db96ec46d8d19fb794fc366bda913fe..cb78d4b375ecaa1f3d2d67c43f0ee99d8aa518d8 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -22,7 +22,7 @@ #include #include -#include "common_components/base_runtime/base_runtime_param.h" +#include "common_components/common_runtime/base_runtime_param.h" #include "common_components/log/log_base.h" #include "common_interfaces/base/common.h" #include "common_interfaces/base/runtime_param.h" @@ -2250,6 +2250,16 @@ public: return disableModuleSnapshot_; } + void DisableGCTimeoutCheck() + { + enableGCTimeoutCheck_ = false; + } + + bool IsEnableGCTimeoutCheck() const + { + return enableGCTimeoutCheck_; + } + static bool ParseBool(const std::string &arg, bool* argBool); static bool ParseInt(const std::string &arg, int* argInt); static bool ParseUint32(const std::string &arg, uint32_t* argUInt32); @@ -2570,6 +2580,7 @@ private: common::RuntimeParam param_; bool enableWarmStartupSmartGC_ {false}; bool disableModuleSnapshot_ { false }; + bool enableGCTimeoutCheck_ {true}; }; } // namespace panda::ecmascript diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index e261123af93dd84b5ec89b204ed09df9cdd1a7b8..8373458b39d45d523790d62772d75ffa9a2c0cc8 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -1109,12 +1109,25 @@ public: return glueData_.allocBuffer_; } + void OnHeapCreated(uintptr_t startAddr) + { + glueData_.heapStartAddr_ = startAddr; + glueData_.heapCurrentEnd_ = 0; + } + + void OnHeapExtended(uintptr_t newEnd) + { + glueData_.heapCurrentEnd_ = newEnd; + } + struct GlueData : public base::AlignedStruct(Index::ThreadHolderIndex)>(isArch32); } + static size_t GetHeapStartAddrOffset(bool isArch32) + { + return GetOffset(Index::HeapStartAddrIndex)>(isArch32); + } + + static size_t GetHeapCurrentEndOffset(bool isArch32) + { + return GetOffset(Index::HeapCurrentEndIndex)>(isArch32); + } + static size_t GetAllocBufferOffset(bool isArch32) { return GetOffset(Index::AllocBufferIndex)>(isArch32); @@ -1511,6 +1536,8 @@ public: alignas(EAS) BCStubEntries bcStubEntries_ {}; alignas(EAS) uint32_t isEnableCMCGC_ {0}; alignas(EAS) uintptr_t threadHolder_ {0}; + alignas(EAS) uintptr_t heapStartAddr_ {0}; + alignas(EAS) uintptr_t heapCurrentEnd_ {0}; alignas(EAS) uintptr_t allocBuffer_ {0}; alignas(EAS) ThreadStateAndFlags stateAndFlags_ {}; alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()}; diff --git a/ecmascript/mem/barriers.h b/ecmascript/mem/barriers.h index 4b4164ef937f2012fe403caf39ea1dddad5acd0c..478f9653782b9e90b43d0f17d503b9d1097f1210 100644 --- a/ecmascript/mem/barriers.h +++ b/ecmascript/mem/barriers.h @@ -88,6 +88,8 @@ public: return *addr; } + static JSTaggedType ReadBarrierForObject(const JSThread *thread, uintptr_t value); + static TaggedObject* GetTaggedObject(const JSThread *thread, const void* obj, size_t offset); static JSTaggedType GetTaggedValue(const JSThread *thread, const void *obj, size_t offset); static JSTaggedType GetTaggedValue(const JSThread *thread, uintptr_t slotAddress); diff --git a/ecmascript/mem/barriers_get-inl.h b/ecmascript/mem/barriers_get-inl.h index 1f02db5552b91cae38d0d11c4fddfa3b0a5bca21..b37705972f6c7ce1d72d1ce68da0b7cd6c99d0ba 100644 --- a/ecmascript/mem/barriers_get-inl.h +++ b/ecmascript/mem/barriers_get-inl.h @@ -70,6 +70,18 @@ static ARK_INLINE JSTaggedType AtomicReadBarrier(const JSThread *thread, const v return value.GetRawData(); } +inline ARK_INLINE JSTaggedType Barriers::ReadBarrierForObject(const JSThread *thread, uintptr_t slotAddress) +{ +#ifdef ENABLE_CMC_RB_DFX + JSTaggedValue valueRB( + reinterpret_cast(common::BaseRuntime::ReadBarrier((void *)slotAddress))); + valueRB.RemoveReadBarrierDFXTag(); + return valueRB.GetRawData(); +#else + return reinterpret_cast(common::BaseRuntime::ReadBarrier((void*)slotAddress)); +#endif +} + inline ARK_INLINE JSTaggedType Barriers::GetTaggedValue(const JSThread *thread, const void *obj, size_t offset) { JSTaggedValue value = *reinterpret_cast(ToUintPtr(obj) + offset); diff --git a/ecmascript/mem/cmc_gc/hooks.cpp b/ecmascript/mem/cmc_gc/hooks.cpp index 5e35ca3ddebd899b5c0cc7b74eb5b087a23c6879..6862688609bf4645bfdddc8951c241809499f270 100644 --- a/ecmascript/mem/cmc_gc/hooks.cpp +++ b/ecmascript/mem/cmc_gc/hooks.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" #include diff --git a/ecmascript/mem/tagged_state_word.h b/ecmascript/mem/tagged_state_word.h index aec23f55a8f56b0b20171fff043b13fda43774d7..402a3158b8e3cffdb56cb0dc86c1cc56e9663403 100644 --- a/ecmascript/mem/tagged_state_word.h +++ b/ecmascript/mem/tagged_state_word.h @@ -27,15 +27,18 @@ class TaggedObject; class TaggedStateWord { public: + static constexpr size_t ADDRESS_WIDTH = 48; + static constexpr uint64_t ADDRESS_MASK = (0x1ULL << ADDRESS_WIDTH) - 1; + // Little endian struct GCStateWord { - common::StateWordType address_ : 48; + common::StateWordType address_ : ADDRESS_WIDTH; common::StateWordType padding_ : 12; common::StateWordType remainded_ : 4; }; struct ClassStateWord { - ClassWordType class_ : 48; + ClassWordType class_ : ADDRESS_WIDTH; ClassWordType padding_ : 12; ClassWordType remainded_ : 4; }; diff --git a/ecmascript/runtime.cpp b/ecmascript/runtime.cpp index 41fd48f07540d5fc6b41d20fc3dc5a8a7f7832e6..cecd39237ca204df1ce9ad01c501e461c0af5122 100644 --- a/ecmascript/runtime.cpp +++ b/ecmascript/runtime.cpp @@ -14,7 +14,8 @@ */ #include "ecmascript/runtime.h" -#include "common_components/base_runtime/hooks.h" +#include "common_components/common_runtime/hooks.h" +#include "common_components/mutator/mutator_manager.h" #include "ecmascript/checkpoint/thread_state_transition.h" #include "common_interfaces/base_runtime.h" #include "ecmascript/dynamic_object_accessor.h" @@ -87,6 +88,7 @@ void Runtime::CreateIfFirstVm(const JSRuntimeOptions &options) // SetConfigHeapSize for cmc gc, pc and persist config may change heap size. const_cast(options).SetConfigHeapSize(MemMapAllocator::GetInstance()->GetCapacity()); common::BaseRuntime::GetInstance()->Init(options.GetRuntimeParam()); + common::g_enableGCTimeoutCheck = options.IsEnableGCTimeoutCheck(); } DaemonThread::CreateNewInstance(); firstVmCreated_ = true; @@ -217,6 +219,8 @@ void Runtime::RegisterThread(JSThread* newThread) ThreadHolder* threadHolder = newThread->GetThreadHolder(); threadHolder->BindMutator(); newThread->SetAllocBuffer(threadHolder->GetAllocBuffer()); + newThread->OnHeapCreated(common::Heap::heapStartAddr_); + newThread->OnHeapExtended(common::Heap::heapCurrentEnd_); threadHolder->RegisterJSThread(newThread); } else { // send all current suspended requests to the new thread diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 18a4aaeefc6872e286943233611a7889922a61bf..5dd40211a3a77086ee6b78d9afb816e7ceb4c396 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -3525,7 +3525,7 @@ void RuntimeStubs::CMCGCMarkingBarrier([[maybe_unused]] uintptr_t argGlue, JSTaggedType RuntimeStubs::ReadBarrier(uintptr_t argGlue, uintptr_t addr) { auto thread = JSThread::GlueToJSThread(argGlue); - return Barriers::GetTaggedValue(thread, addr); + return Barriers::ReadBarrierForObject(thread, addr); } void RuntimeStubs::CopyCallTarget(uintptr_t argGlue, uintptr_t callTarget) diff --git a/ecmascript/tagged_array.cpp b/ecmascript/tagged_array.cpp index 1686de53f8f6345d8ecfa47d312bfc632af176b1..23cac61bdb1ef208926b90ba130387a6b5179803 100644 --- a/ecmascript/tagged_array.cpp +++ b/ecmascript/tagged_array.cpp @@ -118,16 +118,14 @@ void TaggedArray::InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t l { SetLength(length); SetExtraLength(extraLength); - FillRangeWithSpecialValue(initValue, 0, length); + ASSERT(initValue.IsSpecial()); + std::fill_n(GetData(), length, initValue.GetRawData()); } void TaggedArray::FillRangeWithSpecialValue(JSTaggedValue initValue, uint32_t start, uint32_t end) { ASSERT(initValue.IsSpecial()); - for (uint32_t i = start; i < end; i++) { - size_t offset = JSTaggedValue::TaggedTypeSize() * i; - Barriers::SetPrimitive(GetData(), offset, initValue.GetRawData()); - } + std::fill_n(GetData() + start, end - start, initValue.GetRawData()); } JSHandle TaggedArray::SetCapacity(const JSThread *thread, const JSHandle &array, diff --git a/test/jittest/BUILD.gn b/test/jittest/BUILD.gn index dd67dafa9c2a05254821988bb1b94e22780e6ba7..06929dd6e07fa8614fe53234951770a024f42113 100644 --- a/test/jittest/BUILD.gn +++ b/test/jittest/BUILD.gn @@ -102,6 +102,7 @@ group("ark_jit_ts_test") { "constructor", "intrinsic_test", "intrinsic_test2", + "negative_zero_mod", ] # Until we support barriers for HeapConstant table diff --git a/test/jittest/negative_zero_mod/BUILD.gn b/test/jittest/negative_zero_mod/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..58c14272c4de30c9492bb8206bed0102acc6d81d --- /dev/null +++ b/test/jittest/negative_zero_mod/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2025 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. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_jit_test_action("negative_zero_mod") { + deps = [] +} diff --git a/test/jittest/negative_zero_mod/expect_output.txt b/test/jittest/negative_zero_mod/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..b49650a324ce34d44df4d0d033418958883eb438 --- /dev/null +++ b/test/jittest/negative_zero_mod/expect_output.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2025 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. + +compilerResult: true diff --git a/common_components/common_runtime/src/cpu_profiler/cpu_profiler.h b/test/jittest/negative_zero_mod/negative_zero_mod.ts old mode 100755 new mode 100644 similarity index 46% rename from common_components/common_runtime/src/cpu_profiler/cpu_profiler.h rename to test/jittest/negative_zero_mod/negative_zero_mod.ts index a303e57273aa8050fcff5992c5f083a80c1122a4..2f45ee15a71997fea7553d90378525386748b878 --- a/common_components/common_runtime/src/cpu_profiler/cpu_profiler.h +++ b/test/jittest/negative_zero_mod/negative_zero_mod.ts @@ -12,28 +12,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef ARK_COMMON_CPU_PROFILER_H -#define ARK_COMMON_CPU_PROFILER_H -#include +function moduloWithNegativeZeroDividend(a, b, c) { + var temp = a * b; + return temp % c; +} -namespace panda { -class CpuProfiler { -public: - static CpuProfiler& GetInstance() - { - static CpuProfiler instance; - return instance; +for (var i = 1; i < 100; i++) { + var result = moduloWithNegativeZeroDividend(i, 5, 5); + if (result !== 0) { + throw "moduloWithNegativeZeroDividend(i, 5, 5), returned: " + result; } - bool StartCpuProfilerForFile(); - bool StopCpuProfilerForFile(const int fd); - void TryStopSampling(); +} -private: - CpuProfiler() {} - ~CpuProfiler(); - static void DoSampleStack(); - std::thread tid_; -}; -} // namespace panda -#endif +ArkTools.jitCompileAsync(moduloWithNegativeZeroDividend); +var compilerResult = ArkTools.waitJitCompileFinish(moduloWithNegativeZeroDividend); +print("compilerResult: " + compilerResult); + +for (var i = 1; i < 100; i++) { + var result = moduloWithNegativeZeroDividend(-i, 0, 2); + if (!(result === 0 && (1 / result) === -Infinity)) { + throw "moduloWithNegativeZeroDividend(i, 5, 5), returned: " + result; + } +} diff --git a/test/moduletest/proxy/expect_output.txt b/test/moduletest/proxy/expect_output.txt index e600bc134c346f8a1e95486e3963f8963ea7921a..4eaa14397f4d107b33c75cf843bbe45b5c329a63 100644 --- a/test/moduletest/proxy/expect_output.txt +++ b/test/moduletest/proxy/expect_output.txt @@ -29,3 +29,4 @@ test proxy constructor success! false TypeError: ProxyCreate: handler is not Object test proxy getPrototype success! +TypeError diff --git a/test/moduletest/proxy/proxy.js b/test/moduletest/proxy/proxy.js index 9992a3587a67776aae9987c7c7f8f60524640928..c6f0a36a303871d9ead975224831da64e8d8354a 100644 --- a/test/moduletest/proxy/proxy.js +++ b/test/moduletest/proxy/proxy.js @@ -144,4 +144,31 @@ const v7 = new Proxy(Reflect, Reflect); const v9 = new Proxy(v7, Reflect); for (const v10 in v9) { } -print("test proxy getPrototype success!"); \ No newline at end of file +print("test proxy getPrototype success!"); + +{ + try { + const v1 = []; + function f3() { + } + class C25 { + } + const v26 = []; + function f27() { + } + function f30() { + const o31 = { + }; + o31.get = f3; + const v33 = new Proxy(C25, o31); + v33.bind(v33, v33, o31, o31, f27); + return 1; + } + f3 ^= f3; + f27[Symbol.species] = f30; + v26.constructor = f27; + v26.flat(); + } catch (err) { + print(err.name); + } +} \ No newline at end of file diff --git a/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt b/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt index 124bdacf5ba369643309cc837961082fb308184d..6c0132b73cf13e7b3bf2999b537b9ae174699a50 100644 --- a/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt +++ b/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt @@ -26,3 +26,6 @@ regresstest/ark-regress/mjsunit/compiler/lazy-deopt-async-function-resolve.js regresstest/ark-regress/mjsunit/compiler/bigint-compare.js regresstest/ark-regress/mjsunit/regress/regress-crbug-631318-10.js regresstest/ark-regress/mjsunit/regress/regress-2073.js + +#27744 +regresstest/ark-regress/mjsunit/regress/regress-dictionary-to-fast-arguments.js diff --git a/test/ut/ignore-ut-debug-x64-ets_runtime.txt b/test/ut/ignore-ut-debug-x64-ets_runtime.txt index b6fbd83447cb672ac310417a3fe1d6f2d7fd3eb2..79195e02b2db3afca94cfea21c125cea42d8bd60 100644 --- a/test/ut/ignore-ut-debug-x64-ets_runtime.txt +++ b/test/ut/ignore-ut-debug-x64-ets_runtime.txt @@ -21,3 +21,6 @@ obj/arkcompiler/ets_runtime/test/jittest/icnotfound/icnotfound #23099 obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/PGOProfilerTestOne + +#27690 +obj/arkcompiler/ets_runtime/test/jittest/throw_error/throw_error diff --git a/test/ut/ignore-ut-release-qemu-ets_runtime.txt b/test/ut/ignore-ut-release-qemu-ets_runtime.txt index e224840ca792e877faa640b18629f2b0bec34b6e..00881b9376144c890ccd83220a78b10ff9c2c3e0 100644 --- a/test/ut/ignore-ut-release-qemu-ets_runtime.txt +++ b/test/ut/ignore-ut-release-qemu-ets_runtime.txt @@ -203,5 +203,10 @@ obj/arkcompiler/ets_runtime/ecmascript/base/tests/JSHelper_NumberHelper_TestWith obj/arkcompiler/ets_runtime/ecmascript/napi/test/Jsnapi_004_TestWithQemu obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/PGOProfilerTestWithQemu +<<<<<<< HEAD #27484 obj/arkcompiler/ets_runtime/common_components/mutator/tests/Mutator_TestWithQemu +======= +#27555 +obj/arkcompiler/ets_runtime/common_components/mutator/tests/Mutator_Manager_TestWithQemu +>>>>>>> 1530067fd... Update kfl 0710