LCOV - code coverage report
Current view: directory - gfx/angle/src/compiler - PoolAlloc.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 116 0 0.0 %
Date: 2012-06-02 Functions: 14 0 0.0 %

       1                 : //
       2                 : // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
       3                 : // Use of this source code is governed by a BSD-style license that can be
       4                 : // found in the LICENSE file.
       5                 : //
       6                 : 
       7                 : #include "compiler/PoolAlloc.h"
       8                 : 
       9                 : #ifndef _MSC_VER
      10                 : #include <stdint.h>
      11                 : #endif
      12                 : #include <stdio.h>
      13                 : 
      14                 : #include "compiler/InitializeGlobals.h"
      15                 : #include "compiler/osinclude.h"
      16                 : 
      17                 : OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
      18                 : 
      19               0 : void InitializeGlobalPools()
      20                 : {
      21               0 :     TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
      22               0 :     if (globalPools)
      23               0 :         return;
      24                 : 
      25               0 :     TThreadGlobalPools* threadData = new TThreadGlobalPools();
      26               0 :     threadData->globalPoolAllocator = 0;
      27                 : 
      28               0 :     OS_SetTLSValue(PoolIndex, threadData);
      29                 : }
      30                 : 
      31               0 : void FreeGlobalPools()
      32                 : {
      33                 :     // Release the allocated memory for this thread.
      34               0 :     TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
      35               0 :     if (!globalPools)
      36               0 :         return;
      37                 :  
      38                 :     delete globalPools;
      39                 : }
      40                 : 
      41               0 : bool InitializePoolIndex()
      42                 : {
      43                 :     // Allocate a TLS index.
      44               0 :     if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
      45               0 :         return false;
      46                 : 
      47               0 :     return true;
      48                 : }
      49                 : 
      50               0 : void FreePoolIndex()
      51                 : {
      52                 :     // Release the TLS index.
      53               0 :     OS_FreeTLSIndex(PoolIndex);
      54               0 : }
      55                 : 
      56               0 : TPoolAllocator& GetGlobalPoolAllocator()
      57                 : {
      58               0 :     TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
      59                 : 
      60               0 :     return *threadData->globalPoolAllocator;
      61                 : }
      62                 : 
      63               0 : void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
      64                 : {
      65               0 :     TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
      66                 : 
      67               0 :     threadData->globalPoolAllocator = poolAllocator;
      68               0 : }
      69                 : 
      70                 : //
      71                 : // Implement the functionality of the TPoolAllocator class, which
      72                 : // is documented in PoolAlloc.h.
      73                 : //
      74               0 : TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : 
      75                 :     pageSize(growthIncrement),
      76                 :     alignment(allocationAlignment),
      77                 :     freeList(0),
      78                 :     inUseList(0),
      79                 :     numCalls(0),
      80               0 :     totalBytes(0)
      81                 : {
      82                 :     //
      83                 :     // Don't allow page sizes we know are smaller than all common
      84                 :     // OS page sizes.
      85                 :     //
      86               0 :     if (pageSize < 4*1024)
      87               0 :         pageSize = 4*1024;
      88                 : 
      89                 :     //
      90                 :     // A large currentPageOffset indicates a new page needs to
      91                 :     // be obtained to allocate memory.
      92                 :     //
      93               0 :     currentPageOffset = pageSize;
      94                 : 
      95                 :     //
      96                 :     // Adjust alignment to be at least pointer aligned and
      97                 :     // power of 2.
      98                 :     //
      99               0 :     size_t minAlign = sizeof(void*);
     100               0 :     alignment &= ~(minAlign - 1);
     101               0 :     if (alignment < minAlign)
     102               0 :         alignment = minAlign;
     103               0 :     size_t a = 1;
     104               0 :     while (a < alignment)
     105               0 :         a <<= 1;
     106               0 :     alignment = a;
     107               0 :     alignmentMask = a - 1;
     108                 : 
     109                 :     //
     110                 :     // Align header skip
     111                 :     //
     112               0 :     headerSkip = minAlign;
     113               0 :     if (headerSkip < sizeof(tHeader)) {
     114               0 :         headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
     115                 :     }
     116               0 : }
     117                 : 
     118               0 : TPoolAllocator::~TPoolAllocator()
     119                 : {
     120               0 :     while (inUseList) {
     121               0 :         tHeader* next = inUseList->nextPage;
     122               0 :         inUseList->~tHeader();
     123               0 :         delete [] reinterpret_cast<char*>(inUseList);
     124               0 :         inUseList = next;
     125                 :     }
     126                 : 
     127                 :     // We should not check the guard blocks
     128                 :     // here, because we did it already when the block was
     129                 :     // placed into the free list.
     130                 :     //
     131               0 :     while (freeList) {
     132               0 :         tHeader* next = freeList->nextPage;
     133               0 :         delete [] reinterpret_cast<char*>(freeList);
     134               0 :         freeList = next;
     135                 :     }
     136               0 : }
     137                 : 
     138                 : // Support MSVC++ 6.0
     139                 : const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
     140                 : const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
     141                 : const unsigned char TAllocation::userDataFill       = 0xcd;
     142                 : 
     143                 : #ifdef GUARD_BLOCKS
     144                 :     const size_t TAllocation::guardBlockSize = 16;
     145                 : #else
     146                 :     const size_t TAllocation::guardBlockSize = 0;
     147                 : #endif
     148                 : 
     149                 : //
     150                 : // Check a single guard block for damage
     151                 : //
     152               0 : void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
     153                 : {
     154                 : #ifdef GUARD_BLOCKS
     155               0 :     for (size_t x = 0; x < guardBlockSize; x++) {
     156               0 :         if (blockMem[x] != val) {
     157                 :             char assertMsg[80];
     158                 : 
     159                 :             // We don't print the assert message.  It's here just to be helpful.
     160                 :             sprintf(assertMsg, "PoolAlloc: Damage %s %lu byte allocation at 0x%p\n",
     161               0 :                     locText, size, data());
     162               0 :             assert(0 && "PoolAlloc: Damage in guard block");
     163                 :         }
     164                 :     }
     165                 : #endif
     166               0 : }
     167                 : 
     168                 : 
     169               0 : void TPoolAllocator::push()
     170                 : {
     171               0 :     tAllocState state = { currentPageOffset, inUseList };
     172                 : 
     173               0 :     stack.push_back(state);
     174                 :         
     175                 :     //
     176                 :     // Indicate there is no current page to allocate from.
     177                 :     //
     178               0 :     currentPageOffset = pageSize;
     179               0 : }
     180                 : 
     181                 : //
     182                 : // Do a mass-deallocation of all the individual allocations
     183                 : // that have occurred since the last push(), or since the
     184                 : // last pop(), or since the object's creation.
     185                 : //
     186                 : // The deallocated pages are saved for future allocations.
     187                 : //
     188               0 : void TPoolAllocator::pop()
     189                 : {
     190               0 :     if (stack.size() < 1)
     191               0 :         return;
     192                 : 
     193               0 :     tHeader* page = stack.back().page;
     194               0 :     currentPageOffset = stack.back().offset;
     195                 : 
     196               0 :     while (inUseList != page) {
     197                 :         // invoke destructor to free allocation list
     198               0 :         inUseList->~tHeader();
     199                 :         
     200               0 :         tHeader* nextInUse = inUseList->nextPage;
     201               0 :         if (inUseList->pageCount > 1)
     202               0 :             delete [] reinterpret_cast<char*>(inUseList);
     203                 :         else {
     204               0 :             inUseList->nextPage = freeList;
     205               0 :             freeList = inUseList;
     206                 :         }
     207               0 :         inUseList = nextInUse;
     208                 :     }
     209                 : 
     210               0 :     stack.pop_back();
     211                 : }
     212                 : 
     213                 : //
     214                 : // Do a mass-deallocation of all the individual allocations
     215                 : // that have occurred.
     216                 : //
     217               0 : void TPoolAllocator::popAll()
     218                 : {
     219               0 :     while (stack.size() > 0)
     220               0 :         pop();
     221               0 : }
     222                 : 
     223               0 : void* TPoolAllocator::allocate(size_t numBytes)
     224                 : {
     225                 :     // If we are using guard blocks, all allocations are bracketed by
     226                 :     // them: [guardblock][allocation][guardblock].  numBytes is how
     227                 :     // much memory the caller asked for.  allocationSize is the total
     228                 :     // size including guard blocks.  In release build,
     229                 :     // guardBlockSize=0 and this all gets optimized away.
     230               0 :     size_t allocationSize = TAllocation::allocationSize(numBytes);
     231                 :     
     232                 :     //
     233                 :     // Just keep some interesting statistics.
     234                 :     //
     235               0 :     ++numCalls;
     236               0 :     totalBytes += numBytes;
     237                 : 
     238                 :     //
     239                 :     // Do the allocation, most likely case first, for efficiency.
     240                 :     // This step could be moved to be inline sometime.
     241                 :     //
     242               0 :     if (currentPageOffset + allocationSize <= pageSize) {
     243                 :         //
     244                 :         // Safe to allocate from currentPageOffset.
     245                 :         //
     246               0 :         unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
     247               0 :         currentPageOffset += allocationSize;
     248               0 :         currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
     249                 : 
     250               0 :         return initializeAllocation(inUseList, memory, numBytes);
     251                 :     }
     252                 : 
     253               0 :     if (allocationSize + headerSkip > pageSize) {
     254                 :         //
     255                 :         // Do a multi-page allocation.  Don't mix these with the others.
     256                 :         // The OS is efficient and allocating and free-ing multiple pages.
     257                 :         //
     258               0 :         size_t numBytesToAlloc = allocationSize + headerSkip;
     259               0 :         tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
     260               0 :         if (memory == 0)
     261               0 :             return 0;
     262                 : 
     263                 :         // Use placement-new to initialize header
     264               0 :         new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
     265               0 :         inUseList = memory;
     266                 : 
     267               0 :         currentPageOffset = pageSize;  // make next allocation come from a new page
     268                 : 
     269                 :         // No guard blocks for multi-page allocations (yet)
     270               0 :         return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
     271                 :     }
     272                 : 
     273                 :     //
     274                 :     // Need a simple page to allocate from.
     275                 :     //
     276                 :     tHeader* memory;
     277               0 :     if (freeList) {
     278               0 :         memory = freeList;
     279               0 :         freeList = freeList->nextPage;
     280                 :     } else {
     281               0 :         memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
     282               0 :         if (memory == 0)
     283               0 :             return 0;
     284                 :     }
     285                 : 
     286                 :     // Use placement-new to initialize header
     287               0 :     new(memory) tHeader(inUseList, 1);
     288               0 :     inUseList = memory;
     289                 :     
     290               0 :     unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
     291               0 :     currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
     292                 : 
     293               0 :     return initializeAllocation(inUseList, ret, numBytes);
     294                 : }
     295                 : 
     296                 : 
     297                 : //
     298                 : // Check all allocations in a list for damage by calling check on each.
     299                 : //
     300               0 : void TAllocation::checkAllocList() const
     301                 : {
     302               0 :     for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
     303               0 :         alloc->check();
     304               0 : }

Generated by: LCOV version 1.7