222
223 // The memory used by malloc tracking headers
224 static inline size_t tracking_overhead() {
225 return as_snapshot()->malloc_overhead()->size();
226 }
227
228 static MallocMemorySnapshot* as_snapshot() {
229 return (MallocMemorySnapshot*)_snapshot;
230 }
231 };
232
233
234 /*
235 * Malloc tracking header.
236 * To satisfy malloc alignment requirement, NMT uses 2 machine words for tracking purpose,
237 * which ensures 8-bytes alignment on 32-bit systems and 16-bytes on 64-bit systems (Product build).
238 */
239
240 class MallocHeader VALUE_OBJ_CLASS_SPEC {
241 #ifdef _LP64
242 size_t _size : 62;
243 size_t _level : 2;
244 size_t _flags : 8;
245 size_t _pos_idx : 16;
246 size_t _bucket_idx: 40;
247 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40)
248 #define MAX_BUCKET_LENGTH ((size_t)(1 << 16))
249 #define MAX_MALLOC_SIZE (((size_t)1 << 62) - 1)
250 #else
251 size_t _size : 30;
252 size_t _level : 2;
253 size_t _flags : 8;
254 size_t _pos_idx : 8;
255 size_t _bucket_idx: 16;
256 #define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16))
257 #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
261
262 public:
263 // Summary tracking header
264 MallocHeader(size_t size, MEMFLAGS flags) {
265 assert(sizeof(MallocHeader) == sizeof(void*) * 2,
266 "Wrong header size");
267
268 _level = NMT_summary;
269 _flags = flags;
270 set_size(size);
271 MallocMemorySummary::record_malloc(size, flags);
272 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 }
304
305 inline size_t size() const { return _size; }
306 inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; }
307 bool get_stack(NativeCallStack& stack) const;
308
309 // Cleanup tracking information before the memory is released.
310 void release() const;
311
312 private:
313 inline void set_size(size_t size) {
314 assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?");
315 _size = size;
316 }
317 bool record_malloc_site(const NativeCallStack& stack, size_t size,
318 size_t* bucket_idx, size_t* pos_idx) const;
319 };
320
321
322 // Main class called from MemTracker to track malloc activities
323 class MallocTracker : AllStatic {
324 public:
325 // Initialize malloc tracker for specific tracking level
326 static bool initialize(NMT_TrackingLevel level);
327
328 static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
329
330 // malloc tracking header size for specific tracking level
331 static inline size_t malloc_header_size(NMT_TrackingLevel level) {
332 return (level == NMT_off) ? 0 : sizeof(MallocHeader);
333 }
334
335 // Parameter name convention:
336 // memblock : the beginning address for user data
337 // malloc_base: the beginning address that includes malloc tracking header
338 //
339 // The relationship:
340 // memblock = (char*)malloc_base + sizeof(nmt header)
341 //
342
343 // Record malloc on specified memory block
344 static void* record_malloc(void* malloc_base, size_t size, MEMFLAGS flags,
345 const NativeCallStack& stack, NMT_TrackingLevel level);
346
347 // Record free on specified memory block
348 static void* record_free(void* memblock);
349
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
355 static inline void* get_base(void* memblock);
356 static inline void* get_base(void* memblock, NMT_TrackingLevel level) {
357 if (memblock == NULL || level == NMT_off) return memblock;
358 return (char*)memblock - malloc_header_size(level);
359 }
360
361 // Get memory size
362 static inline size_t get_size(void* memblock) {
363 MallocHeader* header = malloc_header(memblock);
364 assert(header->tracking_level() >= NMT_summary,
365 "Wrong tracking level");
366 return header->size();
367 }
368
369 // Get memory type
370 static inline MEMFLAGS get_flags(void* memblock) {
371 MallocHeader* header = malloc_header(memblock);
372 assert(header->tracking_level() >= NMT_summary,
373 "Wrong tracking level");
374 return header->flags();
375 }
376
377 // Get header size
378 static inline size_t get_header_size(void* memblock) {
379 return (memblock == NULL) ? 0 : sizeof(MallocHeader);
380 }
381
382 static inline void record_new_arena(MEMFLAGS flags) {
383 MallocMemorySummary::record_new_arena(flags);
384 }
385
386 static inline void record_arena_free(MEMFLAGS flags) {
387 MallocMemorySummary::record_arena_free(flags);
388 }
389
390 static inline void record_arena_size_change(int size, MEMFLAGS flags) {
391 MallocMemorySummary::record_arena_size_change(size, flags);
392 }
393 private:
394 static inline MallocHeader* malloc_header(void *memblock) {
395 assert(memblock != NULL, "NULL pointer");
396 MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader));
397 assert(header->tracking_level() >= NMT_minimal, "Bad header");
398 return header;
399 }
400 };
401
402 #endif // INCLUDE_NMT
403
404
405 #endif //SHARE_VM_SERVICES_MALLOC_TRACKER_HPP
|
222
223 // The memory used by malloc tracking headers
224 static inline size_t tracking_overhead() {
225 return as_snapshot()->malloc_overhead()->size();
226 }
227
228 static MallocMemorySnapshot* as_snapshot() {
229 return (MallocMemorySnapshot*)_snapshot;
230 }
231 };
232
233
234 /*
235 * Malloc tracking header.
236 * To satisfy malloc alignment requirement, NMT uses 2 machine words for tracking purpose,
237 * which ensures 8-bytes alignment on 32-bit systems and 16-bytes on 64-bit systems (Product build).
238 */
239
240 class MallocHeader VALUE_OBJ_CLASS_SPEC {
241 #ifdef _LP64
242 size_t _size : 64;
243 size_t _flags : 8;
244 size_t _pos_idx : 16;
245 size_t _bucket_idx: 40;
246 #define MAX_MALLOCSITE_TABLE_SIZE right_n_bits(40)
247 #define MAX_BUCKET_LENGTH right_n_bits(16)
248 #else
249 size_t _size : 32;
250 size_t _flags : 8;
251 size_t _pos_idx : 8;
252 size_t _bucket_idx: 16;
253 #define MAX_MALLOCSITE_TABLE_SIZE right_n_bits(16)
254 #define MAX_BUCKET_LENGTH right_n_bits(8)
255 #endif // _LP64
256
257 public:
258 MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) {
259 assert(sizeof(MallocHeader) == sizeof(void*) * 2,
260 "Wrong header size");
261
262 if (level == NMT_minimal) {
263 return;
264 }
265
266 _flags = flags;
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
279 MallocMemorySummary::record_malloc(size, flags);
280 MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader));
281 }
282
283 inline size_t size() const { return _size; }
284 inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; }
285 bool get_stack(NativeCallStack& stack) const;
286
287 // Cleanup tracking information before the memory is released.
288 void release() const;
289
290 private:
291 inline void set_size(size_t size) {
292 _size = size;
293 }
294 bool record_malloc_site(const NativeCallStack& stack, size_t size,
295 size_t* bucket_idx, size_t* pos_idx) const;
296 };
297
298
299 // Main class called from MemTracker to track malloc activities
300 class MallocTracker : AllStatic {
301 public:
302 // Initialize malloc tracker for specific tracking level
303 static bool initialize(NMT_TrackingLevel level);
304
305 static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
306
307 // malloc tracking header size for specific tracking level
308 static inline size_t malloc_header_size(NMT_TrackingLevel level) {
309 return (level == NMT_off) ? 0 : sizeof(MallocHeader);
310 }
311
312 // Parameter name convention:
313 // memblock : the beginning address for user data
314 // malloc_base: the beginning address that includes malloc tracking header
315 //
316 // The relationship:
317 // memblock = (char*)malloc_base + sizeof(nmt header)
318 //
319
320 // Record malloc on specified memory block
321 static void* record_malloc(void* malloc_base, size_t size, MEMFLAGS flags,
322 const NativeCallStack& stack, NMT_TrackingLevel level);
323
324 // Record free on specified memory block
325 static void* record_free(void* memblock);
326
327 // Offset memory address to header address
328 static inline void* get_base(void* memblock);
329 static inline void* get_base(void* memblock, NMT_TrackingLevel level) {
330 if (memblock == NULL || level == NMT_off) return memblock;
331 return (char*)memblock - malloc_header_size(level);
332 }
333
334 // Get memory size
335 static inline size_t get_size(void* memblock) {
336 MallocHeader* header = malloc_header(memblock);
337 return header->size();
338 }
339
340 // Get memory type
341 static inline MEMFLAGS get_flags(void* memblock) {
342 MallocHeader* header = malloc_header(memblock);
343 return header->flags();
344 }
345
346 // Get header size
347 static inline size_t get_header_size(void* memblock) {
348 return (memblock == NULL) ? 0 : sizeof(MallocHeader);
349 }
350
351 static inline void record_new_arena(MEMFLAGS flags) {
352 MallocMemorySummary::record_new_arena(flags);
353 }
354
355 static inline void record_arena_free(MEMFLAGS flags) {
356 MallocMemorySummary::record_arena_free(flags);
357 }
358
359 static inline void record_arena_size_change(int size, MEMFLAGS flags) {
360 MallocMemorySummary::record_arena_size_change(size, flags);
361 }
362 private:
363 static inline MallocHeader* malloc_header(void *memblock) {
364 assert(memblock != NULL, "NULL pointer");
365 MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader));
366 return header;
367 }
368 };
369
370 #endif // INCLUDE_NMT
371
372
373 #endif //SHARE_VM_SERVICES_MALLOC_TRACKER_HPP
|