LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrMemoryPool.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 144 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "GrMemoryPool.h"
       9             : #include "SkMalloc.h"
      10             : #ifdef SK_DEBUG
      11             : #include "SkAtomics.h"
      12             : #endif
      13             : 
      14             : #ifdef SK_DEBUG
      15             :     #define VALIDATE this->validate()
      16             : #else
      17             :     #define VALIDATE
      18             : #endif
      19             : 
      20             : constexpr size_t GrMemoryPool::kSmallestMinAllocSize;
      21             : 
      22           0 : GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize) {
      23           0 :     SkDEBUGCODE(fAllocationCnt = 0);
      24           0 :     SkDEBUGCODE(fAllocBlockCnt = 0);
      25             : 
      26           0 :     minAllocSize = SkTMax<size_t>(GrSizeAlignUp(minAllocSize, kAlignment), kSmallestMinAllocSize);
      27           0 :     preallocSize = SkTMax<size_t>(GrSizeAlignUp(preallocSize, kAlignment), minAllocSize);
      28             : 
      29           0 :     fMinAllocSize = minAllocSize;
      30           0 :     fSize = 0;
      31             : 
      32           0 :     fHead = CreateBlock(preallocSize);
      33           0 :     fTail = fHead;
      34           0 :     fHead->fNext = nullptr;
      35           0 :     fHead->fPrev = nullptr;
      36           0 :     VALIDATE;
      37           0 : };
      38             : 
      39           0 : GrMemoryPool::~GrMemoryPool() {
      40           0 :     VALIDATE;
      41             : #ifdef SK_DEBUG
      42           0 :     int i = 0;
      43           0 :     int n = fAllocatedIDs.count();
      44           0 :     fAllocatedIDs.foreach([&i, n] (int32_t id) {
      45           0 :         if (++i == 1) {
      46           0 :             SkDebugf("Leaked IDs (in no particular order): %d", id);
      47           0 :         } else if (i < 11) {
      48           0 :             SkDebugf(", %d%s", id, (n == i ? "\n" : ""));
      49           0 :         } else if (i == 11) {
      50           0 :             SkDebugf(", ...\n");
      51             :         }
      52           0 :     });
      53             : #endif
      54           0 :     SkASSERT(0 == fAllocationCnt);
      55           0 :     SkASSERT(fHead == fTail);
      56           0 :     SkASSERT(0 == fHead->fLiveCount);
      57           0 :     DeleteBlock(fHead);
      58           0 : };
      59             : 
      60           0 : void* GrMemoryPool::allocate(size_t size) {
      61           0 :     VALIDATE;
      62           0 :     size += kPerAllocPad;
      63           0 :     size = GrSizeAlignUp(size, kAlignment);
      64           0 :     if (fTail->fFreeSize < size) {
      65           0 :         size_t blockSize = size + kHeaderSize;
      66           0 :         blockSize = SkTMax<size_t>(blockSize, fMinAllocSize);
      67           0 :         BlockHeader* block = CreateBlock(blockSize);
      68             : 
      69           0 :         block->fPrev = fTail;
      70           0 :         block->fNext = nullptr;
      71           0 :         SkASSERT(nullptr == fTail->fNext);
      72           0 :         fTail->fNext = block;
      73           0 :         fTail = block;
      74           0 :         fSize += block->fSize;
      75           0 :         SkDEBUGCODE(++fAllocBlockCnt);
      76             :     }
      77           0 :     SkASSERT(kAssignedMarker == fTail->fBlockSentinal);
      78           0 :     SkASSERT(fTail->fFreeSize >= size);
      79           0 :     intptr_t ptr = fTail->fCurrPtr;
      80             :     // We stash a pointer to the block header, just before the allocated space,
      81             :     // so that we can decrement the live count on delete in constant time.
      82           0 :     AllocHeader* allocData = reinterpret_cast<AllocHeader*>(ptr);
      83           0 :     SkDEBUGCODE(allocData->fSentinal = kAssignedMarker);
      84           0 :     SkDEBUGCODE(allocData->fID = []{static int32_t gID; return sk_atomic_inc(&gID) + 1;}());
      85             :     // You can set a breakpoint here when a leaked ID is allocated to see the stack frame.
      86           0 :     SkDEBUGCODE(fAllocatedIDs.add(allocData->fID));
      87           0 :     allocData->fHeader = fTail;
      88           0 :     ptr += kPerAllocPad;
      89           0 :     fTail->fPrevPtr = fTail->fCurrPtr;
      90           0 :     fTail->fCurrPtr += size;
      91           0 :     fTail->fFreeSize -= size;
      92           0 :     fTail->fLiveCount += 1;
      93           0 :     SkDEBUGCODE(++fAllocationCnt);
      94           0 :     VALIDATE;
      95           0 :     return reinterpret_cast<void*>(ptr);
      96             : }
      97             : 
      98           0 : void GrMemoryPool::release(void* p) {
      99           0 :     VALIDATE;
     100           0 :     intptr_t ptr = reinterpret_cast<intptr_t>(p) - kPerAllocPad;
     101           0 :     AllocHeader* allocData = reinterpret_cast<AllocHeader*>(ptr);
     102           0 :     SkASSERT(kAssignedMarker == allocData->fSentinal);
     103           0 :     SkDEBUGCODE(allocData->fSentinal = kFreedMarker);
     104           0 :     SkDEBUGCODE(fAllocatedIDs.remove(allocData->fID));
     105           0 :     BlockHeader* block = allocData->fHeader;
     106           0 :     SkASSERT(kAssignedMarker == block->fBlockSentinal);
     107           0 :     if (1 == block->fLiveCount) {
     108             :         // the head block is special, it is reset rather than deleted
     109           0 :         if (fHead == block) {
     110           0 :             fHead->fCurrPtr = reinterpret_cast<intptr_t>(fHead) + kHeaderSize;
     111           0 :             fHead->fLiveCount = 0;
     112           0 :             fHead->fFreeSize = fHead->fSize - kHeaderSize;
     113             :         } else {
     114           0 :             BlockHeader* prev = block->fPrev;
     115           0 :             BlockHeader* next = block->fNext;
     116           0 :             SkASSERT(prev);
     117           0 :             prev->fNext = next;
     118           0 :             if (next) {
     119           0 :                 next->fPrev = prev;
     120             :             } else {
     121           0 :                 SkASSERT(fTail == block);
     122           0 :                 fTail = prev;
     123             :             }
     124           0 :             fSize -= block->fSize;
     125           0 :             DeleteBlock(block);
     126           0 :             SkDEBUGCODE(fAllocBlockCnt--);
     127             :         }
     128             :     } else {
     129           0 :         --block->fLiveCount;
     130             :         // Trivial reclaim: if we're releasing the most recent allocation, reuse it
     131           0 :         if (block->fPrevPtr == ptr) {
     132           0 :             block->fFreeSize += (block->fCurrPtr - block->fPrevPtr);
     133           0 :             block->fCurrPtr = block->fPrevPtr;
     134             :         }
     135             :     }
     136           0 :     SkDEBUGCODE(--fAllocationCnt);
     137           0 :     VALIDATE;
     138           0 : }
     139             : 
     140           0 : GrMemoryPool::BlockHeader* GrMemoryPool::CreateBlock(size_t blockSize) {
     141           0 :     blockSize = SkTMax<size_t>(blockSize, kHeaderSize);
     142             :     BlockHeader* block =
     143           0 :         reinterpret_cast<BlockHeader*>(sk_malloc_throw(blockSize));
     144             :     // we assume malloc gives us aligned memory
     145           0 :     SkASSERT(!(reinterpret_cast<intptr_t>(block) % kAlignment));
     146           0 :     SkDEBUGCODE(block->fBlockSentinal = kAssignedMarker);
     147           0 :     block->fLiveCount = 0;
     148           0 :     block->fFreeSize = blockSize - kHeaderSize;
     149           0 :     block->fCurrPtr = reinterpret_cast<intptr_t>(block) + kHeaderSize;
     150           0 :     block->fPrevPtr = 0; // gcc warns on assigning nullptr to an intptr_t.
     151           0 :     block->fSize = blockSize;
     152           0 :     return block;
     153             : }
     154             : 
     155           0 : void GrMemoryPool::DeleteBlock(BlockHeader* block) {
     156           0 :     SkASSERT(kAssignedMarker == block->fBlockSentinal);
     157           0 :     SkDEBUGCODE(block->fBlockSentinal = kFreedMarker); // FWIW
     158           0 :     sk_free(block);
     159           0 : }
     160             : 
     161           0 : void GrMemoryPool::validate() {
     162             : #ifdef SK_DEBUG
     163           0 :     BlockHeader* block = fHead;
     164           0 :     BlockHeader* prev = nullptr;
     165           0 :     SkASSERT(block);
     166           0 :     int allocCount = 0;
     167           0 :     do {
     168           0 :         SkASSERT(kAssignedMarker == block->fBlockSentinal);
     169           0 :         allocCount += block->fLiveCount;
     170           0 :         SkASSERT(prev == block->fPrev);
     171           0 :         if (prev) {
     172           0 :             SkASSERT(prev->fNext == block);
     173             :         }
     174             : 
     175           0 :         intptr_t b = reinterpret_cast<intptr_t>(block);
     176           0 :         size_t ptrOffset = block->fCurrPtr - b;
     177           0 :         size_t totalSize = ptrOffset + block->fFreeSize;
     178           0 :         intptr_t userStart = b + kHeaderSize;
     179             : 
     180           0 :         SkASSERT(!(b % kAlignment));
     181           0 :         SkASSERT(!(totalSize % kAlignment));
     182           0 :         SkASSERT(!(block->fCurrPtr % kAlignment));
     183           0 :         if (fHead != block) {
     184           0 :             SkASSERT(block->fLiveCount);
     185           0 :             SkASSERT(totalSize >= fMinAllocSize);
     186             :         } else {
     187           0 :             SkASSERT(totalSize == block->fSize);
     188             :         }
     189           0 :         if (!block->fLiveCount) {
     190           0 :             SkASSERT(ptrOffset ==  kHeaderSize);
     191           0 :             SkASSERT(userStart == block->fCurrPtr);
     192             :         } else {
     193           0 :             AllocHeader* allocData = reinterpret_cast<AllocHeader*>(userStart);
     194           0 :             SkASSERT(allocData->fSentinal == kAssignedMarker ||
     195             :                      allocData->fSentinal == kFreedMarker);
     196           0 :             SkASSERT(block == allocData->fHeader);
     197             :         }
     198             : 
     199           0 :         prev = block;
     200           0 :     } while ((block = block->fNext));
     201           0 :     SkASSERT(allocCount == fAllocationCnt);
     202           0 :     SkASSERT(fAllocationCnt == fAllocatedIDs.count());
     203           0 :     SkASSERT(prev == fTail);
     204           0 :     SkASSERT(fAllocBlockCnt != 0 || fSize == 0);
     205             : #endif
     206           0 : }

Generated by: LCOV version 1.13