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-02-27 11:41:18 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                 :    1192644 : void ContextMemoryManager::newChunk() {
      33                 :            : 
      34                 :            :   // Increment index to chunk list
      35                 :    1192644 :   ++d_indexChunkList;
      36 [ -  + ][ -  + ]:    1192644 :   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         [ +  + ]:    1192644 :   if(d_freeChunks.empty()) {
      41                 :     167524 :     d_chunkList.push_back((char*)malloc(chunkSizeBytes));
      42         [ -  + ]:     167524 :     if(d_chunkList.back() == NULL) {
      43                 :          0 :       throw std::bad_alloc();
      44                 :            :     }
      45                 :            : 
      46                 :            : #ifdef CVC5_VALGRIND
      47                 :            :     VALGRIND_MAKE_MEM_NOACCESS(d_chunkList.back(), chunkSizeBytes);
      48                 :            : #endif /* CVC5_VALGRIND */
      49                 :            :   }
      50                 :            :   // If there is a free chunk, use that
      51                 :            :   else {
      52                 :    1025120 :     d_chunkList.push_back(d_freeChunks.back());
      53                 :    1025120 :     d_freeChunks.pop_back();
      54                 :            :   }
      55                 :            :   // Set up the current chunk pointers
      56                 :    1192644 :   d_nextFree = d_chunkList.back();
      57                 :    1192644 :   d_endChunk = d_nextFree + chunkSizeBytes;
      58                 :    1192644 : }
      59                 :            : 
      60                 :            : 
      61                 :   15781116 : ContextMemoryManager::ContextMemoryManager() : d_indexChunkList(0) {
      62                 :            :   // Create initial chunk
      63                 :   15781116 :   d_chunkList.push_back((char*)malloc(chunkSizeBytes));
      64                 :   15781116 :   d_nextFree = d_chunkList.back();
      65         [ -  + ]:   15781116 :   if(d_nextFree == NULL) {
      66                 :          0 :     throw std::bad_alloc();
      67                 :            :   }
      68                 :   15781116 :   d_endChunk = d_nextFree + chunkSizeBytes;
      69                 :            : 
      70                 :            : #ifdef CVC5_VALGRIND
      71                 :            :   VALGRIND_CREATE_MEMPOOL(this, 0, false);
      72                 :            :   VALGRIND_MAKE_MEM_NOACCESS(d_nextFree, chunkSizeBytes);
      73                 :            :   d_allocations.push_back(std::vector<char*>());
      74                 :            : #endif /* CVC5_VALGRIND */
      75                 :   15781116 : }
      76                 :            : 
      77                 :            : 
      78                 :   15758920 : ContextMemoryManager::~ContextMemoryManager() {
      79                 :            : #ifdef CVC5_VALGRIND
      80                 :            :   VALGRIND_DESTROY_MEMPOOL(this);
      81                 :            : #endif /* CVC5_VALGRIND */
      82                 :            : 
      83                 :            :   // Delete all chunks
      84         [ +  + ]:   31517840 :   while(!d_chunkList.empty()) {
      85                 :   15758920 :     free(d_chunkList.back());
      86                 :   15758920 :     d_chunkList.pop_back();
      87                 :            :   }
      88         [ +  + ]:   15882178 :   while(!d_freeChunks.empty()) {
      89                 :     123258 :     free(d_freeChunks.back());
      90                 :     123258 :     d_freeChunks.pop_back();
      91                 :            :   }
      92                 :   15758920 : }
      93                 :            : 
      94                 :            : 
      95                 :  346120836 : void* ContextMemoryManager::newData(size_t size) {
      96                 :            :   // Use next available free location in current chunk
      97                 :  346120836 :   void* res = (void*)d_nextFree;
      98                 :  346120836 :   d_nextFree += size;
      99                 :            :   // Check if the request is too big for the chunk
     100         [ +  + ]:  346120836 :   if(d_nextFree > d_endChunk) {
     101                 :    1192644 :     newChunk();
     102                 :    1192644 :     res = (void*)d_nextFree;
     103                 :    1192644 :     d_nextFree += size;
     104 [ -  + ][ -  + ]:    1192644 :     AlwaysAssert(d_nextFree <= d_endChunk)
                 [ -  - ]
     105                 :          0 :         << "Request is bigger than memory chunk size";
     106                 :            :   }
     107                 :            : 
     108                 :            : #ifdef CVC5_VALGRIND
     109                 :            :   VALGRIND_MEMPOOL_ALLOC(this, static_cast<char*>(res), size);
     110                 :            :   d_allocations.back().push_back(static_cast<char*>(res));
     111                 :            : #endif /* CVC5_VALGRIND */
     112                 :            : 
     113                 :  346120836 :   return res;
     114                 :            : }
     115                 :            : 
     116                 :            : 
     117                 :   19133794 : void ContextMemoryManager::push() {
     118                 :            : #ifdef CVC5_VALGRIND
     119                 :            :   d_allocations.push_back(std::vector<char*>());
     120                 :            : #endif /* CVC5_VALGRIND */
     121                 :            : 
     122                 :            :   // Store current state on the stack
     123                 :   19133794 :   d_nextFreeStack.push_back(d_nextFree);
     124                 :   19133794 :   d_endChunkStack.push_back(d_endChunk);
     125                 :   19133794 :   d_indexChunkListStack.push_back(d_indexChunkList);
     126                 :   19133794 : }
     127                 :            : 
     128                 :            : 
     129                 :   19132433 : void ContextMemoryManager::pop() {
     130                 :            : #ifdef CVC5_VALGRIND
     131                 :            :   for (auto allocation : d_allocations.back())
     132                 :            :   {
     133                 :            :     VALGRIND_MEMPOOL_FREE(this, allocation);
     134                 :            :   }
     135                 :            :   d_allocations.pop_back();
     136                 :            : #endif /* CVC5_VALGRIND */
     137                 :            : 
     138 [ +  - ][ +  - ]:   19132433 :   Assert(d_nextFreeStack.size() > 0 && d_endChunkStack.size() > 0);
         [ -  + ][ -  + ]
                 [ -  - ]
     139                 :            : 
     140                 :            :   // Restore state from stack
     141                 :   19132433 :   d_nextFree = d_nextFreeStack.back();
     142                 :   19132433 :   d_nextFreeStack.pop_back();
     143                 :   19132433 :   d_endChunk = d_endChunkStack.back();
     144                 :   19132433 :   d_endChunkStack.pop_back();
     145                 :            : 
     146                 :            :   // Free all the new chunks since the last push
     147         [ +  + ]:   20325063 :   while(d_indexChunkList > d_indexChunkListStack.back()) {
     148                 :    1192630 :     d_freeChunks.push_back(d_chunkList.back());
     149                 :            : #ifdef CVC5_VALGRIND
     150                 :            :     VALGRIND_MAKE_MEM_NOACCESS(d_chunkList.back(), chunkSizeBytes);
     151                 :            : #endif /* CVC5_VALGRIND */
     152                 :    1192630 :     d_chunkList.pop_back();
     153                 :    1192630 :     --d_indexChunkList;
     154                 :            :   }
     155                 :   19132433 :   d_indexChunkListStack.pop_back();
     156                 :            : 
     157                 :            :   // Delete excess free chunks
     158         [ +  + ]:   19176685 :   while(d_freeChunks.size() > maxFreeChunks) {
     159                 :      44252 :     free(d_freeChunks.front());
     160                 :      44252 :     d_freeChunks.pop_front();
     161                 :            :   }
     162                 :   19132433 : }
     163                 :            : #else
     164                 :            : 
     165                 :            : unsigned ContextMemoryManager::getMaxAllocationSize()
     166                 :            : {
     167                 :            :   return std::numeric_limits<unsigned>::max();
     168                 :            : }
     169                 :            : 
     170                 :            : #endif /* CVC5_DEBUG_CONTEXT_MEMORY_MANAGER */
     171                 :            : 
     172                 :            : }  // namespace cvc5::context

Generated by: LCOV version 1.14