LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/context - context_mm.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 54 58 93.1 %
Date: 2026-04-07 10:40:57 Functions: 6 6 100.0 %
Branches: 22 38 57.9 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Implementation of Context Memory Manager
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <cstdlib>
      14                 :            : #include <deque>
      15                 :            : #include <limits>
      16                 :            : #include <new>
      17                 :            : #include <ostream>
      18                 :            : #include <vector>
      19                 :            : 
      20                 :            : #ifdef CVC5_VALGRIND
      21                 :            : #include <valgrind/memcheck.h>
      22                 :            : #endif /* CVC5_VALGRIND */
      23                 :            : 
      24                 :            : #include "base/check.h"
      25                 :            : #include "base/output.h"
      26                 :            : #include "context/context_mm.h"
      27                 :            : 
      28                 :            : namespace cvc5::context {
      29                 :            : 
      30                 :            : #ifndef CVC5_DEBUG_CONTEXT_MEMORY_MANAGER
      31                 :            : 
      32                 :    1222737 : void ContextMemoryManager::newChunk() {
      33                 :            : 
      34                 :            :   // Increment index to chunk list
      35                 :    1222737 :   ++d_indexChunkList;
      36 [ -  + ][ -  + ]:    1222737 :   Assert(d_chunkList.size() == d_indexChunkList)
                 [ -  - ]
      37                 :          0 :       << "Index should be at the end of the list";
      38                 :            : 
      39                 :            :   // Create new chunk if no free chunk available
      40         [ +  + ]:    1222737 :   if(d_freeChunks.empty()) {
      41                 :     170125 :     d_chunkList.push_back((char*)malloc(chunkSizeBytes));
      42         [ -  + ]:     170125 :     if (d_chunkList.back() == nullptr)
      43                 :            :     {
      44                 :          0 :       throw std::bad_alloc();
      45                 :            :     }
      46                 :            : 
      47                 :            : #ifdef CVC5_VALGRIND
      48                 :            :     VALGRIND_MAKE_MEM_NOACCESS(d_chunkList.back(), chunkSizeBytes);
      49                 :            : #endif /* CVC5_VALGRIND */
      50                 :            :   }
      51                 :            :   // If there is a free chunk, use that
      52                 :            :   else {
      53                 :    1052612 :     d_chunkList.push_back(d_freeChunks.back());
      54                 :    1052612 :     d_freeChunks.pop_back();
      55                 :            :   }
      56                 :            :   // Set up the current chunk pointers
      57                 :    1222737 :   d_nextFree = d_chunkList.back();
      58                 :    1222737 :   d_endChunk = d_nextFree + chunkSizeBytes;
      59                 :    1222737 : }
      60                 :            : 
      61                 :            : 
      62                 :   16529937 : ContextMemoryManager::ContextMemoryManager() : d_indexChunkList(0) {
      63                 :            :   // Create initial chunk
      64                 :   16529937 :   d_chunkList.push_back((char*)malloc(chunkSizeBytes));
      65                 :   16529937 :   d_nextFree = d_chunkList.back();
      66         [ -  + ]:   16529937 :   if (d_nextFree == nullptr)
      67                 :            :   {
      68                 :          0 :     throw std::bad_alloc();
      69                 :            :   }
      70                 :   16529937 :   d_endChunk = d_nextFree + chunkSizeBytes;
      71                 :            : 
      72                 :            : #ifdef CVC5_VALGRIND
      73                 :            :   VALGRIND_CREATE_MEMPOOL(this, 0, false);
      74                 :            :   VALGRIND_MAKE_MEM_NOACCESS(d_nextFree, chunkSizeBytes);
      75                 :            :   d_allocations.push_back(std::vector<char*>());
      76                 :            : #endif /* CVC5_VALGRIND */
      77                 :   16529937 : }
      78                 :            : 
      79                 :            : 
      80                 :   16507624 : ContextMemoryManager::~ContextMemoryManager() {
      81                 :            : #ifdef CVC5_VALGRIND
      82                 :            :   VALGRIND_DESTROY_MEMPOOL(this);
      83                 :            : #endif /* CVC5_VALGRIND */
      84                 :            : 
      85                 :            :   // Delete all chunks
      86         [ +  + ]:   33015248 :   while(!d_chunkList.empty()) {
      87                 :   16507624 :     free(d_chunkList.back());
      88                 :   16507624 :     d_chunkList.pop_back();
      89                 :            :   }
      90         [ +  + ]:   16632588 :   while(!d_freeChunks.empty()) {
      91                 :     124964 :     free(d_freeChunks.back());
      92                 :     124964 :     d_freeChunks.pop_back();
      93                 :            :   }
      94                 :   16507624 : }
      95                 :            : 
      96                 :            : 
      97                 :  352717980 : void* ContextMemoryManager::newData(size_t size) {
      98                 :            :   // Use next available free location in current chunk
      99                 :  352717980 :   void* res = (void*)d_nextFree;
     100                 :  352717980 :   d_nextFree += size;
     101                 :            :   // Check if the request is too big for the chunk
     102         [ +  + ]:  352717980 :   if(d_nextFree > d_endChunk) {
     103                 :    1222737 :     newChunk();
     104                 :    1222737 :     res = (void*)d_nextFree;
     105                 :    1222737 :     d_nextFree += size;
     106 [ -  + ][ -  + ]:    1222737 :     AlwaysAssert(d_nextFree <= d_endChunk)
                 [ -  - ]
     107                 :          0 :         << "Request is bigger than memory chunk size";
     108                 :            :   }
     109                 :            : 
     110                 :            : #ifdef CVC5_VALGRIND
     111                 :            :   VALGRIND_MEMPOOL_ALLOC(this, static_cast<char*>(res), size);
     112                 :            :   d_allocations.back().push_back(static_cast<char*>(res));
     113                 :            : #endif /* CVC5_VALGRIND */
     114                 :            : 
     115                 :  352717980 :   return res;
     116                 :            : }
     117                 :            : 
     118                 :            : 
     119                 :   19524956 : void ContextMemoryManager::push() {
     120                 :            : #ifdef CVC5_VALGRIND
     121                 :            :   d_allocations.push_back(std::vector<char*>());
     122                 :            : #endif /* CVC5_VALGRIND */
     123                 :            : 
     124                 :            :   // Store current state on the stack
     125                 :   19524956 :   d_nextFreeStack.push_back(d_nextFree);
     126                 :   19524956 :   d_endChunkStack.push_back(d_endChunk);
     127                 :   19524956 :   d_indexChunkListStack.push_back(d_indexChunkList);
     128                 :   19524956 : }
     129                 :            : 
     130                 :            : 
     131                 :   19523595 : void ContextMemoryManager::pop() {
     132                 :            : #ifdef CVC5_VALGRIND
     133                 :            :   for (auto allocation : d_allocations.back())
     134                 :            :   {
     135                 :            :     VALGRIND_MEMPOOL_FREE(this, allocation);
     136                 :            :   }
     137                 :            :   d_allocations.pop_back();
     138                 :            : #endif /* CVC5_VALGRIND */
     139                 :            : 
     140 [ +  - ][ +  - ]:   19523595 :   Assert(d_nextFreeStack.size() > 0 && d_endChunkStack.size() > 0);
         [ -  + ][ -  + ]
                 [ -  - ]
     141                 :            : 
     142                 :            :   // Restore state from stack
     143                 :   19523595 :   d_nextFree = d_nextFreeStack.back();
     144                 :   19523595 :   d_nextFreeStack.pop_back();
     145                 :   19523595 :   d_endChunk = d_endChunkStack.back();
     146                 :   19523595 :   d_endChunkStack.pop_back();
     147                 :            : 
     148                 :            :   // Free all the new chunks since the last push
     149         [ +  + ]:   20746318 :   while(d_indexChunkList > d_indexChunkListStack.back()) {
     150                 :    1222723 :     d_freeChunks.push_back(d_chunkList.back());
     151                 :            : #ifdef CVC5_VALGRIND
     152                 :            :     VALGRIND_MAKE_MEM_NOACCESS(d_chunkList.back(), chunkSizeBytes);
     153                 :            : #endif /* CVC5_VALGRIND */
     154                 :    1222723 :     d_chunkList.pop_back();
     155                 :    1222723 :     --d_indexChunkList;
     156                 :            :   }
     157                 :   19523595 :   d_indexChunkListStack.pop_back();
     158                 :            : 
     159                 :            :   // Delete excess free chunks
     160         [ +  + ]:   19568742 :   while(d_freeChunks.size() > maxFreeChunks) {
     161                 :      45147 :     free(d_freeChunks.front());
     162                 :      45147 :     d_freeChunks.pop_front();
     163                 :            :   }
     164                 :   19523595 : }
     165                 :            : #else
     166                 :            : 
     167                 :            : unsigned ContextMemoryManager::getMaxAllocationSize()
     168                 :            : {
     169                 :            :   return std::numeric_limits<unsigned>::max();
     170                 :            : }
     171                 :            : 
     172                 :            : #endif /* CVC5_DEBUG_CONTEXT_MEMORY_MANAGER */
     173                 :            : 
     174                 :            : }  // namespace cvc5::context

Generated by: LCOV version 1.14