LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkArenaAlloc.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 79 93 84.9 %
Date: 2017-07-14 16:53:18 Functions: 11 13 84.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2016 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 <algorithm>
       9             : #include <cstddef>
      10             : #include "SkArenaAlloc.h"
      11             : 
      12         708 : static char* end_chain(char*) { return nullptr; }
      13             : 
      14           0 : char* SkArenaAlloc::SkipPod(char* footerEnd) {
      15           0 :     char* objEnd = footerEnd - (sizeof(Footer) + sizeof(int32_t));
      16             :     int32_t skip;
      17           0 :     memmove(&skip, objEnd, sizeof(int32_t));
      18           0 :     return objEnd - skip;
      19             : }
      20             : 
      21        3367 : void SkArenaAlloc::RunDtorsOnBlock(char* footerEnd) {
      22        5348 :     while (footerEnd != nullptr) {
      23             :         Footer footer;
      24        1981 :         memcpy(&footer, footerEnd - sizeof(Footer), sizeof(Footer));
      25             : 
      26        1981 :         FooterAction* action = (FooterAction*)(footer >> 6);
      27        1981 :         ptrdiff_t padding = footer & 63;
      28             : 
      29        1981 :         footerEnd = action(footerEnd) - padding;
      30             :     }
      31        1386 : }
      32             : 
      33         226 : char* SkArenaAlloc::NextBlock(char* footerEnd) {
      34         226 :     char* objEnd = footerEnd - (sizeof(Footer) + sizeof(char*));
      35             :     char* next;
      36         226 :     memmove(&next, objEnd, sizeof(char*));
      37         226 :     RunDtorsOnBlock(next);
      38         226 :     delete [] objEnd;
      39         226 :     return nullptr;
      40             : }
      41             : 
      42        1162 : SkArenaAlloc::SkArenaAlloc(char* block, size_t size, size_t extraSize)
      43             :     : fDtorCursor {block}
      44             :     , fCursor     {block}
      45        1162 :     , fEnd        {block + SkTo<uint32_t>(size)}
      46             :     , fFirstBlock {block}
      47        1162 :     , fFirstSize  {SkTo<uint32_t>(size)}
      48        3486 :     , fExtraSize  {SkTo<uint32_t>(extraSize)}
      49             : {
      50        1162 :     if (size < sizeof(Footer)) {
      51         454 :         fEnd = fCursor = fDtorCursor = nullptr;
      52             :     }
      53             : 
      54        1162 :     if (fCursor != nullptr) {
      55         708 :         this->installFooter(end_chain, 0);
      56             :     }
      57        1162 : }
      58             : 
      59        2320 : SkArenaAlloc::~SkArenaAlloc() {
      60        1160 :     RunDtorsOnBlock(fDtorCursor);
      61        1160 : }
      62             : 
      63         226 : void SkArenaAlloc::reset() {
      64         226 :     this->~SkArenaAlloc();
      65         226 :     new (this) SkArenaAlloc{fFirstBlock, fFirstSize, fExtraSize};
      66         226 : }
      67             : 
      68        1994 : void SkArenaAlloc::installFooter(FooterAction* action, uint32_t padding) {
      69        1994 :     SkASSERT(padding < 64);
      70        1994 :     int64_t actionInt = (int64_t)(intptr_t)action;
      71             : 
      72             :     // The top 14 bits should be either all 0s or all 1s. Check this.
      73        1994 :     SkASSERT((actionInt << 6) >> 6 == actionInt);
      74        1994 :     Footer encodedFooter = (actionInt << 6) | padding;
      75        1994 :     memmove(fCursor, &encodedFooter, sizeof(Footer));
      76        1994 :     fCursor += sizeof(Footer);
      77        1994 :     fDtorCursor = fCursor;
      78        1994 : }
      79             : 
      80         239 : void SkArenaAlloc::installPtrFooter(FooterAction* action, char* ptr, uint32_t padding) {
      81         239 :     memmove(fCursor, &ptr, sizeof(char*));
      82         239 :     fCursor += sizeof(char*);
      83         239 :     this->installFooter(action, padding);
      84         239 : }
      85             : 
      86           0 : void SkArenaAlloc::installUint32Footer(FooterAction* action, uint32_t value, uint32_t padding) {
      87           0 :     memmove(fCursor, &value, sizeof(uint32_t));
      88           0 :     fCursor += sizeof(uint32_t);
      89           0 :     this->installFooter(action, padding);
      90           0 : }
      91             : 
      92         239 : void SkArenaAlloc::ensureSpace(uint32_t size, uint32_t alignment) {
      93         239 :     constexpr uint32_t headerSize = sizeof(Footer) + sizeof(ptrdiff_t);
      94             :     // The chrome c++ library we use does not define std::max_align_t.
      95             :     // This must be conservative to add the right amount of extra memory to handle the alignment
      96             :     // padding.
      97         239 :     constexpr uint32_t alignof_max_align_t = 8;
      98         239 :     uint32_t objSizeAndOverhead = size + headerSize + sizeof(Footer);
      99         239 :     if (alignment > alignof_max_align_t) {
     100           0 :         objSizeAndOverhead += alignment - 1;
     101             :     }
     102             : 
     103         239 :     uint32_t allocationSize = std::max(objSizeAndOverhead, fExtraSize * fFib0);
     104         239 :     fFib0 += fFib1;
     105         239 :     std::swap(fFib0, fFib1);
     106             : 
     107             :     // Round up to a nice size. If > 32K align to 4K boundary else up to max_align_t. The > 32K
     108             :     // heuristic is from the JEMalloc behavior.
     109             :     {
     110         239 :         uint32_t mask = allocationSize > (1 << 15) ? (1 << 12) - 1 : 16 - 1;
     111         239 :         allocationSize = (allocationSize + mask) & ~mask;
     112             :     }
     113             : 
     114         478 :     char* newBlock = new char[allocationSize];
     115             : 
     116         239 :     auto previousDtor = fDtorCursor;
     117         239 :     fCursor = newBlock;
     118         239 :     fDtorCursor = newBlock;
     119         239 :     fEnd = fCursor + allocationSize;
     120         239 :     this->installPtrFooter(NextBlock, previousDtor, 0);
     121         239 : }
     122             : 
     123        1226 : char* SkArenaAlloc::allocObject(uint32_t size, uint32_t alignment) {
     124        1226 :     uintptr_t mask = alignment - 1;
     125        1226 :     char* objStart = (char*)((uintptr_t)(fCursor + mask) & ~mask);
     126        1226 :     if ((ptrdiff_t)size > fEnd - objStart) {
     127         239 :         this->ensureSpace(size, alignment);
     128         239 :         objStart = (char*)((uintptr_t)(fCursor + mask) & ~mask);
     129             :     }
     130        1226 :     return objStart;
     131             : }
     132             : 
     133        1047 : char* SkArenaAlloc::allocObjectWithFooter(uint32_t sizeIncludingFooter, uint32_t alignment) {
     134        1047 :     uintptr_t mask = alignment - 1;
     135             : 
     136             : restart:
     137        1047 :     uint32_t skipOverhead = 0;
     138        1047 :     bool needsSkipFooter = fCursor != fDtorCursor;
     139        1047 :     if (needsSkipFooter) {
     140           0 :         skipOverhead = sizeof(Footer) + sizeof(uint32_t);
     141             :     }
     142        1047 :     char* objStart = (char*)((uintptr_t)(fCursor + skipOverhead + mask) & ~mask);
     143        1047 :     uint32_t totalSize = sizeIncludingFooter + skipOverhead;
     144             : 
     145        1047 :     if ((ptrdiff_t)totalSize > fEnd - objStart) {
     146           0 :         this->ensureSpace(totalSize, alignment);
     147           0 :         goto restart;
     148             :     }
     149             : 
     150        1047 :     SkASSERT((ptrdiff_t)totalSize <= fEnd - objStart);
     151             : 
     152             :     // Install a skip footer if needed, thus terminating a run of POD data. The calling code is
     153             :     // responsible for installing the footer after the object.
     154        1047 :     if (needsSkipFooter) {
     155           0 :         this->installUint32Footer(SkipPod, SkTo<uint32_t>(fCursor - fDtorCursor), 0);
     156             :     }
     157             : 
     158        1047 :     return objStart;
     159             : }
     160             : 

Generated by: LCOV version 1.13