src/share/vm/services/memTracker.hpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/services/memTracker.hpp
src/share/vm/services/memTracker.hpp
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,7 ----
/*
! * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 52,61 ****
--- 52,71 ----
NMT_error_reporting, // shutdown by vmError::report_and_die()
NMT_out_of_generation, // running out of generation queue
NMT_sequence_overflow // overflow the sequence number
};
+ class Tracker {
+ public:
+ void discard() { }
+
+ void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL) { }
+ void record(address old_addr, address new_addr, size_t size,
+ MEMFLAGS flags, address pc = NULL) { }
+ };
+
+
public:
static inline void init_tracking_options(const char* option_line) { }
static inline bool is_on() { return false; }
static const char* reason() { return "Native memory tracking is not implemented"; }
*** 66,88 ****
static inline void start() { }
static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
address pc = 0, Thread* thread = NULL) { }
static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { }
- static inline void record_realloc(address old_addr, address new_addr, size_t size,
- MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
static inline void record_arena_size(address addr, size_t size) { }
static inline void record_virtual_memory_reserve(address addr, size_t size,
! address pc = 0, Thread* thread = NULL) { }
static inline void record_virtual_memory_commit(address addr, size_t size,
address pc = 0, Thread* thread = NULL) { }
- static inline void record_virtual_memory_uncommit(address addr, size_t size,
- Thread* thread = NULL) { }
- static inline void record_virtual_memory_release(address addr, size_t size,
- Thread* thread = NULL) { }
static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
Thread* thread = NULL) { }
static inline bool baseline() { return false; }
static inline bool has_baseline() { return false; }
static inline void set_autoShutdown(bool value) { }
static void shutdown(ShutdownReason reason) { }
--- 76,97 ----
static inline void start() { }
static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
address pc = 0, Thread* thread = NULL) { }
static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { }
static inline void record_arena_size(address addr, size_t size) { }
static inline void record_virtual_memory_reserve(address addr, size_t size,
! MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
! static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size,
! MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
static inline void record_virtual_memory_commit(address addr, size_t size,
address pc = 0, Thread* thread = NULL) { }
static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
Thread* thread = NULL) { }
+ static inline Tracker get_realloc_tracker() { return Tracker(); }
+ static inline Tracker get_virtual_memory_uncommit_tracker() { return Tracker(); }
+ static inline Tracker get_virtual_memory_release_tracker() { return Tracker(); }
static inline bool baseline() { return false; }
static inline bool has_baseline() { return false; }
static inline void set_autoShutdown(bool value) { }
static void shutdown(ShutdownReason reason) { }
*** 163,172 ****
--- 172,220 ----
NMT_final_shutdown, // in final phase of shutdown
NMT_shutdown // shutdown
};
public:
+ class Tracker : public StackObj {
+ friend class MemTracker;
+ public:
+ enum MemoryOperation {
+ NoOp, // no op
+ Malloc, // malloc
+ Realloc, // realloc
+ Free, // free
+ Reserve, // virtual memory reserve
+ Commit, // virtual memory commit
+ ReserveAndCommit, // virtual memory reserve and commit
+ StackAlloc = ReserveAndCommit, // allocate thread stack
+ Type, // assign virtual memory type
+ Uncommit, // virtual memory uncommit
+ Release, // virtual memory release
+ ArenaSize, // set arena size
+ StackRelease // release thread stack
+ };
+
+
+ protected:
+ Tracker(MemoryOperation op, Thread* thr = NULL);
+
+ public:
+ void discard();
+
+ void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL);
+ void record(address old_addr, address new_addr, size_t size,
+ MEMFLAGS flags, address pc = NULL);
+
+ private:
+ bool _need_thread_critical_lock;
+ JavaThread* _java_thread;
+ MemoryOperation _op; // memory operation
+ jint _seq; // reserved sequence number
+ };
+
+
+ public:
// native memory tracking level
enum NMTLevel {
NMT_off, // native memory tracking is off
NMT_summary, // don't track callsite
NMT_detail // track callsite also
*** 274,386 ****
static void start();
// record a 'malloc' call
static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
address pc = 0, Thread* thread = NULL) {
! if (is_on() && NMT_CAN_TRACK(flags)) {
! assert(size > 0, "Sanity check");
! create_memory_record(addr, (flags|MemPointerRecord::malloc_tag()), size, pc, thread);
! }
}
// record a 'free' call
static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) {
! if (is_on() && NMT_CAN_TRACK(flags)) {
! create_memory_record(addr, MemPointerRecord::free_tag(), 0, 0, thread);
! }
! }
! // record a 'realloc' call
! static inline void record_realloc(address old_addr, address new_addr, size_t size,
! MEMFLAGS flags, address pc = 0, Thread* thread = NULL) {
! if (is_on() && NMT_CAN_TRACK(flags)) {
! assert(size > 0, "Sanity check");
! record_free(old_addr, flags, thread);
! record_malloc(new_addr, size, flags, pc, thread);
! }
}
- // record arena memory size
static inline void record_arena_size(address addr, size_t size) {
! // we add a positive offset to arena address, so we can have arena memory record
! // sorted after arena record
! if (is_on() && !UseMallocOnly) {
! assert(addr != NULL, "Sanity check");
! create_memory_record((addr + sizeof(void*)), MemPointerRecord::arena_size_tag(), size,
! DEBUG_CALLER_PC, NULL);
! }
}
// record a virtual memory 'reserve' call
static inline void record_virtual_memory_reserve(address addr, size_t size,
! address pc = 0, Thread* thread = NULL) {
! if (is_on()) {
assert(size > 0, "Sanity check");
! create_memory_record(addr, MemPointerRecord::virtual_memory_reserve_tag(),
! size, pc, thread);
! }
}
static inline void record_thread_stack(address addr, size_t size, Thread* thr,
address pc = 0) {
! if (is_on()) {
! assert(size > 0 && thr != NULL, "Sanity check");
! create_memory_record(addr, MemPointerRecord::virtual_memory_reserve_tag() | mtThreadStack,
! size, pc, thr);
! create_memory_record(addr, MemPointerRecord::virtual_memory_commit_tag() | mtThreadStack,
! size, pc, thr);
! }
}
static inline void release_thread_stack(address addr, size_t size, Thread* thr) {
! if (is_on()) {
! assert(size > 0 && thr != NULL, "Sanity check");
! assert(!thr->is_Java_thread(), "too early");
! create_memory_record(addr, MemPointerRecord::virtual_memory_uncommit_tag() | mtThreadStack,
! size, DEBUG_CALLER_PC, thr);
! create_memory_record(addr, MemPointerRecord::virtual_memory_release_tag() | mtThreadStack,
! size, DEBUG_CALLER_PC, thr);
! }
}
// record a virtual memory 'commit' call
static inline void record_virtual_memory_commit(address addr, size_t size,
address pc, Thread* thread = NULL) {
! if (is_on()) {
! assert(size > 0, "Sanity check");
! create_memory_record(addr, MemPointerRecord::virtual_memory_commit_tag(),
! size, pc, thread);
! }
}
! // record a virtual memory 'uncommit' call
! static inline void record_virtual_memory_uncommit(address addr, size_t size,
! Thread* thread = NULL) {
! if (is_on()) {
! assert(size > 0, "Sanity check");
! create_memory_record(addr, MemPointerRecord::virtual_memory_uncommit_tag(),
! size, DEBUG_CALLER_PC, thread);
! }
}
- // record a virtual memory 'release' call
- static inline void record_virtual_memory_release(address addr, size_t size,
- Thread* thread = NULL) {
- if (is_on()) {
- assert(size > 0, "Sanity check");
- create_memory_record(addr, MemPointerRecord::virtual_memory_release_tag(),
- size, DEBUG_CALLER_PC, thread);
- }
- }
// record memory type on virtual memory base address
static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
Thread* thread = NULL) {
! if (is_on()) {
! assert(base > 0, "wrong base address");
! assert((flags & (~mt_masks)) == 0, "memory type only");
! create_memory_record(base, (flags | MemPointerRecord::virtual_memory_type_tag()),
! 0, DEBUG_CALLER_PC, thread);
}
}
// create memory baseline of current memory snapshot
static bool baseline();
--- 322,399 ----
static void start();
// record a 'malloc' call
static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
address pc = 0, Thread* thread = NULL) {
! Tracker tkr(Tracker::Malloc, thread);
! tkr.record(addr, size, flags, pc);
}
// record a 'free' call
static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) {
! Tracker tkr(Tracker::Free, thread);
! tkr.record(addr, 0, flags, DEBUG_CALLER_PC);
}
static inline void record_arena_size(address addr, size_t size) {
! Tracker tkr(Tracker::ArenaSize);
! tkr.record(addr, size);
}
// record a virtual memory 'reserve' call
static inline void record_virtual_memory_reserve(address addr, size_t size,
! MEMFLAGS flags, address pc = 0, Thread* thread = NULL) {
assert(size > 0, "Sanity check");
! Tracker tkr(Tracker::Reserve, thread);
! tkr.record(addr, size, flags, pc);
}
static inline void record_thread_stack(address addr, size_t size, Thread* thr,
address pc = 0) {
! Tracker tkr(Tracker::StackAlloc, thr);
! tkr.record(addr, size, mtThreadStack, pc);
}
static inline void release_thread_stack(address addr, size_t size, Thread* thr) {
! Tracker tkr(Tracker::StackRelease, thr);
! tkr.record(addr, size, mtThreadStack, DEBUG_CALLER_PC);
}
// record a virtual memory 'commit' call
static inline void record_virtual_memory_commit(address addr, size_t size,
address pc, Thread* thread = NULL) {
! Tracker tkr(Tracker::Commit, thread);
! tkr.record(addr, size, mtNone, pc);
}
! static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size,
! MEMFLAGS flags, address pc, Thread* thread = NULL) {
! Tracker tkr(Tracker::ReserveAndCommit, thread);
! tkr.record(addr, size, flags, pc);
}
// record memory type on virtual memory base address
static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
Thread* thread = NULL) {
! Tracker tkr(Tracker::Type);
! tkr.record(base, 0, flags);
! }
!
! // Get memory trackers for memory operations that can result race conditions.
! // The memory tracker has to be obtained before realloc, virtual memory uncommit
! // and virtual memory release, and call tracker.record() method if operation
! // succeeded, or tracker.discard() to abort the tracking.
! static inline Tracker get_realloc_tracker() {
! return Tracker(Tracker::Realloc);
! }
!
! static inline Tracker get_virtual_memory_uncommit_tracker() {
! return Tracker(Tracker::Uncommit);
}
+
+ static inline Tracker get_virtual_memory_release_tracker() {
+ return Tracker(Tracker::Release);
}
// create memory baseline of current memory snapshot
static bool baseline();
*** 442,451 ****
--- 455,489 ----
// when they are overflowed or collected at nmt sync point.
static void enqueue_pending_recorder(MemRecorder* rec);
static MemRecorder* get_pending_recorders();
static void delete_all_pending_recorders();
+ // write a memory tracking record in recorder
+ static void write_tracking_record(address addr, MEMFLAGS type,
+ size_t size, jint seq, address pc, JavaThread* thread);
+
+ static bool is_single_threaded_bootstrap() {
+ return _state == NMT_bootstrapping_single_thread;
+ }
+
+ static void check_NMT_load(Thread* thr) {
+ assert(thr != NULL, "Sanity check");
+ if (_slowdown_calling_thread && thr != _worker_thread) {
+ os::yield_all();
+ }
+ }
+
+ static void inc_pending_op_count() {
+ Atomic::inc(&_pending_op_count);
+ }
+
+ static void dec_pending_op_count() {
+ Atomic::dec(&_pending_op_count);
+ assert(_pending_op_count >= 0, "Sanity check");
+ }
+
+
private:
// retrieve a pooled memory record or create new one if there is not
// one available
static MemRecorder* get_new_or_pooled_instance();
static void create_memory_record(address addr, MEMFLAGS type,
*** 520,529 ****
--- 558,573 ----
static volatile bool _worker_thread_idle;
// if NMT should slow down calling thread to allow
// worker thread to catch up
static volatile bool _slowdown_calling_thread;
+
+ // pending memory op count.
+ // Certain memory ops need to pre-reserve sequence number
+ // before memory operation can happen to avoid race condition.
+ // See MemTracker::Tracker for detail
+ static volatile jint _pending_op_count;
};
#endif // !INCLUDE_NMT
#endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP
src/share/vm/services/memTracker.hpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File