src/share/vm/services/memTracker.hpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/services/memTracker.hpp Mon May 13 16:35:13 2013
--- new/src/share/vm/services/memTracker.hpp Mon May 13 16:35:12 2013
*** 1,7 ****
--- 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.
*** 63,88 ****
--- 63,72 ----
static inline void bootstrap_single_thread() { }
static inline void bootstrap_multi_thread() { }
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) { }
*** 96,109 ****
--- 80,122 ----
static inline void sync() { }
static inline void thread_exiting(JavaThread* thread) { }
};
+ class NMTTrackOp : public StackObj {
+
+ public:
+ enum NMTMemoryOps {
+ NoOp,
+ MallocOp,
+ ReallocOp,
+ FreeOp,
+ ReserveOp,
+ CommitOp,
+ ReserveAndCommitOp,
+ StackAlloc = ReserveAndCommitOp,
+ TypeOp,
+ UncommitOp,
+ ReleaseOp,
+ ArenaSizeOp,
+ StackReleaseOp
+ };
+
+ NMTTrackOp(NMTMemoryOps op, Thread* thr = NULL) { }
+ ~NMTTrackOp() { }
+
+ void abort_op() { }
+
+ void execute_op(address addr, size_t size = 0, MEMFLAGS flags = 0, address pc = NULL) { }
+ void execute_op(address old_addr, address new_addr, size_t size,
+ MEMFLAGS flags, address pc = NULL) { }
+ };
#else // !INCLUDE_NMT
#include "memory/allocation.hpp"
+ #include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
#include "runtime/mutex.hpp"
#include "runtime/os.hpp"
#include "runtime/thread.hpp"
#include "services/memPtr.hpp"
*** 141,158 ****
--- 154,173 ----
};
class BaselineOutputer;
class MemSnapshot;
class MemTrackWorker;
+ class NMTTrackOp;
class Thread;
/*
* MemTracker is the 'gate' class to native memory tracking runtime.
*/
class MemTracker : AllStatic {
friend class GenerationData;
friend class MemTrackWorker;
friend class MemSnapshot;
+ friend class NMTTrackOp;
friend class SyncThreadRecorderClosure;
// NMT state
enum NMTStates {
NMT_uninited, // not yet initialized
*** 271,389 ****
--- 286,295 ----
// start() has to be called when VM still in single thread mode, but after
// command line option parsing is done.
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();
// is there a memory baseline
static bool has_baseline() {
return _baseline.baselined();
*** 442,459 ****
--- 348,382 ----
// 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,
size_t size, address pc, Thread* thread);
static void create_record_in_recorder(address addr, MEMFLAGS type,
size_t size, address pc, JavaThread* thread);
static void set_current_processing_generation(unsigned long generation) {
_worker_thread_idle = false;
_processing_generation = generation;
}
*** 517,529 ****
--- 440,504 ----
static volatile unsigned long _processing_generation;
// although NMT is still procesing current generation, but
// there is not more recorder to process, set idle state
static volatile bool _worker_thread_idle;
+ // pending memory op count.
+ // Certain memory ops need to pre-reserve sequence number
+ // before memory operation can happen to avoid race condition.
+ // See NMTTrackOp for detail
+ static volatile jint _pending_op_count;
+
// if NMT should slow down calling thread to allow
// worker thread to catch up
static volatile bool _slowdown_calling_thread;
};
+ /*
+ * This class intercepts memory operations, and this class has
+ * to be instantiated before the memory operations.
+ * It also decides if it has to a pre-reserve sequence number
+ * ahead of the memory operation. If so, it reserves a sequence
+ * number and increments MemTracker::_pending_op_count to prevent
+ * NMT from reaching NMT sync point.
+ *
+ */
+ class NMTTrackOp : public StackObj {
+
+ public:
+ enum NMTMemoryOps {
+ NoOp, // no op
+ MallocOp, // malloc
+ ReallocOp, // realloc
+ FreeOp, // free
+ ReserveOp, // virtual memory reserve
+ CommitOp, // virtual memory commit
+ ReserveAndCommitOp, // virtual memory reserve and commit
+ StackAllocOp = ReserveAndCommitOp, // allocate thread stack
+ TypeOp, // assign virtual memory type
+ UncommitOp, // virtual memory uncommit
+ ReleaseOp, // virtual memory release
+ ArenaSizeOp, // set arena size
+ StackReleaseOp // release thread stack
+ };
+
+ NMTTrackOp(NMTMemoryOps op, Thread* thr = NULL);
+ ~NMTTrackOp() { }
+
+ // abort this tracking op
+ void abort_op();
+
+ // execute this tracking op
+ void execute_op(address addr, size_t size = 0, MEMFLAGS flags = 0, address pc = NULL);
+ void execute_op(address old_addr, address new_addr, size_t size, MEMFLAGS flags, address pc = NULL);
+
+ private:
+
+ bool _need_thread_critical_lock;
+ JavaThread* _java_thread;
+ NMTMemoryOps _op;
+ jint _seq; // reserved sequence number
+ };
+
#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