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__ |