| 1 |
/* |
| 2 |
* 42TinyJS |
| 3 |
* |
| 4 |
* A fork of TinyJS with the goal to makes a more JavaScript/ECMA compliant engine |
| 5 |
* |
| 6 |
* Authored By Armin Diedering <armin@diedering.de> |
| 7 |
* |
| 8 |
* Copyright (C) 2010-2013 ardisoft |
| 9 |
* |
| 10 |
* |
| 11 |
* Permission is hereby granted, free of charge, to any person obtaining a copy of |
| 12 |
* this software and associated documentation files (the "Software"), to deal in |
| 13 |
* the Software without restriction, including without limitation the rights to |
| 14 |
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
| 15 |
* of the Software, and to permit persons to whom the Software is furnished to do |
| 16 |
* so, subject to the following conditions: |
| 17 |
|
| 18 |
* The above copyright notice and this permission notice shall be included in all |
| 19 |
* copies or substantial portions of the Software. |
| 20 |
|
| 21 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 22 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 23 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 24 |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 25 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 26 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 27 |
* SOFTWARE. |
| 28 |
*/ |
| 29 |
|
| 30 |
|
| 31 |
#ifndef pool_allocator_h__ |
| 32 |
#define pool_allocator_h__ |
| 33 |
|
| 34 |
#include <typeinfo> |
| 35 |
#include <stdint.h> |
| 36 |
#include <string> |
| 37 |
#include "config.h" |
| 38 |
#include "TinyJS_Threading.h" |
| 39 |
|
| 40 |
/************************************************************************ |
| 41 |
* TinyJS must many many times allocates and frees objects |
| 42 |
* To prevent memory fragmentation and speed ups allocates & frees, i have |
| 43 |
* added to 42TinyJS a pool_allocator. This allocator allocates every 64 objects |
| 44 |
* as a pool of objects. Is an object needed it can faster allocated from this pool as |
| 45 |
* from the heap. |
| 46 |
************************************************************************/ |
| 47 |
|
| 48 |
#if !defined(DEBUG_POOL_ALLOCATOR) && (defined(_DEBUG) || defined(LOG_POOL_ALLOCATOR_MEMORY_USAGE)) |
| 49 |
# define DEBUG_POOL_ALLOCATOR |
| 50 |
#endif |
| 51 |
|
| 52 |
struct block_head; |
| 53 |
class fixed_size_allocator { |
| 54 |
public: |
| 55 |
~fixed_size_allocator(); |
| 56 |
static void *alloc(size_t,const char* for_class=0); |
| 57 |
static void free(void *, size_t); |
| 58 |
size_t objectSize() { return object_size; } |
| 59 |
#ifndef NO_THREADING |
| 60 |
static CScriptMutex locker; |
| 61 |
#endif |
| 62 |
private: |
| 63 |
fixed_size_allocator(size_t num_objects, size_t object_size, const char* for_class); |
| 64 |
fixed_size_allocator(const fixed_size_allocator&); |
| 65 |
fixed_size_allocator& operator=(const fixed_size_allocator&); |
| 66 |
void *_alloc(size_t); |
| 67 |
bool _free(void* p, size_t); |
| 68 |
size_t num_objects; |
| 69 |
size_t object_size; |
| 70 |
void *head_of_free_list; |
| 71 |
block_head *head; |
| 72 |
int refs; |
| 73 |
#ifdef DEBUG_POOL_ALLOCATOR |
| 74 |
// Debug |
| 75 |
std::string name; |
| 76 |
int allocs; |
| 77 |
int frees; |
| 78 |
int current; |
| 79 |
int max; |
| 80 |
int blocks; |
| 81 |
#endif |
| 82 |
}; |
| 83 |
//************************************************************************************** |
| 84 |
template<typename T, int num_objects=64> |
| 85 |
class fixed_size_object { |
| 86 |
public: |
| 87 |
static void* operator new(size_t size) { |
| 88 |
#ifdef DEBUG_POOL_ALLOCATOR |
| 89 |
return fixed_size_allocator::alloc(size, typeid(T).name()); |
| 90 |
#else |
| 91 |
return fixed_size_allocator::alloc(size); |
| 92 |
#endif |
| 93 |
} |
| 94 |
static void* operator new(size_t size, void* p) { |
| 95 |
return p; |
| 96 |
} |
| 97 |
static void operator delete(void* p, size_t size) { |
| 98 |
fixed_size_allocator::free(p, size); |
| 99 |
} |
| 100 |
private: |
| 101 |
}; |
| 102 |
#if 0 // under construction |
| 103 |
template<typename T> |
| 104 |
class block_allocator_stl { |
| 105 |
public : |
| 106 |
// typedefs |
| 107 |
|
| 108 |
typedef T value_type; |
| 109 |
typedef value_type* pointer; |
| 110 |
typedef const value_type* const_pointer; |
| 111 |
typedef value_type& reference; |
| 112 |
typedef const value_type& const_reference; |
| 113 |
typedef std::size_t size_type; |
| 114 |
typedef std::ptrdiff_t difference_type; |
| 115 |
public : |
| 116 |
// convert an allocator<T> to allocator<U> |
| 117 |
|
| 118 |
template<typename U> |
| 119 |
struct rebind { |
| 120 |
typedef block_allocator_stl<U> other; |
| 121 |
}; |
| 122 |
|
| 123 |
inline explicit block_allocator_stl() {} |
| 124 |
inline ~block_allocator_stl() {} |
| 125 |
inline block_allocator_stl(block_allocator_stl const&) {} |
| 126 |
template<typename U> |
| 127 |
inline block_allocator_stl(block_allocator_stl<U> const&) {} |
| 128 |
inline block_allocator_stl<T> &operator=(block_allocator_stl<T> const&) {} |
| 129 |
template<typename U> |
| 130 |
inline block_allocator_stl<T> &operator=(block_allocator_stl<U> const&) {} |
| 131 |
|
| 132 |
// address |
| 133 |
|
| 134 |
inline pointer address(reference r) { return &r; } |
| 135 |
inline const_pointer address(const_reference r) { return &r; } |
| 136 |
|
| 137 |
// memory allocation |
| 138 |
inline pointer allocate(size_type cnt, const void*) { |
| 139 |
return reinterpret_cast<pointer>(fixed_size_allocator::get(cnt * sizeof (T), true, typeid(T).name())->alloc(cnt * sizeof (T))); |
| 140 |
// return reinterpret_cast<pointer>(::operator new(cnt * sizeof (T))); |
| 141 |
} |
| 142 |
inline void deallocate(pointer p, size_type cnt) { |
| 143 |
fixed_size_allocator::get(cnt * sizeof (T), false)->free(p, cnt * sizeof (T)); |
| 144 |
// ::operator delete(p); |
| 145 |
} |
| 146 |
|
| 147 |
// size |
| 148 |
|
| 149 |
inline size_type max_size() const { |
| 150 |
return SIZE_MAX / sizeof(T); |
| 151 |
} |
| 152 |
|
| 153 |
inline void construct(pointer _Ptr, value_type& _Val) { |
| 154 |
::new ((void*)_Ptr) value_type(_Val); |
| 155 |
} |
| 156 |
inline void destroy(pointer _Ptr) { |
| 157 |
_Ptr->~value_type(); |
| 158 |
} |
| 159 |
}; |
| 160 |
#endif |
| 161 |
|
| 162 |
#endif // pool_allocator_h__ |