jitcraft/PoolAllocator.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 27 02:28:39 2012 -0700 (2012-06-27)
changeset 5 9b63fb7cf5bf
parent 0 c455ebb9a5dc
child 55 e073a9fe8e57
permissions -rw-r--r--
Always add a sign when spewing jump distances.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     6  * JITCraft is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * JITCraft. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #include <assert.h>
    19 #include <stdlib.h>
    20 #include <new>
    21 #include "PoolAllocator.h"
    22 
    23 using namespace jc;
    24 
    25 PoolAllocator::PoolAllocator()
    26   : reserved_(NULL),
    27     last_(NULL)
    28 {
    29 }
    30 
    31 PoolAllocator::~PoolAllocator()
    32 {
    33     unwind(NULL);
    34     if (reserved_)
    35         free(reserved_);
    36 }
    37 
    38 char *
    39 PoolAllocator::enter()
    40 {
    41     if (!last_)
    42         return NULL;
    43     return last_->ptr;
    44 }
    45 
    46 void
    47 PoolAllocator::leave(char *pos)
    48 {
    49     unwind(pos);
    50 }
    51 
    52 void
    53 PoolAllocator::unwind(char *pos)
    54 {
    55     while (last_) {
    56         if (pos && pos >= last_->base && pos < last_->end)
    57             break;
    58         Pool *prev = last_->prev;
    59         {
    60             if (last_->size() <= kMaxReserveSize &&
    61                 (!reserved_ || reserved_->size() < last_->size()))
    62             {
    63                 if (reserved_)
    64                     free(reserved_);
    65                 reserved_ = last_;
    66             } else {
    67                 free(last_);
    68             }
    69         }
    70         last_ = prev;
    71     }
    72 
    73     if (!last_) {
    74         assert(!pos);
    75         return;
    76     }
    77 
    78     last_->ptr = pos;
    79 }
    80 
    81 void *
    82 PoolAllocator::slowAllocate(size_t actualBytes)
    83 {
    84     size_t bytesNeeded = actualBytes + sizeof(Pool);
    85     if (bytesNeeded < kDefaultPoolSize)
    86         bytesNeeded = kDefaultPoolSize;
    87 
    88     Pool *pool;
    89     if (reserved_ && reserved_->size() >= bytesNeeded) {
    90         pool = reserved_;
    91         reserved_ = NULL;
    92     } else {
    93         pool = (Pool *)malloc(bytesNeeded);
    94         if (!pool)
    95             throw std::bad_alloc();
    96         pool->base = (char *)(pool + 1);
    97         pool->end = (char *)pool + bytesNeeded;
    98     }
    99     pool->ptr = pool->base + actualBytes;
   100     pool->prev = last_;
   101     last_ = pool;
   102     return pool->base;
   103 }