jitcraft/PoolAllocator.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jul 24 23:53:34 2012 -0700 (2012-07-24)
changeset 86 32ad0523b309
parent 69 dfce0539a77d
permissions -rw-r--r--
Renamed jitcraft/ to src/, fixed some /Wp64 warnings.
     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 #include "Zone.h"
    23 
    24 using namespace ke;
    25 
    26 PoolAllocator::PoolAllocator()
    27   : reserved_(NULL),
    28     last_(NULL)
    29 {
    30 }
    31 
    32 PoolAllocator::~PoolAllocator()
    33 {
    34     unwind(NULL);
    35     if (reserved_)
    36         free(reserved_);
    37 }
    38 
    39 char *
    40 PoolAllocator::enter()
    41 {
    42     if (!last_)
    43         return NULL;
    44     return last_->ptr;
    45 }
    46 
    47 void
    48 PoolAllocator::leave(char *pos)
    49 {
    50     unwind(pos);
    51 }
    52 
    53 void
    54 PoolAllocator::unwind(char *pos)
    55 {
    56     while (last_) {
    57         if (pos && pos >= last_->base && pos < last_->end)
    58             break;
    59         Pool *prev = last_->prev;
    60         {
    61             if (last_->size() <= kMaxReserveSize &&
    62                 (!reserved_ || reserved_->size() < last_->size()))
    63             {
    64                 if (reserved_)
    65                     free(reserved_);
    66                 reserved_ = last_;
    67             } else {
    68                 free(last_);
    69             }
    70         }
    71         last_ = prev;
    72     }
    73 
    74     if (!last_) {
    75         assert(!pos);
    76         return;
    77     }
    78 
    79     last_->ptr = pos;
    80 }
    81 
    82 void *
    83 PoolAllocator::slowAllocate(size_t actualBytes)
    84 {
    85     size_t bytesNeeded = actualBytes + sizeof(Pool);
    86     if (bytesNeeded < kDefaultPoolSize)
    87         bytesNeeded = kDefaultPoolSize;
    88 
    89     Pool *pool;
    90     if (reserved_ && reserved_->size() >= bytesNeeded) {
    91         pool = reserved_;
    92         reserved_ = NULL;
    93     } else {
    94         pool = (Pool *)malloc(bytesNeeded);
    95         if (!pool) {
    96             ZONE()->reportOutOfMemory();
    97             return NULL;
    98         }
    99         pool->base = (char *)(pool + 1);
   100         pool->end = (char *)pool + bytesNeeded;
   101     }
   102     pool->ptr = pool->base + actualBytes;
   103     pool->prev = last_;
   104     last_ = pool;
   105     return pool->base;
   106 }
   107 
   108 void
   109 PoolAllocationPolicy::reportOutOfMemory()
   110 {
   111     ZONE()->reportOutOfMemory();
   112 }
   113 
   114 void
   115 PoolAllocationPolicy::reportAllocationOverflow()
   116 {
   117     ZONE()->reportError(Message_AllocationOverflow);
   118 }
   119 
   120 void *
   121 PoolAllocationPolicy::malloc(size_t bytes)
   122 {
   123     return ZONE()->pool().allocate(bytes);
   124 }
   125 
   126 void
   127 PoolAllocationPolicy::free(void *ptr)
   128 {
   129 }