14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include <fstream>
204514f5e3Sopenharmony_ci#include <limits.h>
214514f5e3Sopenharmony_ci#include <sstream>
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_ci#include "ecmascript/dfx/hprof/file_stream.h"
244514f5e3Sopenharmony_ci#include "ecmascript/mem/c_containers.h"
254514f5e3Sopenharmony_ci#include "ecmascript/mem/c_string.h"
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_ci#include "securec.h"
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_cinamespace panda::ecmascript {
304514f5e3Sopenharmony_ciusing fstream = std::fstream;
314514f5e3Sopenharmony_ciusing stringstream = std::stringstream;
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_ciclass HeapSnapshot;
344514f5e3Sopenharmony_ciclass TraceNode;
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_ciclass StreamWriter {
374514f5e3Sopenharmony_cipublic:
384514f5e3Sopenharmony_ci    explicit StreamWriter(Stream *stream)
394514f5e3Sopenharmony_ci        : stream_(stream), chunkSize_(stream->GetSize()), chunk_(chunkSize_), current_(0)
404514f5e3Sopenharmony_ci    {
414514f5e3Sopenharmony_ci    }
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_ci    void WriteString(const CString &str)
444514f5e3Sopenharmony_ci    {
454514f5e3Sopenharmony_ci        auto len = str.size();
464514f5e3Sopenharmony_ci        ASSERT(len <= static_cast<size_t>(INT_MAX));
474514f5e3Sopenharmony_ci        if (len == 0) {
484514f5e3Sopenharmony_ci            return;
494514f5e3Sopenharmony_ci        }
504514f5e3Sopenharmony_ci        const char *cur = str.c_str();
514514f5e3Sopenharmony_ci        const char *end = cur + len;
524514f5e3Sopenharmony_ci        while (cur < end) {
534514f5e3Sopenharmony_ci            int dstSize = chunkSize_ - current_;
544514f5e3Sopenharmony_ci            int writeSize = std::min(static_cast<int>(end - cur), dstSize);
554514f5e3Sopenharmony_ci            ASSERT(writeSize > 0);
564514f5e3Sopenharmony_ci            if (memcpy_s(chunk_.data() + current_, dstSize, cur, writeSize) != EOK) {
574514f5e3Sopenharmony_ci                LOG_FULL(FATAL) << "memcpy_s failed";
584514f5e3Sopenharmony_ci            }
594514f5e3Sopenharmony_ci            cur += writeSize;
604514f5e3Sopenharmony_ci            current_ += writeSize;
614514f5e3Sopenharmony_ci            MaybeWriteChunk();
624514f5e3Sopenharmony_ci        }
634514f5e3Sopenharmony_ci    }
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_ci    void WriteChar(char c)
664514f5e3Sopenharmony_ci    {
674514f5e3Sopenharmony_ci        ASSERT(c != '\0');
684514f5e3Sopenharmony_ci        ASSERT(current_ < chunkSize_);
694514f5e3Sopenharmony_ci        chunk_[current_++] = c;
704514f5e3Sopenharmony_ci        MaybeWriteChunk();
714514f5e3Sopenharmony_ci    }
724514f5e3Sopenharmony_ci
734514f5e3Sopenharmony_ci    void WriteNumber(uint64_t num)
744514f5e3Sopenharmony_ci    {
754514f5e3Sopenharmony_ci        WriteString(ToCString(num));
764514f5e3Sopenharmony_ci    }
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ci    void End()
794514f5e3Sopenharmony_ci    {
804514f5e3Sopenharmony_ci        if (current_ > 0) {
814514f5e3Sopenharmony_ci            WriteChunk();
824514f5e3Sopenharmony_ci        }
834514f5e3Sopenharmony_ci        stream_->EndOfStream();
844514f5e3Sopenharmony_ci    }
854514f5e3Sopenharmony_ci
864514f5e3Sopenharmony_ciprivate:
874514f5e3Sopenharmony_ci    void MaybeWriteChunk()
884514f5e3Sopenharmony_ci    {
894514f5e3Sopenharmony_ci        ASSERT(current_ <= chunkSize_);
904514f5e3Sopenharmony_ci        if (current_ == chunkSize_) {
914514f5e3Sopenharmony_ci            WriteChunk();
924514f5e3Sopenharmony_ci        }
934514f5e3Sopenharmony_ci    }
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ci    void WriteChunk()
964514f5e3Sopenharmony_ci    {
974514f5e3Sopenharmony_ci        stream_->WriteChunk(chunk_.data(), current_);
984514f5e3Sopenharmony_ci        current_ = 0;
994514f5e3Sopenharmony_ci    }
1004514f5e3Sopenharmony_ci
1014514f5e3Sopenharmony_ci    Stream *stream_ {nullptr};
1024514f5e3Sopenharmony_ci    int chunkSize_ {0};
1034514f5e3Sopenharmony_ci    CVector<char> chunk_;
1044514f5e3Sopenharmony_ci    int current_ {0};
1054514f5e3Sopenharmony_ci};
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ciclass HeapSnapshotJSONSerializer {
1084514f5e3Sopenharmony_cipublic:
1094514f5e3Sopenharmony_ci    explicit HeapSnapshotJSONSerializer() = default;
1104514f5e3Sopenharmony_ci    ~HeapSnapshotJSONSerializer() = default;
1114514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(HeapSnapshotJSONSerializer);
1124514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(HeapSnapshotJSONSerializer);
1134514f5e3Sopenharmony_ci    static bool Serialize(HeapSnapshot *snapshot, Stream *stream);
1144514f5e3Sopenharmony_ci    static void DumpStringTable(HeapSnapshot *snapshot, Stream *stream);
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_ciprivate:
1174514f5e3Sopenharmony_ci    static constexpr char ASCII_US = 31;
1184514f5e3Sopenharmony_ci    static constexpr char ASCII_DEL = 127;
1194514f5e3Sopenharmony_ci    static constexpr uint8_t UTF8_MAX_BYTES = 4;
1204514f5e3Sopenharmony_ci
1214514f5e3Sopenharmony_ciprivate:
1224514f5e3Sopenharmony_ci    static void SerializeSnapshotHeader(HeapSnapshot *snapshot, StreamWriter *writer);
1234514f5e3Sopenharmony_ci    static void SerializeNodes(HeapSnapshot *snapshot, StreamWriter *writer);
1244514f5e3Sopenharmony_ci    static void SerializeEdges(HeapSnapshot *snapshot, StreamWriter *writer);
1254514f5e3Sopenharmony_ci    static void SerializeTraceFunctionInfo(HeapSnapshot *snapshot, StreamWriter *writer);
1264514f5e3Sopenharmony_ci    static void SerializeTraceTree(HeapSnapshot *snapshot, StreamWriter *writer);
1274514f5e3Sopenharmony_ci    static void SerializeTraceNode(TraceNode *node, StreamWriter *writer);
1284514f5e3Sopenharmony_ci    static void SerializeSamples(HeapSnapshot *snapshot, StreamWriter *writer);
1294514f5e3Sopenharmony_ci    static void SerializeLocations(StreamWriter *writer);
1304514f5e3Sopenharmony_ci    static void SerializeStringTable(HeapSnapshot *snapshot, StreamWriter *writer);
1314514f5e3Sopenharmony_ci    static void SerializeString(CString *str, StreamWriter *writer);
1324514f5e3Sopenharmony_ci    static void SerializeUnicodeChar(uint32_t unicodeChar, StreamWriter *writer);
1334514f5e3Sopenharmony_ci    static void SerializerSnapshotClosure(StreamWriter *writer);
1344514f5e3Sopenharmony_ci};
1354514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
1364514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
137