1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkVarAlloc.h"
9
10// We use non-standard malloc diagnostic methods to make sure our allocations are sized well.
11#if defined(SK_BUILD_FOR_MAC)
12    #include <malloc/malloc.h>
13#elif defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN32)
14    #include <malloc.h>
15#endif
16
17struct SkVarAlloc::Block {
18    Block* prev;
19    char* data() { return (char*)(this + 1); }
20
21    static Block* Alloc(Block* prev, size_t size, unsigned flags) {
22        SkASSERT(size >= sizeof(Block));
23        Block* b = (Block*)sk_malloc_flags(size, flags);
24        b->prev = prev;
25        return b;
26    }
27};
28
29SkVarAlloc::SkVarAlloc(size_t minLgSize)
30    : fBytesAllocated(0)
31    , fByte(NULL)
32    , fRemaining(0)
33    , fLgSize(minLgSize)
34    , fBlock(NULL) {}
35
36SkVarAlloc::SkVarAlloc(size_t minLgSize, char* storage, size_t len)
37    : fBytesAllocated(0)
38    , fByte(storage)
39    , fRemaining(len)
40    , fLgSize(minLgSize)
41    , fBlock(NULL) {}
42
43SkVarAlloc::~SkVarAlloc() {
44    Block* b = fBlock;
45    while (b) {
46        Block* prev = b->prev;
47        sk_free(b);
48        b = prev;
49    }
50}
51
52void SkVarAlloc::makeSpace(size_t bytes, unsigned flags) {
53    SkASSERT(SkIsAlignPtr(bytes));
54
55    size_t alloc = 1<<fLgSize++;
56    while (alloc < bytes + sizeof(Block)) {
57        alloc *= 2;
58    }
59    fBytesAllocated += alloc;
60    fBlock = Block::Alloc(fBlock, alloc, flags);
61    fByte = fBlock->data();
62    fRemaining = alloc - sizeof(Block);
63
64#if defined(SK_BUILD_FOR_MAC)
65    SkASSERT(alloc == malloc_good_size(alloc));
66#elif defined(SK_BUILD_FOR_UNIX) && !defined(__UCLIBC__)
67    // TODO(mtklein): tune so we can assert something like this
68    //SkASSERT(alloc == malloc_usable_size(fBlock));
69#endif
70}
71