1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_SERVICES_MEM_PTR_HPP
  26 #define SHARE_VM_SERVICES_MEM_PTR_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "runtime/atomic.hpp"
  30 #include "runtime/os.hpp"
  31 #include "runtime/safepoint.hpp"
  32 
  33 /*
  34  * global sequence generator that generates sequence numbers to serialize
  35  * memory records.
  36  */
  37 class SequenceGenerator : AllStatic {
  38  public:
  39   static jint next();
  40 
  41   // peek last sequence number
  42   static jint peek() {
  43     return _seq_number;
  44   }
  45 
  46   // reset sequence number
  47   static void reset() {
  48     assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
  49     _seq_number = 1;
  50     DEBUG_ONLY(_generation ++;)
  51   };
  52 
  53   DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; })
  54   NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; })
  55 
  56  private:
  57   static volatile jint _seq_number;
  58   NOT_PRODUCT(static jint _max_seq_number; )
  59   DEBUG_ONLY(static volatile unsigned long _generation; )
  60 };
  61 
  62 /*
  63  * followings are the classes that are used to hold memory activity records in different stages.
  64  *   MemPointer
  65  *     |--------MemPointerRecord
  66  *                     |
  67  *                     |----MemPointerRecordEx
  68  *                     |           |
  69  *                     |           |-------SeqMemPointerRecordEx
  70  *                     |
  71  *                     |----SeqMemPointerRecord
  72  *                     |
  73  *                     |----VMMemRegion
  74  *                               |
  75  *                               |-----VMMemRegionEx
  76  *
  77  *
  78  *  prefix 'Seq' - sequenced, the record contains a sequence number
  79  *  surfix 'Ex'  - extension, the record contains a caller's pc
  80  *
  81  *  per-thread recorder : SeqMemPointerRecord(Ex)
  82  *  snapshot staging    : SeqMemPointerRecord(Ex)
  83  *  snapshot            : MemPointerRecord(Ex) and VMMemRegion(Ex)
  84  *
  85  */
  86 
  87 /*
  88  * class that wraps an address to a memory block,
  89  * the memory pointer either points to a malloc'd
  90  * memory block, or a mmap'd memory block
  91  */
  92 class MemPointer : public _ValueObj {
  93  public:
  94   MemPointer(): _addr(0) { }
  95   MemPointer(address addr): _addr(addr) { }
  96 
  97   MemPointer(const MemPointer& copy_from) {
  98     _addr = copy_from.addr();
  99   }
 100 
 101   inline address addr() const {
 102     return _addr;
 103   }
 104 
 105   inline operator address() const {
 106     return addr();
 107   }
 108 
 109   inline bool operator == (const MemPointer& other) const {
 110     return addr() == other.addr();
 111   }
 112 
 113   inline MemPointer& operator = (const MemPointer& other) {
 114     _addr = other.addr();
 115     return *this;
 116   }
 117 
 118  protected:
 119   inline void set_addr(address addr) { _addr = addr; }
 120 
 121  protected:
 122   // memory address
 123   address    _addr;
 124 };
 125 
 126 /* MemPointerRecord records an activityand associated
 127  * attributes on a memory block.
 128  */
 129 class MemPointerRecord : public MemPointer {
 130  private:
 131   MEMFLAGS       _flags;
 132   size_t         _size;
 133 
 134 public:
 135   /* extension of MemoryType enum
 136    * see share/vm/memory/allocation.hpp for details.
 137    *
 138    * The tag values are associated to sorting orders, so be
 139    * careful if changes are needed.
 140    * The allocation records should be sorted ahead of tagging
 141    * records, which in turn ahead of deallocation records
 142    */
 143   enum MemPointerTags {
 144     tag_alloc            = 0x0001, // malloc or reserve record
 145     tag_commit           = 0x0002, // commit record
 146     tag_type             = 0x0003, // tag virtual memory to a memory type
 147     tag_uncommit         = 0x0004, // uncommit record
 148     tag_release          = 0x0005, // free or release record
 149     tag_size             = 0x0006, // arena size
 150     tag_masks            = 0x0007, // all tag bits
 151     vmBit                = 0x0008
 152   };
 153 
 154   /* helper functions to interpret the tagging flags */
 155 
 156   inline static bool is_allocation_record(MEMFLAGS flags) {
 157     return (flags & tag_masks) == tag_alloc;
 158   }
 159 
 160   inline static bool is_deallocation_record(MEMFLAGS flags) {
 161     return (flags & tag_masks) == tag_release;
 162   }
 163 
 164   inline static bool is_arena_record(MEMFLAGS flags) {
 165     return (flags & (otArena | tag_size)) == otArena;
 166   }
 167 
 168   inline static bool is_arena_size_record(MEMFLAGS flags) {
 169     return (flags & (otArena | tag_size)) == (otArena | tag_size);
 170   }
 171 
 172   inline static bool is_virtual_memory_record(MEMFLAGS flags) {
 173     return (flags & vmBit) != 0;
 174   }
 175 
 176   inline static bool is_virtual_memory_reserve_record(MEMFLAGS flags) {
 177     return (flags & 0x0F) == (tag_alloc | vmBit);
 178   }
 179 
 180   inline static bool is_virtual_memory_commit_record(MEMFLAGS flags) {
 181     return (flags & 0x0F) == (tag_commit | vmBit);
 182   }
 183 
 184   inline static bool is_virtual_memory_uncommit_record(MEMFLAGS flags) {
 185     return (flags & 0x0F) == (tag_uncommit | vmBit);
 186   }
 187 
 188   inline static bool is_virtual_memory_release_record(MEMFLAGS flags) {
 189     return (flags & 0x0F) == (tag_release | vmBit);
 190   }
 191 
 192   inline static bool is_virtual_memory_type_record(MEMFLAGS flags) {
 193     return (flags & 0x0F) == (tag_type | vmBit);
 194   }
 195 
 196   /* tagging flags */
 197   inline static MEMFLAGS malloc_tag()                 { return tag_alloc;   }
 198   inline static MEMFLAGS free_tag()                   { return tag_release; }
 199   inline static MEMFLAGS arena_size_tag()             { return tag_size | otArena; }
 200   inline static MEMFLAGS virtual_memory_tag()         { return vmBit; }
 201   inline static MEMFLAGS virtual_memory_reserve_tag() { return (tag_alloc | vmBit); }
 202   inline static MEMFLAGS virtual_memory_commit_tag()  { return (tag_commit | vmBit); }
 203   inline static MEMFLAGS virtual_memory_uncommit_tag(){ return (tag_uncommit | vmBit); }
 204   inline static MEMFLAGS virtual_memory_release_tag() { return (tag_release | vmBit); }
 205   inline static MEMFLAGS virtual_memory_type_tag()    { return (tag_type | vmBit); }
 206 
 207  public:
 208   MemPointerRecord(): _size(0), _flags(mtNone) { }
 209 
 210   MemPointerRecord(address addr, MEMFLAGS memflags, size_t size = 0):
 211       MemPointer(addr), _flags(memflags), _size(size) { }
 212 
 213   MemPointerRecord(const MemPointerRecord& copy_from):
 214     MemPointer(copy_from), _flags(copy_from.flags()),
 215     _size(copy_from.size()) {
 216   }
 217 
 218   /* MemPointerRecord is not sequenced, it always return
 219    * 0 to indicate non-sequenced
 220    */
 221   virtual jint seq() const               { return 0; }
 222 
 223   inline size_t   size()  const          { return _size; }
 224   inline void set_size(size_t size)      { _size = size; }
 225 
 226   inline MEMFLAGS flags() const          { return _flags; }
 227   inline void set_flags(MEMFLAGS flags)  { _flags = flags; }
 228 
 229   MemPointerRecord& operator= (const MemPointerRecord& ptr) {
 230     MemPointer::operator=(ptr);
 231     _flags = ptr.flags();
 232 #ifdef ASSERT
 233     if (IS_ARENA_OBJ(_flags)) {
 234       assert(!is_vm_pointer(), "wrong flags");
 235       assert((_flags & ot_masks) == otArena, "wrong flags");
 236     }
 237 #endif
 238     _size = ptr.size();
 239     return *this;
 240   }
 241 
 242   // if the pointer represents a malloc-ed memory address
 243   inline bool is_malloced_pointer() const {
 244     return !is_vm_pointer();
 245   }
 246 
 247   // if the pointer represents a virtual memory address
 248   inline bool is_vm_pointer() const {
 249     return is_virtual_memory_record(_flags);
 250   }
 251 
 252   // if this record records a 'malloc' or virtual memory
 253   // 'reserve' call
 254   inline bool is_allocation_record() const {
 255     return is_allocation_record(_flags);
 256   }
 257 
 258   // if this record records a size information of an arena
 259   inline bool is_arena_size_record() const {
 260     return is_arena_size_record(_flags);
 261   }
 262 
 263   // if this pointer represents an address to an arena object
 264   inline bool is_arena_record() const {
 265     return is_arena_record(_flags);
 266   }
 267 
 268   // if this record represents a size information of specific arena
 269   inline bool is_size_record_of_arena(const MemPointerRecord* arena_rc) {
 270     assert(is_arena_size_record(), "not size record");
 271     assert(arena_rc->is_arena_record(), "not arena record");
 272     return (arena_rc->addr() + sizeof(void*)) == addr();
 273   }
 274 
 275   // if this record records a 'free' or virtual memory 'free' call
 276   inline bool is_deallocation_record() const {
 277     return is_deallocation_record(_flags);
 278   }
 279 
 280   // if this record records a virtual memory 'commit' call
 281   inline bool is_commit_record() const {
 282     return is_virtual_memory_commit_record(_flags);
 283   }
 284 
 285   // if this record records a virtual memory 'uncommit' call
 286   inline bool is_uncommit_record() const {
 287     return is_virtual_memory_uncommit_record(_flags);
 288   }
 289 
 290   // if this record is a tagging record of a virtual memory block
 291   inline bool is_type_tagging_record() const {
 292     return is_virtual_memory_type_record(_flags);
 293   }
 294 
 295   // if the two memory pointer records actually represent the same
 296   // memory block
 297   inline bool is_same_region(const MemPointerRecord* other) const {
 298     return (addr() == other->addr() && size() == other->size());
 299   }
 300 
 301   // if this memory region fully contains another one
 302   inline bool contains_region(const MemPointerRecord* other) const {
 303     return contains_region(other->addr(), other->size());
 304   }
 305 
 306   // if this memory region fully contains specified memory range
 307   inline bool contains_region(address add, size_t sz) const {
 308     return (addr() <= add && addr() + size() >= add + sz);
 309   }
 310 
 311   inline bool contains_address(address add) const {
 312     return (addr() <= add && addr() + size() > add);
 313   }
 314 };
 315 
 316 // MemPointerRecordEx also records callsite pc, from where
 317 // the memory block is allocated
 318 class MemPointerRecordEx : public MemPointerRecord {
 319  private:
 320   address      _pc;  // callsite pc
 321 
 322  public:
 323   MemPointerRecordEx(): _pc(0) { }
 324 
 325   MemPointerRecordEx(address addr, MEMFLAGS memflags, size_t size = 0, address pc = 0):
 326     MemPointerRecord(addr, memflags, size), _pc(pc) {}
 327 
 328   MemPointerRecordEx(const MemPointerRecordEx& copy_from):
 329     MemPointerRecord(copy_from), _pc(copy_from.pc()) {}
 330 
 331   inline address pc() const { return _pc; }
 332 
 333   void init(const MemPointerRecordEx* mpe) {
 334     MemPointerRecord::operator=(*mpe);
 335     _pc = mpe->pc();
 336   }
 337 
 338   void init(const MemPointerRecord* mp) {
 339     MemPointerRecord::operator=(*mp);
 340     _pc = 0;
 341   }
 342 };
 343 
 344 // a virtual memory region. The region can represent a reserved
 345 // virtual memory region or a committed memory region
 346 class VMMemRegion : public MemPointerRecord {
 347 public:
 348   VMMemRegion() { }
 349 
 350   void init(const MemPointerRecord* mp) {
 351     assert(mp->is_vm_pointer(), "Sanity check");
 352     _addr = mp->addr();
 353       set_size(mp->size());
 354     set_flags(mp->flags());
 355   }
 356 
 357   VMMemRegion& operator=(const VMMemRegion& other) {
 358     MemPointerRecord::operator=(other);
 359     return *this;
 360   }
 361 
 362   inline bool is_reserved_region() const {
 363     return is_allocation_record();
 364   }
 365 
 366   inline bool is_committed_region() const {
 367     return is_commit_record();
 368   }
 369 
 370   /* base address of this virtual memory range */
 371   inline address base() const {
 372     return addr();
 373   }
 374 
 375   /* tag this virtual memory range to the specified memory type */
 376   inline void tag(MEMFLAGS f) {
 377     set_flags(flags() | (f & mt_masks));
 378   }
 379 
 380   // expand this region to also cover specified range.
 381   // The range has to be on either end of the memory region.
 382   void expand_region(address addr, size_t sz) {
 383     if (addr < base()) {
 384       assert(addr + sz == base(), "Sanity check");
 385       _addr = addr;
 386       set_size(size() + sz);
 387     } else {
 388       assert(base() + size() == addr, "Sanity check");
 389       set_size(size() + sz);
 390     }
 391   }
 392 
 393   // exclude the specified address range from this region.
 394   // The excluded memory range has to be on either end of this memory
 395   // region.
 396   inline void exclude_region(address add, size_t sz) {
 397     assert(is_reserved_region() || is_committed_region(), "Sanity check");
 398     assert(addr() != NULL && size() != 0, "Sanity check");
 399     assert(add >= addr() && add < addr() + size(), "Sanity check");
 400     assert(add == addr() || (add + sz) == (addr() + size()),
 401       "exclude in the middle");
 402     if (add == addr()) {
 403       set_addr(add + sz);
 404       set_size(size() - sz);
 405     } else {
 406       set_size(size() - sz);
 407     }
 408   }
 409 };
 410 
 411 class VMMemRegionEx : public VMMemRegion {
 412  private:
 413   jint   _seq;  // sequence number
 414 
 415  public:
 416   VMMemRegionEx(): _pc(0) { }
 417 
 418   void init(const MemPointerRecordEx* mpe) {
 419     VMMemRegion::init(mpe);
 420     _pc = mpe->pc();
 421   }
 422 
 423   void init(const MemPointerRecord* mpe) {
 424     VMMemRegion::init(mpe);
 425     _pc = 0;
 426   }
 427 
 428   VMMemRegionEx& operator=(const VMMemRegionEx& other) {
 429     VMMemRegion::operator=(other);
 430     _pc = other.pc();
 431     return *this;
 432   }
 433 
 434   inline address pc() const { return _pc; }
 435  private:
 436   address   _pc;
 437 };
 438 
 439 /*
 440  * Sequenced memory record
 441  */
 442 class SeqMemPointerRecord : public MemPointerRecord {
 443  private:
 444    jint _seq;  // sequence number
 445 
 446  public:
 447   SeqMemPointerRecord(): _seq(0){ }
 448 
 449   SeqMemPointerRecord(address addr, MEMFLAGS flags, size_t size)
 450     : MemPointerRecord(addr, flags, size) {
 451     _seq = SequenceGenerator::next();
 452   }
 453 
 454   SeqMemPointerRecord(const SeqMemPointerRecord& copy_from)
 455     : MemPointerRecord(copy_from) {
 456     _seq = copy_from.seq();
 457   }
 458 
 459   SeqMemPointerRecord& operator= (const SeqMemPointerRecord& ptr) {
 460     MemPointerRecord::operator=(ptr);
 461     _seq = ptr.seq();
 462     return *this;
 463   }
 464 
 465   inline jint seq() const {
 466     return _seq;
 467   }
 468 };
 469 
 470 
 471 
 472 class SeqMemPointerRecordEx : public MemPointerRecordEx {
 473  private:
 474   jint    _seq;  // sequence number
 475 
 476  public:
 477   SeqMemPointerRecordEx(): _seq(0) { }
 478 
 479   SeqMemPointerRecordEx(address addr, MEMFLAGS flags, size_t size,
 480     address pc): MemPointerRecordEx(addr, flags, size, pc) {
 481     _seq = SequenceGenerator::next();
 482   }
 483 
 484   SeqMemPointerRecordEx(const SeqMemPointerRecordEx& copy_from)
 485     : MemPointerRecordEx(copy_from) {
 486     _seq = copy_from.seq();
 487   }
 488 
 489   SeqMemPointerRecordEx& operator= (const SeqMemPointerRecordEx& ptr) {
 490     MemPointerRecordEx::operator=(ptr);
 491     _seq = ptr.seq();
 492     return *this;
 493   }
 494 
 495   inline jint seq() const {
 496     return _seq;
 497   }
 498 };
 499 
 500 #endif // SHARE_VM_SERVICES_MEM_PTR_HPP