CACAO
dumpmemory.cpp
Go to the documentation of this file.
1 /* src/mm/dumpmemory.cpp - dump memory management
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5  Copyright (C) 2008 Theobroma Systems Ltd.
6 
7  This file is part of CACAO.
8 
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.
13 
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.
18 
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
22  02110-1301, USA.
23 
24 */
25 
26 #include "mm/dumpmemory.hpp"
27 #include <stdio.h> // for fprintf, stderr
28 #include "config.h" // for ENABLE_MEMCHECK, etc
29 #include "mm/memory.hpp" // for MEMORY_CANARY_SIZE, etc
30 #include "vm/os.hpp" // for os
31 #include "vm/vm.hpp" // for vm_abort
32 #include "vm/options.hpp"
33 
34 STAT_DECLARE_GROUP(max_mem_stat)
35 STAT_DECLARE_GROUP(not_freed_mem_stat)
36 STAT_REGISTER_GROUP_VAR(int,maxdumpsize,0,"maxdumpsize","max. dump memory",max_mem_stat)
37 STAT_REGISTER_GROUP_VAR(int,globalallocateddumpsize,0,"globalallocateddumpsize","dump memory not freed",not_freed_mem_stat)
38 
39 /*******************************************************************************
40 
41  This structure is used for dump memory allocation if cacao
42  runs without threads.
43 
44 *******************************************************************************/
45 
46 /**
47  * Allocate a new thread-local dump memory structure.
48  */
49 DumpMemory::DumpMemory() : _size(0), _used(0)
50 {
51 }
52 
53 
54 /**
55  * Stupid realloc implementation for dump memory. Avoid, if possible.
56  */
57 void* DumpMemory::reallocate(void* src, size_t len1, size_t len2)
58 {
59  void* dst = allocate(len2);
60 
61  (void) os::memcpy(dst, src, len1);
62 
63 #if defined(ENABLE_MEMCHECK)
64  // Destroy the source.
65  (void) os::memset(src, MEMORY_CLEAR_BYTE, len1);
66 #endif
67 
68  return dst;
69 }
70 
71 
72 /**
73  * Add the given dump area to the area list.
74  *
75  * @param dm Pointer to dump area.
76  */
78 {
79  _areas.push_back(dma);
80 
81  // Increase the size count of the dump memory.
82  _size += dma->get_size();
83 
84  STATISTICS(maxdumpsize.max(_size));
85 }
86 
87 
88 /**
89  * Remove the given dump area from the area list.
90  *
91  * @param dm Pointer to dump area.
92  */
94 {
95  // Sanity check.
96  assert(_areas.back() == dma);
97 
98  // Remove the last area from the list. The check above guarantees
99  // we are removing the correct area.
100  _areas.pop_back();
101 
102  // Decrease the size and used count.
103  _size -= dma->get_size();
104  _used -= dma->get_used();
105 }
106 
107 
108 /**
109  * Allocate a new dump memory area.
110  *
111  * @ param size Required memory size.
112  */
113 DumpMemoryArea::DumpMemoryArea(size_t size) : _size(0), _used(0)
114 {
115  // Get the DumpMemory object of the current thread.
117 
118  // Add this area to the areas list.
119  dm->add_area(this);
120 }
121 
122 
123 /**
124  * Release all dump memory blocks in the current dump area.
125  */
127 {
128  // Get the DumpMemory object of the current thread.
130 
131 #if defined(ENABLE_MEMCHECK)
132  // Check canaries.
133 
134  check_canaries();
135 
136  // Iterate over all dump memory allocations about to be released.
137 
138  for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
139  DumpMemoryAllocation* dma = *it;
140 
141  // Invalidate the freed memory.
142  (void) os::memset(dma->get_mem(), MEMORY_CLEAR_BYTE, dma->get_size());
143 
144  // Call the destructor of the current allocation.
145  delete dma;
146  }
147 #endif /* defined(ENABLE_MEMCHECK) */
148 
149  // Free all memory blocks.
150  for (std::vector<DumpMemoryBlock*>::iterator it = _blocks.begin(); it != _blocks.end(); it++) {
151  // Call the destructor of the current block.
152  delete *it;
153  }
154 
155  // Remove this area for the area list.
156  dm->remove_area(this);
157 }
158 
159 
160 /**
161  * Allocate a dump memory block for the current dump memory area.
162  *
163  * @param size Required memory size.
164  *
165  * @return Pointer to the newly allocated block.
166  */
168 {
169  DumpMemoryBlock* dmb = new DumpMemoryBlock(size);
170  _blocks.push_back(dmb);
171 
172 #if defined(ENABLE_STATISTICS)
174  dm->add_size(dmb->get_size());
175 
176  STATISTICS(maxdumpsize.max(dm->get_size()));
177 #endif
178 
179  return dmb;
180 }
181 
182 
183 /**
184  * Checks canaries in this dump memory area. If any canary has been changed,
185  * this function aborts the VM with an error message.
186  */
187 #if defined(ENABLE_MEMCHECK)
188 void DumpMemoryArea::check_canaries()
189 {
190  uint8_t* pm;
191 
192  // Iterate over all dump memory allocations.
193 
194  for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
195  DumpMemoryAllocation* dma = *it;
196 
197  // Check canaries.
198 
199  pm = ((uint8_t *) dma->get_mem()) - MEMORY_CANARY_SIZE;
200 
201  for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
202  if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
203  fprintf(stderr, "canary bytes:");
204 
205  for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
206  fprintf(stderr, " %02x", pm[j]);
207 
208  fprintf(stderr,"\n");
209 
210  vm_abort("error: dump memory bottom canary killed: "
211  "%p (%d bytes allocated at %p)\n",
212  pm + i, dma->get_size(), dma->get_mem());
213  }
214  }
215 
216  pm = ((uint8_t *) dma->get_mem()) + dma->get_size();
217 
218  for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
219  if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
220  fprintf(stderr, "canary bytes:");
221 
222  for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
223  fprintf(stderr, " %02x", pm[j]);
224 
225  fprintf(stderr, "\n");
226 
227  vm_abort("error: dump memory top canary killed: "
228  "%p (%d bytes allocated at %p)\n",
229  pm + i, dma->get_size(), dma->get_mem());
230  }
231  }
232  }
233 }
234 #endif /* defined(ENABLE_MEMCHECK) */
235 
236 
237 /**
238  * Allocate a memory block for the current dump memory block.
239  *
240  * @param size Required memory size.
241  */
242 DumpMemoryBlock::DumpMemoryBlock(size_t size) : _size(0), _used(0), _block(0)
243 {
244  // If requested size is greater than the default, make the new
245  // memory block as big as the requested size. Otherwise use the
246  // default size.
247  _size = (size > DEFAULT_SIZE) ? size : DEFAULT_SIZE;
248 
249  // Allocate a memory block.
251 
252  // The amount of globally allocated dump memory (thread safe).
253  STATISTICS(globalallocateddumpsize += _size);
254 }
255 
256 
257 /**
258  * Release the memory block for the dump memory block.
259  *
260  * @param size Required memory size.
261  */
263 {
264  // Release the memory block.
265  mem_free(_block, /* XXX */ 1);
266 
267  // The amount of globally allocated dump memory (thread safe).
268  STATISTICS(globalallocateddumpsize -= _size);
269 }
270 
271 /*
272  * These are local overrides for various environment variables in Emacs.
273  * Please do not remove this and leave it at the end of the file, where
274  * Emacs will automagically detect them.
275  * ---------------------------------------------------------------------
276  * Local variables:
277  * mode: c++
278  * indent-tabs-mode: t
279  * c-basic-offset: 4
280  * tab-width: 4
281  * End:
282  * vim:noexpandtab:sw=4:ts=4:
283  */
DumpMemoryArea(size_t size=0)
Allocate a new dump memory area.
Definition: dumpmemory.cpp:113
static void * memset(void *s, int c, size_t n)
Definition: os.hpp:501
std::vector< DumpMemoryBlock * > _blocks
List of memory blocks in this area.
Definition: dumpmemory.hpp:94
#define STATISTICS(x)
Wrapper for statistics only code.
Definition: statistics.hpp:975
void remove_area(DumpMemoryArea *dma)
Remove the given dump area from the area list.
Definition: dumpmemory.cpp:93
#define max(a, b)
Definition: lsra.hpp:80
Dump memory block.
Definition: dumpmemory.hpp:122
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
DumpMemoryBlock(size_t size=0)
Checks canaries in this dump memory area.
Definition: dumpmemory.cpp:242
size_t get_size() const
Definition: dumpmemory.hpp:103
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
~DumpMemoryArea()
Release all dump memory blocks in the current dump area.
Definition: dumpmemory.cpp:126
size_t _size
Size of the dump areas in this dump memory.
Definition: dumpmemory.hpp:62
void * memory_checked_alloc(size_t size)
Definition: memory.cpp:73
size_t _size
Size of the current memory block.
Definition: dumpmemory.hpp:126
Dump memory area.
Definition: dumpmemory.hpp:90
void mem_free(void *m, int32_t size)
Definition: memory.cpp:141
size_t get_size() const
Definition: dumpmemory.hpp:75
#define STAT_REGISTER_GROUP_VAR(type, var, init, name, description, group)
Register an statistics variable and add it to a group.
Definition: statistics.hpp:967
static void * reallocate(void *src, size_t len1, size_t len2)
Stupid realloc implementation for dump memory.
Definition: dumpmemory.cpp:57
void add_size(size_t size)
Definition: dumpmemory.hpp:73
size_t get_used() const
Definition: dumpmemory.hpp:104
MIIterator i
static void * memcpy(void *dest, const void *src, size_t n)
Definition: os.hpp:492
size_t _used
Used memory in this dump memory.
Definition: dumpmemory.hpp:63
~DumpMemoryBlock()
Release the memory block for the dump memory block.
Definition: dumpmemory.cpp:262
void * _block
List of memory blocks in this area.
Definition: dumpmemory.hpp:128
#define STAT_DECLARE_GROUP(var)
Declare an external group (or subgroup).
Definition: statistics.hpp:970
static void * allocate(size_t size)
Definition: dumpmemory.hpp:251
std::list< DumpMemoryArea * > _areas
Pointer to the current dump area.
Definition: dumpmemory.hpp:64
DumpMemoryBlock * allocate_new_block(size_t size)
Allocate a dump memory block for the current dump memory area.
Definition: dumpmemory.cpp:167
Thread-local dump memory structure.
Definition: dumpmemory.hpp:60
size_t get_size() const
Definition: dumpmemory.hpp:134
static const size_t DEFAULT_SIZE
Definition: dumpmemory.hpp:124
void add_area(DumpMemoryArea *dma)
Add the given dump area to the area list.
Definition: dumpmemory.cpp:77
static DumpMemory * get_current()
Definition: dumpmemory.hpp:238