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

#include <algorithm>
#include "SkArenaAlloc.h"

struct Skipper {
    char* operator()(char* objEnd, ptrdiff_t size) { return objEnd + size; }
};

struct NextBlock {
    char* operator()(char* objEnd, ptrdiff_t size) { delete [] objEnd; return objEnd + size; }
};

SkArenaAlloc::SkArenaAlloc(char* block, size_t size, size_t extraSize)
    : fDtorCursor{block}
    , fCursor    {block}
    , fEnd       {block + size}
    , fExtraSize {extraSize}
{
    if (size < sizeof(Footer)) {
        fEnd = fCursor = fDtorCursor = nullptr;
    }

    if (fCursor != nullptr) {
        this->installFooter(EndChain, 0);
    }
}

SkArenaAlloc::~SkArenaAlloc() {
    this->reset();
}

void SkArenaAlloc::reset() {
    Footer f;
    memmove(&f, fDtorCursor - sizeof(Footer), sizeof(Footer));
    char* releaser = fDtorCursor;
    while (releaser != nullptr) {
        releaser = this->callFooterAction(releaser);
    }
}

void SkArenaAlloc::installFooter(FooterAction* releaser, ptrdiff_t padding) {
    ptrdiff_t releaserDiff = (char *)releaser - (char *)EndChain;
    ptrdiff_t footerData = SkLeftShift((int64_t)releaserDiff, 5) | padding;
    if (padding >= 32 || !SkTFitsIn<int32_t>(footerData)) {
        // Footer data will not fit.
        SkFAIL("Constraints are busted.");
    }

    Footer footer = (Footer)(footerData);
    memmove(fCursor, &footer, sizeof(Footer));
    Footer check;
    memmove(&check, fCursor, sizeof(Footer));
    fCursor += sizeof(Footer);
    fDtorCursor = fCursor;
}

void SkArenaAlloc::ensureSpace(size_t size, size_t alignment) {
    constexpr size_t headerSize = sizeof(Footer) + sizeof(ptrdiff_t);
    // The chrome c++ library we use does not define std::max_align_t.
    // This must be conservative to add the right amount of extra memory to handle the alignment
    // padding.
    constexpr size_t alignof_max_align_t = 8;
    auto objSizeAndOverhead = size + headerSize + sizeof(Footer);
    if (alignment > alignof_max_align_t) {
        objSizeAndOverhead += alignment - 1;
    }

    auto allocationSize = std::max(objSizeAndOverhead, fExtraSize);

    // Round up to a nice size. If > 32K align to 4K boundary else up to max_align_t. The > 32K
    // heuristic is from the JEMalloc behavior.
    {
        size_t mask = allocationSize > (1 << 15) ? (1 << 12) - 1 : 32 - 1;
        allocationSize = (allocationSize + mask) & ~mask;
    }

    char* newBlock = new char[allocationSize];

    auto previousDtor = fDtorCursor;
    fCursor = newBlock;
    fDtorCursor = newBlock;
    fEnd = fCursor + allocationSize;
    this->installIntFooter<NextBlock>(previousDtor - fCursor, 0);
}

char* SkArenaAlloc::allocObject(size_t size, size_t alignment) {
    size_t mask = alignment - 1;
    char* objStart = (char*)((uintptr_t)(fCursor + mask) & ~mask);
    if (objStart + size > fEnd) {
        this->ensureSpace(size, alignment);
        objStart = (char*)((uintptr_t)(fCursor + mask) & ~mask);
    }
    return objStart;
}

// * sizeAndFooter - the memory for the footer in addition to the size for the object.
// * alignment - alignment needed by the object.
char* SkArenaAlloc::allocObjectWithFooter(size_t sizeIncludingFooter, size_t alignment) {
    size_t mask = alignment - 1;

    restart:
    size_t skipOverhead = 0;
    bool needsSkipFooter = fCursor != fDtorCursor;
    if (needsSkipFooter) {
        size_t skipSize = SkTFitsIn<int32_t>(fDtorCursor - fCursor)
                          ? sizeof(int32_t)
                          : sizeof(ptrdiff_t);
        skipOverhead = sizeof(Footer) + skipSize;
    }
    char* objStart = (char*)((uintptr_t)(fCursor + skipOverhead + mask) & ~mask);
    size_t totalSize = sizeIncludingFooter + skipOverhead;

    if (objStart + totalSize > fEnd) {
        this->ensureSpace(totalSize, alignment);
        goto restart;
    }

    SkASSERT(objStart + totalSize <= fEnd);

    // Install a skip footer if needed, thus terminating a run of POD data. The calling code is
    // responsible for installing the footer after the object.
    if (needsSkipFooter) {
        this->installIntFooter<Skipper>(fDtorCursor - fCursor, 0);
    }

    return objStart;
}

char* SkArenaAlloc::callFooterAction(char* end) {
    Footer footer;
    memcpy(&footer, end - sizeof(Footer), sizeof(Footer));

    FooterAction* releaser = (FooterAction*)((char*)EndChain + (footer >> 5));
    ptrdiff_t padding = footer & 31;

    char* r = releaser(end) - padding;

    return r;
}

char* SkArenaAlloc::EndChain(char*) { return nullptr; }

