Coverage for /Syzygy/agent/memprof/function_call_logger.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
87.5%49560.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   2    :  //
   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    :  #include "syzygy/agent/memprof/function_call_logger.h"
  16    :  
  17    :  #include "syzygy/agent/common/stack_capture.h"
  18    :  
  19    :  namespace agent {
  20    :  namespace memprof {
  21    :  
  22    :  FunctionCallLogger::FunctionCallLogger(
  23    :      trace::client::RpcSession* session)
  24    :      : session_(session),
  25    :        stack_trace_tracking_(kTrackingNone),
  26    :        serialize_timestamps_(false),
  27    :        call_counter_(0),
  28  E :        serial_(0) {
  29  E :    DCHECK_NE(static_cast<trace::client::RpcSession*>(nullptr), session);
  30    :  
  31    :    // Generate a unique 'serial number' for this instance. This is so that we
  32    :    // can tell one logger from the next in unittests, where they often end up
  33    :    // having the same address.
  34  E :    uint64 t = ::trace::common::GetTsc();
  35    :    serial_ = static_cast<uint32>(t & 0xFFFFFFFF) ^
  36    :              static_cast<uint32>((t >> 32) & 0xFFFFFFFF) ^
  37  E :              reinterpret_cast<uint32>(this);
  38  E :  }
  39    :  
  40    :  // Given a function name returns it's ID. If this is the first time seeing
  41    :  // a given function name then emits a record to the call-trace buffer.
  42    :  uint32 FunctionCallLogger::GetFunctionId(TraceFileSegment* segment,
  43  E :                                           const std::string& function_name) {
  44  E :    DCHECK_NE(static_cast<TraceFileSegment*>(nullptr), segment);
  45  E :    size_t id = 0;
  46    :  
  47    :    {
  48  E :      base::AutoLock lock(lock_);
  49  E :      auto it = function_id_map_.find(function_name);
  50  E :      if (it != function_id_map_.end())
  51  E :        return it->second;
  52  E :      id = function_id_map_.size();
  53  E :      function_id_map_.insert(std::make_pair(function_name, id));
  54  E :    }
  55    :  
  56    :    size_t data_size = FIELD_OFFSET(TraceFunctionNameTableEntry, name) +
  57  E :        function_name.size() + 1;
  58    :  
  59  E :    if (!segment->CanAllocate(data_size) && !FlushSegment(segment))
  60  i :      return id;
  61  E :    DCHECK(segment->CanAllocate(data_size));
  62    :  
  63    :    TraceFunctionNameTableEntry* data =
  64  E :        segment->AllocateTraceRecord<TraceFunctionNameTableEntry>(data_size);
  65  E :    DCHECK_NE(static_cast<TraceFunctionNameTableEntry*>(nullptr), data);
  66  E :    data->function_id = id;
  67  E :    data->name_length = function_name.size() + 1;
  68  E :    ::memcpy(data->name, function_name.data(), data->name_length);
  69    :  
  70  E :    return id;
  71  E :  }
  72    :  
  73  E :  uint32 FunctionCallLogger::GetStackTraceId(TraceFileSegment* segment) {
  74  E :    DCHECK_NE(static_cast<TraceFileSegment*>(nullptr), segment);
  75  E :    if (stack_trace_tracking_ == kTrackingNone)
  76  E :      return 0;
  77    :  
  78  E :    agent::common::StackCapture stack;
  79  E :    stack.InitFromStack();
  80  E :    if (stack_trace_tracking_ == kTrackingTrack)
  81  E :      return stack.absolute_stack_id();
  82    :  
  83    :    // Insert the stack ID. If it already exists it doesn't need to be emitted
  84    :    // so return early.
  85  E :    bool inserted = false;
  86    :    {
  87  E :      base::AutoLock lock(lock_);
  88  E :      inserted = emitted_stack_ids_.insert(stack.absolute_stack_id()).second;
  89  E :    }
  90  E :    if (!inserted)
  91  i :      return stack.absolute_stack_id();
  92    :  
  93  E :    size_t frame_size = sizeof(void*) * stack.num_frames();
  94  E :    size_t data_size = FIELD_OFFSET(TraceStackTrace, frames) + frame_size;
  95  E :    if (!segment->CanAllocate(data_size) && !FlushSegment(segment))
  96  i :      return stack.absolute_stack_id();
  97  E :    DCHECK(segment->CanAllocate(data_size));
  98    :  
  99    :    TraceStackTrace* data = segment->AllocateTraceRecord<TraceStackTrace>(
 100  E :        data_size);
 101  E :    DCHECK_NE(static_cast<TraceStackTrace*>(nullptr), data);
 102  E :    data->num_frames = stack.num_frames();
 103  E :    data->stack_trace_id = stack.absolute_stack_id();
 104  E :    ::memcpy(data->frames, stack.frames(), frame_size);
 105    :  
 106  E :    return stack.absolute_stack_id();
 107  E :  }
 108    :  
 109  i :  bool FunctionCallLogger::FlushSegment(TraceFileSegment* segment) {
 110  i :    DCHECK_NE(static_cast<TraceFileSegment*>(nullptr), segment);
 111  i :    return session_->ExchangeBuffer(segment);
 112  i :  }
 113    :  
 114    :  }  // namespace memprof
 115    :  }  // namespace agent

Coverage information generated Thu Jan 14 17:40:38 2016.