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