Coverage for /Syzygy/agent/asan/stack_capture_cache.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
92.0%81880.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 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/asan/stack_capture_cache.h"
  16    :  
  17    :  #include "base/logging.h"
  18    :  #include "base/stringprintf.h"
  19    :  #include "syzygy/agent/asan/asan_logger.h"
  20    :  #include "syzygy/agent/asan/stack_capture.h"
  21    :  
  22    :  namespace agent {
  23    :  namespace asan {
  24    :  
  25    :  size_t StackCaptureCache::compression_reporting_period_ =
  26    :      StackCaptureCache::kDefaultCompressionReportingPeriod;
  27    :  
  28  E :  StackCaptureCache::CachePage::~CachePage() {
  29  E :    if (next_page_ != NULL)
  30  i :      delete next_page_;
  31  E :  }
  32    :  
  33    :  StackCapture* StackCaptureCache::CachePage::GetNextStackCapture(
  34  E :      size_t max_num_frames) {
  35  E :    size_t size = StackCapture::GetSize(max_num_frames);
  36  E :    if (bytes_used_ + size > kCachePageSize)
  37  E :      return NULL;
  38    :  
  39    :    // Use placement new.
  40  E :    StackCapture* stack = new(data_ + bytes_used_) StackCapture(max_num_frames);
  41  E :    bytes_used_ += size;
  42    :  
  43  E :    return stack;
  44  E :  }
  45    :  
  46    :  void StackCaptureCache::CachePage::ReleaseStackCapture(
  47  E :      StackCapture* stack_capture) {
  48  E :    DCHECK(stack_capture != NULL);
  49    :  
  50  E :    uint8* stack = reinterpret_cast<uint8*>(stack_capture);
  51  E :    size_t size = stack_capture->Size();
  52  E :    DCHECK_EQ(data_ + bytes_used_, stack + size);
  53  E :    bytes_used_ -= size;
  54  E :  }
  55    :  
  56    :  StackCaptureCache::StackCaptureCache(AsanLogger* logger)
  57    :      : logger_(logger),
  58    :        max_num_frames_(StackCapture::kMaxNumFrames),
  59    :        current_page_(new CachePage(NULL)),
  60    :        total_allocations_(0),
  61  E :        cached_allocations_(0) {
  62  E :    CHECK(current_page_ != NULL);
  63  E :    DCHECK(logger_ != NULL);
  64  E :  }
  65    :  
  66    :  StackCaptureCache::StackCaptureCache(AsanLogger* logger, size_t max_num_frames)
  67    :      : logger_(logger),
  68    :        max_num_frames_(0),
  69    :        current_page_(new CachePage(NULL)),
  70    :        total_allocations_(0),
  71  E :        cached_allocations_(0) {
  72  E :    CHECK(current_page_ != NULL);
  73  E :    DCHECK(logger_ != NULL);
  74  E :    DCHECK_LT(0u, max_num_frames);
  75    :    max_num_frames_ = static_cast<uint8>(
  76  E :        std::min(max_num_frames, StackCapture::kMaxNumFrames));
  77  E :  }
  78    :  
  79  E :  StackCaptureCache::~StackCaptureCache() {
  80  E :    if (current_page_ != NULL)
  81  E :      delete current_page_;
  82  E :  }
  83    :  
  84    :  const StackCapture* StackCaptureCache::SaveStackTrace(
  85  E :      StackId stack_id, const void* const* frames, size_t num_frames) {
  86  E :    DCHECK(frames != NULL);
  87  E :    DCHECK(num_frames != 0);
  88  E :    DCHECK(current_page_ != NULL);
  89    :  
  90  E :    bool must_log_ratio = false;
  91  E :    double compression_ratio = 1.0;
  92  E :    const StackCapture* stack_trace = NULL;
  93    :  
  94    :    {
  95    :      // Get or insert the current stack trace while under the lock.
  96  E :      base::AutoLock auto_lock(lock_);
  97    :  
  98    :      // If the current page has been entirely consumed, allocate a new page
  99    :      // that links to the current page.
 100    :      StackCapture* unused_trace = current_page_->GetNextStackCapture(
 101  E :          max_num_frames_);
 102  E :      if (unused_trace == NULL) {
 103  i :        current_page_ = new CachePage(current_page_);
 104  i :        CHECK(current_page_ != NULL);
 105  i :        unused_trace = current_page_->GetNextStackCapture(max_num_frames_);
 106    :      }
 107  E :      DCHECK(unused_trace != NULL);
 108    :  
 109    :      // Attempt to insert it into the known stacks map.
 110  E :      unused_trace->set_stack_id(stack_id);
 111    :      std::pair<StackSet::const_iterator, bool> result = known_stacks_.insert(
 112  E :          unused_trace);
 113    :  
 114    :      // If the insertion was successful, then this capture has not already been
 115    :      // cached and we have to initialize the data.
 116  E :      if (result.second) {
 117  E :        DCHECK_EQ(unused_trace, *result.first);
 118  E :        unused_trace->InitFromBuffer(stack_id, frames, num_frames);
 119  E :        ++cached_allocations_;
 120  E :      } else {
 121    :        // If we didn't need the stack capture then return it.
 122  E :        current_page_->ReleaseStackCapture(unused_trace);
 123  E :        unused_trace = NULL;
 124    :      }
 125    :  
 126  E :      ++total_allocations_;
 127  E :      stack_trace = *result.first;
 128    :  
 129    :      if (compression_reporting_period_ != 0 &&
 130  E :          total_allocations_ % compression_reporting_period_ == 0) {
 131  i :        must_log_ratio = true;
 132  i :        compression_ratio = GetCompressionRatioUnlocked();
 133    :      }
 134  E :    }
 135    :  
 136  E :    DCHECK(stack_trace != NULL);
 137    :  
 138  E :    if (must_log_ratio)
 139  i :      LogCompressionRatioImpl(compression_ratio);
 140    :  
 141    :    // Return the stack trace pointer that is now in the cache.
 142  E :    return stack_trace;
 143  E :  }
 144    :  
 145    :  const StackCapture* StackCaptureCache::SaveStackTrace(
 146  E :      const StackCapture& stack_capture) {
 147    :    return SaveStackTrace(stack_capture.stack_id(),
 148    :                          stack_capture.frames(),
 149  E :                          stack_capture.num_frames());
 150  E :  }
 151    :  
 152  E :  void StackCaptureCache::LogCompressionRatio() const {
 153  E :    double compression_ratio = 0.0;
 154    :  
 155    :    {
 156  E :      base::AutoLock auto_lock(lock_);
 157  E :      compression_ratio = GetCompressionRatioUnlocked();
 158  E :    }
 159    :  
 160  E :    LogCompressionRatioImpl(compression_ratio);
 161  E :  }
 162    :  
 163  E :  double StackCaptureCache::GetCompressionRatioUnlocked() const {
 164  E :    lock_.AssertAcquired();
 165  E :    if (total_allocations_ == 0)
 166  E :      return 1.0;
 167  E :    return static_cast<double>(cached_allocations_) / total_allocations_;
 168  E :  }
 169    :  
 170  E :  void StackCaptureCache::LogCompressionRatioImpl(double ratio) const {
 171  E :    DCHECK_LE(0.0, ratio);
 172  E :    DCHECK_GE(1.0, ratio);
 173    :    logger_->Write(base::StringPrintf(
 174  E :        "Allocation stack cache compression: %.2f%%.\n", (1.0 - ratio) * 100.0));
 175  E :  }
 176    :  
 177    :  }  // namespace asan
 178    :  }  // namespace agent

Coverage information generated Thu Mar 14 11:53:36 2013.