1 /* src/mm/dumpmemory.hpp - dump memory management
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 Copyright (C) 2008 Theobroma Systems Ltd.
7 This file is part of CACAO.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #ifndef _DUMPMEMORY_HPP
28 #define _DUMPMEMORY_HPP
41 #include <stdio.h> // REMOVEME
44 // Forward declaration.
46 class DumpMemoryBlock;
47 #if defined(ENABLE_MEMCHECK)
48 class DumpMemoryAllocation;
53 * All classes intended to be allocated on dump memory should extend this
54 * base class to inherit the appropriate allocation operators.
58 void* operator new(size_t size);
59 void operator delete(void* p);
64 * Thread-local dump memory structure.
68 size_t _size; ///< Size of the dump areas in this dump memory.
69 size_t _used; ///< Used memory in this dump memory.
70 std::list<DumpMemoryArea*> _areas; ///< Pointer to the current dump area.
76 static inline DumpMemory* get_current();
77 static inline void* allocate(size_t size);
79 inline void add_size(size_t size) { _size += size; }
81 inline size_t get_size() const { return _size; }
82 inline size_t get_used() const { return _used; }
84 inline DumpMemoryArea* get_current_area() const;
86 static void* reallocate(void* src, size_t len1, size_t len2);
88 void add_area(DumpMemoryArea* dma);
89 void remove_area(DumpMemoryArea* dma);
96 class DumpMemoryArea {
98 size_t _size; ///< Size of the current memory block.
99 size_t _used; ///< Used memory in the current memory block.
100 std::vector<DumpMemoryBlock*> _blocks; ///< List of memory blocks in this area.
101 #if defined(ENABLE_MEMCHECK)
102 std::vector<DumpMemoryAllocation*> _allocs; ///< List of allocations in this area.
106 DumpMemoryArea(size_t size = 0);
109 inline size_t get_size() const { return _size; }
110 inline size_t get_used() const { return _used; }
113 inline void* allocate(size_t size);
114 inline DumpMemoryBlock* get_current_block() const;
116 DumpMemoryBlock* allocate_new_block(size_t size);
118 #if defined(ENABLE_MEMCHECK)
120 void check_canaries();
128 class DumpMemoryBlock {
130 static const size_t DEFAULT_SIZE = 2 << 13; // 2 * 8192 bytes
132 size_t _size; ///< Size of the current memory block.
133 size_t _used; ///< Used memory in the current memory block.
134 void* _block; ///< List of memory blocks in this area.
137 DumpMemoryBlock(size_t size = 0);
140 inline size_t get_size() const { return _size; }
141 inline size_t get_used() const { return _used; }
142 inline size_t get_free() const { return _size - _used; }
145 inline void* allocate(size_t size);
150 * Allocator for the dump memory.
152 template<class T> class DumpMemoryAllocator {
155 typedef T value_type;
157 typedef const T* const_pointer;
158 typedef T& reference;
159 typedef const T& const_reference;
160 typedef std::size_t size_type;
161 typedef std::ptrdiff_t difference_type;
163 // Rebind allocator to type U.
164 template <class U> struct rebind {
165 typedef DumpMemoryAllocator<U> other;
168 // Constructors and destructor, nothing to do because the
169 // allocator has no state.
170 DumpMemoryAllocator() throw() {}
171 DumpMemoryAllocator(const DumpMemoryAllocator&) throw() {}
172 template <class U> DumpMemoryAllocator(const DumpMemoryAllocator<U>&) throw() {}
174 ~DumpMemoryAllocator() throw() {}
176 pointer allocate(size_type n, void* = 0) {
177 // printf("allocate: n=%d * %d\n", n, sizeof(T));
178 return static_cast<pointer>(DumpMemory::allocate(n * sizeof(T)));
181 // Initialize elements of allocated storage p with value value.
182 void construct(pointer p, const T& value) {
183 // printf("construct: p=%p, value=%p\n", (void*) p, (void*) value);
184 // Initialize memory with placement new.
185 new ((void*) p) T(value);
188 // Destroy elements of initialized storage p.
189 void destroy(pointer p) {
190 // printf("destroy: p=%p\n", (void*) p);
191 // Destroy objects by calling their destructor.
195 void deallocate(pointer p, size_type n) {
196 // printf("deallocate: p=%p, n=%d\n", (void*) p, n);
197 // We don't need to deallocate on dump memory.
203 * Dump memory allocation, used for for ENABLE_MEMCHECK.
205 #if defined(ENABLE_MEMCHECK)
206 class DumpMemoryAllocation {
212 DumpMemoryAllocation() : _size(0), _mem(NULL) {}
213 DumpMemoryAllocation(size_t size, void* mem) : _size(size), _mem(mem) {}
214 ~DumpMemoryAllocation() {};
216 inline size_t get_size() const { return _size; }
217 inline void* get_mem() const { return _mem; }
223 #include "mm/memory.hpp"
225 #include "threads/thread.hpp"
227 #include "vm/options.h"
229 #if defined(ENABLE_STATISTICS)
230 # include "vm/statistics.h"
236 inline void* DumpClass::operator new(size_t size)
238 return DumpMemory::allocate(size);
241 inline void DumpClass::operator delete(void* p)
243 // We don't need to deallocate on dump memory.
246 inline DumpMemory* DumpMemory::get_current()
248 // Get the DumpMemory object of the current thread.
249 threadobject* t = thread_get_current();
250 DumpMemory* dm = t->_dumpmemory;
254 inline DumpMemoryArea* DumpMemory::get_current_area() const
256 return _areas.back();
259 inline void* DumpMemory::allocate(size_t size)
261 DumpMemory* dm = get_current();
262 DumpMemoryArea* dma = dm->get_current_area();
264 size_t alignedsize = size;
266 #if defined(ENABLE_MEMCHECK)
267 alignedsize += 2 * MEMORY_CANARY_SIZE;
270 // Align the allocation size.
271 alignedsize = MEMORY_ALIGN(alignedsize, ALIGNSIZE);
273 void* p = dma->allocate(alignedsize);
275 // Increase the used count of the dump memory.
276 dm->_used += alignedsize;
281 inline DumpMemoryBlock* DumpMemoryArea::get_current_block() const
283 return _blocks.empty() ? NULL : _blocks.back();
286 inline void* DumpMemoryArea::allocate(size_t size)
288 DumpMemoryBlock* dmb = get_current_block();
290 // Check if we have a memory block or have enough memory in the
291 // current memory block.
292 if (dmb == NULL || size > dmb->get_free()) {
293 // No, allocate a new one.
294 dmb = allocate_new_block(size);
296 // Increase the size of the memory area. We use get_size()
297 // here because the default size is very likely to be bigger
299 _size += dmb->get_size();
302 void* p = dmb->allocate(size);
304 #if defined(ENABLE_MEMCHECK)
306 size_t origsize = size - 2 * MEMORY_CANARY_SIZE;
308 // Make p point after the bottom canary.
310 p = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
312 // Add the allocation to our list of allocations
314 DumpMemoryAllocation* dma = new DumpMemoryAllocation(origsize, p);
316 _allocs.push_back(dma);
318 // Write the canaries.
320 pm = ((uint8_t *) p) - MEMORY_CANARY_SIZE;
322 for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
323 pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
325 pm = ((uint8_t *) p) + dma->get_size();
327 for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
328 pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
332 (void) os::memset(p, MEMORY_CLEAR_BYTE, dma->get_size());
333 #endif /* defined(ENABLE_MEMCHECK) */
335 // Increase the used size of the memory area.
342 * Allocate memory in the current dump memory area.
344 * This function is a fast allocator suitable for scratch memory that
345 * can be collectively freed when the current activity (eg. compiling)
348 * You cannot selectively free dump memory. Before you start
349 * allocating it, you remember the current size returned by
350 * `dumpmemory_marker`. Later, when you no longer need the memory,
351 * call `dumpmemory_release` with the remembered size and all dump
352 * memory allocated since the call to `dumpmemory_marker` will be
355 * @parm size Size of block to allocate in bytes. May be zero, in which case NULL is returned
357 * @return Pointer to allocated memory, or NULL iff size was zero.
359 void* DumpMemoryBlock::allocate(size_t size)
365 assert(size <= (_size - _used));
367 // Calculate the memory address of the newly allocated memory.
368 void* p = (void*) (((uint8_t*) _block) + _used);
370 // Increase used memory block size by the allocated memory size.
378 // Legacy C interface.
380 void* DumpMemory_allocate(size_t size);
381 void* DumpMemory_reallocate(void* src, size_t len1, size_t len2);
383 #define DNEW(type) ((type*) DumpMemory_allocate(sizeof(type)))
384 #define DMNEW(type,num) ((type*) DumpMemory_allocate(sizeof(type) * (num)))
385 #define DMREALLOC(ptr,type,num1,num2) ((type*) DumpMemory_reallocate((ptr), sizeof(type) * (num1), sizeof(type) * (num2)))
389 #endif // _DUMPMEMORY_HPP
393 * These are local overrides for various environment variables in Emacs.
394 * Please do not remove this and leave it at the end of the file, where
395 * Emacs will automagically detect them.
396 * ---------------------------------------------------------------------
399 * indent-tabs-mode: t
403 * vim:noexpandtab:sw=4:ts=4: