1.1 --- a/src/share/vm/services/memTracker.hpp Wed Aug 27 09:36:55 2014 +0200 1.2 +++ b/src/share/vm/services/memTracker.hpp Wed Aug 27 08:19:12 2014 -0400 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -25,574 +25,289 @@ 1.11 #ifndef SHARE_VM_SERVICES_MEM_TRACKER_HPP 1.12 #define SHARE_VM_SERVICES_MEM_TRACKER_HPP 1.13 1.14 -#include "utilities/macros.hpp" 1.15 +#include "services/nmtCommon.hpp" 1.16 + 1.17 +class NativeCallStack; 1.18 +extern NativeCallStack emptyStack; 1.19 1.20 #if !INCLUDE_NMT 1.21 1.22 -#include "utilities/ostream.hpp" 1.23 +#define CURRENT_PC emptyStack 1.24 +#define CALLER_PC emptyStack 1.25 1.26 -class BaselineOutputer : public StackObj { 1.27 - 1.28 -}; 1.29 - 1.30 -class BaselineTTYOutputer : public BaselineOutputer { 1.31 - public: 1.32 - BaselineTTYOutputer(outputStream* st) { } 1.33 +class Tracker : public StackObj { 1.34 + public: 1.35 + Tracker() { } 1.36 + void record(address addr, size_t size) { } 1.37 }; 1.38 1.39 class MemTracker : AllStatic { 1.40 - public: 1.41 - enum ShutdownReason { 1.42 - NMT_shutdown_none, // no shutdown requested 1.43 - NMT_shutdown_user, // user requested shutdown 1.44 - NMT_normal, // normal shutdown, process exit 1.45 - NMT_out_of_memory, // shutdown due to out of memory 1.46 - NMT_initialization, // shutdown due to initialization failure 1.47 - NMT_use_malloc_only, // can not combine NMT with UseMallocOnly flag 1.48 - NMT_error_reporting, // shutdown by vmError::report_and_die() 1.49 - NMT_out_of_generation, // running out of generation queue 1.50 - NMT_sequence_overflow // overflow the sequence number 1.51 - }; 1.52 + public: 1.53 + static inline NMT_TrackingLevel tracking_level() { return NMT_off; } 1.54 + static inline void shutdown() { } 1.55 + static inline void init() { } 1.56 + static bool check_launcher_nmt_support(const char* value) { return true; } 1.57 + static bool verify_nmt_option() { return true; } 1.58 1.59 - class Tracker { 1.60 - public: 1.61 - void discard() { } 1.62 + static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag, 1.63 + const NativeCallStack& stack, NMT_TrackingLevel level) { return mem_base; } 1.64 + static inline size_t malloc_header_size(NMT_TrackingLevel level) { return 0; } 1.65 + static inline size_t malloc_header_size(void* memblock) { return 0; } 1.66 + static inline void* malloc_base(void* memblock) { return memblock; } 1.67 + static inline void* record_free(void* memblock) { return memblock; } 1.68 1.69 - void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL) { } 1.70 - void record(address old_addr, address new_addr, size_t size, 1.71 - MEMFLAGS flags, address pc = NULL) { } 1.72 - }; 1.73 + static inline void record_new_arena(MEMFLAGS flag) { } 1.74 + static inline void record_arena_free(MEMFLAGS flag) { } 1.75 + static inline void record_arena_size_change(int diff, MEMFLAGS flag) { } 1.76 + static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, 1.77 + MEMFLAGS flag = mtNone) { } 1.78 + static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, 1.79 + const NativeCallStack& stack, MEMFLAGS flag = mtNone) { } 1.80 + static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { } 1.81 + static inline Tracker get_virtual_memory_uncommit_tracker() { return Tracker(); } 1.82 + static inline Tracker get_virtual_memory_release_tracker() { } 1.83 + static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { } 1.84 + static inline void record_thread_stack(void* addr, size_t size) { } 1.85 + static inline void release_thread_stack(void* addr, size_t size) { } 1.86 1.87 - private: 1.88 - static Tracker _tkr; 1.89 - 1.90 - 1.91 - public: 1.92 - static inline void init_tracking_options(const char* option_line) { } 1.93 - static inline bool is_on() { return false; } 1.94 - static const char* reason() { return "Native memory tracking is not implemented"; } 1.95 - static inline bool can_walk_stack() { return false; } 1.96 - 1.97 - static inline void bootstrap_single_thread() { } 1.98 - static inline void bootstrap_multi_thread() { } 1.99 - static inline void start() { } 1.100 - 1.101 - static inline void record_malloc(address addr, size_t size, MEMFLAGS flags, 1.102 - address pc = 0, Thread* thread = NULL) { } 1.103 - static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { } 1.104 - static inline void record_arena_size(address addr, size_t size) { } 1.105 - static inline void record_virtual_memory_reserve(address addr, size_t size, 1.106 - MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { } 1.107 - static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size, 1.108 - MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { } 1.109 - static inline void record_virtual_memory_commit(address addr, size_t size, 1.110 - address pc = 0, Thread* thread = NULL) { } 1.111 - static inline void record_virtual_memory_release(address addr, size_t size, 1.112 - Thread* thread = NULL) { } 1.113 - static inline void record_virtual_memory_type(address base, MEMFLAGS flags, 1.114 - Thread* thread = NULL) { } 1.115 - static inline Tracker get_realloc_tracker() { return _tkr; } 1.116 - static inline Tracker get_virtual_memory_uncommit_tracker() { return _tkr; } 1.117 - static inline Tracker get_virtual_memory_release_tracker() { return _tkr; } 1.118 - static inline bool baseline() { return false; } 1.119 - static inline bool has_baseline() { return false; } 1.120 - 1.121 - static inline void set_autoShutdown(bool value) { } 1.122 - static void shutdown(ShutdownReason reason) { } 1.123 - static inline bool shutdown_in_progress() { return false; } 1.124 - static bool print_memory_usage(BaselineOutputer& out, size_t unit, 1.125 - bool summary_only = true) { return false; } 1.126 - static bool compare_memory_usage(BaselineOutputer& out, size_t unit, 1.127 - bool summary_only = true) { return false; } 1.128 - 1.129 - static bool wbtest_wait_for_data_merge() { return false; } 1.130 - 1.131 - static inline void sync() { } 1.132 - static inline void thread_exiting(JavaThread* thread) { } 1.133 + static void final_report(outputStream*) { } 1.134 }; 1.135 1.136 +#else 1.137 1.138 -#else // !INCLUDE_NMT 1.139 +#include "runtime/atomic.hpp" 1.140 +#include "runtime/threadCritical.hpp" 1.141 +#include "services/mallocTracker.hpp" 1.142 +#include "services/virtualMemoryTracker.hpp" 1.143 1.144 -#include "memory/allocation.hpp" 1.145 -#include "runtime/globals.hpp" 1.146 -#include "runtime/mutex.hpp" 1.147 -#include "runtime/os.hpp" 1.148 -#include "runtime/thread.hpp" 1.149 -#include "services/memPtr.hpp" 1.150 -#include "services/memRecorder.hpp" 1.151 -#include "services/memSnapshot.hpp" 1.152 -#include "services/memTrackWorker.hpp" 1.153 +extern volatile bool NMT_stack_walkable; 1.154 1.155 -extern bool NMT_track_callsite; 1.156 +#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \ 1.157 + NativeCallStack(0, true) : emptyStack) 1.158 +#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \ 1.159 + NativeCallStack(1, true) : emptyStack) 1.160 1.161 -#ifndef MAX_UNSIGNED_LONG 1.162 -#define MAX_UNSIGNED_LONG (unsigned long)(-1) 1.163 -#endif 1.164 +class MemBaseline; 1.165 +class Mutex; 1.166 1.167 -#ifdef ASSERT 1.168 - #define DEBUG_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) 1.169 -#else 1.170 - #define DEBUG_CALLER_PC 0 1.171 -#endif 1.172 - 1.173 -// The thread closure walks threads to collect per-thread 1.174 -// memory recorders at NMT sync point 1.175 -class SyncThreadRecorderClosure : public ThreadClosure { 1.176 - private: 1.177 - int _thread_count; 1.178 - 1.179 +// Tracker is used for guarding 'release' semantics of virtual memory operation, to avoid 1.180 +// the other thread obtains and records the same region that is just 'released' by current 1.181 +// thread but before it can record the operation. 1.182 +class Tracker : public StackObj { 1.183 public: 1.184 - SyncThreadRecorderClosure() { 1.185 - _thread_count =0; 1.186 - } 1.187 - 1.188 - void do_thread(Thread* thread); 1.189 - int get_thread_count() const { 1.190 - return _thread_count; 1.191 - } 1.192 -}; 1.193 - 1.194 -class BaselineOutputer; 1.195 -class MemSnapshot; 1.196 -class MemTrackWorker; 1.197 -class Thread; 1.198 -/* 1.199 - * MemTracker is the 'gate' class to native memory tracking runtime. 1.200 - */ 1.201 -class MemTracker : AllStatic { 1.202 - friend class GenerationData; 1.203 - friend class MemTrackWorker; 1.204 - friend class MemSnapshot; 1.205 - friend class SyncThreadRecorderClosure; 1.206 - 1.207 - // NMT state 1.208 - enum NMTStates { 1.209 - NMT_uninited, // not yet initialized 1.210 - NMT_bootstrapping_single_thread, // bootstrapping, VM is in single thread mode 1.211 - NMT_bootstrapping_multi_thread, // bootstrapping, VM is about to enter multi-thread mode 1.212 - NMT_started, // NMT fully started 1.213 - NMT_shutdown_pending, // shutdown pending 1.214 - NMT_final_shutdown, // in final phase of shutdown 1.215 - NMT_shutdown // shutdown 1.216 + enum TrackerType { 1.217 + uncommit, 1.218 + release 1.219 }; 1.220 1.221 public: 1.222 - class Tracker : public StackObj { 1.223 - friend class MemTracker; 1.224 - public: 1.225 - enum MemoryOperation { 1.226 - NoOp, // no op 1.227 - Malloc, // malloc 1.228 - Realloc, // realloc 1.229 - Free, // free 1.230 - Reserve, // virtual memory reserve 1.231 - Commit, // virtual memory commit 1.232 - ReserveAndCommit, // virtual memory reserve and commit 1.233 - StackAlloc = ReserveAndCommit, // allocate thread stack 1.234 - Type, // assign virtual memory type 1.235 - Uncommit, // virtual memory uncommit 1.236 - Release, // virtual memory release 1.237 - ArenaSize, // set arena size 1.238 - StackRelease // release thread stack 1.239 - }; 1.240 + Tracker(enum TrackerType type) : _type(type) { } 1.241 + void record(address addr, size_t size); 1.242 + private: 1.243 + enum TrackerType _type; 1.244 + // Virtual memory tracking data structures are protected by ThreadCritical lock. 1.245 + ThreadCritical _tc; 1.246 +}; 1.247 1.248 - 1.249 - protected: 1.250 - Tracker(MemoryOperation op, Thread* thr = NULL); 1.251 - 1.252 - public: 1.253 - void discard(); 1.254 - 1.255 - void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL); 1.256 - void record(address old_addr, address new_addr, size_t size, 1.257 - MEMFLAGS flags, address pc = NULL); 1.258 - 1.259 - private: 1.260 - bool _need_thread_critical_lock; 1.261 - JavaThread* _java_thread; 1.262 - MemoryOperation _op; // memory operation 1.263 - jint _seq; // reserved sequence number 1.264 - }; 1.265 - 1.266 - 1.267 +class MemTracker : AllStatic { 1.268 public: 1.269 - // native memory tracking level 1.270 - enum NMTLevel { 1.271 - NMT_off, // native memory tracking is off 1.272 - NMT_summary, // don't track callsite 1.273 - NMT_detail // track callsite also 1.274 - }; 1.275 - 1.276 - enum ShutdownReason { 1.277 - NMT_shutdown_none, // no shutdown requested 1.278 - NMT_shutdown_user, // user requested shutdown 1.279 - NMT_normal, // normal shutdown, process exit 1.280 - NMT_out_of_memory, // shutdown due to out of memory 1.281 - NMT_initialization, // shutdown due to initialization failure 1.282 - NMT_use_malloc_only, // can not combine NMT with UseMallocOnly flag 1.283 - NMT_error_reporting, // shutdown by vmError::report_and_die() 1.284 - NMT_out_of_generation, // running out of generation queue 1.285 - NMT_sequence_overflow // overflow the sequence number 1.286 - }; 1.287 - 1.288 - public: 1.289 - // initialize NMT tracking level from command line options, called 1.290 - // from VM command line parsing code 1.291 - static void init_tracking_options(const char* option_line); 1.292 - 1.293 - // if NMT is enabled to record memory activities 1.294 - static inline bool is_on() { 1.295 - return (_tracking_level >= NMT_summary && 1.296 - _state >= NMT_bootstrapping_single_thread); 1.297 - } 1.298 - 1.299 - static inline enum NMTLevel tracking_level() { 1.300 + static inline NMT_TrackingLevel tracking_level() { 1.301 + if (_tracking_level == NMT_unknown) { 1.302 + // No fencing is needed here, since JVM is in single-threaded 1.303 + // mode. 1.304 + _tracking_level = init_tracking_level(); 1.305 + _cmdline_tracking_level = _tracking_level; 1.306 + } 1.307 return _tracking_level; 1.308 } 1.309 1.310 - // user readable reason for shutting down NMT 1.311 - static const char* reason() { 1.312 - switch(_reason) { 1.313 - case NMT_shutdown_none: 1.314 - return "Native memory tracking is not enabled"; 1.315 - case NMT_shutdown_user: 1.316 - return "Native memory tracking has been shutdown by user"; 1.317 - case NMT_normal: 1.318 - return "Native memory tracking has been shutdown due to process exiting"; 1.319 - case NMT_out_of_memory: 1.320 - return "Native memory tracking has been shutdown due to out of native memory"; 1.321 - case NMT_initialization: 1.322 - return "Native memory tracking failed to initialize"; 1.323 - case NMT_error_reporting: 1.324 - return "Native memory tracking has been shutdown due to error reporting"; 1.325 - case NMT_out_of_generation: 1.326 - return "Native memory tracking has been shutdown due to running out of generation buffer"; 1.327 - case NMT_sequence_overflow: 1.328 - return "Native memory tracking has been shutdown due to overflow the sequence number"; 1.329 - case NMT_use_malloc_only: 1.330 - return "Native memory tracking is not supported when UseMallocOnly is on"; 1.331 - default: 1.332 - ShouldNotReachHere(); 1.333 - return NULL; 1.334 + // A late initialization, for the stuff(s) can not be 1.335 + // done in init_tracking_level(), which can NOT malloc 1.336 + // any memory. 1.337 + static void init(); 1.338 + 1.339 + // Shutdown native memory tracking 1.340 + static void shutdown(); 1.341 + 1.342 + // Verify native memory tracking command line option. 1.343 + // This check allows JVM to detect if compatible launcher 1.344 + // is used. 1.345 + // If an incompatible launcher is used, NMT may not be 1.346 + // able to start, even it is enabled by command line option. 1.347 + // A warning message should be given if it is encountered. 1.348 + static bool check_launcher_nmt_support(const char* value); 1.349 + 1.350 + // This method checks native memory tracking environment 1.351 + // variable value passed by launcher. 1.352 + // Launcher only obligates to pass native memory tracking 1.353 + // option value, but not obligates to validate the value, 1.354 + // and launcher has option to discard native memory tracking 1.355 + // option from the command line once it sets up the environment 1.356 + // variable, so NMT has to catch the bad value here. 1.357 + static bool verify_nmt_option(); 1.358 + 1.359 + // Transition the tracking level to specified level 1.360 + static bool transition_to(NMT_TrackingLevel level); 1.361 + 1.362 + static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag, 1.363 + const NativeCallStack& stack, NMT_TrackingLevel level) { 1.364 + return MallocTracker::record_malloc(mem_base, size, flag, stack, level); 1.365 + } 1.366 + 1.367 + static inline size_t malloc_header_size(NMT_TrackingLevel level) { 1.368 + return MallocTracker::malloc_header_size(level); 1.369 + } 1.370 + 1.371 + static size_t malloc_header_size(void* memblock) { 1.372 + if (tracking_level() != NMT_off) { 1.373 + return MallocTracker::get_header_size(memblock); 1.374 + } 1.375 + return 0; 1.376 + } 1.377 + 1.378 + // To malloc base address, which is the starting address 1.379 + // of malloc tracking header if tracking is enabled. 1.380 + // Otherwise, it returns the same address. 1.381 + static void* malloc_base(void* memblock); 1.382 + 1.383 + // Record malloc free and return malloc base address 1.384 + static inline void* record_free(void* memblock) { 1.385 + return MallocTracker::record_free(memblock); 1.386 + } 1.387 + 1.388 + 1.389 + // Record creation of an arena 1.390 + static inline void record_new_arena(MEMFLAGS flag) { 1.391 + if (tracking_level() < NMT_summary) return; 1.392 + MallocTracker::record_new_arena(flag); 1.393 + } 1.394 + 1.395 + // Record destruction of an arena 1.396 + static inline void record_arena_free(MEMFLAGS flag) { 1.397 + if (tracking_level() < NMT_summary) return; 1.398 + MallocTracker::record_arena_free(flag); 1.399 + } 1.400 + 1.401 + // Record arena size change. Arena size is the size of all arena 1.402 + // chuncks that backing up the arena. 1.403 + static inline void record_arena_size_change(int diff, MEMFLAGS flag) { 1.404 + if (tracking_level() < NMT_summary) return; 1.405 + MallocTracker::record_arena_size_change(diff, flag); 1.406 + } 1.407 + 1.408 + static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, 1.409 + MEMFLAGS flag = mtNone) { 1.410 + if (tracking_level() < NMT_summary) return; 1.411 + if (addr != NULL) { 1.412 + ThreadCritical tc; 1.413 + // Recheck to avoid potential racing during NMT shutdown 1.414 + if (tracking_level() < NMT_summary) return; 1.415 + VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag); 1.416 } 1.417 } 1.418 1.419 - // test if we can walk native stack 1.420 - static bool can_walk_stack() { 1.421 - // native stack is not walkable during bootstrapping on sparc 1.422 -#if defined(SPARC) 1.423 - return (_state == NMT_started); 1.424 -#else 1.425 - return (_state >= NMT_bootstrapping_single_thread && _state <= NMT_started); 1.426 -#endif 1.427 - } 1.428 - 1.429 - // if native memory tracking tracks callsite 1.430 - static inline bool track_callsite() { return _tracking_level == NMT_detail; } 1.431 - 1.432 - // NMT automatically shuts itself down under extreme situation by default. 1.433 - // When the value is set to false, NMT will try its best to stay alive, 1.434 - // even it has to slow down VM. 1.435 - static inline void set_autoShutdown(bool value) { 1.436 - AutoShutdownNMT = value; 1.437 - if (AutoShutdownNMT && _slowdown_calling_thread) { 1.438 - _slowdown_calling_thread = false; 1.439 + static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, 1.440 + const NativeCallStack& stack, MEMFLAGS flag = mtNone) { 1.441 + if (tracking_level() < NMT_summary) return; 1.442 + if (addr != NULL) { 1.443 + ThreadCritical tc; 1.444 + if (tracking_level() < NMT_summary) return; 1.445 + VirtualMemoryTracker::add_reserved_region((address)addr, size, 1.446 + stack, flag, true); 1.447 } 1.448 } 1.449 1.450 - // shutdown native memory tracking capability. Native memory tracking 1.451 - // can be shutdown by VM when it encounters low memory scenarios. 1.452 - // Memory tracker should gracefully shutdown itself, and preserve the 1.453 - // latest memory statistics for post morten diagnosis. 1.454 - static void shutdown(ShutdownReason reason); 1.455 - 1.456 - // if there is shutdown requested 1.457 - static inline bool shutdown_in_progress() { 1.458 - return (_state >= NMT_shutdown_pending); 1.459 - } 1.460 - 1.461 - // bootstrap native memory tracking, so it can start to collect raw data 1.462 - // before worker thread can start 1.463 - 1.464 - // the first phase of bootstrapping, when VM still in single-threaded mode 1.465 - static void bootstrap_single_thread(); 1.466 - // the second phase of bootstrapping, VM is about or already in multi-threaded mode 1.467 - static void bootstrap_multi_thread(); 1.468 - 1.469 - 1.470 - // start() has to be called when VM still in single thread mode, but after 1.471 - // command line option parsing is done. 1.472 - static void start(); 1.473 - 1.474 - // record a 'malloc' call 1.475 - static inline void record_malloc(address addr, size_t size, MEMFLAGS flags, 1.476 - address pc = 0, Thread* thread = NULL) { 1.477 - Tracker tkr(Tracker::Malloc, thread); 1.478 - tkr.record(addr, size, flags, pc); 1.479 - } 1.480 - // record a 'free' call 1.481 - static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { 1.482 - Tracker tkr(Tracker::Free, thread); 1.483 - tkr.record(addr, 0, flags, DEBUG_CALLER_PC); 1.484 - } 1.485 - 1.486 - static inline void record_arena_size(address addr, size_t size) { 1.487 - Tracker tkr(Tracker::ArenaSize); 1.488 - tkr.record(addr, size); 1.489 - } 1.490 - 1.491 - // record a virtual memory 'reserve' call 1.492 - static inline void record_virtual_memory_reserve(address addr, size_t size, 1.493 - MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { 1.494 - assert(size > 0, "Sanity check"); 1.495 - Tracker tkr(Tracker::Reserve, thread); 1.496 - tkr.record(addr, size, flags, pc); 1.497 - } 1.498 - 1.499 - static inline void record_thread_stack(address addr, size_t size, Thread* thr, 1.500 - address pc = 0) { 1.501 - Tracker tkr(Tracker::StackAlloc, thr); 1.502 - tkr.record(addr, size, mtThreadStack, pc); 1.503 - } 1.504 - 1.505 - static inline void release_thread_stack(address addr, size_t size, Thread* thr) { 1.506 - Tracker tkr(Tracker::StackRelease, thr); 1.507 - tkr.record(addr, size, mtThreadStack, DEBUG_CALLER_PC); 1.508 - } 1.509 - 1.510 - // record a virtual memory 'commit' call 1.511 - static inline void record_virtual_memory_commit(address addr, size_t size, 1.512 - address pc, Thread* thread = NULL) { 1.513 - Tracker tkr(Tracker::Commit, thread); 1.514 - tkr.record(addr, size, mtNone, pc); 1.515 - } 1.516 - 1.517 - static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size, 1.518 - MEMFLAGS flags, address pc, Thread* thread = NULL) { 1.519 - Tracker tkr(Tracker::ReserveAndCommit, thread); 1.520 - tkr.record(addr, size, flags, pc); 1.521 - } 1.522 - 1.523 - static inline void record_virtual_memory_release(address addr, size_t size, 1.524 - Thread* thread = NULL) { 1.525 - if (is_on()) { 1.526 - Tracker tkr(Tracker::Release, thread); 1.527 - tkr.record(addr, size); 1.528 + static inline void record_virtual_memory_commit(void* addr, size_t size, 1.529 + const NativeCallStack& stack) { 1.530 + if (tracking_level() < NMT_summary) return; 1.531 + if (addr != NULL) { 1.532 + ThreadCritical tc; 1.533 + if (tracking_level() < NMT_summary) return; 1.534 + VirtualMemoryTracker::add_committed_region((address)addr, size, stack); 1.535 } 1.536 } 1.537 1.538 - // record memory type on virtual memory base address 1.539 - static inline void record_virtual_memory_type(address base, MEMFLAGS flags, 1.540 - Thread* thread = NULL) { 1.541 - Tracker tkr(Tracker::Type); 1.542 - tkr.record(base, 0, flags); 1.543 - } 1.544 - 1.545 - // Get memory trackers for memory operations that can result race conditions. 1.546 - // The memory tracker has to be obtained before realloc, virtual memory uncommit 1.547 - // and virtual memory release, and call tracker.record() method if operation 1.548 - // succeeded, or tracker.discard() to abort the tracking. 1.549 - static inline Tracker get_realloc_tracker() { 1.550 - return Tracker(Tracker::Realloc); 1.551 - } 1.552 - 1.553 static inline Tracker get_virtual_memory_uncommit_tracker() { 1.554 - return Tracker(Tracker::Uncommit); 1.555 + assert(tracking_level() >= NMT_summary, "Check by caller"); 1.556 + return Tracker(Tracker::uncommit); 1.557 } 1.558 1.559 static inline Tracker get_virtual_memory_release_tracker() { 1.560 - return Tracker(Tracker::Release); 1.561 + assert(tracking_level() >= NMT_summary, "Check by caller"); 1.562 + return Tracker(Tracker::release); 1.563 } 1.564 1.565 - 1.566 - // create memory baseline of current memory snapshot 1.567 - static bool baseline(); 1.568 - // is there a memory baseline 1.569 - static bool has_baseline() { 1.570 - return _baseline.baselined(); 1.571 - } 1.572 - 1.573 - // print memory usage from current snapshot 1.574 - static bool print_memory_usage(BaselineOutputer& out, size_t unit, 1.575 - bool summary_only = true); 1.576 - // compare memory usage between current snapshot and baseline 1.577 - static bool compare_memory_usage(BaselineOutputer& out, size_t unit, 1.578 - bool summary_only = true); 1.579 - 1.580 - // the version for whitebox testing support, it ensures that all memory 1.581 - // activities before this method call, are reflected in the snapshot 1.582 - // database. 1.583 - static bool wbtest_wait_for_data_merge(); 1.584 - 1.585 - // sync is called within global safepoint to synchronize nmt data 1.586 - static void sync(); 1.587 - 1.588 - // called when a thread is about to exit 1.589 - static void thread_exiting(JavaThread* thread); 1.590 - 1.591 - // retrieve global snapshot 1.592 - static MemSnapshot* get_snapshot() { 1.593 - if (shutdown_in_progress()) { 1.594 - return NULL; 1.595 - } 1.596 - return _snapshot; 1.597 - } 1.598 - 1.599 - // print tracker stats 1.600 - NOT_PRODUCT(static void print_tracker_stats(outputStream* st);) 1.601 - NOT_PRODUCT(static void walk_stack(int toSkip, char* buf, int len);) 1.602 - 1.603 - private: 1.604 - // start native memory tracking worker thread 1.605 - static bool start_worker(MemSnapshot* snapshot); 1.606 - 1.607 - // called by worker thread to complete shutdown process 1.608 - static void final_shutdown(); 1.609 - 1.610 - protected: 1.611 - // retrieve per-thread recorder of the specified thread. 1.612 - // if the recorder is full, it will be enqueued to overflow 1.613 - // queue, a new recorder is acquired from recorder pool or a 1.614 - // new instance is created. 1.615 - // when thread == NULL, it means global recorder 1.616 - static MemRecorder* get_thread_recorder(JavaThread* thread); 1.617 - 1.618 - // per-thread recorder pool 1.619 - static void release_thread_recorder(MemRecorder* rec); 1.620 - static void delete_all_pooled_recorders(); 1.621 - 1.622 - // pending recorder queue. Recorders are queued to pending queue 1.623 - // when they are overflowed or collected at nmt sync point. 1.624 - static void enqueue_pending_recorder(MemRecorder* rec); 1.625 - static MemRecorder* get_pending_recorders(); 1.626 - static void delete_all_pending_recorders(); 1.627 - 1.628 - // write a memory tracking record in recorder 1.629 - static void write_tracking_record(address addr, MEMFLAGS type, 1.630 - size_t size, jint seq, address pc, JavaThread* thread); 1.631 - 1.632 - static bool is_single_threaded_bootstrap() { 1.633 - return _state == NMT_bootstrapping_single_thread; 1.634 - } 1.635 - 1.636 - static void check_NMT_load(Thread* thr) { 1.637 - assert(thr != NULL, "Sanity check"); 1.638 - if (_slowdown_calling_thread && thr != _worker_thread) { 1.639 -#ifdef _WINDOWS 1.640 - // On Windows, os::NakedYield() does not work as well 1.641 - // as os::yield_all() 1.642 - os::yield_all(); 1.643 -#else 1.644 - // On Solaris, os::yield_all() depends on os::sleep() 1.645 - // which requires JavaTherad in _thread_in_vm state. 1.646 - // Transits thread to _thread_in_vm state can be dangerous 1.647 - // if caller holds lock, as it may deadlock with Threads_lock. 1.648 - // So use NaKedYield instead. 1.649 - // 1.650 - // Linux and BSD, NakedYield() and yield_all() implementations 1.651 - // are the same. 1.652 - os::NakedYield(); 1.653 -#endif 1.654 + static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { 1.655 + if (tracking_level() < NMT_summary) return; 1.656 + if (addr != NULL) { 1.657 + ThreadCritical tc; 1.658 + if (tracking_level() < NMT_summary) return; 1.659 + VirtualMemoryTracker::set_reserved_region_type((address)addr, flag); 1.660 } 1.661 } 1.662 1.663 - static void inc_pending_op_count() { 1.664 - Atomic::inc(&_pending_op_count); 1.665 + static inline void record_thread_stack(void* addr, size_t size) { 1.666 + if (tracking_level() < NMT_summary) return; 1.667 + if (addr != NULL) { 1.668 + // uses thread stack malloc slot for book keeping number of threads 1.669 + MallocMemorySummary::record_malloc(0, mtThreadStack); 1.670 + record_virtual_memory_reserve_and_commit(addr, size, CALLER_PC, mtThreadStack); 1.671 + } 1.672 } 1.673 1.674 - static void dec_pending_op_count() { 1.675 - Atomic::dec(&_pending_op_count); 1.676 - assert(_pending_op_count >= 0, "Sanity check"); 1.677 + static inline void release_thread_stack(void* addr, size_t size) { 1.678 + if (tracking_level() < NMT_summary) return; 1.679 + if (addr != NULL) { 1.680 + // uses thread stack malloc slot for book keeping number of threads 1.681 + MallocMemorySummary::record_free(0, mtThreadStack); 1.682 + ThreadCritical tc; 1.683 + if (tracking_level() < NMT_summary) return; 1.684 + VirtualMemoryTracker::remove_released_region((address)addr, size); 1.685 + } 1.686 } 1.687 1.688 + // Query lock is used to synchronize the access to tracking data. 1.689 + // So far, it is only used by JCmd query, but it may be used by 1.690 + // other tools. 1.691 + static inline Mutex* query_lock() { return _query_lock; } 1.692 + 1.693 + // Make a final report and shutdown. 1.694 + // This function generates summary report without creating snapshots, 1.695 + // to avoid additional memory allocation. It uses native memory summary 1.696 + // counters, and makes adjustment to them, once the adjustment is made, 1.697 + // the counters are no longer accurate. As the result, this function 1.698 + // should only be used for final reporting before shutting down. 1.699 + static void final_report(outputStream*); 1.700 + 1.701 + // Stored baseline 1.702 + static inline MemBaseline& get_baseline() { 1.703 + return _baseline; 1.704 + } 1.705 + 1.706 + static NMT_TrackingLevel cmdline_tracking_level() { 1.707 + return _cmdline_tracking_level; 1.708 + } 1.709 + 1.710 + static void tuning_statistics(outputStream* out); 1.711 1.712 private: 1.713 - // retrieve a pooled memory record or create new one if there is not 1.714 - // one available 1.715 - static MemRecorder* get_new_or_pooled_instance(); 1.716 - static void create_memory_record(address addr, MEMFLAGS type, 1.717 - size_t size, address pc, Thread* thread); 1.718 - static void create_record_in_recorder(address addr, MEMFLAGS type, 1.719 - size_t size, address pc, JavaThread* thread); 1.720 - 1.721 - static void set_current_processing_generation(unsigned long generation) { 1.722 - _worker_thread_idle = false; 1.723 - _processing_generation = generation; 1.724 - } 1.725 - 1.726 - static void report_worker_idle() { 1.727 - _worker_thread_idle = true; 1.728 - } 1.729 + static NMT_TrackingLevel init_tracking_level(); 1.730 1.731 private: 1.732 - // global memory snapshot 1.733 - static MemSnapshot* _snapshot; 1.734 - 1.735 - // a memory baseline of snapshot 1.736 + // Tracking level 1.737 + static volatile NMT_TrackingLevel _tracking_level; 1.738 + // If NMT option value passed by launcher through environment 1.739 + // variable is valid 1.740 + static bool _is_nmt_env_valid; 1.741 + // command line tracking level 1.742 + static NMT_TrackingLevel _cmdline_tracking_level; 1.743 + // Stored baseline 1.744 static MemBaseline _baseline; 1.745 - 1.746 - // query lock 1.747 + // Query lock 1.748 static Mutex* _query_lock; 1.749 - 1.750 - // a thread can start to allocate memory before it is attached 1.751 - // to VM 'Thread', those memory activities are recorded here. 1.752 - // ThreadCritical is required to guard this global recorder. 1.753 - static MemRecorder* volatile _global_recorder; 1.754 - 1.755 - // main thread id 1.756 - debug_only(static intx _main_thread_tid;) 1.757 - 1.758 - // pending recorders to be merged 1.759 - static MemRecorder* volatile _merge_pending_queue; 1.760 - 1.761 - NOT_PRODUCT(static volatile jint _pending_recorder_count;) 1.762 - 1.763 - // pooled memory recorders 1.764 - static MemRecorder* volatile _pooled_recorders; 1.765 - 1.766 - // memory recorder pool management, uses following 1.767 - // counter to determine if a released memory recorder 1.768 - // should be pooled 1.769 - 1.770 - // latest thread count 1.771 - static int _thread_count; 1.772 - // pooled recorder count 1.773 - static volatile jint _pooled_recorder_count; 1.774 - 1.775 - 1.776 - // worker thread to merge pending recorders into snapshot 1.777 - static MemTrackWorker* _worker_thread; 1.778 - 1.779 - // how many safepoints we skipped without entering sync point 1.780 - static int _sync_point_skip_count; 1.781 - 1.782 - // if the tracker is properly intialized 1.783 - static bool _is_tracker_ready; 1.784 - // tracking level (off, summary and detail) 1.785 - static enum NMTLevel _tracking_level; 1.786 - 1.787 - // current nmt state 1.788 - static volatile enum NMTStates _state; 1.789 - // the reason for shutting down nmt 1.790 - static enum ShutdownReason _reason; 1.791 - // the generation that NMT is processing 1.792 - static volatile unsigned long _processing_generation; 1.793 - // although NMT is still procesing current generation, but 1.794 - // there is not more recorder to process, set idle state 1.795 - static volatile bool _worker_thread_idle; 1.796 - 1.797 - // if NMT should slow down calling thread to allow 1.798 - // worker thread to catch up 1.799 - static volatile bool _slowdown_calling_thread; 1.800 - 1.801 - // pending memory op count. 1.802 - // Certain memory ops need to pre-reserve sequence number 1.803 - // before memory operation can happen to avoid race condition. 1.804 - // See MemTracker::Tracker for detail 1.805 - static volatile jint _pending_op_count; 1.806 }; 1.807 1.808 -#endif // !INCLUDE_NMT 1.809 +#endif // INCLUDE_NMT 1.810 1.811 #endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP 1.812 +