< prev index next >

src/hotspot/share/oops/markOop.hpp

Print this page




  89 //    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread
  90 //    [0           | epoch | age | 1 | 01]       lock is anonymously biased
  91 //
  92 //  - the two lock bits are used to describe three states: locked/unlocked and monitor.
  93 //
  94 //    [ptr             | 00]  locked             ptr points to real header on stack
  95 //    [header      | 0 | 01]  unlocked           regular object header
  96 //    [ptr             | 10]  monitor            inflated lock (header is wapped out)
  97 //    [ptr             | 11]  marked             used by markSweep to mark an object
  98 //                                               not valid at any other time
  99 //
 100 //    We assume that stack/thread pointers have the lowest two bits cleared.
 101 //
 102 //    Always locked: since displaced and monitor references require memory at a
 103 //    fixed address, and hash code can be displaced, an efficiently providing a
 104 //    *permanent lock* leaves us with specializing the biased pattern (even when
 105 //    biased locking isn't enabled). Since biased_lock_alignment for the thread
 106 //    reference doesn't use the lowest bit ("2 << thread_shift"), we can use
 107 //    this illegal thread pointer alignment to denote "always locked" pattern.
 108 //
 109 //    [ <unused> |1| epoch | age | 1 | 01]       permanently locked


 110 //
 111 
 112 class BasicLock;
 113 class ObjectMonitor;
 114 class JavaThread;
 115 
 116 class markOopDesc: public oopDesc {
 117  private:
 118   // Conversion
 119   uintptr_t value() const { return (uintptr_t) this; }
 120 
 121  public:
 122   // Constants
 123   enum { age_bits                 = 4,
 124          lock_bits                = 2,
 125          biased_lock_bits         = 1,
 126          max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits,
 127          hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits,
 128          cms_bits                 = LP64_ONLY(1) NOT_LP64(0),
 129          epoch_bits               = 2


 130   };
 131 
 132   // The biased locking code currently requires that the age bits be
 133   // contiguous to the lock bits.
 134   enum { lock_shift               = 0,
 135          biased_lock_shift        = lock_bits,
 136          age_shift                = lock_bits + biased_lock_bits,
 137          cms_shift                = age_shift + age_bits,
 138          hash_shift               = cms_shift + cms_bits,
 139          epoch_shift              = hash_shift,
 140          thread_shift             = epoch_shift + epoch_bits

 141   };
 142 
 143   enum { lock_mask                = right_n_bits(lock_bits),
 144          lock_mask_in_place       = lock_mask << lock_shift,
 145          biased_lock_mask         = right_n_bits(lock_bits + biased_lock_bits),
 146          biased_lock_mask_in_place= biased_lock_mask << lock_shift,
 147          biased_lock_bit_in_place = 1 << biased_lock_shift,
 148          age_mask                 = right_n_bits(age_bits),
 149          age_mask_in_place        = age_mask << age_shift,
 150          epoch_mask               = right_n_bits(epoch_bits),
 151          epoch_mask_in_place      = epoch_mask << epoch_shift,
 152          cms_mask                 = right_n_bits(cms_bits),
 153          cms_mask_in_place        = cms_mask << cms_shift
 154 #ifndef _WIN64
 155          ,hash_mask               = right_n_bits(hash_bits),
 156          hash_mask_in_place       = (address_word)hash_mask << hash_shift
 157 #endif


 158   };
 159 
 160   // Alignment of JavaThread pointers encoded in object header required by biased locking
 161   enum { biased_lock_alignment    = 2 << thread_shift
 162   };
 163 
 164 #ifdef _WIN64
 165     // These values are too big for Win64
 166     const static uintptr_t hash_mask = right_n_bits(hash_bits);
 167     const static uintptr_t hash_mask_in_place  =
 168                             (address_word)hash_mask << hash_shift;
 169 #endif
 170 
 171   enum { locked_value             = 0,
 172          unlocked_value           = 1,
 173          monitor_value            = 2,
 174          marked_value             = 3,
 175          biased_lock_pattern      = 5,
 176          always_locked_pattern    = 1 << thread_shift | biased_lock_pattern
 177   };
 178 
 179   enum { no_hash                  = 0 };  // no hash value assigned
 180 
 181   enum { no_hash_in_place         = (address_word)no_hash << hash_shift,
 182          no_lock_in_place         = unlocked_value
 183   };
 184 
 185   enum { max_age                  = age_mask };
 186 
 187   enum { max_bias_epoch           = epoch_mask };
 188 


 189   static markOop always_locked_prototype() {
 190     return markOop(always_locked_pattern);
 191   }
 192 
 193   bool is_always_locked() const { return mask_bits(value(), always_locked_pattern) == always_locked_pattern; }
 194 
 195   // Biased Locking accessors.
 196   // These must be checked by all code which calls into the
 197   // ObjectSynchronizer and other code. The biasing is not understood
 198   // by the lower-level CAS-based locking code, although the runtime
 199   // fixes up biased locks to be compatible with it when a bias is
 200   // revoked.
 201   bool has_bias_pattern() const {
 202     return (mask_bits(value(), biased_lock_mask_in_place) == biased_lock_pattern);
 203   }
 204   JavaThread* biased_locker() const {
 205     assert(has_bias_pattern(), "should not call this otherwise");
 206     assert(!is_always_locked(), "invariant");
 207     return (JavaThread*) ((intptr_t) (mask_bits(value(), ~(biased_lock_mask_in_place | age_mask_in_place | epoch_mask_in_place))));
 208   }


 354   // age operations
 355   markOop set_marked()   { return markOop((value() & ~lock_mask_in_place) | marked_value); }
 356   markOop set_unmarked() { return markOop((value() & ~lock_mask_in_place) | unlocked_value); }
 357 
 358   uint    age()               const { return mask_bits(value() >> age_shift, age_mask); }
 359   markOop set_age(uint v) const {
 360     assert((v & ~age_mask) == 0, "shouldn't overflow age field");
 361     return markOop((value() & ~age_mask_in_place) | (((uintptr_t)v & age_mask) << age_shift));
 362   }
 363   markOop incr_age()          const { return age() == max_age ? markOop(this) : set_age(age() + 1); }
 364 
 365   // hash operations
 366   intptr_t hash() const {
 367     return mask_bits(value() >> hash_shift, hash_mask);
 368   }
 369 
 370   bool has_no_hash() const {
 371     return hash() == no_hash;
 372   }
 373 











 374   // Prototype mark for initialization
 375   static markOop prototype() {
 376     return markOop( no_hash_in_place | no_lock_in_place );
 377   }
 378 
 379   // Helper function for restoration of unmarked mark oops during GC
 380   static inline markOop prototype_for_object(oop obj);
 381 
 382   // Debugging
 383   void print_on(outputStream* st) const;
 384 
 385   // Prepare address of oop for placement into mark
 386   inline static markOop encode_pointer_as_mark(void* p) { return markOop(p)->set_marked(); }
 387 
 388   // Recover address of oop from encoded form used in mark
 389   inline void* decode_pointer() { if (has_bias_pattern()) return NULL; return clear_lock_bits(); }
 390 
 391   // These markOops indicate cms free chunk blocks and not objects.
 392   // In 64 bit, the markOop is set to distinguish them from oops.
 393   // These are defined in 32 bit mode for vmStructs.




  89 //    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread
  90 //    [0           | epoch | age | 1 | 01]       lock is anonymously biased
  91 //
  92 //  - the two lock bits are used to describe three states: locked/unlocked and monitor.
  93 //
  94 //    [ptr             | 00]  locked             ptr points to real header on stack
  95 //    [header      | 0 | 01]  unlocked           regular object header
  96 //    [ptr             | 10]  monitor            inflated lock (header is wapped out)
  97 //    [ptr             | 11]  marked             used by markSweep to mark an object
  98 //                                               not valid at any other time
  99 //
 100 //    We assume that stack/thread pointers have the lowest two bits cleared.
 101 //
 102 //    Always locked: since displaced and monitor references require memory at a
 103 //    fixed address, and hash code can be displaced, an efficiently providing a
 104 //    *permanent lock* leaves us with specializing the biased pattern (even when
 105 //    biased locking isn't enabled). Since biased_lock_alignment for the thread
 106 //    reference doesn't use the lowest bit ("2 << thread_shift"), we can use
 107 //    this illegal thread pointer alignment to denote "always locked" pattern.
 108 //
 109 //    [ <unused> | larval |1| epoch | age | 1 | 01]       permanently locked
 110 //
 111 //    A private buffered value is always locked and can be in a larval state.
 112 //
 113 
 114 class BasicLock;
 115 class ObjectMonitor;
 116 class JavaThread;
 117 
 118 class markOopDesc: public oopDesc {
 119  private:
 120   // Conversion
 121   uintptr_t value() const { return (uintptr_t) this; }
 122 
 123  public:
 124   // Constants
 125   enum { age_bits                 = 4,
 126          lock_bits                = 2,
 127          biased_lock_bits         = 1,
 128          max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits,
 129          hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits,
 130          cms_bits                 = LP64_ONLY(1) NOT_LP64(0),
 131          epoch_bits               = 2,
 132          always_locked_bits       = 1,
 133          larval_bits              = 1
 134   };
 135 
 136   // The biased locking code currently requires that the age bits be
 137   // contiguous to the lock bits.
 138   enum { lock_shift               = 0,
 139          biased_lock_shift        = lock_bits,
 140          age_shift                = lock_bits + biased_lock_bits,
 141          cms_shift                = age_shift + age_bits,
 142          hash_shift               = cms_shift + cms_bits,
 143          epoch_shift              = hash_shift,
 144          thread_shift             = epoch_shift + epoch_bits,
 145          larval_shift             = thread_shift + always_locked_bits
 146   };
 147 
 148   enum { lock_mask                = right_n_bits(lock_bits),
 149          lock_mask_in_place       = lock_mask << lock_shift,
 150          biased_lock_mask         = right_n_bits(lock_bits + biased_lock_bits),
 151          biased_lock_mask_in_place= biased_lock_mask << lock_shift,
 152          biased_lock_bit_in_place = 1 << biased_lock_shift,
 153          age_mask                 = right_n_bits(age_bits),
 154          age_mask_in_place        = age_mask << age_shift,
 155          epoch_mask               = right_n_bits(epoch_bits),
 156          epoch_mask_in_place      = epoch_mask << epoch_shift,
 157          cms_mask                 = right_n_bits(cms_bits),
 158          cms_mask_in_place        = cms_mask << cms_shift,
 159 #ifndef _WIN64
 160          hash_mask                = right_n_bits(hash_bits),
 161          hash_mask_in_place       = (address_word)hash_mask << hash_shift,
 162 #endif
 163          larval_mask              = right_n_bits(larval_bits),
 164          larval_mask_in_place     = larval_mask << larval_shift
 165   };
 166 
 167   // Alignment of JavaThread pointers encoded in object header required by biased locking
 168   enum { biased_lock_alignment    = 2 << thread_shift
 169   };
 170 
 171 #ifdef _WIN64
 172     // These values are too big for Win64
 173     const static uintptr_t hash_mask = right_n_bits(hash_bits);
 174     const static uintptr_t hash_mask_in_place  =
 175                             (address_word)hash_mask << hash_shift;
 176 #endif
 177 
 178   enum { locked_value             = 0,
 179          unlocked_value           = 1,
 180          monitor_value            = 2,
 181          marked_value             = 3,
 182          biased_lock_pattern      = 5,
 183          always_locked_pattern    = 1 << thread_shift | biased_lock_pattern
 184   };
 185 
 186   enum { no_hash                  = 0 };  // no hash value assigned
 187 
 188   enum { no_hash_in_place         = (address_word)no_hash << hash_shift,
 189          no_lock_in_place         = unlocked_value
 190   };
 191 
 192   enum { max_age                  = age_mask };
 193 
 194   enum { max_bias_epoch           = epoch_mask };
 195 
 196   enum { larval_state_pattern     = (1 << larval_shift) };
 197 
 198   static markOop always_locked_prototype() {
 199     return markOop(always_locked_pattern);
 200   }
 201 
 202   bool is_always_locked() const { return mask_bits(value(), always_locked_pattern) == always_locked_pattern; }
 203 
 204   // Biased Locking accessors.
 205   // These must be checked by all code which calls into the
 206   // ObjectSynchronizer and other code. The biasing is not understood
 207   // by the lower-level CAS-based locking code, although the runtime
 208   // fixes up biased locks to be compatible with it when a bias is
 209   // revoked.
 210   bool has_bias_pattern() const {
 211     return (mask_bits(value(), biased_lock_mask_in_place) == biased_lock_pattern);
 212   }
 213   JavaThread* biased_locker() const {
 214     assert(has_bias_pattern(), "should not call this otherwise");
 215     assert(!is_always_locked(), "invariant");
 216     return (JavaThread*) ((intptr_t) (mask_bits(value(), ~(biased_lock_mask_in_place | age_mask_in_place | epoch_mask_in_place))));
 217   }


 363   // age operations
 364   markOop set_marked()   { return markOop((value() & ~lock_mask_in_place) | marked_value); }
 365   markOop set_unmarked() { return markOop((value() & ~lock_mask_in_place) | unlocked_value); }
 366 
 367   uint    age()               const { return mask_bits(value() >> age_shift, age_mask); }
 368   markOop set_age(uint v) const {
 369     assert((v & ~age_mask) == 0, "shouldn't overflow age field");
 370     return markOop((value() & ~age_mask_in_place) | (((uintptr_t)v & age_mask) << age_shift));
 371   }
 372   markOop incr_age()          const { return age() == max_age ? markOop(this) : set_age(age() + 1); }
 373 
 374   // hash operations
 375   intptr_t hash() const {
 376     return mask_bits(value() >> hash_shift, hash_mask);
 377   }
 378 
 379   bool has_no_hash() const {
 380     return hash() == no_hash;
 381   }
 382 
 383   // private buffered value operations
 384   markOop enter_larval_state() const {
 385     return markOop((value() & ~larval_mask_in_place) | larval_state_pattern);
 386   }
 387   markOop exit_larval_state() const {
 388     return markOop(value() & ~larval_mask_in_place);
 389   }
 390   bool is_larval_state() const {
 391     return (value() & larval_mask_in_place) == larval_state_pattern;
 392   }
 393 
 394   // Prototype mark for initialization
 395   static markOop prototype() {
 396     return markOop( no_hash_in_place | no_lock_in_place );
 397   }
 398 
 399   // Helper function for restoration of unmarked mark oops during GC
 400   static inline markOop prototype_for_object(oop obj);
 401 
 402   // Debugging
 403   void print_on(outputStream* st) const;
 404 
 405   // Prepare address of oop for placement into mark
 406   inline static markOop encode_pointer_as_mark(void* p) { return markOop(p)->set_marked(); }
 407 
 408   // Recover address of oop from encoded form used in mark
 409   inline void* decode_pointer() { if (has_bias_pattern()) return NULL; return clear_lock_bits(); }
 410 
 411   // These markOops indicate cms free chunk blocks and not objects.
 412   // In 64 bit, the markOop is set to distinguish them from oops.
 413   // These are defined in 32 bit mode for vmStructs.


< prev index next >