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 * Thread-local dump memory structure.
57 size_t _size; ///< Size of the dump areas in this dump memory.
58 size_t _used; ///< Used memory in this dump memory.
59 std::list<DumpMemoryArea*> _areas; ///< Pointer to the current dump area.
65 static inline DumpMemory* get_current();
66 static inline void* allocate(size_t size);
68 inline void add_size(size_t size) { _size += size; }
70 inline size_t get_size() const { return _size; }
71 inline size_t get_used() const { return _used; }
73 inline DumpMemoryArea* get_current_area() const;
75 static void* reallocate(void* src, size_t len1, size_t len2);
77 void add_area(DumpMemoryArea* dma);
78 void remove_area(DumpMemoryArea* dma);
85 class DumpMemoryArea {
87 size_t _size; ///< Size of the current memory block.
88 size_t _used; ///< Used memory in the current memory block.
89 std::vector<DumpMemoryBlock*> _blocks; ///< List of memory blocks in this area.
90 #if defined(ENABLE_MEMCHECK)
91 std::vector<DumpMemoryAllocation*> _allocs; ///< List of allocations in this area.
95 DumpMemoryArea(size_t size = 0);
98 inline size_t get_size() const { return _size; }
99 inline size_t get_used() const { return _used; }
102 inline void* allocate(size_t size);
103 inline DumpMemoryBlock* get_current_block() const;
105 DumpMemoryBlock* allocate_new_block(size_t size);
107 #if defined(ENABLE_MEMCHECK)
109 void check_canaries();
117 class DumpMemoryBlock {
119 static const size_t DEFAULT_SIZE = 2 << 13; // 2 * 8192 bytes
121 size_t _size; ///< Size of the current memory block.
122 size_t _used; ///< Used memory in the current memory block.
123 void* _block; ///< List of memory blocks in this area.
126 DumpMemoryBlock(size_t size = 0);
129 inline size_t get_size() const { return _size; }
130 inline size_t get_used() const { return _used; }
131 inline size_t get_free() const { return _size - _used; }
134 inline void* allocate(size_t size);
139 * Allocator for the dump memory.
141 template<class T> class DumpMemoryAllocator {
144 typedef T value_type;
146 typedef const T* const_pointer;
147 typedef T& reference;
148 typedef const T& const_reference;
149 typedef std::size_t size_type;
150 typedef std::ptrdiff_t difference_type;
152 // Rebind allocator to type U.
153 template <class U> struct rebind {
154 typedef DumpMemoryAllocator<U> other;
157 // Constructors and destructor, nothing to do because the
158 // allocator has no state.
159 DumpMemoryAllocator() throw() {}
160 DumpMemoryAllocator(const DumpMemoryAllocator&) throw() {}
161 template <class U> DumpMemoryAllocator(const DumpMemoryAllocator<U>&) throw() {}
163 ~DumpMemoryAllocator() throw() {}
165 pointer allocate(size_type n, void* = 0) {
166 // printf("allocate: n=%d * %d\n", n, sizeof(T));
167 return static_cast<pointer>(DumpMemory::allocate(n * sizeof(T)));
170 // Initialize elements of allocated storage p with value value.
171 void construct(pointer p, const T& value) {
172 // printf("construct: p=%p, value=%p\n", (void*) p, (void*) value);
173 // Initialize memory with placement new.
174 new ((void*) p) T(value);
177 // Destroy elements of initialized storage p.
178 void destroy(pointer p) {
179 // printf("destroy: p=%p\n", (void*) p);
180 // Destroy objects by calling their destructor.
184 void deallocate(pointer p, size_type n) {
185 // printf("deallocate: p=%p, n=%d\n", (void*) p, n);
186 // We don't need to deallocate on dump memory.
192 * Dump memory allocation, used for for ENABLE_MEMCHECK.
194 #if defined(ENABLE_MEMCHECK)
195 class DumpMemoryAllocation {
201 DumpMemoryAllocation() : _size(0), _mem(NULL) {}
202 DumpMemoryAllocation(size_t size, void* mem) : _size(size), _mem(mem) {}
203 ~DumpMemoryAllocation() {};
205 inline size_t get_size() const { return _size; }
206 inline void* get_mem() const { return _mem; }
212 #include "mm/memory.hpp"
214 #include "threads/thread.hpp"
216 #include "vm/options.h"
218 #if defined(ENABLE_STATISTICS)
219 # include "vm/statistics.h"
225 inline DumpMemory* DumpMemory::get_current()
227 // Get the DumpMemory object of the current thread.
228 threadobject* t = thread_get_current();
229 DumpMemory* dm = t->_dumpmemory;
233 inline DumpMemoryArea* DumpMemory::get_current_area() const
235 return _areas.back();
238 inline void* DumpMemory::allocate(size_t size)
240 DumpMemory* dm = get_current();
241 DumpMemoryArea* dma = dm->get_current_area();
243 size_t alignedsize = size;
245 #if defined(ENABLE_MEMCHECK)
246 alignedsize += 2 * MEMORY_CANARY_SIZE;
249 // Align the allocation size.
250 alignedsize = MEMORY_ALIGN(alignedsize, ALIGNSIZE);
252 void* p = dma->allocate(alignedsize);
254 // Increase the used count of the dump memory.
255 dm->_used += alignedsize;
260 inline DumpMemoryBlock* DumpMemoryArea::get_current_block() const
262 return _blocks.empty() ? NULL : _blocks.back();
265 inline void* DumpMemoryArea::allocate(size_t size)
267 DumpMemoryBlock* dmb = get_current_block();
269 // Check if we have a memory block or have enough memory in the
270 // current memory block.
271 if (dmb == NULL || size > dmb->get_free()) {
272 // No, allocate a new one.
273 dmb = allocate_new_block(size);
275 // Increase the size of the memory area. We use get_size()
276 // here because the default size is very likely to be bigger
278 _size += dmb->get_size();
281 void* p = dmb->allocate(size);
283 #if defined(ENABLE_MEMCHECK)
285 size_t origsize = size - 2 * MEMORY_CANARY_SIZE;
287 // Make p point after the bottom canary.
289 p = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
291 // Add the allocation to our list of allocations
293 DumpMemoryAllocation* dma = new DumpMemoryAllocation(origsize, p);
295 _allocs.push_back(dma);
297 // Write the canaries.
299 pm = ((uint8_t *) p) - MEMORY_CANARY_SIZE;
301 for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
302 pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
304 pm = ((uint8_t *) p) + dma->get_size();
306 for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
307 pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
311 (void) os::memset(p, MEMORY_CLEAR_BYTE, dma->get_size());
312 #endif /* defined(ENABLE_MEMCHECK) */
314 // Increase the used size of the memory area.
321 * Allocate memory in the current dump memory area.
323 * This function is a fast allocator suitable for scratch memory that
324 * can be collectively freed when the current activity (eg. compiling)
327 * You cannot selectively free dump memory. Before you start
328 * allocating it, you remember the current size returned by
329 * `dumpmemory_marker`. Later, when you no longer need the memory,
330 * call `dumpmemory_release` with the remembered size and all dump
331 * memory allocated since the call to `dumpmemory_marker` will be
334 * @parm size Size of block to allocate in bytes. May be zero, in which case NULL is returned
336 * @return Pointer to allocated memory, or NULL iff size was zero.
338 void* DumpMemoryBlock::allocate(size_t size)
344 assert(size <= (_size - _used));
346 // Calculate the memory address of the newly allocated memory.
347 void* p = (void*) (((uint8_t*) _block) + _used);
349 // Increase used memory block size by the allocated memory size.
357 // Legacy C interface.
359 void* DumpMemory_allocate(size_t size);
360 void* DumpMemory_reallocate(void* src, size_t len1, size_t len2);
362 #define DNEW(type) ((type*) DumpMemory_allocate(sizeof(type)))
363 #define DMNEW(type,num) ((type*) DumpMemory_allocate(sizeof(type) * (num)))
364 #define DMREALLOC(ptr,type,num1,num2) ((type*) DumpMemory_reallocate((ptr), sizeof(type) * (num1), sizeof(type) * (num2)))
368 #endif // _DUMPMEMORY_HPP
372 * These are local overrides for various environment variables in Emacs.
373 * Please do not remove this and leave it at the end of the file, where
374 * Emacs will automagically detect them.
375 * ---------------------------------------------------------------------
378 * indent-tabs-mode: t
382 * vim:noexpandtab:sw=4:ts=4: