* configure.ac: New switch for disabling -O2 (--disable-optimizations).
[cacao.git] / src / mm / memory.cpp
1 /* src/mm/memory.cpp - memory management
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30
31 #if defined(__DARWIN__)
32 /* If we compile with -ansi on darwin, <sys/types.h> is not
33    included. So let's do it here. */
34 # include <sys/types.h>
35 #endif
36
37 #include "vm/types.h"
38
39 #include "arch.h"
40
41 #include "mm/memory.hpp"
42
43 #include "native/native.hpp"
44
45 #include "threads/lock.hpp"
46 #include "threads/thread.hpp"
47
48 #include "toolbox/logging.hpp"
49
50 #include "vm/global.h"
51 #include "vm/string.hpp"
52 #include "vm/vm.hpp"
53
54 #include "vm/options.h"
55 #include "vm/os.hpp"
56
57 #if defined(ENABLE_STATISTICS)
58 # include "vm/statistics.h"
59 #endif
60
61
62 /* memory_mprotect *************************************************************
63
64    Convenience function for mprotect.  This function also does error
65    checking.
66
67 *******************************************************************************/
68
69 void memory_mprotect(void *addr, size_t len, int prot)
70 {
71         if (os::mprotect(addr, len, prot) != 0)
72                 os::abort_errno("memory_mprotect: os::mprotect failed");
73 }
74
75
76 /* memory_checked_alloc ********************************************************
77
78    Allocated zeroed-out memory and does an OOM check.
79
80    ERROR HANDLING:
81       XXX If no memory could be allocated, this function justs *exists*.
82
83 *******************************************************************************/
84
85 void *memory_checked_alloc(size_t size)
86 {
87         /* always allocate memory zeroed out */
88
89         void *p = os::calloc(size, 1);
90
91         if (p == NULL)
92                 vm_abort("memory_checked_alloc: calloc failed: out of memory");
93
94         return p;
95 }
96
97
98 void *mem_alloc(int32_t size)
99 {
100         void *m;
101
102         if (size == 0)
103                 return NULL;
104
105 #if defined(ENABLE_STATISTICS)
106         if (opt_stat) {
107                 memoryusage += size;
108
109                 if (memoryusage > maxmemusage)
110                         maxmemusage = memoryusage;
111         }
112 #endif
113
114         m = memory_checked_alloc(size);
115
116 #if defined(ENABLE_MEMCHECK)
117         /* XXX we would like to poison the memory, but callers rely on */
118         /* the zeroing. This should change sooner or later.            */
119         /* memset(m, MEMORY_CLEAR_BYTE, size); */
120 #endif
121
122         return m;
123 }
124
125
126 void *mem_realloc(void *src, int32_t len1, int32_t len2)
127 {
128         void *dst;
129
130         /* prevent compiler warnings */
131
132         dst = NULL;
133
134         if (src == NULL)
135                 if (len1 != 0)
136                         vm_abort("mem_realloc: reallocating memoryblock with address NULL, length != 0");
137
138 #if defined(ENABLE_STATISTICS)
139         if (opt_stat)
140                 memoryusage = (memoryusage - len1) + len2;
141 #endif
142
143 #if defined(ENABLE_MEMCHECK)
144         if (len2 < len1)
145                 os::memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2);
146 #endif
147
148         dst = realloc(src, len2);
149
150         if (dst == NULL)
151                 vm_abort("mem_realloc: realloc failed: out of memory");
152
153 #if defined(ENABLE_MEMCHECK)
154         if (len2 > len1)
155                 os::memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1);
156 #endif
157
158         return dst;
159 }
160
161
162 void mem_free(void *m, int32_t size)
163 {
164         if (!m) {
165                 if (size == 0)
166                         return;
167
168                 log_text("returned memoryblock with address NULL, length != 0");
169                 assert(0);
170         }
171
172 #if defined(ENABLE_STATISTICS)
173         if (opt_stat)
174                 memoryusage -= size;
175 #endif
176
177 #if defined(ENABLE_MEMCHECK)
178         /* destroy the contents */
179         os::memset(m, MEMORY_CLEAR_BYTE, size);
180 #endif
181
182         os::free(m);
183 }
184
185
186 /* memory_thread ***************************************************************
187
188    Prints regularly memory statistics.
189
190 *******************************************************************************/
191
192 #if defined(ENABLE_THREADS) && !defined(NDEBUG)
193 static void memory_thread(void)
194 {
195         int32_t seconds;
196
197         /* Prevent compiler warning. */
198
199         seconds = 1;
200
201         /* If both arguments are specified, use the value of
202            ProfileMemoryUsage. */
203
204         if (opt_ProfileGCMemoryUsage)
205                 seconds = opt_ProfileGCMemoryUsage;
206
207         if (opt_ProfileMemoryUsage)
208                 seconds = opt_ProfileMemoryUsage;
209
210         while (true) {
211                 /* sleep thread */
212
213                 threads_sleep(seconds * 1000, 0);
214
215 # if defined(ENABLE_STATISTICS)
216                 /* Print current date and time (only when we print to the
217                    stdout). */
218
219                 if (!opt_ProfileMemoryUsageGNUPlot)
220                         statistics_print_date();
221
222                 /* print memory usage */
223
224                 if (opt_ProfileMemoryUsage)
225                         statistics_print_memory_usage();
226
227                 /* print GC memory usage */
228
229                 if (opt_ProfileGCMemoryUsage)
230                         statistics_print_gc_memory_usage();
231 # endif
232         }
233 }
234 #endif
235
236
237 /* memory_start_thread *********************************************************
238
239    Starts the memory profiling thread.
240
241 *******************************************************************************/
242
243 #if defined(ENABLE_THREADS) && !defined(NDEBUG)
244 bool memory_start_thread(void)
245 {
246         utf *name;
247
248         name = utf_new_char("Memory Profiler");
249
250         /* start the memory profiling thread */
251
252         if (!threads_thread_start_internal(name, memory_thread))
253                 return false;
254
255         /* everything's ok */
256
257         return true;
258 }
259 #endif
260
261
262 /*
263  * These are local overrides for various environment variables in Emacs.
264  * Please do not remove this and leave it at the end of the file, where
265  * Emacs will automagically detect them.
266  * ---------------------------------------------------------------------
267  * Local variables:
268  * mode: c++
269  * indent-tabs-mode: t
270  * c-basic-offset: 4
271  * tab-width: 4
272  * End:
273  * vim:noexpandtab:sw=4:ts=4:
274  */