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