src/share/vm/services/memTracker.hpp

changeset 7074
833b0f92429a
parent 5578
4c84d351cca9
child 7078
c6211b707068
     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 +

mercurial