[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/anderlli0053/daScript/master/src/misc/memory_model.cpp [Back]  [Original]

#include "daScript/misc/platform.h"

#include "daScript/misc/memory_model.h"
#include "daScript/misc/debug_break.h"

namespace das {

#if DAS_TRACK_ALLOCATIONS
    uint64_t    g_tracker = 0;
    uint64_t    g_breakpoint= -1ul;

    void das_track_breakpoint ( uint64_t id ) {
        g_breakpoint = id;
    }
#endif

    MemoryModel::MemoryModel () {
        alignMask = 15;
        totalAllocated = 0;
        maxAllocated = 0;
    }

    MemoryModel::~MemoryModel() {
        shoe.clear();
        for ( auto & itb : bigStuff ) {
            das_aligned_free16(itb.first);
        }
        bigStuff.clear();
#if DAS_SANITIZER
        for ( auto & itb : deletedBigStuff ) {
            das_aligned_free16(itb.first);
        }
        deletedBigStuff.clear();
#endif
    }

    void MemoryModel::setInitialSize ( uint32_t size ) {
        initialSize = size;
    }

    uint32_t MemoryModel::grow ( uint32_t si ) {
        if ( shoe.chunks[si] ) {
            uint32_t size = shoe.chunks[si]->total;
            if ( customGrow ) {
                size = customGrow(size);
            } else {
                size = size * 2;
            }
            return size;
        } else {
            if ( !initialSize ) {
                initialSize = default_initial_size;
            }
            return initialSize / ((si+1) 4) - 1;
            uint32_t total = grow(si);
            shoe.chunks[si] = new Deck(total, size, shoe.chunks[si]);
            return shoe.chunks[si]->allocate();
        }
#endif
    }

    bool MemoryModel::free ( char * ptr, uint32_t size ) {
        if ( !size ) return true;
        size = (size + alignMask) & ~alignMask;

#if DAS_SANITIZER
        memset(ptr, 0xcd, size);
#endif
#if !DAS_TRACK_ALLOCATIONS
        if ( size second==size, "free size mismatch, %u allocated vs %u freed", itb->second, size );
#if DAS_SANITIZER
            deletedBigStuff[itb->first] = itb->second;
#else
            das_aligned_free16(itb->first);
#endif
            bigStuff.erase(itb);
            totalAllocated -= size;
#if DAS_TRACK_ALLOCATIONS
            bigStuffId.erase(ptr);
            bigStuffAt.erase(ptr);
            bigStuffComment.erase(ptr);
#endif
            return true;
        }
        DAS_ASSERTF(0, "we are trying to delete pointer, which we did not allocate");
        return false;
    }

    char * MemoryModel::reallocate ( char * ptr, uint32_t size, uint32_t nsize ) {
        if ( !ptr ) return allocate(nsize);
        size = (size + alignMask) & ~alignMask;
        nsize = (nsize + alignMask) & ~alignMask;
        char * nptr = allocate(nsize);
        DAS_ASSERT(nptr && "out of memory?");
        memcpy ( nptr, ptr, das::min(size,nsize) );
#if DAS_TRACK_ALLOCATIONS
        auto pAt = bigStuffAt.find(ptr);
        if ( pAt != bigStuffAt.end() ) {
            bigStuffAt[nptr] = pAt->second;
        }
        auto pCm = bigStuffComment.find(ptr);
        if ( pCm != bigStuffComment.end() ) {
            bigStuffComment[nptr] = pCm->second;
        }
#endif
        free(ptr, size);
        return nptr;
    }

    void MemoryModel::reset() {
        for ( auto & itb : bigStuff ) {
#if DAS_SANITIZER
            deletedBigStuff[itb.first] = itb.second;
#else
            das_aligned_free16(itb.first);
#endif
        }
        bigStuff.clear();
#if DAS_TRACK_ALLOCATIONS
        bigStuffId.clear();
        bigStuffAt.clear();
        bigStuffComment.clear();
#endif
        shoe.reset();
    }

    uint64_t MemoryModel::totalAlignedMemoryAllocated() const {
        uint64_t mem = shoe.totalBytesAllocated();
        for (const auto & it : bigStuff) {
            mem += it.second;
        }
        return mem;
    }

    void MemoryModel::sweep() {
        totalAllocated = 0;
#if !DAS_TRACK_ALLOCATIONS
        for ( uint32_t si=0; si!=DAS_MAX_SHOE_CUNKS; ++si ) {   // we re-track all small allocations
            for ( auto ch=shoe.chunks[si]; ch; ch=ch->next ) {
                ch->afterGC();
                uint32_t utotal = ch->total / 32;
                for ( uint32_t i=0; i!=utotal; ++i ) {
                    uint32_t b = ch->bits[i];
                    for ( uint32_t j=0; j!=32; ++j ) {          // TODO: this is COUNTBITS * size
                        if ( b & (1data + (i*32+j)*ch->size, 0xcd, ch->size );
#endif
                        }
                    }
                }
            }
        }
#endif
        for ( auto it = bigStuff.begin(); it!=bigStuff.end() ; ) {
            if ( it->second & DAS_PAGE_GC_MASK ) {
                it->second &= ~DAS_PAGE_GC_MASK;
                totalAllocated += it->second;
                ++ it;
            } else {
#if DAS_SANITIZER
                memset ( it->first, 0xcd, it->second );
#endif
                das_aligned_free16(it->first);
                it = bigStuff.erase(it);
            }
        }
    }

    char * LinearChunkAllocator::reallocate ( char * ptr, uint32_t size, uint32_t nsize ) {
        if ( !ptr ) return allocate(nsize);
        size = (size + alignMask) & ~alignMask;
        nsize = (nsize + alignMask) & ~alignMask;
        // TODO: we can 'expand' in certain cases
        char * nptr = allocate(nsize);
        memcpy ( nptr, ptr, das::min(size,nsize) );
        free(ptr, size);
        return nptr;
    }

    void LinearChunkAllocator::free ( char * ptr, uint32_t s ) {
        s = (s + alignMask) & ~alignMask;
        for ( auto ch=chunk; ch; ch=ch->next ) {
            if ( ch->isOwnPtr(ptr) ) {
                ch->free(ptr,s);
                break;
            }
        }
    }

    uint32_t LinearChunkAllocator::grow ( uint32_t size ) {
        return customGrow ? customGrow(size) : size * 2;
    }

    char * LinearChunkAllocator::allocate ( uint32_t s ) {
        if ( !s ) return nullptr;
        s = (s + alignMask) & ~alignMask;
        if ( !chunk ) {
            if ( !initialSize ) {
                initialSize = default_initial_size;
            }
            chunk = new HeapChunk ( das::max(initialSize, s), nullptr );
            // printf("[HC] %i\n", chunk->size);
        }
        for ( ;; ) {
            if ( char * res = chunk->allocate(s) ) {
                // printf("[A] %i bytes, offs=%i\n", int(s), int(res-chunk->data));
                return res;
            }
            chunk = new HeapChunk ( das::max(grow(chunk->size), s), chunk);
            // printf("[HC] %i bytes\n", chunk->size);
        }
    }

    void LinearChunkAllocator::reset() {
        if ( chunk && chunk->next ) {
            auto maxAllocated = (uint32_t(bytesAllocated())+1023) & ~1023;
            initialSize = das::max(initialSize, maxAllocated);
            delete chunk;
            chunk = nullptr;
        } else if ( chunk ) {
            chunk->offset = 0;
        }
    }

    char * LinearChunkAllocator::allocateName ( const string & name ) {
        if (!name.empty()) {
            auto length = uint32_t(name.length());
            if (auto str = (char *)allocate(length + 1)) {
                memcpy(str, name.c_str(), length);
                str[length] = 0;
                return str;
            }
        }
        return nullptr;
    }

    void LinearChunkAllocator::getStats ( uint32_t & depth, uint64_t & bytes, uint64_t & total )  const {
        depth = 0;
        bytes = 0;
        total = 0;
        for ( auto ch=chunk; ch; ch=ch->next ) {
            depth ++;
            bytes += ch->offset;
            total += ch->size;
        }
    }

    uint32_t LinearChunkAllocator::depth() const {
        uint32_t d; uint64_t b, t;
        getStats(d, b, t);
        return d;
    }

    uint64_t LinearChunkAllocator::bytesAllocated() const {
        uint32_t d; uint64_t b, t;
        getStats(d, b, t);
        return b;
    }

    uint64_t LinearChunkAllocator::totalAlignedMemoryAllocated() const {
        uint32_t d; uint64_t b, t;
        getStats(d, b, t);
        return t;
    }
}


Web Proxy Viewer  |  New URL  |  Original Page