| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "chrome/profiling/memlog_stream_parser.h" | 
|  | 6 | 
|  | 7 #include <algorithm> | 
|  | 8 | 
|  | 9 #include "base/containers/stack_container.h" | 
|  | 10 #include "base/strings/stringprintf.h" | 
|  | 11 #include "chrome/common/profiling/memlog_stream.h" | 
|  | 12 #include "chrome/profiling/address.h" | 
|  | 13 #include "chrome/profiling/backtrace.h" | 
|  | 14 #include "chrome/profiling/profiling_globals.h" | 
|  | 15 | 
|  | 16 namespace profiling { | 
|  | 17 | 
|  | 18 namespace { | 
|  | 19 | 
|  | 20 using AddressVector = base::StackVector<Address, 128>; | 
|  | 21 | 
|  | 22 }  // namespace | 
|  | 23 | 
|  | 24 MemlogStreamParser::Block::Block(std::unique_ptr<char[]> d, size_t s) | 
|  | 25     : data(std::move(d)), size(s) {} | 
|  | 26 | 
|  | 27 MemlogStreamParser::MemlogStreamParser(MemlogReceiver* receiver) | 
|  | 28     : receiver_(receiver) {} | 
|  | 29 | 
|  | 30 MemlogStreamParser::~MemlogStreamParser() {} | 
|  | 31 | 
|  | 32 void MemlogStreamParser::OnStreamData(std::unique_ptr<char[]> data, size_t sz) { | 
|  | 33   blocks_.emplace_back(std::move(data), sz); | 
|  | 34 | 
|  | 35   if (!received_header_) { | 
|  | 36     received_header_ = true; | 
|  | 37     ReadStatus status = ParseHeader(); | 
|  | 38     if (status != READ_OK) | 
|  | 39       return;  // TODO(brettw) signal error. | 
|  | 40   } | 
|  | 41 | 
|  | 42   while (true) { | 
|  | 43     uint32_t msg_type; | 
|  | 44     if (!PeekBytes(sizeof(msg_type), &msg_type)) | 
|  | 45       return; | 
|  | 46 | 
|  | 47     ReadStatus status; | 
|  | 48     switch (msg_type) { | 
|  | 49       case kAllocPacketType: | 
|  | 50         status = ParseAlloc(); | 
|  | 51         break; | 
|  | 52       case kFreePacketType: | 
|  | 53         status = ParseFree(); | 
|  | 54         break; | 
|  | 55       default: | 
|  | 56         return;  // TODO(brettw) signal error. | 
|  | 57     } | 
|  | 58     if (status != READ_OK) | 
|  | 59       return;  // TODO(brettw) signal error. | 
|  | 60   } | 
|  | 61 } | 
|  | 62 | 
|  | 63 void MemlogStreamParser::OnStreamComplete() { | 
|  | 64   receiver_->OnComplete(); | 
|  | 65 } | 
|  | 66 | 
|  | 67 bool MemlogStreamParser::AreBytesAvailable(size_t count) const { | 
|  | 68   size_t used = 0; | 
|  | 69   size_t current_block_offset = block_zero_offset_; | 
|  | 70   for (auto it = blocks_.begin(); it != blocks_.end() && used < count; ++it) { | 
|  | 71     used += it->size - current_block_offset; | 
|  | 72     current_block_offset = 0; | 
|  | 73   } | 
|  | 74   return used >= count; | 
|  | 75 } | 
|  | 76 | 
|  | 77 bool MemlogStreamParser::PeekBytes(size_t count, void* dest) const { | 
|  | 78   char* dest_char = static_cast<char*>(dest); | 
|  | 79   size_t used = 0; | 
|  | 80 | 
|  | 81   size_t current_block_offset = block_zero_offset_; | 
|  | 82   for (const auto& block : blocks_) { | 
|  | 83     size_t in_current_block = block.size - current_block_offset; | 
|  | 84     size_t to_copy = std::min(count - used, in_current_block); | 
|  | 85 | 
|  | 86     memcpy(&dest_char[used], &block.data[current_block_offset], to_copy); | 
|  | 87     used += to_copy; | 
|  | 88 | 
|  | 89     // All subsequent blocks start reading at offset 0. | 
|  | 90     current_block_offset = 0; | 
|  | 91   } | 
|  | 92   return used == count; | 
|  | 93 } | 
|  | 94 | 
|  | 95 bool MemlogStreamParser::ReadBytes(size_t count, void* dest) { | 
|  | 96   if (!PeekBytes(count, dest)) | 
|  | 97     return false; | 
|  | 98   ConsumeBytes(count); | 
|  | 99   return true; | 
|  | 100 } | 
|  | 101 | 
|  | 102 void MemlogStreamParser::ConsumeBytes(size_t count) { | 
|  | 103   DCHECK(AreBytesAvailable(count)); | 
|  | 104   while (count > 0) { | 
|  | 105     size_t bytes_left_in_block = blocks_.front().size - block_zero_offset_; | 
|  | 106     if (bytes_left_in_block > count) { | 
|  | 107       // Still data left in this block; | 
|  | 108       block_zero_offset_ += count; | 
|  | 109       return; | 
|  | 110     } | 
|  | 111 | 
|  | 112     // Current block is consumed. | 
|  | 113     blocks_.pop_front(); | 
|  | 114     block_zero_offset_ = 0; | 
|  | 115     count -= bytes_left_in_block; | 
|  | 116   } | 
|  | 117 } | 
|  | 118 | 
|  | 119 MemlogStreamParser::ReadStatus MemlogStreamParser::ParseHeader() { | 
|  | 120   StreamHeader header; | 
|  | 121   if (!ReadBytes(sizeof(StreamHeader), &header)) | 
|  | 122     return READ_NO_DATA; | 
|  | 123 | 
|  | 124   if (header.signature != kStreamSignature) | 
|  | 125     return READ_ERROR; | 
|  | 126 | 
|  | 127   receiver_->OnHeader(header); | 
|  | 128   return READ_OK; | 
|  | 129 } | 
|  | 130 | 
|  | 131 MemlogStreamParser::ReadStatus MemlogStreamParser::ParseAlloc() { | 
|  | 132   // Read the packet. Can't commit the read until the stack is read and | 
|  | 133   // that has to be done below. | 
|  | 134   AllocPacket alloc_packet; | 
|  | 135   if (!PeekBytes(sizeof(AllocPacket), &alloc_packet)) | 
|  | 136     return READ_NO_DATA; | 
|  | 137 | 
|  | 138   std::vector<Address> stack; | 
|  | 139   stack.resize(alloc_packet.stack_len); | 
|  | 140   size_t stack_byte_size = sizeof(Address) * alloc_packet.stack_len; | 
|  | 141 | 
|  | 142   if (!AreBytesAvailable(sizeof(AllocPacket) + stack_byte_size)) | 
|  | 143     return READ_NO_DATA; | 
|  | 144 | 
|  | 145   // Everything will fit, mark packet consumed, read stack. | 
|  | 146   ConsumeBytes(sizeof(AllocPacket)); | 
|  | 147   if (!stack.empty()) | 
|  | 148     ReadBytes(stack_byte_size, stack.data()); | 
|  | 149 | 
|  | 150   receiver_->OnAlloc(alloc_packet, std::move(stack)); | 
|  | 151   return READ_OK; | 
|  | 152 } | 
|  | 153 | 
|  | 154 MemlogStreamParser::ReadStatus MemlogStreamParser::ParseFree() { | 
|  | 155   FreePacket free_packet; | 
|  | 156   if (!ReadBytes(sizeof(FreePacket), &free_packet)) | 
|  | 157     return READ_NO_DATA; | 
|  | 158 | 
|  | 159   receiver_->OnFree(free_packet); | 
|  | 160   return READ_OK; | 
|  | 161 } | 
|  | 162 | 
|  | 163 }  // namespace profiling | 
| OLD | NEW | 
|---|