11ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck/*
21ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * Copyright 2012, The Android Open Source Project
31ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *
41ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * Redistribution and use in source and binary forms, with or without
51ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * modification, are permitted provided that the following conditions
61ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * are met:
71ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *  * Redistributions of source code must retain the above copyright
81ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *    notice, this list of conditions and the following disclaimer.
91ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *  * Redistributions in binary form must reproduce the above copyright
101ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *    notice, this list of conditions and the following disclaimer in the
111ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *    documentation and/or other materials provided with the distribution.
121ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *
131ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
141ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
151ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
161ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
171ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
181ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
191ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
201ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
211ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
221ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
231ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
241ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck */
251ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
261ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define LOG_NDEBUG 1
271ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
281ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include "utils/LinearAllocator.h"
291ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
301ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <stdlib.h>
311ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <utils/Log.h>
321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
331ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck// The ideal size of a page allocation (these need to be multiples of 8)
35afb052142a53602ee7b3debb6a3b871de21feac0John Reck#define INITIAL_PAGE_SIZE ((size_t)512) // 512b
361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define MAX_PAGE_SIZE ((size_t)131072) // 128kb
371ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
381ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck// The maximum amount of wasted space we can have per page
391ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck// Allocations exceeding this will have their own dedicated page
401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck// If this is too low, we will malloc too much
411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck// Too high, and we may waste too much space
421ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck// Must be smaller than INITIAL_PAGE_SIZE
43afb052142a53602ee7b3debb6a3b871de21feac0John Reck#define MAX_WASTE_RATIO (0.5f)
441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#if ALIGN_DOUBLE
461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define ALIGN_SZ (sizeof(double))
471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#else
481ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define ALIGN_SZ (sizeof(int))
491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#endif
501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define ALIGN(x) ((x + ALIGN_SZ - 1 ) & ~(ALIGN_SZ - 1))
521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define ALIGN_PTR(p) ((void*)(ALIGN((size_t)p)))
531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#if LOG_NDEBUG
5581a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik#define ADD_ALLOCATION()
5681a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik#define RM_ALLOCATION()
571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#else
581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <utils/Thread.h>
591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <utils/Timers.h>
601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic size_t s_totalAllocations = 0;
611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic nsecs_t s_nextLog = 0;
621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic android::Mutex s_mutex;
631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic void _logUsageLocked() {
651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (now > s_nextLog) {
671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        s_nextLog = now + milliseconds_to_nanoseconds(10);
6881a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik        ALOGV("Total pages allocated: %zu", s_totalAllocations);
691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
701ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
711ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
7281a1d2a15927b06b84359f839ab03ac8a20970bdChris Craikstatic void _addAllocation(int count) {
731ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    android::AutoMutex lock(s_mutex);
7481a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik    s_totalAllocations += count;
751ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    _logUsageLocked();
761ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
771ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
7881a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik#define ADD_ALLOCATION(size) _addAllocation(1);
7981a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik#define RM_ALLOCATION(size) _addAllocation(-1);
801ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#endif
811ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
821ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define min(x,y) (((x) < (y)) ? (x) : (y))
831ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
841ed723723d9e42a064d54799cc24bdc24891e44dJohn Recknamespace android {
851ed723723d9e42a064d54799cc24bdc24891e44dJohn Recknamespace uirenderer {
861ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
871ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckclass LinearAllocator::Page {
881ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckpublic:
891ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* next() { return mNextPage; }
901ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void setNext(Page* next) { mNextPage = next; }
911ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
921ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page()
931ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        : mNextPage(0)
941ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    {}
951ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
961ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* operator new(size_t /*size*/, void* buf) { return buf; }
971ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
981ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* start() {
991ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return (void*) (((size_t)this) + sizeof(Page));
1001ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1011ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1021ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* end(int pageSize) {
1031ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return (void*) (((size_t)start()) + pageSize);
1041ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1051ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1061ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckprivate:
1071ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page(const Page& /*other*/) {}
1081ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* mNextPage;
1091ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck};
1101ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1111ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckLinearAllocator::LinearAllocator()
1121ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    : mPageSize(INITIAL_PAGE_SIZE)
113afb052142a53602ee7b3debb6a3b871de21feac0John Reck    , mMaxAllocSize(INITIAL_PAGE_SIZE * MAX_WASTE_RATIO)
1141ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mNext(0)
1151ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mCurrentPage(0)
1161ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mPages(0)
1171ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mTotalAllocated(0)
1181ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mWastedSpace(0)
1191ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mPageCount(0)
1201ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mDedicatedPageCount(0) {}
1211ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1221ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckLinearAllocator::~LinearAllocator(void) {
123b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    while (mDtorList) {
124b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        auto node = mDtorList;
125b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        mDtorList = node->next;
126b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        node->dtor(node->addr);
127b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    }
1281ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* p = mPages;
1291ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    while (p) {
1301ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        Page* next = p->next();
1311ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        p->~Page();
1321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        free(p);
13381a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik        RM_ALLOCATION();
1341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        p = next;
1351ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1371ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1381ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid* LinearAllocator::start(Page* p) {
13925c8d5b1c2d1405e2a8afa857713af072bedad53Chris Craik    return ALIGN_PTR((size_t)p + sizeof(Page));
1401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1421ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid* LinearAllocator::end(Page* p) {
1431ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return ((char*)p) + mPageSize;
1441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckbool LinearAllocator::fitsInCurrentPage(size_t size) {
1471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return mNext && ((char*)mNext + size) <= end(mCurrentPage);
1481ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid LinearAllocator::ensureNext(size_t size) {
1511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (fitsInCurrentPage(size)) return;
1521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (mCurrentPage && mPageSize < MAX_PAGE_SIZE) {
1541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPageSize = min(MAX_PAGE_SIZE, mPageSize * 2);
155afb052142a53602ee7b3debb6a3b871de21feac0John Reck        mMaxAllocSize = mPageSize * MAX_WASTE_RATIO;
1561ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPageSize = ALIGN(mPageSize);
1571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mWastedSpace += mPageSize;
1591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* p = newPage(mPageSize);
1601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (mCurrentPage) {
1611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mCurrentPage->setNext(p);
1621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mCurrentPage = p;
1641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (!mPages) {
1651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPages = mCurrentPage;
1661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mNext = start(mCurrentPage);
1681ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1707df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reckvoid* LinearAllocator::allocImpl(size_t size) {
1711ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    size = ALIGN(size);
1721ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (size > mMaxAllocSize && !fitsInCurrentPage(size)) {
1731ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        ALOGV("Exceeded max size %zu > %zu", size, mMaxAllocSize);
1741ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        // Allocation is too large, create a dedicated page for the allocation
1751ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        Page* page = newPage(size);
1761ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mDedicatedPageCount++;
1771ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        page->setNext(mPages);
1781ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPages = page;
1791ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        if (!mCurrentPage)
1801ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            mCurrentPage = mPages;
1811ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return start(page);
1821ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1831ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ensureNext(size);
1841ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* ptr = mNext;
1851ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mNext = ((char*)mNext) + size;
1861ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mWastedSpace -= size;
1871ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return ptr;
1881ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1891ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
190b5bc454870c8b7df88a633b18c4c6499361c3a08John Reckvoid LinearAllocator::addToDestructionList(Destructor dtor, void* addr) {
191b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    static_assert(std::is_standard_layout<DestructorNode>::value,
192b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                  "DestructorNode must have standard layout");
193b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    static_assert(std::is_trivially_destructible<DestructorNode>::value,
194b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                  "DestructorNode must be trivially destructable");
1957df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    auto node = new (allocImpl(sizeof(DestructorNode))) DestructorNode();
196b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    node->dtor = dtor;
197b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    node->addr = addr;
198b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    node->next = mDtorList;
199b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    mDtorList = node;
200b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck}
201b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
202b5bc454870c8b7df88a633b18c4c6499361c3a08John Reckvoid LinearAllocator::runDestructorFor(void* addr) {
203b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    auto node = mDtorList;
204b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    DestructorNode* previous = nullptr;
205b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    while (node) {
206b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        if (node->addr == addr) {
207b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            if (previous) {
208b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                previous->next = node->next;
209b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            } else {
210b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                mDtorList = node->next;
211b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            }
212b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            node->dtor(node->addr);
213b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            rewindIfLastAlloc(node, sizeof(DestructorNode));
214b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            break;
215b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        }
216b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        previous = node;
217b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        node = node->next;
218b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    }
219b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck}
220b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
2211ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize) {
222b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    // First run the destructor as running the destructor will
223b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    // also rewind for the DestructorNode allocation which will
224b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    // have been allocated after this void* if it has a destructor
225b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    runDestructorFor(ptr);
2261ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    // Don't bother rewinding across pages
2271ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    allocSize = ALIGN(allocSize);
2281ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (ptr >= start(mCurrentPage) && ptr < end(mCurrentPage)
2291ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            && ptr == ((char*)mNext - allocSize)) {
2301ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mWastedSpace += allocSize;
2311ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mNext = ptr;
2321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2331ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2351ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckLinearAllocator::Page* LinearAllocator::newPage(size_t pageSize) {
2361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    pageSize = ALIGN(pageSize + sizeof(LinearAllocator::Page));
23781a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik    ADD_ALLOCATION();
2381ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mTotalAllocated += pageSize;
2391ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mPageCount++;
2401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* buf = malloc(pageSize);
2411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return new (buf) Page();
2421ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2431ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic const char* toSize(size_t value, float& result) {
2451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (value < 2000) {
2461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        result = value;
2471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return "B";
2481ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (value < 2000000) {
2501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        result = value / 1024.0f;
2511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return "KB";
2521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    result = value / 1048576.0f;
2541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return "MB";
2551ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2561ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid LinearAllocator::dumpMemoryStats(const char* prefix) {
2581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    float prettySize;
2591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    const char* prettySuffix;
2601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    prettySuffix = toSize(mTotalAllocated, prettySize);
2611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix);
2621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    prettySuffix = toSize(mWastedSpace, prettySize);
2631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix,
2641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck          (float) mWastedSpace / (float) mTotalAllocated * 100.0f);
2651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGD("%sPages %zu (dedicated %zu)", prefix, mPageCount, mDedicatedPageCount);
2661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2681ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}; // namespace uirenderer
2691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}; // namespace android
270