1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
17 #define ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
18 
19 #include <fstream>
20 #include <limits.h>
21 #include <sstream>
22 
23 #include "ecmascript/dfx/hprof/file_stream.h"
24 #include "ecmascript/mem/c_containers.h"
25 #include "ecmascript/mem/c_string.h"
26 
27 #include "securec.h"
28 
29 namespace panda::ecmascript {
30 using fstream = std::fstream;
31 using stringstream = std::stringstream;
32 
33 class HeapSnapshot;
34 class TraceNode;
35 
36 class StreamWriter {
37 public:
StreamWriter(Stream *stream)38     explicit StreamWriter(Stream *stream)
39         : stream_(stream), chunkSize_(stream->GetSize()), chunk_(chunkSize_), current_(0)
40     {
41     }
42 
WriteString(const CString &str)43     void WriteString(const CString &str)
44     {
45         auto len = str.size();
46         ASSERT(len <= static_cast<size_t>(INT_MAX));
47         if (len == 0) {
48             return;
49         }
50         const char *cur = str.c_str();
51         const char *end = cur + len;
52         while (cur < end) {
53             int dstSize = chunkSize_ - current_;
54             int writeSize = std::min(static_cast<int>(end - cur), dstSize);
55             ASSERT(writeSize > 0);
56             if (memcpy_s(chunk_.data() + current_, dstSize, cur, writeSize) != EOK) {
57                 LOG_FULL(FATAL) << "memcpy_s failed";
58             }
59             cur += writeSize;
60             current_ += writeSize;
61             MaybeWriteChunk();
62         }
63     }
64 
WriteChar(char c)65     void WriteChar(char c)
66     {
67         ASSERT(c != '\0');
68         ASSERT(current_ < chunkSize_);
69         chunk_[current_++] = c;
70         MaybeWriteChunk();
71     }
72 
73     void WriteNumber(uint64_t num)
74     {
75         WriteString(ToCString(num));
76     }
77 
78     void End()
79     {
80         if (current_ > 0) {
81             WriteChunk();
82         }
83         stream_->EndOfStream();
84     }
85 
86 private:
MaybeWriteChunk()87     void MaybeWriteChunk()
88     {
89         ASSERT(current_ <= chunkSize_);
90         if (current_ == chunkSize_) {
91             WriteChunk();
92         }
93     }
94 
WriteChunk()95     void WriteChunk()
96     {
97         stream_->WriteChunk(chunk_.data(), current_);
98         current_ = 0;
99     }
100 
101     Stream *stream_ {nullptr};
102     int chunkSize_ {0};
103     CVector<char> chunk_;
104     int current_ {0};
105 };
106 
107 class HeapSnapshotJSONSerializer {
108 public:
109     explicit HeapSnapshotJSONSerializer() = default;
110     ~HeapSnapshotJSONSerializer() = default;
111     NO_MOVE_SEMANTIC(HeapSnapshotJSONSerializer);
112     NO_COPY_SEMANTIC(HeapSnapshotJSONSerializer);
113     static bool Serialize(HeapSnapshot *snapshot, Stream *stream);
114     static void DumpStringTable(HeapSnapshot *snapshot, Stream *stream);
115 
116 private:
117     static constexpr char ASCII_US = 31;
118     static constexpr char ASCII_DEL = 127;
119     static constexpr uint8_t UTF8_MAX_BYTES = 4;
120 
121 private:
122     static void SerializeSnapshotHeader(HeapSnapshot *snapshot, StreamWriter *writer);
123     static void SerializeNodes(HeapSnapshot *snapshot, StreamWriter *writer);
124     static void SerializeEdges(HeapSnapshot *snapshot, StreamWriter *writer);
125     static void SerializeTraceFunctionInfo(HeapSnapshot *snapshot, StreamWriter *writer);
126     static void SerializeTraceTree(HeapSnapshot *snapshot, StreamWriter *writer);
127     static void SerializeTraceNode(TraceNode *node, StreamWriter *writer);
128     static void SerializeSamples(HeapSnapshot *snapshot, StreamWriter *writer);
129     static void SerializeLocations(StreamWriter *writer);
130     static void SerializeStringTable(HeapSnapshot *snapshot, StreamWriter *writer);
131     static void SerializeString(CString *str, StreamWriter *writer);
132     static void SerializeUnicodeChar(uint32_t unicodeChar, StreamWriter *writer);
133     static void SerializerSnapshotClosure(StreamWriter *writer);
134 };
135 }  // namespace panda::ecmascript
136 #endif  // ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
137