Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/skia/skia/src/base/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quelle  SkArenaAlloc.cpp   Sprache: C

 
/*
 * 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 "src/base/SkArenaAlloc.h"

#include "include/private/base/SkMalloc.h"

#include <algorithm>
#include <cassert>
#include <cstddef>

static char* end_chain(char*) { return nullptr; }

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

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

SkArenaAlloc::~SkArenaAlloc() {
    RunDtorsOnBlock(fDtorCursor);
}

void SkArenaAlloc::installFooter(FooterAction* action, uint32_t padding) {
    assert(SkTFitsIn<uint8_t>(padding));
    this->installRaw(action);
    this->installRaw((uint8_t)padding);
    fDtorCursor = fCursor;
}

char* SkArenaAlloc::SkipPod(char* footerEnd) {
    char* objEnd = footerEnd - (sizeof(Footer) + sizeof(uint32_t));
    uint32_t skip;
    memmove(&skip, objEnd, sizeof(uint32_t));
    return objEnd - (ptrdiff_t) skip;
}

void SkArenaAlloc::RunDtorsOnBlock(char* footerEnd) {
    while (footerEnd != nullptr) {
        FooterAction* action;
        uint8_t       padding;

        memcpy(&action,  footerEnd - sizeof( Footer), sizeof( action));
        memcpy(&padding, footerEnd - sizeof(padding), sizeof(padding));

        footerEnd = action(footerEnd) - (ptrdiff_t)padding;
    }
}

char* SkArenaAlloc::NextBlock(char* footerEnd) {
    char* objEnd = footerEnd - (sizeof(char*) + sizeof(Footer));
    char* next;
    memmove(&next, objEnd, sizeof(char*));
    RunDtorsOnBlock(next);
    sk_free(objEnd);
    return nullptr;
}

void SkArenaAlloc::ensureSpace(uint32_t size, uint32_t alignment) {
    constexpr uint32_t headerSize = sizeof(Footer) + sizeof(ptrdiff_t);
    constexpr uint32_t maxSize = std::numeric_limits<uint32_t>::max();
    constexpr uint32_t overhead = headerSize + sizeof(Footer);
    AssertRelease(size <= maxSize - overhead);
    uint32_t objSizeAndOverhead = size + overhead;

    const uint32_t alignmentOverhead = alignment - 1;
    AssertRelease(objSizeAndOverhead <= maxSize - alignmentOverhead);
    objSizeAndOverhead += alignmentOverhead;

    uint32_t minAllocationSize = fFibonacciProgression.nextBlockSize();
    uint32_t allocationSize = std::max(objSizeAndOverhead, minAllocationSize);

    // 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.
    {
        uint32_t mask = allocationSize > (1 << 15) ? (1 << 12) - 1 : 16 - 1;
        AssertRelease(allocationSize <= maxSize - mask);
        allocationSize = (allocationSize + mask) & ~mask;
    }

    char* newBlock = static_cast<char*>(sk_malloc_throw(allocationSize));

    auto previousDtor = fDtorCursor;
    fCursor = newBlock;
    fDtorCursor = newBlock;
    fEnd = fCursor + allocationSize;

    // poison the unused bytes in the block.
    sk_asan_poison_memory_region(fCursor, fEnd - fCursor);

    this->installRaw(previousDtor);
    this->installFooter(NextBlock, 0);
}

char* SkArenaAlloc::allocObjectWithFooter(uint32_t sizeIncludingFooter, uint32_t alignment) {
    uintptr_t mask = alignment - 1;

restart:
    uint32_t skipOverhead = 0;
    const bool needsSkipFooter = fCursor != fDtorCursor;
    if (needsSkipFooter) {
        skipOverhead = sizeof(Footer) + sizeof(uint32_t);
    }
    const uint32_t totalSize = sizeIncludingFooter + skipOverhead;

    // Math on null fCursor/fEnd is undefined behavior, so explicitly check for first alloc.
    if (!fCursor) {
        this->ensureSpace(totalSize, alignment);
        goto restart;
    }

    assert(fEnd);
    // This test alone would be enough nullptr were defined to be 0, but it's not.
    char* objStart = (char*)((uintptr_t)(fCursor + skipOverhead + mask) & ~mask);
    if ((ptrdiff_t)totalSize > fEnd - objStart) {
        this->ensureSpace(totalSize, alignment);
        goto restart;
    }

    AssertRelease((ptrdiff_t)totalSize <= fEnd - objStart);

    // 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->installRaw(SkToU32(fCursor - fDtorCursor));
        this->installFooter(SkipPod, 0);
    }

    return objStart;
}

SkArenaAllocWithReset::SkArenaAllocWithReset(char* block,
                                             size_t size,
                                             size_t firstHeapAllocation)
        : SkArenaAlloc(block, size, firstHeapAllocation)
        , fFirstBlock{block}
        , fFirstSize{SkToU32(size)}
        , fFirstHeapAllocationSize{SkToU32(firstHeapAllocation)} {}

void SkArenaAllocWithReset::reset() {
    charconst    firstBlock              = fFirstBlock;
    const uint32_t firstSize               = fFirstSize;
    const uint32_t firstHeapAllocationSize = fFirstHeapAllocationSize;
    this->~SkArenaAllocWithReset();
    new (this) SkArenaAllocWithReset{firstBlock, firstSize, firstHeapAllocationSize};
}

bool SkArenaAllocWithReset::isEmpty() {
    return this->cursor() == nullptr ||
           this->cursor() == fFirstBlock + sizeof(Footer);
}

// SkFibonacci47 is the first 47 Fibonacci numbers. Fib(47) is the largest value less than 2 ^ 32.
// Used by SkFibBlockSizes.
std::array<const uint32_t, 47> SkFibonacci47 {
                1,         1,          2,          3,          5,          8,
               13,        21,         34,         55,         89,        144,
              233,       377,        610,        987,       1597,       2584,
             4181,      6765,      10946,      17711,      28657,      46368,
            75025,    121393,     196418,     317811,     514229,     832040,
          1346269,   2178309,    3524578,    5702887,    9227465,   14930352,
         24157817,  39088169,   63245986,  102334155,  165580141,  267914296,
        433494437, 701408733, 1134903170, 1836311903, 2971215073,
};

Messung V0.5
C=92 H=92 G=91

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.