Mercurial > hg > graal-jvmci-8
comparison src/share/vm/services/mallocTracker.hpp @ 20630:787c9c28311f
8058251: assert(_count > 0) failed: Negative counter when running runtime/NMT/MallocTrackingVerify.java
Summary: Fixed an issue when overflowing the MallocSite hash table bucket
Reviewed-by: coleenp, gtriantafill
author | ctornqvi |
---|---|
date | Tue, 11 Nov 2014 10:48:06 -0800 |
parents | 417e3b8d04c5 |
children | ec2c6fdd1ce6 |
comparison
equal
deleted
inserted
replaced
20629:09259e52a610 | 20630:787c9c28311f |
---|---|
237 * which ensures 8-bytes alignment on 32-bit systems and 16-bytes on 64-bit systems (Product build). | 237 * which ensures 8-bytes alignment on 32-bit systems and 16-bytes on 64-bit systems (Product build). |
238 */ | 238 */ |
239 | 239 |
240 class MallocHeader VALUE_OBJ_CLASS_SPEC { | 240 class MallocHeader VALUE_OBJ_CLASS_SPEC { |
241 #ifdef _LP64 | 241 #ifdef _LP64 |
242 size_t _size : 62; | 242 size_t _size : 64; |
243 size_t _level : 2; | |
244 size_t _flags : 8; | 243 size_t _flags : 8; |
245 size_t _pos_idx : 16; | 244 size_t _pos_idx : 16; |
246 size_t _bucket_idx: 40; | 245 size_t _bucket_idx: 40; |
247 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40) | 246 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40) |
248 #define MAX_BUCKET_LENGTH ((size_t)(1 << 16)) | 247 #define MAX_BUCKET_LENGTH ((size_t)(1 << 16)) |
249 #define MAX_MALLOC_SIZE (((size_t)1 << 62) - 1) | |
250 #else | 248 #else |
251 size_t _size : 30; | 249 size_t _size : 32; |
252 size_t _level : 2; | |
253 size_t _flags : 8; | 250 size_t _flags : 8; |
254 size_t _pos_idx : 8; | 251 size_t _pos_idx : 8; |
255 size_t _bucket_idx: 16; | 252 size_t _bucket_idx: 16; |
256 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16)) | 253 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16)) |
257 #define MAX_BUCKET_LENGTH ((size_t)(1 << 8)) | 254 #define MAX_BUCKET_LENGTH ((size_t)(1 << 8)) |
258 // Max malloc size = 1GB - 1 on 32 bit system, such has total 4GB memory | |
259 #define MAX_MALLOC_SIZE ((size_t)(1 << 30) - 1) | |
260 #endif // _LP64 | 255 #endif // _LP64 |
261 | 256 |
262 public: | 257 public: |
263 // Summary tracking header | 258 MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) { |
264 MallocHeader(size_t size, MEMFLAGS flags) { | |
265 assert(sizeof(MallocHeader) == sizeof(void*) * 2, | 259 assert(sizeof(MallocHeader) == sizeof(void*) * 2, |
266 "Wrong header size"); | 260 "Wrong header size"); |
267 | 261 |
268 _level = NMT_summary; | 262 if (level == NMT_minimal) { |
263 return; | |
264 } | |
265 | |
269 _flags = flags; | 266 _flags = flags; |
270 set_size(size); | 267 set_size(size); |
268 if (level == NMT_detail) { | |
269 size_t bucket_idx; | |
270 size_t pos_idx; | |
271 if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { | |
272 assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); | |
273 assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); | |
274 _bucket_idx = bucket_idx; | |
275 _pos_idx = pos_idx; | |
276 } | |
277 } | |
278 | |
271 MallocMemorySummary::record_malloc(size, flags); | 279 MallocMemorySummary::record_malloc(size, flags); |
272 MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); | 280 MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); |
273 } | |
274 // Detail tracking header | |
275 MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack) { | |
276 assert(sizeof(MallocHeader) == sizeof(void*) * 2, | |
277 "Wrong header size"); | |
278 | |
279 _level = NMT_detail; | |
280 _flags = flags; | |
281 set_size(size); | |
282 size_t bucket_idx; | |
283 size_t pos_idx; | |
284 if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { | |
285 assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); | |
286 assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); | |
287 _bucket_idx = bucket_idx; | |
288 _pos_idx = pos_idx; | |
289 } | |
290 MallocMemorySummary::record_malloc(size, flags); | |
291 MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); | |
292 } | |
293 // Minimal tracking header | |
294 MallocHeader() { | |
295 assert(sizeof(MallocHeader) == sizeof(void*) * 2, | |
296 "Wrong header size"); | |
297 | |
298 _level = (unsigned short)NMT_minimal; | |
299 } | |
300 | |
301 inline NMT_TrackingLevel tracking_level() const { | |
302 return (NMT_TrackingLevel)_level; | |
303 } | 281 } |
304 | 282 |
305 inline size_t size() const { return _size; } | 283 inline size_t size() const { return _size; } |
306 inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; } | 284 inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; } |
307 bool get_stack(NativeCallStack& stack) const; | 285 bool get_stack(NativeCallStack& stack) const; |
309 // Cleanup tracking information before the memory is released. | 287 // Cleanup tracking information before the memory is released. |
310 void release() const; | 288 void release() const; |
311 | 289 |
312 private: | 290 private: |
313 inline void set_size(size_t size) { | 291 inline void set_size(size_t size) { |
314 assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?"); | |
315 _size = size; | 292 _size = size; |
316 } | 293 } |
317 bool record_malloc_site(const NativeCallStack& stack, size_t size, | 294 bool record_malloc_site(const NativeCallStack& stack, size_t size, |
318 size_t* bucket_idx, size_t* pos_idx) const; | 295 size_t* bucket_idx, size_t* pos_idx) const; |
319 }; | 296 }; |
345 const NativeCallStack& stack, NMT_TrackingLevel level); | 322 const NativeCallStack& stack, NMT_TrackingLevel level); |
346 | 323 |
347 // Record free on specified memory block | 324 // Record free on specified memory block |
348 static void* record_free(void* memblock); | 325 static void* record_free(void* memblock); |
349 | 326 |
350 // Get tracking level of specified memory block | |
351 static inline NMT_TrackingLevel get_memory_tracking_level(void* memblock); | |
352 | |
353 | |
354 // Offset memory address to header address | 327 // Offset memory address to header address |
355 static inline void* get_base(void* memblock); | 328 static inline void* get_base(void* memblock); |
356 static inline void* get_base(void* memblock, NMT_TrackingLevel level) { | 329 static inline void* get_base(void* memblock, NMT_TrackingLevel level) { |
357 if (memblock == NULL || level == NMT_off) return memblock; | 330 if (memblock == NULL || level == NMT_off) return memblock; |
358 return (char*)memblock - malloc_header_size(level); | 331 return (char*)memblock - malloc_header_size(level); |
359 } | 332 } |
360 | 333 |
361 // Get memory size | 334 // Get memory size |
362 static inline size_t get_size(void* memblock) { | 335 static inline size_t get_size(void* memblock) { |
363 MallocHeader* header = malloc_header(memblock); | 336 MallocHeader* header = malloc_header(memblock); |
364 assert(header->tracking_level() >= NMT_summary, | |
365 "Wrong tracking level"); | |
366 return header->size(); | 337 return header->size(); |
367 } | 338 } |
368 | 339 |
369 // Get memory type | 340 // Get memory type |
370 static inline MEMFLAGS get_flags(void* memblock) { | 341 static inline MEMFLAGS get_flags(void* memblock) { |
371 MallocHeader* header = malloc_header(memblock); | 342 MallocHeader* header = malloc_header(memblock); |
372 assert(header->tracking_level() >= NMT_summary, | |
373 "Wrong tracking level"); | |
374 return header->flags(); | 343 return header->flags(); |
375 } | 344 } |
376 | 345 |
377 // Get header size | 346 // Get header size |
378 static inline size_t get_header_size(void* memblock) { | 347 static inline size_t get_header_size(void* memblock) { |
392 } | 361 } |
393 private: | 362 private: |
394 static inline MallocHeader* malloc_header(void *memblock) { | 363 static inline MallocHeader* malloc_header(void *memblock) { |
395 assert(memblock != NULL, "NULL pointer"); | 364 assert(memblock != NULL, "NULL pointer"); |
396 MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); | 365 MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); |
397 assert(header->tracking_level() >= NMT_minimal, "Bad header"); | |
398 return header; | 366 return header; |
399 } | 367 } |
400 }; | 368 }; |
401 | 369 |
402 #endif // INCLUDE_NMT | 370 #endif // INCLUDE_NMT |