6948539: CMS+UseCompressedOops: placement of cms_free bit interferes with promoted object link

Mon, 17 May 2010 00:47:28 -0700

author
ysr
date
Mon, 17 May 2010 00:47:28 -0700
changeset 1901
a00b51b2dda4
parent 1900
cc387008223e
child 1902
fb1a39993f69

6948539: CMS+UseCompressedOops: placement of cms_free bit interferes with promoted object link
Summary: When using compressed oops, use compressed promoted pointers in b63:b31 of the mark word, so as not to interfere with the CMS "freeness bit" at b7. Updated mark-word layout documentation.
Reviewed-by: minqi, poonam, jmasa, coleenp

src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/markOop.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Fri May 14 10:28:46 2010 -0700
     1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Mon May 17 00:47:28 2010 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * Copyright 2010 Sun Microsystems, Inc.  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
     2.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp	Fri May 14 10:28:46 2010 -0700
     2.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp	Mon May 17 00:47:28 2010 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
     2.6 + * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -32,30 +32,75 @@
    2.11      displaced_mark = nth_bit(2),        // i.e. 0x4
    2.12      next_mask      = ~(right_n_bits(3)) // i.e. ~(0x7)
    2.13    };
    2.14 -  intptr_t _next;
    2.15 +
    2.16 +  // Below, we want _narrow_next in the "higher" 32 bit slot,
    2.17 +  // whose position will depend on endian-ness of the platform.
    2.18 +  // This is so that there is no interference with the
    2.19 +  // cms_free_bit occupying bit position 7 (lsb == 0)
    2.20 +  // when we are using compressed oops; see FreeChunk::isFree().
    2.21 +  // We cannot move the cms_free_bit down because currently
    2.22 +  // biased locking code assumes that age bits are contiguous
    2.23 +  // with the lock bits. Even if that assumption were relaxed,
    2.24 +  // the least position we could move this bit to would be
    2.25 +  // to bit position 3, which would require 16 byte alignment.
    2.26 +  typedef struct {
    2.27 +#ifdef VM_LITTLE_ENDIAN
    2.28 +    LP64_ONLY(narrowOop _pad;)
    2.29 +              narrowOop _narrow_next;
    2.30 +#else
    2.31 +              narrowOop _narrow_next;
    2.32 +    LP64_ONLY(narrowOop _pad;)
    2.33 +#endif
    2.34 +  } Data;
    2.35 +
    2.36 +  union {
    2.37 +    intptr_t _next;
    2.38 +    Data     _data;
    2.39 +  };
    2.40   public:
    2.41    inline PromotedObject* next() const {
    2.42 -    return (PromotedObject*)(_next & next_mask);
    2.43 +    assert(!((FreeChunk*)this)->isFree(), "Error");
    2.44 +    PromotedObject* res;
    2.45 +    if (UseCompressedOops) {
    2.46 +      // The next pointer is a compressed oop stored in the top 32 bits
    2.47 +      res = (PromotedObject*)oopDesc::decode_heap_oop(_data._narrow_next);
    2.48 +    } else {
    2.49 +      res = (PromotedObject*)(_next & next_mask);
    2.50 +    }
    2.51 +    assert(oop(res)->is_oop_or_null(true /* ignore mark word */), "Not an oop?");
    2.52 +    return res;
    2.53    }
    2.54    inline void setNext(PromotedObject* x) {
    2.55 -    assert(((intptr_t)x & ~next_mask) == 0,
    2.56 -           "Conflict in bit usage, "
    2.57 -           " or insufficient alignment of objects");
    2.58 -    _next |= (intptr_t)x;
    2.59 +    assert(((intptr_t)x & ~next_mask) == 0, "Conflict in bit usage, "
    2.60 +           "or insufficient alignment of objects");
    2.61 +    if (UseCompressedOops) {
    2.62 +      assert(_data._narrow_next == 0, "Overwrite?");
    2.63 +      _data._narrow_next = oopDesc::encode_heap_oop(oop(x));
    2.64 +    } else {
    2.65 +      _next |= (intptr_t)x;
    2.66 +    }
    2.67 +    assert(!((FreeChunk*)this)->isFree(), "Error");
    2.68    }
    2.69    inline void setPromotedMark() {
    2.70      _next |= promoted_mask;
    2.71 +    assert(!((FreeChunk*)this)->isFree(), "Error");
    2.72    }
    2.73    inline bool hasPromotedMark() const {
    2.74 +    assert(!((FreeChunk*)this)->isFree(), "Error");
    2.75      return (_next & promoted_mask) == promoted_mask;
    2.76    }
    2.77    inline void setDisplacedMark() {
    2.78      _next |= displaced_mark;
    2.79 +    assert(!((FreeChunk*)this)->isFree(), "Error");
    2.80    }
    2.81    inline bool hasDisplacedMark() const {
    2.82 +    assert(!((FreeChunk*)this)->isFree(), "Error");
    2.83      return (_next & displaced_mark) != 0;
    2.84    }
    2.85 -  inline void clearNext()        { _next = 0; }
    2.86 +  inline void clearNext()        {
    2.87 +    _next = 0;
    2.88 +    assert(!((FreeChunk*)this)->isFree(), "Error");
    2.89 +  }
    2.90    debug_only(void *next_addr() { return (void *) &_next; })
    2.91  };
    2.92  
     3.1 --- a/src/share/vm/oops/markOop.hpp	Fri May 14 10:28:46 2010 -0700
     3.2 +++ b/src/share/vm/oops/markOop.hpp	Mon May 17 00:47:28 2010 -0700
     3.3 @@ -27,12 +27,26 @@
     3.4  // Note that the mark is not a real oop but just a word.
     3.5  // It is placed in the oop hierarchy for historical reasons.
     3.6  //
     3.7 -// Bit-format of an object header (most significant first):
     3.8 +// Bit-format of an object header (most significant first, big endian layout below):
     3.9  //
    3.10 -//  32 bits: unused:0  hash:25 age:4 biased_lock:1 lock:2
    3.11 -//  64 bits: unused:24 hash:31 cms:2 age:4 biased_lock:1 lock:2
    3.12 -//           unused:20 size:35 cms:2 age:4 biased_lock:1 lock:2 (if cms
    3.13 -//                                                               free chunk)
    3.14 +//  32 bits:
    3.15 +//  --------
    3.16 +//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
    3.17 +//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
    3.18 +//             size:32 ------------------------------------------>| (CMS free block)
    3.19 +//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
    3.20 +//
    3.21 +//  64 bits:
    3.22 +//  --------
    3.23 +//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
    3.24 +//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
    3.25 +//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
    3.26 +//  size:64 ----------------------------------------------------->| (CMS free block)
    3.27 +//
    3.28 +//  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
    3.29 +//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
    3.30 +//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
    3.31 +//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
    3.32  //
    3.33  //  - hash contains the identity hash value: largest value is
    3.34  //    31 bits, see os::random().  Also, 64-bit vm's require
    3.35 @@ -61,8 +75,9 @@
    3.36  //    significant fraction of the eden semispaces and were not
    3.37  //    promoted promptly, causing an increase in the amount of copying
    3.38  //    performed. The runtime system aligns all JavaThread* pointers to
    3.39 -//    a very large value (currently 128 bytes) to make room for the
    3.40 -//    age bits when biased locking is enabled.
    3.41 +//    a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))
    3.42 +//    to make room for the age bits & the epoch bits (used in support of
    3.43 +//    biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs).
    3.44  //
    3.45  //    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread
    3.46  //    [0           | epoch | age | 1 | 01]       lock is anonymously biased

mercurial