/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/GrMemoryPool.h"

#include "include/private/SkTPin.h"
#include "src/core/SkASAN.h"

#ifdef SK_DEBUG
    #include <atomic>
#endif

#include <tuple>

///////////////////////////////////////////////////////////////////////////////////////////////////

std::unique_ptr<GrMemoryPool> GrMemoryPool::Make(size_t preallocSize, size_t minAllocSize) {
    static_assert(sizeof(GrMemoryPool) < GrMemoryPool::kMinAllocationSize);

    preallocSize = SkTPin(preallocSize, kMinAllocationSize,
                          (size_t) SkBlockAllocator::kMaxAllocationSize);
    minAllocSize = SkTPin(minAllocSize, kMinAllocationSize,
                          (size_t) SkBlockAllocator::kMaxAllocationSize);
    void* mem = operator new(preallocSize);
    return std::unique_ptr<GrMemoryPool>(new (mem) GrMemoryPool(preallocSize, minAllocSize));
}

GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize)
        : fAllocator(SkBlockAllocator::GrowthPolicy::kFixed, minAllocSize,
                     preallocSize - offsetof(GrMemoryPool, fAllocator) - sizeof(SkBlockAllocator)) {
    SkDEBUGCODE(
        fDebug = new Debug;
        fDebug->fAllocationCount = 0;
    )
}

GrMemoryPool::~GrMemoryPool() {
    this->reportLeaks();
    SkASSERT(0 == fDebug->fAllocationCount);
    SkASSERT(this->isEmpty());
    SkDEBUGCODE(delete fDebug;)
}

void GrMemoryPool::reportLeaks() const {
#ifdef SK_DEBUG
    int i = 0;
    int n = fDebug->fAllocatedIDs.count();
    for (int id : fDebug->fAllocatedIDs) {
        if (++i == 1) {
            SkDebugf("Leaked %d IDs (in no particular order): %d%s", n, id, (n == i) ? "\n" : "");
        } else if (i < 11) {
            SkDebugf(", %d%s", id, (n == i ? "\n" : ""));
        } else if (i == 11) {
            SkDebugf(", ...\n");
            break;
        }
    }
#endif
}

void* GrMemoryPool::allocate(size_t size) {
    static_assert(alignof(Header) <= kAlignment);
    SkDEBUGCODE(this->validate();)

    SkBlockAllocator::ByteRange alloc = fAllocator.allocate<kAlignment, sizeof(Header)>(size);

    // Initialize GrMemoryPool's custom header at the start of the allocation
    Header* header = static_cast<Header*>(alloc.fBlock->ptr(alloc.fAlignedOffset - sizeof(Header)));
    header->fStart = alloc.fStart;
    header->fEnd = alloc.fEnd;

    // Update live count within the block
    alloc.fBlock->setMetadata(alloc.fBlock->metadata() + 1);

#if defined(SK_SANITIZE_ADDRESS)
    sk_asan_poison_memory_region(&header->fSentinel, sizeof(header->fSentinel));
#elif defined(SK_DEBUG)
    header->fSentinel = SkBlockAllocator::kAssignedMarker;
#endif

#if defined(SK_DEBUG)
    header->fID = []{
        static std::atomic<int> nextID{1};
        return nextID.fetch_add(1, std::memory_order_relaxed);
    }();

    // You can set a breakpoint here when a leaked ID is allocated to see the stack frame.
    fDebug->fAllocatedIDs.add(header->fID);
    fDebug->fAllocationCount++;
#endif

    // User-facing pointer is after the header padding
    return alloc.fBlock->ptr(alloc.fAlignedOffset);
}

void GrMemoryPool::release(void* p) {
    Header* header = reinterpret_cast<Header*>(reinterpret_cast<intptr_t>(p) - sizeof(Header));

#if defined(SK_SANITIZE_ADDRESS)
    sk_asan_unpoison_memory_region(&header->fSentinel, sizeof(header->fSentinel));
#elif defined(SK_DEBUG)
    SkASSERT(SkBlockAllocator::kAssignedMarker == header->fSentinel);
    header->fSentinel = SkBlockAllocator::kFreedMarker;
#endif

#if defined(SK_DEBUG)
    fDebug->fAllocatedIDs.remove(header->fID);
    fDebug->fAllocationCount--;
#endif

    SkBlockAllocator::Block* block = fAllocator.owningBlock<kAlignment>(header, header->fStart);

#if defined(SK_DEBUG)
    // (p - block) matches the original alignedOffset value from SkBlockAllocator::allocate().
    intptr_t alignedOffset = (intptr_t)p - (intptr_t)block;
    SkASSERT(p == block->ptr(alignedOffset));

    // Scrub the block contents to prevent use-after-free errors.
    memset(p, 0xDD, header->fEnd - alignedOffset);
#endif

    int alive = block->metadata();
    if (alive == 1) {
        // This was last allocation in the block, so remove it
        fAllocator.releaseBlock(block);
    } else {
        // Update count and release storage of the allocation itself
        block->setMetadata(alive - 1);
        block->release(header->fStart, header->fEnd);
    }
}

#ifdef SK_DEBUG
void GrMemoryPool::validate() const {
    fAllocator.validate();

    int allocCount = 0;
    for (const auto* b : fAllocator.blocks()) {
        allocCount += b->metadata();
    }
    SkASSERT(allocCount == fDebug->fAllocationCount);
    SkASSERT(fDebug->fAllocationCount == fDebug->fAllocatedIDs.count());
    SkASSERT(allocCount > 0 || this->isEmpty());
}
#endif
