LinearAllocator.cpp revision b5bc454870c8b7df88a633b18c4c6499361c3a08
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)
351ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define INITIAL_PAGE_SIZE ((size_t)4096) // 4kb
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
431ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define MAX_WASTE_SIZE ((size_t)1024)
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
551ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define ADD_ALLOCATION(size)
561ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define RM_ALLOCATION(size)
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);
681ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        ALOGV("Total memory usage: %zu kb", s_totalAllocations / 1024);
691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
701ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
711ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
721ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic void _addAllocation(size_t size) {
731ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    android::AutoMutex lock(s_mutex);
741ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    s_totalAllocations += size;
751ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    _logUsageLocked();
761ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
771ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
781ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define ADD_ALLOCATION(size) _addAllocation(size);
791ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define RM_ALLOCATION(size) _addAllocation(-size);
801ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#endif
811ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
821ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define min(x,y) (((x) < (y)) ? (x) : (y))
831ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
84b5bc454870c8b7df88a633b18c4c6499361c3a08John Reckvoid* operator new(std::size_t size, android::uirenderer::LinearAllocator& la) {
85b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    return la.alloc(size);
86b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck}
87b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
881ed723723d9e42a064d54799cc24bdc24891e44dJohn Recknamespace android {
891ed723723d9e42a064d54799cc24bdc24891e44dJohn Recknamespace uirenderer {
901ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
911ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckclass LinearAllocator::Page {
921ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckpublic:
931ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* next() { return mNextPage; }
941ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void setNext(Page* next) { mNextPage = next; }
951ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
961ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page()
971ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        : mNextPage(0)
981ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    {}
991ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1001ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* operator new(size_t /*size*/, void* buf) { return buf; }
1011ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1021ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* start() {
1031ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return (void*) (((size_t)this) + sizeof(Page));
1041ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1051ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1061ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* end(int pageSize) {
1071ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return (void*) (((size_t)start()) + pageSize);
1081ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1091ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1101ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckprivate:
1111ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page(const Page& /*other*/) {}
1121ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* mNextPage;
1131ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck};
1141ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1151ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckLinearAllocator::LinearAllocator()
1161ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    : mPageSize(INITIAL_PAGE_SIZE)
1171ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mMaxAllocSize(MAX_WASTE_SIZE)
1181ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mNext(0)
1191ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mCurrentPage(0)
1201ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mPages(0)
1211ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mTotalAllocated(0)
1221ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mWastedSpace(0)
1231ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mPageCount(0)
1241ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    , mDedicatedPageCount(0) {}
1251ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1261ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckLinearAllocator::~LinearAllocator(void) {
127b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    while (mDtorList) {
128b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        auto node = mDtorList;
129b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        mDtorList = node->next;
130b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        node->dtor(node->addr);
131b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    }
1321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* p = mPages;
1331ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    while (p) {
1341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        Page* next = p->next();
1351ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        p->~Page();
1361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        free(p);
1371ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        RM_ALLOCATION(mPageSize);
1381ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        p = next;
1391ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1421ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid* LinearAllocator::start(Page* p) {
1431ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return ALIGN_PTR(((size_t*)p) + sizeof(Page));
1441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid* LinearAllocator::end(Page* p) {
1471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return ((char*)p) + mPageSize;
1481ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckbool LinearAllocator::fitsInCurrentPage(size_t size) {
1511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return mNext && ((char*)mNext + size) <= end(mCurrentPage);
1521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid LinearAllocator::ensureNext(size_t size) {
1551ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (fitsInCurrentPage(size)) return;
1561ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (mCurrentPage && mPageSize < MAX_PAGE_SIZE) {
1581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPageSize = min(MAX_PAGE_SIZE, mPageSize * 2);
1591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPageSize = ALIGN(mPageSize);
1601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mWastedSpace += mPageSize;
1621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    Page* p = newPage(mPageSize);
1631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (mCurrentPage) {
1641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mCurrentPage->setNext(p);
1651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mCurrentPage = p;
1671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (!mPages) {
1681ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPages = mCurrentPage;
1691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1701ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mNext = start(mCurrentPage);
1711ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1721ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1731ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid* LinearAllocator::alloc(size_t size) {
1741ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    size = ALIGN(size);
1751ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (size > mMaxAllocSize && !fitsInCurrentPage(size)) {
1761ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        ALOGV("Exceeded max size %zu > %zu", size, mMaxAllocSize);
1771ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        // Allocation is too large, create a dedicated page for the allocation
1781ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        Page* page = newPage(size);
1791ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mDedicatedPageCount++;
1801ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        page->setNext(mPages);
1811ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mPages = page;
1821ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        if (!mCurrentPage)
1831ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            mCurrentPage = mPages;
1841ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return start(page);
1851ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1861ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ensureNext(size);
1871ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* ptr = mNext;
1881ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mNext = ((char*)mNext) + size;
1891ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mWastedSpace -= size;
1901ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return ptr;
1911ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1921ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
193b5bc454870c8b7df88a633b18c4c6499361c3a08John Reckvoid LinearAllocator::addToDestructionList(Destructor dtor, void* addr) {
194b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    static_assert(std::is_standard_layout<DestructorNode>::value,
195b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                  "DestructorNode must have standard layout");
196b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    static_assert(std::is_trivially_destructible<DestructorNode>::value,
197b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                  "DestructorNode must be trivially destructable");
198b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    auto node = new (*this) DestructorNode();
199b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    node->dtor = dtor;
200b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    node->addr = addr;
201b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    node->next = mDtorList;
202b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    mDtorList = node;
203b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck}
204b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
205b5bc454870c8b7df88a633b18c4c6499361c3a08John Reckvoid LinearAllocator::runDestructorFor(void* addr) {
206b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    auto node = mDtorList;
207b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    DestructorNode* previous = nullptr;
208b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    while (node) {
209b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        if (node->addr == addr) {
210b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            if (previous) {
211b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                previous->next = node->next;
212b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            } else {
213b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                mDtorList = node->next;
214b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            }
215b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            node->dtor(node->addr);
216b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            rewindIfLastAlloc(node, sizeof(DestructorNode));
217b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            break;
218b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        }
219b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        previous = node;
220b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        node = node->next;
221b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    }
222b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck}
223b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
2241ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize) {
225b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    // First run the destructor as running the destructor will
226b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    // also rewind for the DestructorNode allocation which will
227b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    // have been allocated after this void* if it has a destructor
228b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck    runDestructorFor(ptr);
2291ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    // Don't bother rewinding across pages
2301ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    allocSize = ALIGN(allocSize);
2311ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (ptr >= start(mCurrentPage) && ptr < end(mCurrentPage)
2321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            && ptr == ((char*)mNext - allocSize)) {
2331ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mWastedSpace += allocSize;
2341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        mNext = ptr;
2351ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2371ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2381ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckLinearAllocator::Page* LinearAllocator::newPage(size_t pageSize) {
2391ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    pageSize = ALIGN(pageSize + sizeof(LinearAllocator::Page));
2401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ADD_ALLOCATION(pageSize);
2411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mTotalAllocated += pageSize;
2421ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mPageCount++;
2431ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    void* buf = malloc(pageSize);
2441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return new (buf) Page();
2451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic const char* toSize(size_t value, float& result) {
2481ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (value < 2000) {
2491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        result = value;
2501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return "B";
2511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (value < 2000000) {
2531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        result = value / 1024.0f;
2541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return "KB";
2551ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2561ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    result = value / 1048576.0f;
2571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return "MB";
2581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid LinearAllocator::dumpMemoryStats(const char* prefix) {
2611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    float prettySize;
2621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    const char* prettySuffix;
2631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    prettySuffix = toSize(mTotalAllocated, prettySize);
2641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix);
2651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    prettySuffix = toSize(mWastedSpace, prettySize);
2661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix,
2671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck          (float) mWastedSpace / (float) mTotalAllocated * 100.0f);
2681ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGD("%sPages %zu (dedicated %zu)", prefix, mPageCount, mDedicatedPageCount);
2691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2701ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2711ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}; // namespace uirenderer
2721ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}; // namespace android
273