Mercurial > hg > truffle
annotate src/share/vm/memory/allocation.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | f4f596978298 |
children | ebfb7c68865e |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_allocation.cpp.incl" | |
27 | |
28 void* CHeapObj::operator new(size_t size){ | |
29 return (void *) AllocateHeap(size, "CHeapObj-new"); | |
30 } | |
31 | |
32 void CHeapObj::operator delete(void* p){ | |
33 FreeHeap(p); | |
34 } | |
35 | |
36 void* StackObj::operator new(size_t size) { ShouldNotCallThis(); return 0; }; | |
37 void StackObj::operator delete(void* p) { ShouldNotCallThis(); }; | |
38 void* _ValueObj::operator new(size_t size) { ShouldNotCallThis(); return 0; }; | |
39 void _ValueObj::operator delete(void* p) { ShouldNotCallThis(); }; | |
40 | |
41 void* ResourceObj::operator new(size_t size, allocation_type type) { | |
42 address res; | |
43 switch (type) { | |
44 case C_HEAP: | |
45 res = (address)AllocateHeap(size, "C_Heap: ResourceOBJ"); | |
1685 | 46 DEBUG_ONLY(set_allocation_type(res, C_HEAP);) |
0 | 47 break; |
48 case RESOURCE_AREA: | |
1688
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
49 // new(size) sets allocation type RESOURCE_AREA. |
0 | 50 res = (address)operator new(size); |
51 break; | |
52 default: | |
53 ShouldNotReachHere(); | |
54 } | |
55 return res; | |
56 } | |
57 | |
58 void ResourceObj::operator delete(void* p) { | |
59 assert(((ResourceObj *)p)->allocated_on_C_heap(), | |
60 "delete only allowed for C_HEAP objects"); | |
1721
413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
johnc
parents:
1689
diff
changeset
|
61 DEBUG_ONLY(((ResourceObj *)p)->_allocation = (uintptr_t) badHeapOopVal;) |
0 | 62 FreeHeap(p); |
63 } | |
64 | |
1685 | 65 #ifdef ASSERT |
66 void ResourceObj::set_allocation_type(address res, allocation_type type) { | |
67 // Set allocation type in the resource object | |
68 uintptr_t allocation = (uintptr_t)res; | |
1688
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
69 assert((allocation & allocation_mask) == 0, "address should be aligned to 4 bytes at least"); |
1685 | 70 assert(type <= allocation_mask, "incorrect allocation type"); |
71 ((ResourceObj *)res)->_allocation = ~(allocation + type); | |
72 } | |
73 | |
1688
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
74 ResourceObj::allocation_type ResourceObj::get_allocation_type() const { |
1685 | 75 assert(~(_allocation | allocation_mask) == (uintptr_t)this, "lost resource object"); |
76 return (allocation_type)((~_allocation) & allocation_mask); | |
77 } | |
78 | |
1688
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
79 ResourceObj::ResourceObj() { // default constructor |
1685 | 80 if (~(_allocation | allocation_mask) != (uintptr_t)this) { |
81 set_allocation_type((address)this, STACK_OR_EMBEDDED); | |
1688
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
82 } else if (allocated_on_stack()) { |
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
83 // For some reason we got a value which looks like an allocation on stack. |
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
84 // Pass if it is really allocated on stack. |
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
85 assert(Thread::current()->on_local_stack((address)this),"should be on stack"); |
1685 | 86 } else { |
87 assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena(), | |
88 "allocation_type should be set by operator new()"); | |
89 } | |
90 } | |
91 | |
1688
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
92 ResourceObj::ResourceObj(const ResourceObj& r) { // default copy constructor |
1685 | 93 // Used in ClassFileParser::parse_constant_pool_entries() for ClassFileStream. |
94 set_allocation_type((address)this, STACK_OR_EMBEDDED); | |
95 } | |
96 | |
97 ResourceObj& ResourceObj::operator=(const ResourceObj& r) { // default copy assignment | |
98 // Used in InlineTree::ok_to_inline() for WarmCallInfo. | |
99 assert(allocated_on_stack(), "copy only into local"); | |
100 // Keep current _allocation value; | |
101 return *this; | |
102 } | |
103 | |
104 ResourceObj::~ResourceObj() { | |
1688
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
105 // allocated_on_C_heap() also checks that encoded (in _allocation) address == this. |
2dfd013a7465
6975078: assert(allocated_on_res_area() || allocated_on_C_heap() || allocated_on_arena()
kvn
parents:
1685
diff
changeset
|
106 if (!allocated_on_C_heap()) { // ResourceObj::delete() zaps _allocation for C_heap. |
1721
413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
johnc
parents:
1689
diff
changeset
|
107 _allocation = (uintptr_t) badHeapOopVal; // zap type |
1685 | 108 } |
109 } | |
110 #endif // ASSERT | |
111 | |
112 | |
0 | 113 void trace_heap_malloc(size_t size, const char* name, void* p) { |
114 // A lock is not needed here - tty uses a lock internally | |
115 tty->print_cr("Heap malloc " INTPTR_FORMAT " %7d %s", p, size, name == NULL ? "" : name); | |
116 } | |
117 | |
118 | |
119 void trace_heap_free(void* p) { | |
120 // A lock is not needed here - tty uses a lock internally | |
121 tty->print_cr("Heap free " INTPTR_FORMAT, p); | |
122 } | |
123 | |
124 bool warn_new_operator = false; // see vm_main | |
125 | |
126 //-------------------------------------------------------------------------------------- | |
127 // ChunkPool implementation | |
128 | |
129 // MT-safe pool of chunks to reduce malloc/free thrashing | |
130 // NB: not using Mutex because pools are used before Threads are initialized | |
131 class ChunkPool { | |
132 Chunk* _first; // first cached Chunk; its first word points to next chunk | |
133 size_t _num_chunks; // number of unused chunks in pool | |
134 size_t _num_used; // number of chunks currently checked out | |
135 const size_t _size; // size of each chunk (must be uniform) | |
136 | |
137 // Our three static pools | |
138 static ChunkPool* _large_pool; | |
139 static ChunkPool* _medium_pool; | |
140 static ChunkPool* _small_pool; | |
141 | |
142 // return first element or null | |
143 void* get_first() { | |
144 Chunk* c = _first; | |
145 if (_first) { | |
146 _first = _first->next(); | |
147 _num_chunks--; | |
148 } | |
149 return c; | |
150 } | |
151 | |
152 public: | |
153 // All chunks in a ChunkPool has the same size | |
154 ChunkPool(size_t size) : _size(size) { _first = NULL; _num_chunks = _num_used = 0; } | |
155 | |
156 // Allocate a new chunk from the pool (might expand the pool) | |
157 void* allocate(size_t bytes) { | |
158 assert(bytes == _size, "bad size"); | |
159 void* p = NULL; | |
160 { ThreadCritical tc; | |
161 _num_used++; | |
162 p = get_first(); | |
163 if (p == NULL) p = os::malloc(bytes); | |
164 } | |
165 if (p == NULL) | |
166 vm_exit_out_of_memory(bytes, "ChunkPool::allocate"); | |
167 | |
168 return p; | |
169 } | |
170 | |
171 // Return a chunk to the pool | |
172 void free(Chunk* chunk) { | |
173 assert(chunk->length() + Chunk::aligned_overhead_size() == _size, "bad size"); | |
174 ThreadCritical tc; | |
175 _num_used--; | |
176 | |
177 // Add chunk to list | |
178 chunk->set_next(_first); | |
179 _first = chunk; | |
180 _num_chunks++; | |
181 } | |
182 | |
183 // Prune the pool | |
184 void free_all_but(size_t n) { | |
185 // if we have more than n chunks, free all of them | |
186 ThreadCritical tc; | |
187 if (_num_chunks > n) { | |
188 // free chunks at end of queue, for better locality | |
189 Chunk* cur = _first; | |
190 for (size_t i = 0; i < (n - 1) && cur != NULL; i++) cur = cur->next(); | |
191 | |
192 if (cur != NULL) { | |
193 Chunk* next = cur->next(); | |
194 cur->set_next(NULL); | |
195 cur = next; | |
196 | |
197 // Free all remaining chunks | |
198 while(cur != NULL) { | |
199 next = cur->next(); | |
200 os::free(cur); | |
201 _num_chunks--; | |
202 cur = next; | |
203 } | |
204 } | |
205 } | |
206 } | |
207 | |
208 // Accessors to preallocated pool's | |
209 static ChunkPool* large_pool() { assert(_large_pool != NULL, "must be initialized"); return _large_pool; } | |
210 static ChunkPool* medium_pool() { assert(_medium_pool != NULL, "must be initialized"); return _medium_pool; } | |
211 static ChunkPool* small_pool() { assert(_small_pool != NULL, "must be initialized"); return _small_pool; } | |
212 | |
213 static void initialize() { | |
214 _large_pool = new ChunkPool(Chunk::size + Chunk::aligned_overhead_size()); | |
215 _medium_pool = new ChunkPool(Chunk::medium_size + Chunk::aligned_overhead_size()); | |
216 _small_pool = new ChunkPool(Chunk::init_size + Chunk::aligned_overhead_size()); | |
217 } | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
218 |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
219 static void clean() { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
220 enum { BlocksToKeep = 5 }; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
221 _small_pool->free_all_but(BlocksToKeep); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
222 _medium_pool->free_all_but(BlocksToKeep); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
223 _large_pool->free_all_but(BlocksToKeep); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
224 } |
0 | 225 }; |
226 | |
227 ChunkPool* ChunkPool::_large_pool = NULL; | |
228 ChunkPool* ChunkPool::_medium_pool = NULL; | |
229 ChunkPool* ChunkPool::_small_pool = NULL; | |
230 | |
231 void chunkpool_init() { | |
232 ChunkPool::initialize(); | |
233 } | |
234 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
235 void |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
236 Chunk::clean_chunk_pool() { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
237 ChunkPool::clean(); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
238 } |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
239 |
0 | 240 |
241 //-------------------------------------------------------------------------------------- | |
242 // ChunkPoolCleaner implementation | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
243 // |
0 | 244 |
245 class ChunkPoolCleaner : public PeriodicTask { | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
246 enum { CleaningInterval = 5000 }; // cleaning interval in ms |
0 | 247 |
248 public: | |
249 ChunkPoolCleaner() : PeriodicTask(CleaningInterval) {} | |
250 void task() { | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
251 ChunkPool::clean(); |
0 | 252 } |
253 }; | |
254 | |
255 //-------------------------------------------------------------------------------------- | |
256 // Chunk implementation | |
257 | |
258 void* Chunk::operator new(size_t requested_size, size_t length) { | |
259 // requested_size is equal to sizeof(Chunk) but in order for the arena | |
260 // allocations to come out aligned as expected the size must be aligned | |
261 // to expected arean alignment. | |
262 // expect requested_size but if sizeof(Chunk) doesn't match isn't proper size we must align it. | |
263 assert(ARENA_ALIGN(requested_size) == aligned_overhead_size(), "Bad alignment"); | |
264 size_t bytes = ARENA_ALIGN(requested_size) + length; | |
265 switch (length) { | |
266 case Chunk::size: return ChunkPool::large_pool()->allocate(bytes); | |
267 case Chunk::medium_size: return ChunkPool::medium_pool()->allocate(bytes); | |
268 case Chunk::init_size: return ChunkPool::small_pool()->allocate(bytes); | |
269 default: { | |
270 void *p = os::malloc(bytes); | |
271 if (p == NULL) | |
272 vm_exit_out_of_memory(bytes, "Chunk::new"); | |
273 return p; | |
274 } | |
275 } | |
276 } | |
277 | |
278 void Chunk::operator delete(void* p) { | |
279 Chunk* c = (Chunk*)p; | |
280 switch (c->length()) { | |
281 case Chunk::size: ChunkPool::large_pool()->free(c); break; | |
282 case Chunk::medium_size: ChunkPool::medium_pool()->free(c); break; | |
283 case Chunk::init_size: ChunkPool::small_pool()->free(c); break; | |
284 default: os::free(c); | |
285 } | |
286 } | |
287 | |
288 Chunk::Chunk(size_t length) : _len(length) { | |
289 _next = NULL; // Chain on the linked list | |
290 } | |
291 | |
292 | |
293 void Chunk::chop() { | |
294 Chunk *k = this; | |
295 while( k ) { | |
296 Chunk *tmp = k->next(); | |
297 // clear out this chunk (to detect allocation bugs) | |
298 if (ZapResourceArea) memset(k->bottom(), badResourceValue, k->length()); | |
299 delete k; // Free chunk (was malloc'd) | |
300 k = tmp; | |
301 } | |
302 } | |
303 | |
304 void Chunk::next_chop() { | |
305 _next->chop(); | |
306 _next = NULL; | |
307 } | |
308 | |
309 | |
310 void Chunk::start_chunk_pool_cleaner_task() { | |
311 #ifdef ASSERT | |
312 static bool task_created = false; | |
313 assert(!task_created, "should not start chuck pool cleaner twice"); | |
314 task_created = true; | |
315 #endif | |
316 ChunkPoolCleaner* cleaner = new ChunkPoolCleaner(); | |
317 cleaner->enroll(); | |
318 } | |
319 | |
320 //------------------------------Arena------------------------------------------ | |
321 | |
322 Arena::Arena(size_t init_size) { | |
323 size_t round_size = (sizeof (char *)) - 1; | |
324 init_size = (init_size+round_size) & ~round_size; | |
325 _first = _chunk = new (init_size) Chunk(init_size); | |
326 _hwm = _chunk->bottom(); // Save the cached hwm, max | |
327 _max = _chunk->top(); | |
328 set_size_in_bytes(init_size); | |
329 } | |
330 | |
331 Arena::Arena() { | |
332 _first = _chunk = new (Chunk::init_size) Chunk(Chunk::init_size); | |
333 _hwm = _chunk->bottom(); // Save the cached hwm, max | |
334 _max = _chunk->top(); | |
335 set_size_in_bytes(Chunk::init_size); | |
336 } | |
337 | |
338 Arena::Arena(Arena *a) : _chunk(a->_chunk), _hwm(a->_hwm), _max(a->_max), _first(a->_first) { | |
339 set_size_in_bytes(a->size_in_bytes()); | |
340 } | |
341 | |
342 Arena *Arena::move_contents(Arena *copy) { | |
343 copy->destruct_contents(); | |
344 copy->_chunk = _chunk; | |
345 copy->_hwm = _hwm; | |
346 copy->_max = _max; | |
347 copy->_first = _first; | |
348 copy->set_size_in_bytes(size_in_bytes()); | |
349 // Destroy original arena | |
350 reset(); | |
351 return copy; // Return Arena with contents | |
352 } | |
353 | |
354 Arena::~Arena() { | |
355 destruct_contents(); | |
356 } | |
357 | |
358 // Destroy this arenas contents and reset to empty | |
359 void Arena::destruct_contents() { | |
360 if (UseMallocOnly && _first != NULL) { | |
361 char* end = _first->next() ? _first->top() : _hwm; | |
362 free_malloced_objects(_first, _first->bottom(), end, _hwm); | |
363 } | |
364 _first->chop(); | |
365 reset(); | |
366 } | |
367 | |
368 | |
369 // Total of all Chunks in arena | |
370 size_t Arena::used() const { | |
371 size_t sum = _chunk->length() - (_max-_hwm); // Size leftover in this Chunk | |
372 register Chunk *k = _first; | |
373 while( k != _chunk) { // Whilst have Chunks in a row | |
374 sum += k->length(); // Total size of this Chunk | |
375 k = k->next(); // Bump along to next Chunk | |
376 } | |
377 return sum; // Return total consumed space. | |
378 } | |
379 | |
380 | |
381 // Grow a new Chunk | |
382 void* Arena::grow( size_t x ) { | |
383 // Get minimal required size. Either real big, or even bigger for giant objs | |
384 size_t len = MAX2(x, (size_t) Chunk::size); | |
385 | |
386 Chunk *k = _chunk; // Get filled-up chunk address | |
387 _chunk = new (len) Chunk(len); | |
388 | |
389 if (_chunk == NULL) | |
390 vm_exit_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow"); | |
391 | |
392 if (k) k->set_next(_chunk); // Append new chunk to end of linked list | |
393 else _first = _chunk; | |
394 _hwm = _chunk->bottom(); // Save the cached hwm, max | |
395 _max = _chunk->top(); | |
396 set_size_in_bytes(size_in_bytes() + len); | |
397 void* result = _hwm; | |
398 _hwm += x; | |
399 return result; | |
400 } | |
401 | |
402 | |
403 | |
404 // Reallocate storage in Arena. | |
405 void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size) { | |
406 assert(new_size >= 0, "bad size"); | |
407 if (new_size == 0) return NULL; | |
408 #ifdef ASSERT | |
409 if (UseMallocOnly) { | |
410 // always allocate a new object (otherwise we'll free this one twice) | |
411 char* copy = (char*)Amalloc(new_size); | |
412 size_t n = MIN2(old_size, new_size); | |
413 if (n > 0) memcpy(copy, old_ptr, n); | |
414 Afree(old_ptr,old_size); // Mostly done to keep stats accurate | |
415 return copy; | |
416 } | |
417 #endif | |
418 char *c_old = (char*)old_ptr; // Handy name | |
419 // Stupid fast special case | |
420 if( new_size <= old_size ) { // Shrink in-place | |
421 if( c_old+old_size == _hwm) // Attempt to free the excess bytes | |
422 _hwm = c_old+new_size; // Adjust hwm | |
423 return c_old; | |
424 } | |
425 | |
426 // make sure that new_size is legal | |
427 size_t corrected_new_size = ARENA_ALIGN(new_size); | |
428 | |
429 // See if we can resize in-place | |
430 if( (c_old+old_size == _hwm) && // Adjusting recent thing | |
431 (c_old+corrected_new_size <= _max) ) { // Still fits where it sits | |
432 _hwm = c_old+corrected_new_size; // Adjust hwm | |
433 return c_old; // Return old pointer | |
434 } | |
435 | |
436 // Oops, got to relocate guts | |
437 void *new_ptr = Amalloc(new_size); | |
438 memcpy( new_ptr, c_old, old_size ); | |
439 Afree(c_old,old_size); // Mostly done to keep stats accurate | |
440 return new_ptr; | |
441 } | |
442 | |
443 | |
444 // Determine if pointer belongs to this Arena or not. | |
445 bool Arena::contains( const void *ptr ) const { | |
446 #ifdef ASSERT | |
447 if (UseMallocOnly) { | |
448 // really slow, but not easy to make fast | |
449 if (_chunk == NULL) return false; | |
450 char** bottom = (char**)_chunk->bottom(); | |
451 for (char** p = (char**)_hwm - 1; p >= bottom; p--) { | |
452 if (*p == ptr) return true; | |
453 } | |
454 for (Chunk *c = _first; c != NULL; c = c->next()) { | |
455 if (c == _chunk) continue; // current chunk has been processed | |
456 char** bottom = (char**)c->bottom(); | |
457 for (char** p = (char**)c->top() - 1; p >= bottom; p--) { | |
458 if (*p == ptr) return true; | |
459 } | |
460 } | |
461 return false; | |
462 } | |
463 #endif | |
464 if( (void*)_chunk->bottom() <= ptr && ptr < (void*)_hwm ) | |
465 return true; // Check for in this chunk | |
466 for (Chunk *c = _first; c; c = c->next()) { | |
467 if (c == _chunk) continue; // current chunk has been processed | |
468 if ((void*)c->bottom() <= ptr && ptr < (void*)c->top()) { | |
469 return true; // Check for every chunk in Arena | |
470 } | |
471 } | |
472 return false; // Not in any Chunk, so not in Arena | |
473 } | |
474 | |
475 | |
476 #ifdef ASSERT | |
477 void* Arena::malloc(size_t size) { | |
478 assert(UseMallocOnly, "shouldn't call"); | |
479 // use malloc, but save pointer in res. area for later freeing | |
480 char** save = (char**)internal_malloc_4(sizeof(char*)); | |
481 return (*save = (char*)os::malloc(size)); | |
482 } | |
483 | |
484 // for debugging with UseMallocOnly | |
485 void* Arena::internal_malloc_4(size_t x) { | |
486 assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); | |
487 if (_hwm + x > _max) { | |
488 return grow(x); | |
489 } else { | |
490 char *old = _hwm; | |
491 _hwm += x; | |
492 return old; | |
493 } | |
494 } | |
495 #endif | |
496 | |
497 | |
498 //-------------------------------------------------------------------------------------- | |
499 // Non-product code | |
500 | |
501 #ifndef PRODUCT | |
502 // The global operator new should never be called since it will usually indicate | |
503 // a memory leak. Use CHeapObj as the base class of such objects to make it explicit | |
504 // that they're allocated on the C heap. | |
505 // Commented out in product version to avoid conflicts with third-party C++ native code. | |
506 // %% note this is causing a problem on solaris debug build. the global | |
507 // new is being called from jdk source and causing data corruption. | |
508 // src/share/native/sun/awt/font/fontmanager/textcache/hsMemory.cpp::hsSoftNew | |
509 // define CATCH_OPERATOR_NEW_USAGE if you want to use this. | |
510 #ifdef CATCH_OPERATOR_NEW_USAGE | |
511 void* operator new(size_t size){ | |
512 static bool warned = false; | |
513 if (!warned && warn_new_operator) | |
514 warning("should not call global (default) operator new"); | |
515 warned = true; | |
516 return (void *) AllocateHeap(size, "global operator new"); | |
517 } | |
518 #endif | |
519 | |
520 void AllocatedObj::print() const { print_on(tty); } | |
521 void AllocatedObj::print_value() const { print_value_on(tty); } | |
522 | |
523 void AllocatedObj::print_on(outputStream* st) const { | |
524 st->print_cr("AllocatedObj(" INTPTR_FORMAT ")", this); | |
525 } | |
526 | |
527 void AllocatedObj::print_value_on(outputStream* st) const { | |
528 st->print("AllocatedObj(" INTPTR_FORMAT ")", this); | |
529 } | |
530 | |
531 size_t Arena::_bytes_allocated = 0; | |
532 | |
533 AllocStats::AllocStats() { | |
534 start_mallocs = os::num_mallocs; | |
535 start_frees = os::num_frees; | |
536 start_malloc_bytes = os::alloc_bytes; | |
537 start_res_bytes = Arena::_bytes_allocated; | |
538 } | |
539 | |
540 int AllocStats::num_mallocs() { return os::num_mallocs - start_mallocs; } | |
541 size_t AllocStats::alloc_bytes() { return os::alloc_bytes - start_malloc_bytes; } | |
542 size_t AllocStats::resource_bytes() { return Arena::_bytes_allocated - start_res_bytes; } | |
543 int AllocStats::num_frees() { return os::num_frees - start_frees; } | |
544 void AllocStats::print() { | |
545 tty->print("%d mallocs (%ldK), %d frees, %ldK resrc", | |
546 num_mallocs(), alloc_bytes()/K, num_frees(), resource_bytes()/K); | |
547 } | |
548 | |
549 | |
550 // debugging code | |
551 inline void Arena::free_all(char** start, char** end) { | |
552 for (char** p = start; p < end; p++) if (*p) os::free(*p); | |
553 } | |
554 | |
555 void Arena::free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2) { | |
556 assert(UseMallocOnly, "should not call"); | |
557 // free all objects malloced since resource mark was created; resource area | |
558 // contains their addresses | |
559 if (chunk->next()) { | |
560 // this chunk is full, and some others too | |
561 for (Chunk* c = chunk->next(); c != NULL; c = c->next()) { | |
562 char* top = c->top(); | |
563 if (c->next() == NULL) { | |
564 top = hwm2; // last junk is only used up to hwm2 | |
565 assert(c->contains(hwm2), "bad hwm2"); | |
566 } | |
567 free_all((char**)c->bottom(), (char**)top); | |
568 } | |
569 assert(chunk->contains(hwm), "bad hwm"); | |
570 assert(chunk->contains(max), "bad max"); | |
571 free_all((char**)hwm, (char**)max); | |
572 } else { | |
573 // this chunk was partially used | |
574 assert(chunk->contains(hwm), "bad hwm"); | |
575 assert(chunk->contains(hwm2), "bad hwm2"); | |
576 free_all((char**)hwm, (char**)hwm2); | |
577 } | |
578 } | |
579 | |
580 | |
581 ReallocMark::ReallocMark() { | |
582 #ifdef ASSERT | |
583 Thread *thread = ThreadLocalStorage::get_thread_slow(); | |
584 _nesting = thread->resource_area()->nesting(); | |
585 #endif | |
586 } | |
587 | |
588 void ReallocMark::check() { | |
589 #ifdef ASSERT | |
590 if (_nesting != Thread::current()->resource_area()->nesting()) { | |
591 fatal("allocation bug: array could grow within nested ResourceMark"); | |
592 } | |
593 #endif | |
594 } | |
595 | |
596 #endif // Non-product |