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 #include "ecmascript/dfx/hprof/string_hashmap.h" 27 28 #include "securec.h" 29 30 namespace panda::ecmascript { 31 using fstream = std::fstream; 32 using stringstream = std::stringstream; 33 34 class HeapSnapshot; 35 class TraceNode; 36 37 class StreamWriter { 38 public: StreamWriter(Stream * stream)39 explicit StreamWriter(Stream *stream) 40 : stream_(stream), chunkSize_(stream->GetSize()), chunk_(chunkSize_), current_(0) 41 { 42 } 43 WriteString(const CString & str)44 void WriteString(const CString &str) 45 { 46 auto len = str.size(); 47 ASSERT(len <= static_cast<size_t>(INT_MAX)); 48 if (len == 0) { 49 return; 50 } 51 const char *cur = str.c_str(); 52 const char *end = cur + len; 53 while (cur < end) { 54 int dstSize = chunkSize_ - current_; 55 int writeSize = std::min(static_cast<int>(end - cur), dstSize); 56 ASSERT(writeSize > 0); 57 if (memcpy_s(chunk_.data() + current_, dstSize, cur, writeSize) != EOK) { 58 LOG_FULL(FATAL) << "memcpy_s failed"; 59 } 60 cur += writeSize; 61 current_ += writeSize; 62 MaybeWriteChunk(); 63 } 64 } 65 WriteChar(char c)66 void WriteChar(char c) 67 { 68 ASSERT(c != '\0'); 69 ASSERT(current_ < chunkSize_); 70 chunk_[current_++] = c; 71 MaybeWriteChunk(); 72 } 73 WriteNumber(uint64_t num)74 void WriteNumber(uint64_t num) 75 { 76 WriteString(ToCString(num)); 77 } 78 End()79 void End() 80 { 81 if (current_ > 0) { 82 WriteChunk(); 83 } 84 stream_->EndOfStream(); 85 } 86 87 private: MaybeWriteChunk()88 void MaybeWriteChunk() 89 { 90 ASSERT(current_ <= chunkSize_); 91 if (current_ == chunkSize_) { 92 WriteChunk(); 93 } 94 } 95 WriteChunk()96 void WriteChunk() 97 { 98 stream_->WriteChunk(chunk_.data(), current_); 99 current_ = 0; 100 } 101 102 Stream *stream_ {nullptr}; 103 int chunkSize_ {0}; 104 CVector<char> chunk_; 105 int current_ {0}; 106 }; 107 108 class HeapSnapshotJSONSerializer { 109 public: 110 explicit HeapSnapshotJSONSerializer() = default; 111 ~HeapSnapshotJSONSerializer() = default; 112 NO_MOVE_SEMANTIC(HeapSnapshotJSONSerializer); 113 NO_COPY_SEMANTIC(HeapSnapshotJSONSerializer); 114 static bool Serialize(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