hotspot source code - mark word

vm/oops/markOop.hpp30行,关于markOopDesc数据结构的说明,markOop是指向class markOopDesc类型对象的指针,源码如下:

30313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
// The markOop describes the header of an object.//// Note that the mark is not a real oop but just a word.// It is placed in the oop hierarchy for historical reasons.//// Bit-format of an object header (most significant first, big endian layout below):////  32 bits://  --------//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)//             size:32 ------------------------------------------>| (CMS free block)//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)////  64 bits://  --------//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)//  size:64 ----------------------------------------------------->| (CMS free block)////  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)////  - hash contains the identity hash value: largest value is//    31 bits, see os::random().  Also, 64-bit vm's require//    a hash value no bigger than 32 bits because they will not//    properly generate a mask larger than that: see library_call.cpp//    and c1_CodePatterns_sparc.cpp.////  - the biased lock pattern is used to bias a lock toward a given//    thread. When this pattern is set in the low three bits, the lock//    is either biased toward a given thread or "anonymously" biased,//    indicating that it is possible for it to be biased. When the//    lock is biased toward a given thread, locking and unlocking can//    be performed by that thread without using atomic operations.//    When a lock's bias is revoked, it reverts back to the normal//    locking scheme described below.////    Note that we are overloading the meaning of the "unlocked" state//    of the header. Because we steal a bit from the age we can//    guarantee that the bias pattern will never be seen for a truly//    unlocked object.////    Note also that the biased state contains the age bits normally//    contained in the object header. Large increases in scavenge//    times were seen when these bits were absent and an arbitrary age//    assigned to all biased objects, because they tended to consume a//    significant fraction of the eden semispaces and were not//    promoted promptly, causing an increase in the amount of copying//    performed. The runtime system aligns all JavaThread* pointers to//    a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))//    to make room for the age bits & the epoch bits (used in support of//    biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs).////    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread//    [0           | epoch | age | 1 | 01]       lock is anonymously biased////  - the two lock bits are used to describe three states: locked/unlocked and monitor.////    [ptr             | 00]  locked             ptr points to real header on stack//    [header      | 0 | 01]  unlocked           regular object header//    [ptr             | 10]  monitor            inflated lock (header is wapped out)//    [ptr             | 11]  marked             used by markSweep to mark an object//                                               not valid at any other time////    We assume that stack/thread pointers have the lowest two bits cleared.class BasicLock;class ObjectMonitor;class JavaThread;class markOopDesc: public oopDesc { private:  // Conversion  uintptr_t value() const { return (uintptr_t) this; } public:  // Constants  enum { age_bits                 = 4,         lock_bits                = 2,         biased_lock_bits         = 1,         max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits,         hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits,         cms_bits                 = LP64_ONLY(1) NOT_LP64(0),         epoch_bits               = 2  };  // The biased locking code currently requires that the age bits be  // contiguous to the lock bits.  enum { lock_shift               = 0,         biased_lock_shift        = lock_bits,         age_shift                = lock_bits + biased_lock_bits,         cms_shift                = age_shift + age_bits,         hash_shift               = cms_shift + cms_bits,         epoch_shift              = hash_shift  };  enum { lock_mask                = right_n_bits(lock_bits),         lock_mask_in_place       = lock_mask << lock_shift,         biased_lock_mask         = right_n_bits(lock_bits + biased_lock_bits),         biased_lock_mask_in_place= biased_lock_mask << lock_shift,         biased_lock_bit_in_place = 1 << biased_lock_shift,         age_mask                 = right_n_bits(age_bits),         age_mask_in_place        = age_mask << age_shift,         epoch_mask               = right_n_bits(epoch_bits),         epoch_mask_in_place      = epoch_mask << epoch_shift,         cms_mask                 = right_n_bits(cms_bits),         cms_mask_in_place        = cms_mask << cms_shift#ifndef _WIN64         ,hash_mask               = right_n_bits(hash_bits),         hash_mask_in_place       = (address_word)hash_mask << hash_shift#endif  };  // Alignment of JavaThread pointers encoded in object header required by biased locking  enum { biased_lock_alignment    = 2 << (epoch_shift + epoch_bits)  };#ifdef _WIN64    // These values are too big for Win64    const static uintptr_t hash_mask = right_n_bits(hash_bits);    const static uintptr_t hash_mask_in_place  =                            (address_word)hash_mask << hash_shift;#endif  enum { locked_value             = 0,         unlocked_value           = 1,         monitor_value            = 2,         marked_value             = 3,         biased_lock_pattern      = 5  };  enum { no_hash                  = 0 };  // no hash value assigned  enum { no_hash_in_place         = (address_word)no_hash << hash_shift,         no_lock_in_place         = unlocked_value  };  enum { max_age                  = age_mask };  enum { max_bias_epoch           = epoch_mask };  // Biased Locking accessors.  // These must be checked by all code which calls into the  // ObjectSynchronizer and other code. The biasing is not understood  // by the lower-level CAS-based locking code, although the runtime  // fixes up biased locks to be compatible with it when a bias is  // revoked.  bool has_bias_pattern() const {    return (mask_bits(value(), biased_lock_mask_in_place) == biased_lock_pattern);  }  JavaThread* biased_locker() const {    assert(has_bias_pattern(), "should not call this otherwise");    return (JavaThread*) ((intptr_t) (mask_bits(value(), ~(biased_lock_mask_in_place | age_mask_in_place | epoch_mask_in_place))));  }  // Indicates that the mark has the bias bit set but that it has not  // yet been biased toward a particular thread  bool is_biased_anonymously() const {    return (has_bias_pattern() && (biased_locker() == NULL));  }  // Indicates epoch in which this bias was acquired. If the epoch  // changes due to too many bias revocations occurring, the biases  // from the previous epochs are all considered invalid.  int bias_epoch() const {    assert(has_bias_pattern(), "should not call this otherwise");    return (mask_bits(value(), epoch_mask_in_place) >> epoch_shift);  }  markOop set_bias_epoch(int epoch) {    assert(has_bias_pattern(), "should not call this otherwise");    assert((epoch & (~epoch_mask)) == 0, "epoch overflow");    return markOop(mask_bits(value(), ~epoch_mask_in_place) | (epoch << epoch_shift));  }  markOop incr_bias_epoch() {    return set_bias_epoch((1 + bias_epoch()) & epoch_mask);  }  // Prototype mark for initialization  static markOop biased_locking_prototype() {    return markOop( biased_lock_pattern );  }  // lock accessors (note that these assume lock_shift == 0)  bool is_locked()   const {    return (mask_bits(value(), lock_mask_in_place) != unlocked_value);  }  bool is_unlocked() const {    return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value);  }  bool is_marked()   const {    return (mask_bits(value(), lock_mask_in_place) == marked_value);  }  bool is_neutral()  const { return (mask_bits(value(), biased_lock_mask_in_place) == unlocked_value); }  // Special temporary state of the markOop while being inflated.  // Code that looks at mark outside a lock need to take this into account.  bool is_being_inflated() const { return (value() == 0); }  // Distinguished markword value - used when inflating over  // an existing stacklock.  0 indicates the markword is "BUSY".  // Lockword mutators that use a LD...CAS idiom should always  // check for and avoid overwriting a 0 value installed by some  // other thread.  (They should spin or block instead.  The 0 value  // is transient and *should* be short-lived).  static markOop INFLATING() { return (markOop) 0; }    // inflate-in-progress  // Should this header be preserved during GC?  inline bool must_be_preserved(oop obj_containing_mark) const;  inline bool must_be_preserved_with_bias(oop obj_containing_mark) const;  // Should this header (including its age bits) be preserved in the  // case of a promotion failure during scavenge?  // Note that we special case this situation. We want to avoid  // calling BiasedLocking::preserve_marks()/restore_marks() (which  // decrease the number of mark words that need to be preserved  // during GC) during each scavenge. During scavenges in which there  // is no promotion failure, we actually don't need to call the above  // routines at all, since we don't mutate and re-initialize the  // marks of promoted objects using init_mark(). However, during  // scavenges which result in promotion failure, we do re-initialize  // the mark words of objects, meaning that we should have called  // these mark word preservation routines. Currently there's no good  // place in which to call them in any of the scavengers (although  // guarded by appropriate locks we could make one), but the  // observation is that promotion failures are quite rare and  // reducing the number of mark words preserved during them isn't a  // high priority.  inline bool must_be_preserved_for_promotion_failure(oop obj_containing_mark) const;  inline bool must_be_preserved_with_bias_for_promotion_failure(oop obj_containing_mark) const;  // Should this header be preserved during a scavenge where CMS is  // the old generation?  // (This is basically the same body as must_be_preserved_for_promotion_failure(),  // but takes the Klass* as argument instead)  inline bool must_be_preserved_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const;  inline bool must_be_preserved_with_bias_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const;  // WARNING: The following routines are used EXCLUSIVELY by  // synchronization functions. They are not really gc safe.  // They must get updated if markOop layout get changed.  markOop set_unlocked() const {    return markOop(value() | unlocked_value);  }  bool has_locker() const {    return ((value() & lock_mask_in_place) == locked_value);  }  BasicLock* locker() const {    assert(has_locker(), "check");    return (BasicLock*) value();  }  bool has_monitor() const {    return ((value() & monitor_value) != 0);  }  ObjectMonitor* monitor() const {    assert(has_monitor(), "check");    // Use xor instead of &~ to provide one extra tag-bit check.    return (ObjectMonitor*) (value() ^ monitor_value);  }  bool has_displaced_mark_helper() const {    return ((value() & unlocked_value) == 0);  }  markOop displaced_mark_helper() const {    assert(has_displaced_mark_helper(), "check");    intptr_t ptr = (value() & ~monitor_value);    return *(markOop*)ptr;  }  void set_displaced_mark_helper(markOop m) const {    assert(has_displaced_mark_helper(), "check");    intptr_t ptr = (value() & ~monitor_value);    *(markOop*)ptr = m;  }

vm/oops/oop.hpp35行,关于markOopDesc基类oopDesc数据结构的说明,oop是指向class oopDesc类型对象的指针,第158行处定义了锁的状态枚举值,源码如下:

30313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
// oopDesc is the top baseclass for objects classes.  The {name}Desc classes describe// the format of Java objects so the fields can be accessed from C++.// oopDesc is abstract.// (see oopHierarchy for complete oop class hierarchy)//// no virtual functions allowed// store into oop with store checktemplate <class T> void oop_store(T* p, oop v);template <class T> void oop_store(volatile T* p, oop v);extern bool always_do_update_barrier;// Forward declarations.class OopClosure;class ScanClosure;class FastScanClosure;class FilteringClosure;class BarrierSet;class CMSIsAliveClosure;class PSPromotionManager;class ParCompactionManager;class oopDesc {  friend class VMStructs; private:  volatile markOop  _mark;  union _metadata {    Klass*      _klass;    narrowKlass _compressed_klass;  } _metadata;  // Fast access to barrier set.  Must be initialized.  static BarrierSet* _bs; public:  markOop  mark() const         { return _mark; }  markOop* mark_addr() const    { return (markOop*) &_mark; }  void set_mark(volatile markOop m)      { _mark = m;   }  void    release_set_mark(markOop m);  markOop cas_set_mark(markOop new_mark, markOop old_mark);  // Used only to re-initialize the mark word (e.g., of promoted  // objects during a GC) -- requires a valid klass pointer  void init_mark();  Klass* klass() const;  Klass* klass_or_null() const volatile;  Klass** klass_addr();  narrowKlass* compressed_klass_addr();  void set_klass(Klass* k);  // For klass field compression  int klass_gap() const;  void set_klass_gap(int z);  // For when the klass pointer is being used as a linked list "next" field.  void set_klass_to_list_ptr(oop k);  oop list_ptr_from_klass();  // size of object header, aligned to platform wordSize  static int header_size()          { return sizeof(oopDesc)/HeapWordSize; }  // Returns whether this is an instance of k or an instance of a subclass of k  bool is_a(Klass* k)  const;  // Returns the actual oop size of the object  int size();  // Sometimes (for complicated concurrency-related reasons), it is useful  // to be able to figure out the size of an object knowing its klass.  int size_given_klass(Klass* klass);  // type test operations (inlined in oop.inline.h)  bool is_instance()            const;  bool is_instanceMirror()      const;  bool is_instanceClassLoader() const;  bool is_instanceRef()         const;  bool is_array()               const;  bool is_objArray()            const;  bool is_typeArray()           const;

References

  1. vm/oops/markOop.hpp
  2. vm/oops/oop.hpp