1 /* src/mm/dumpmemory.cpp - 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
31 #include "mm/dumpmemory.hpp"
32 #include "mm/memory.hpp"
34 #include "threads/thread.hpp"
36 #include "vm/options.h"
39 #if defined(ENABLE_STATISTICS)
40 # include "vm/statistics.h"
46 /*******************************************************************************
48 This structure is used for dump memory allocation if cacao
51 *******************************************************************************/
53 #if !defined(ENABLE_THREADS)
54 static dumpinfo_t _no_threads_dumpinfo;
59 * Allocate a new thread-local dump memory structure.
61 DumpMemory::DumpMemory() : _size(0), _used(0)
67 * Stupid realloc implementation for dump memory. Avoid, if possible.
69 void* DumpMemory::reallocate(void* src, size_t len1, size_t len2)
71 void* dst = allocate(len2);
73 (void) os::memcpy(dst, src, len1);
75 #if defined(ENABLE_MEMCHECK)
76 // Destroy the source.
77 (void) os::memset(src, MEMORY_CLEAR_BYTE, len1);
85 * Add the given dump area to the area list.
87 * @param dm Pointer to dump area.
89 void DumpMemory::add_area(DumpMemoryArea* dma)
91 _areas.push_back(dma);
93 // Increase the size count of the dump memory.
94 _size += dma->get_size();
96 #if defined(ENABLE_STATISTICS)
98 if (_size > (size_t) maxdumpsize)
106 * Remove the given dump area from the area list.
108 * @param dm Pointer to dump area.
110 void DumpMemory::remove_area(DumpMemoryArea* dma)
113 assert(_areas.back() == dma);
115 // Remove the last area from the list. The check above guarantees
116 // we are removing the correct area.
119 // Decrease the size and used count.
120 _size -= dma->get_size();
121 _used -= dma->get_used();
126 * Allocate a new dump memory area.
128 * @ param size Required memory size.
130 DumpMemoryArea::DumpMemoryArea(size_t size) : _size(0), _used(0)
132 // Get the DumpMemory object of the current thread.
133 DumpMemory* dm = DumpMemory::get_current();
135 // Add this area to the areas list.
141 * Release all dump memory blocks in the current dump area.
143 DumpMemoryArea::~DumpMemoryArea()
145 // Get the DumpMemory object of the current thread.
146 DumpMemory* dm = DumpMemory::get_current();
148 #if defined(ENABLE_MEMCHECK)
153 // Iterate over all dump memory allocations about to be released.
155 for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
156 DumpMemoryAllocation* dma = *it;
158 // Invalidate the freed memory.
159 (void) os::memset(dma->get_mem(), MEMORY_CLEAR_BYTE, dma->get_size());
161 // Call the destructor of the current allocation.
164 #endif /* defined(ENABLE_MEMCHECK) */
166 // Free all memory blocks.
167 for (std::vector<DumpMemoryBlock*>::iterator it = _blocks.begin(); it != _blocks.end(); it++) {
168 // Call the destructor of the current block.
172 // Remove this area for the area list.
173 dm->remove_area(this);
178 * Allocate a dump memory block for the current dump memory area.
180 * @param size Required memory size.
182 * @return Pointer to the newly allocated block.
184 DumpMemoryBlock* DumpMemoryArea::allocate_new_block(size_t size)
186 DumpMemoryBlock* dmb = new DumpMemoryBlock(size);
187 _blocks.push_back(dmb);
189 #if defined(ENABLE_STATISTICS)
191 DumpMemory* dm = DumpMemory::get_current();
192 dm->add_size(dmb->get_size());
194 if (dm->get_size() > (size_t) maxdumpsize)
195 maxdumpsize = dm->get_size();
204 * Checks canaries in this dump memory area. If any canary has been changed,
205 * this function aborts the VM with an error message.
207 #if defined(ENABLE_MEMCHECK)
208 void DumpMemoryArea::check_canaries()
212 // Iterate over all dump memory allocations.
214 for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
215 DumpMemoryAllocation* dma = *it;
219 pm = ((uint8_t *) dma->get_mem()) - MEMORY_CANARY_SIZE;
221 for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
222 if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
223 fprintf(stderr, "canary bytes:");
225 for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
226 fprintf(stderr, " %02x", pm[j]);
228 fprintf(stderr,"\n");
230 vm_abort("error: dump memory bottom canary killed: "
231 "%p (%d bytes allocated at %p)\n",
232 pm + i, dma->get_size(), dma->get_mem());
236 pm = ((uint8_t *) dma->get_mem()) + dma->get_size();
238 for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
239 if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
240 fprintf(stderr, "canary bytes:");
242 for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
243 fprintf(stderr, " %02x", pm[j]);
245 fprintf(stderr, "\n");
247 vm_abort("error: dump memory top canary killed: "
248 "%p (%d bytes allocated at %p)\n",
249 pm + i, dma->get_size(), dma->get_mem());
254 #endif /* defined(ENABLE_MEMCHECK) */
258 * Allocate a memory block for the current dump memory block.
260 * @param size Required memory size.
262 DumpMemoryBlock::DumpMemoryBlock(size_t size) : _size(0), _used(0), _block(0)
264 // If requested size is greater than the default, make the new
265 // memory block as big as the requested size. Otherwise use the
267 _size = (size > DEFAULT_SIZE) ? size : DEFAULT_SIZE;
269 // Allocate a memory block.
270 _block = memory_checked_alloc(_size);
272 #if defined(ENABLE_STATISTICS)
273 // The amount of globally allocated dump memory (thread safe).
275 globalallocateddumpsize += _size;
281 * Release the memory block for the dump memory block.
283 * @param size Required memory size.
285 DumpMemoryBlock::~DumpMemoryBlock()
287 // Release the memory block.
288 mem_free(_block, /* XXX */ 1);
290 #if defined(ENABLE_STATISTICS)
291 // The amount of globally allocated dump memory (thread safe).
293 globalallocateddumpsize -= _size;
298 // Legacy C interface.
301 void* DumpMemory_allocate(size_t size) { return DumpMemory::allocate(size); }
302 void* DumpMemory_reallocate(void* src, size_t len1, size_t len2) { return DumpMemory::reallocate(src, len1, len2); }
307 * These are local overrides for various environment variables in Emacs.
308 * Please do not remove this and leave it at the end of the file, where
309 * Emacs will automagically detect them.
310 * ---------------------------------------------------------------------
313 * indent-tabs-mode: t
317 * vim:noexpandtab:sw=4:ts=4: