Mon, 09 Jun 2008 11:51:19 -0400
6687581: Make CMS work with compressed oops
Summary: Make FreeChunk read markword instead of LSB in _klass pointer to indicate that it's a FreeChunk for compressed oops.
Reviewed-by: ysr, jmasa
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java Fri Jun 06 11:47:26 2008 -0700 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java Mon Jun 09 11:51:19 2008 -0400 1.3 @@ -121,7 +121,7 @@ 1.4 cur = cur.addOffsetTo(adjustObjectSizeInBytes(size)); 1.5 } 1.6 1.7 - if (FreeChunk.secondWordIndicatesFreeChunk(dbg.getAddressValue(klassOop))) { 1.8 + if (FreeChunk.indicatesFreeChunk(cur)) { 1.9 if (! cur.equals(regionStart)) { 1.10 res.add(new MemRegion(regionStart, cur)); 1.11 }
2.1 --- a/agent/src/share/classes/sun/jvm/hotspot/memory/FreeChunk.java Fri Jun 06 11:47:26 2008 -0700 2.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/FreeChunk.java Mon Jun 09 11:51:19 2008 -0400 2.3 @@ -28,6 +28,7 @@ 2.4 import sun.jvm.hotspot.debugger.*; 2.5 import sun.jvm.hotspot.types.*; 2.6 import sun.jvm.hotspot.runtime.*; 2.7 +import sun.jvm.hotspot.oops.*; 2.8 2.9 public class FreeChunk extends VMObject { 2.10 static { 2.11 @@ -42,13 +43,13 @@ 2.12 Type type = db.lookupType("FreeChunk"); 2.13 nextField = type.getAddressField("_next"); 2.14 prevField = type.getAddressField("_prev"); 2.15 - sizeField = type.getCIntegerField("_size"); 2.16 + sizeField = type.getAddressField("_size"); 2.17 } 2.18 2.19 // Fields 2.20 private static AddressField nextField; 2.21 private static AddressField prevField; 2.22 - private static CIntegerField sizeField; 2.23 + private static AddressField sizeField; 2.24 2.25 // Accessors 2.26 public FreeChunk next() { 2.27 @@ -61,20 +62,34 @@ 2.28 } 2.29 2.30 public long size() { 2.31 - return sizeField.getValue(addr); 2.32 + if (VM.getVM().isCompressedOopsEnabled()) { 2.33 + Mark mark = new Mark(sizeField.getValue(addr)); 2.34 + return mark.getSize(); 2.35 + } else { 2.36 + Address size = sizeField.getValue(addr); 2.37 + Debugger dbg = VM.getVM().getDebugger(); 2.38 + return dbg.getAddressValue(size); 2.39 + } 2.40 } 2.41 2.42 public FreeChunk(Address addr) { 2.43 super(addr); 2.44 } 2.45 2.46 - public static boolean secondWordIndicatesFreeChunk(long word) { 2.47 - return (word & 0x1L) == 0x1L; 2.48 + public static boolean indicatesFreeChunk(Address cur) { 2.49 + FreeChunk f = new FreeChunk(cur); 2.50 + return f.isFree(); 2.51 } 2.52 2.53 public boolean isFree() { 2.54 - Debugger dbg = VM.getVM().getDebugger(); 2.55 - Address prev = prevField.getValue(addr); 2.56 - return secondWordIndicatesFreeChunk(dbg.getAddressValue(prev)); 2.57 + if (VM.getVM().isCompressedOopsEnabled()) { 2.58 + Mark mark = new Mark(sizeField.getValue(addr)); 2.59 + return mark.isCmsFreeChunk(); 2.60 + } else { 2.61 + Address prev = prevField.getValue(addr); 2.62 + Debugger dbg = VM.getVM().getDebugger(); 2.63 + long word = dbg.getAddressValue(prev); 2.64 + return (word & 0x1L) == 0x1L; 2.65 + } 2.66 } 2.67 }
3.1 --- a/agent/src/share/classes/sun/jvm/hotspot/oops/Mark.java Fri Jun 06 11:47:26 2008 -0700 3.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Mark.java Mon Jun 09 11:51:19 2008 -0400 3.3 @@ -79,6 +79,11 @@ 3.4 noHashInPlace = db.lookupLongConstant("markOopDesc::no_hash_in_place").longValue(); 3.5 noLockInPlace = db.lookupLongConstant("markOopDesc::no_lock_in_place").longValue(); 3.6 maxAge = db.lookupLongConstant("markOopDesc::max_age").longValue(); 3.7 + 3.8 + /* Constants in markOop used by CMS. */ 3.9 + cmsShift = db.lookupLongConstant("markOopDesc::cms_shift").longValue(); 3.10 + cmsMask = db.lookupLongConstant("markOopDesc::cms_mask").longValue(); 3.11 + sizeShift = db.lookupLongConstant("markOopDesc::size_shift").longValue(); 3.12 } 3.13 3.14 // Field accessors 3.15 @@ -120,6 +125,11 @@ 3.16 3.17 private static long maxAge; 3.18 3.19 + /* Constants in markOop used by CMS. */ 3.20 + private static long cmsShift; 3.21 + private static long cmsMask; 3.22 + private static long sizeShift; 3.23 + 3.24 public Mark(Address addr) { 3.25 super(addr); 3.26 } 3.27 @@ -290,4 +300,11 @@ 3.28 // 3.29 // // Recover address of oop from encoded form used in mark 3.30 // inline void* decode_pointer() { return clear_lock_bits(); } 3.31 + 3.32 + // Copy markOop methods for CMS here. 3.33 + public boolean isCmsFreeChunk() { 3.34 + return isUnlocked() && 3.35 + (Bits.maskBitsLong(value() >> cmsShift, cmsMask) & 0x1L) == 0x1L; 3.36 + } 3.37 + public long getSize() { return (long)(value() >> sizeShift); } 3.38 }
4.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Jun 06 11:47:26 2008 -0700 4.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Mon Jun 09 11:51:19 2008 -0400 4.3 @@ -805,28 +805,30 @@ 4.4 // This must be volatile, or else there is a danger that the compiler 4.5 // will compile the code below into a sometimes-infinite loop, by keeping 4.6 // the value read the first time in a register. 4.7 - oop o = (oop)p; 4.8 - volatile oop* second_word_addr = o->klass_addr(); 4.9 while (true) { 4.10 - klassOop k = (klassOop)(*second_word_addr); 4.11 // We must do this until we get a consistent view of the object. 4.12 - if (FreeChunk::secondWordIndicatesFreeChunk((intptr_t)k)) { 4.13 - FreeChunk* fc = (FreeChunk*)p; 4.14 - volatile size_t* sz_addr = (volatile size_t*)(fc->size_addr()); 4.15 - size_t res = (*sz_addr); 4.16 - klassOop k2 = (klassOop)(*second_word_addr); // Read to confirm. 4.17 - if (k == k2) { 4.18 + if (FreeChunk::indicatesFreeChunk(p)) { 4.19 + volatile FreeChunk* fc = (volatile FreeChunk*)p; 4.20 + size_t res = fc->size(); 4.21 + // If the object is still a free chunk, return the size, else it 4.22 + // has been allocated so try again. 4.23 + if (FreeChunk::indicatesFreeChunk(p)) { 4.24 assert(res != 0, "Block size should not be 0"); 4.25 return res; 4.26 } 4.27 - } else if (k != NULL) { 4.28 - assert(k->is_oop(true /* ignore mark word */), "Should really be klass oop."); 4.29 - assert(o->is_parsable(), "Should be parsable"); 4.30 - assert(o->is_oop(true /* ignore mark word */), "Should be an oop."); 4.31 - size_t res = o->size_given_klass(k->klass_part()); 4.32 - res = adjustObjectSize(res); 4.33 - assert(res != 0, "Block size should not be 0"); 4.34 - return res; 4.35 + } else { 4.36 + // must read from what 'p' points to in each loop. 4.37 + klassOop k = ((volatile oopDesc*)p)->klass_or_null(); 4.38 + if (k != NULL) { 4.39 + assert(k->is_oop(true /* ignore mark word */), "Should really be klass oop."); 4.40 + oop o = (oop)p; 4.41 + assert(o->is_parsable(), "Should be parsable"); 4.42 + assert(o->is_oop(true /* ignore mark word */), "Should be an oop."); 4.43 + size_t res = o->size_given_klass(k->klass_part()); 4.44 + res = adjustObjectSize(res); 4.45 + assert(res != 0, "Block size should not be 0"); 4.46 + return res; 4.47 + } 4.48 } 4.49 } 4.50 } 4.51 @@ -845,31 +847,31 @@ 4.52 // This must be volatile, or else there is a danger that the compiler 4.53 // will compile the code below into a sometimes-infinite loop, by keeping 4.54 // the value read the first time in a register. 4.55 - oop o = (oop)p; 4.56 - volatile oop* second_word_addr = o->klass_addr(); 4.57 DEBUG_ONLY(uint loops = 0;) 4.58 while (true) { 4.59 - klassOop k = (klassOop)(*second_word_addr); 4.60 // We must do this until we get a consistent view of the object. 4.61 - if (FreeChunk::secondWordIndicatesFreeChunk((intptr_t)k)) { 4.62 - FreeChunk* fc = (FreeChunk*)p; 4.63 - volatile size_t* sz_addr = (volatile size_t*)(fc->size_addr()); 4.64 - size_t res = (*sz_addr); 4.65 - klassOop k2 = (klassOop)(*second_word_addr); // Read to confirm. 4.66 - if (k == k2) { 4.67 + if (FreeChunk::indicatesFreeChunk(p)) { 4.68 + volatile FreeChunk* fc = (volatile FreeChunk*)p; 4.69 + size_t res = fc->size(); 4.70 + if (FreeChunk::indicatesFreeChunk(p)) { 4.71 assert(res != 0, "Block size should not be 0"); 4.72 assert(loops == 0, "Should be 0"); 4.73 return res; 4.74 } 4.75 - } else if (k != NULL && o->is_parsable()) { 4.76 - assert(k->is_oop(), "Should really be klass oop."); 4.77 - assert(o->is_oop(), "Should be an oop"); 4.78 - size_t res = o->size_given_klass(k->klass_part()); 4.79 - res = adjustObjectSize(res); 4.80 - assert(res != 0, "Block size should not be 0"); 4.81 - return res; 4.82 } else { 4.83 - return c->block_size_if_printezis_bits(p); 4.84 + // must read from what 'p' points to in each loop. 4.85 + klassOop k = ((volatile oopDesc*)p)->klass_or_null(); 4.86 + if (k != NULL && ((oopDesc*)p)->is_parsable()) { 4.87 + assert(k->is_oop(), "Should really be klass oop."); 4.88 + oop o = (oop)p; 4.89 + assert(o->is_oop(), "Should be an oop"); 4.90 + size_t res = o->size_given_klass(k->klass_part()); 4.91 + res = adjustObjectSize(res); 4.92 + assert(res != 0, "Block size should not be 0"); 4.93 + return res; 4.94 + } else { 4.95 + return c->block_size_if_printezis_bits(p); 4.96 + } 4.97 } 4.98 assert(loops == 0, "Can loop at most once"); 4.99 DEBUG_ONLY(loops++;) 4.100 @@ -907,9 +909,8 @@ 4.101 // and those objects (if garbage) may have been modified to hold 4.102 // live range information. 4.103 // assert(ParallelGCThreads > 0 || _bt.block_start(p) == p, "Should be a block boundary"); 4.104 - klassOop k = oop(p)->klass(); 4.105 - intptr_t ki = (intptr_t)k; 4.106 - if (FreeChunk::secondWordIndicatesFreeChunk(ki)) return false; 4.107 + if (FreeChunk::indicatesFreeChunk(p)) return false; 4.108 + klassOop k = oop(p)->klass_or_null(); 4.109 if (k != NULL) { 4.110 // Ignore mark word because it may have been used to 4.111 // chain together promoted objects (the last one 4.112 @@ -1027,7 +1028,7 @@ 4.113 FreeChunk* fc = (FreeChunk*)res; 4.114 fc->markNotFree(); 4.115 assert(!fc->isFree(), "shouldn't be marked free"); 4.116 - assert(oop(fc)->klass() == NULL, "should look uninitialized"); 4.117 + assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized"); 4.118 // Verify that the block offset table shows this to 4.119 // be a single block, but not one which is unallocated. 4.120 _bt.verify_single_block(res, size); 4.121 @@ -2593,7 +2594,7 @@ 4.122 } 4.123 res->markNotFree(); 4.124 assert(!res->isFree(), "shouldn't be marked free"); 4.125 - assert(oop(res)->klass() == NULL, "should look uninitialized"); 4.126 + assert(oop(res)->klass_or_null() == NULL, "should look uninitialized"); 4.127 // mangle a just allocated object with a distinct pattern. 4.128 debug_only(res->mangleAllocated(word_sz)); 4.129 return (HeapWord*)res;
5.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Jun 06 11:47:26 2008 -0700 5.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Mon Jun 09 11:51:19 2008 -0400 5.3 @@ -190,7 +190,8 @@ 5.4 // depends on this property. 5.5 debug_only( 5.6 FreeChunk* junk = NULL; 5.7 - assert(junk->prev_addr() == (void*)(oop(junk)->klass_addr()), 5.8 + assert(UseCompressedOops || 5.9 + junk->prev_addr() == (void*)(oop(junk)->klass_addr()), 5.10 "Offset of FreeChunk::_prev within FreeChunk must match" 5.11 " that of OopDesc::_klass within OopDesc"); 5.12 ) 5.13 @@ -1039,7 +1040,7 @@ 5.14 // mark end of object 5.15 } 5.16 // check that oop looks uninitialized 5.17 - assert(oop(start)->klass() == NULL, "_klass should be NULL"); 5.18 + assert(oop(start)->klass_or_null() == NULL, "_klass should be NULL"); 5.19 } 5.20 5.21 void CMSCollector::promoted(bool par, HeapWord* start, 5.22 @@ -1309,17 +1310,25 @@ 5.23 } 5.24 } 5.25 oop obj = oop(obj_ptr); 5.26 - assert(obj->klass() == NULL, "Object should be uninitialized here."); 5.27 + assert(obj->klass_or_null() == NULL, "Object should be uninitialized here."); 5.28 // Otherwise, copy the object. Here we must be careful to insert the 5.29 // klass pointer last, since this marks the block as an allocated object. 5.30 + // Except with compressed oops it's the mark word. 5.31 HeapWord* old_ptr = (HeapWord*)old; 5.32 if (word_sz > (size_t)oopDesc::header_size()) { 5.33 Copy::aligned_disjoint_words(old_ptr + oopDesc::header_size(), 5.34 obj_ptr + oopDesc::header_size(), 5.35 word_sz - oopDesc::header_size()); 5.36 } 5.37 + 5.38 + if (UseCompressedOops) { 5.39 + // Copy gap missed by (aligned) header size calculation above 5.40 + obj->set_klass_gap(old->klass_gap()); 5.41 + } 5.42 + 5.43 // Restore the mark word copied above. 5.44 obj->set_mark(m); 5.45 + 5.46 // Now we can track the promoted object, if necessary. We take care 5.47 // To delay the transition from uninitialized to full object 5.48 // (i.e., insertion of klass pointer) until after, so that it 5.49 @@ -1327,7 +1336,8 @@ 5.50 if (promoInfo->tracking()) { 5.51 promoInfo->track((PromotedObject*)obj, old->klass()); 5.52 } 5.53 - // Finally, install the klass pointer. 5.54 + 5.55 + // Finally, install the klass pointer (this should be volatile). 5.56 obj->set_klass(old->klass()); 5.57 5.58 assert(old->is_oop(), "Will dereference klass ptr below"); 5.59 @@ -6165,7 +6175,7 @@ 5.60 HeapWord* CMSCollector::next_card_start_after_block(HeapWord* addr) const { 5.61 size_t sz = 0; 5.62 oop p = (oop)addr; 5.63 - if (p->klass() != NULL && p->is_parsable()) { 5.64 + if (p->klass_or_null() != NULL && p->is_parsable()) { 5.65 sz = CompactibleFreeListSpace::adjustObjectSize(p->size()); 5.66 } else { 5.67 sz = block_size_using_printezis_bits(addr); 5.68 @@ -6602,7 +6612,7 @@ 5.69 } 5.70 if (_bitMap->isMarked(addr)) { 5.71 // it's marked; is it potentially uninitialized? 5.72 - if (p->klass() != NULL) { 5.73 + if (p->klass_or_null() != NULL) { 5.74 if (CMSPermGenPrecleaningEnabled && !p->is_parsable()) { 5.75 // Signal precleaning to redirty the card since 5.76 // the klass pointer is already installed. 5.77 @@ -6615,11 +6625,8 @@ 5.78 if (p->is_objArray()) { 5.79 // objArrays are precisely marked; restrict scanning 5.80 // to dirty cards only. 5.81 - size = p->oop_iterate(_scanningClosure, mr); 5.82 - assert(size == CompactibleFreeListSpace::adjustObjectSize(size), 5.83 - "adjustObjectSize should be the identity for array sizes, " 5.84 - "which are necessarily larger than minimum object size of " 5.85 - "two heap words"); 5.86 + size = CompactibleFreeListSpace::adjustObjectSize( 5.87 + p->oop_iterate(_scanningClosure, mr)); 5.88 } else { 5.89 // A non-array may have been imprecisely marked; we need 5.90 // to scan object in its entirety. 5.91 @@ -6653,7 +6660,7 @@ 5.92 } 5.93 } else { 5.94 // Either a not yet marked object or an uninitialized object 5.95 - if (p->klass() == NULL || !p->is_parsable()) { 5.96 + if (p->klass_or_null() == NULL || !p->is_parsable()) { 5.97 // An uninitialized object, skip to the next card, since 5.98 // we may not be able to read its P-bits yet. 5.99 assert(size == 0, "Initial value"); 5.100 @@ -6710,7 +6717,7 @@ 5.101 HeapWord* addr = (HeapWord*)p; 5.102 DEBUG_ONLY(_collector->verify_work_stacks_empty();) 5.103 assert(!_span.contains(addr), "we are scanning the survivor spaces"); 5.104 - assert(p->klass() != NULL, "object should be initializd"); 5.105 + assert(p->klass_or_null() != NULL, "object should be initializd"); 5.106 assert(p->is_parsable(), "must be parsable."); 5.107 // an initialized object; ignore mark word in verification below 5.108 // since we are running concurrent with mutators 5.109 @@ -6868,7 +6875,7 @@ 5.110 assert(_skipBits == 0, "tautology"); 5.111 _skipBits = 2; // skip next two marked bits ("Printezis-marks") 5.112 oop p = oop(addr); 5.113 - if (p->klass() == NULL || !p->is_parsable()) { 5.114 + if (p->klass_or_null() == NULL || !p->is_parsable()) { 5.115 DEBUG_ONLY(if (!_verifying) {) 5.116 // We re-dirty the cards on which this object lies and increase 5.117 // the _threshold so that we'll come back to scan this object 5.118 @@ -6890,7 +6897,7 @@ 5.119 if (_threshold < end_card_addr) { 5.120 _threshold = end_card_addr; 5.121 } 5.122 - if (p->klass() != NULL) { 5.123 + if (p->klass_or_null() != NULL) { 5.124 // Redirty the range of cards... 5.125 _mut->mark_range(redirty_range); 5.126 } // ...else the setting of klass will dirty the card anyway. 5.127 @@ -7048,7 +7055,7 @@ 5.128 assert(_skip_bits == 0, "tautology"); 5.129 _skip_bits = 2; // skip next two marked bits ("Printezis-marks") 5.130 oop p = oop(addr); 5.131 - if (p->klass() == NULL || !p->is_parsable()) { 5.132 + if (p->klass_or_null() == NULL || !p->is_parsable()) { 5.133 // in the case of Clean-on-Enter optimization, redirty card 5.134 // and avoid clearing card by increasing the threshold. 5.135 return; 5.136 @@ -8023,7 +8030,7 @@ 5.137 "alignment problem"); 5.138 5.139 #ifdef DEBUG 5.140 - if (oop(addr)->klass() != NULL && 5.141 + if (oop(addr)->klass_or_null() != NULL && 5.142 ( !_collector->should_unload_classes() 5.143 || oop(addr)->is_parsable())) { 5.144 // Ignore mark word because we are running concurrent with mutators 5.145 @@ -8036,7 +8043,7 @@ 5.146 5.147 } else { 5.148 // This should be an initialized object that's alive. 5.149 - assert(oop(addr)->klass() != NULL && 5.150 + assert(oop(addr)->klass_or_null() != NULL && 5.151 (!_collector->should_unload_classes() 5.152 || oop(addr)->is_parsable()), 5.153 "Should be an initialized object");
6.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp Fri Jun 06 11:47:26 2008 -0700 6.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp Mon Jun 09 11:51:19 2008 -0400 6.3 @@ -22,88 +22,6 @@ 6.4 * 6.5 */ 6.6 6.7 -// 6.8 -// Free block maintenance for Concurrent Mark Sweep Generation 6.9 -// 6.10 -// The main data structure for free blocks are 6.11 -// . an indexed array of small free blocks, and 6.12 -// . a dictionary of large free blocks 6.13 -// 6.14 - 6.15 -// No virtuals in FreeChunk (don't want any vtables). 6.16 - 6.17 -// A FreeChunk is merely a chunk that can be in a doubly linked list 6.18 -// and has a size field. NOTE: FreeChunks are distinguished from allocated 6.19 -// objects in two ways (by the sweeper). The second word (prev) has the 6.20 -// LSB set to indicate a free chunk; allocated objects' klass() pointers 6.21 -// don't have their LSB set. The corresponding bit in the CMSBitMap is 6.22 -// set when the chunk is allocated. There are also blocks that "look free" 6.23 -// but are not part of the free list and should not be coalesced into larger 6.24 -// free blocks. These free blocks have their two LSB's set. 6.25 - 6.26 -class FreeChunk VALUE_OBJ_CLASS_SPEC { 6.27 - friend class VMStructs; 6.28 - FreeChunk* _next; 6.29 - FreeChunk* _prev; 6.30 - size_t _size; 6.31 - 6.32 - public: 6.33 - NOT_PRODUCT(static const size_t header_size();) 6.34 - // Returns "true" if the "wrd", which is required to be the second word 6.35 - // of a block, indicates that the block represents a free chunk. 6.36 - static bool secondWordIndicatesFreeChunk(intptr_t wrd) { 6.37 - return (wrd & 0x1) == 0x1; 6.38 - } 6.39 - bool isFree() const { 6.40 - return secondWordIndicatesFreeChunk((intptr_t)_prev); 6.41 - } 6.42 - bool cantCoalesce() const { return (((intptr_t)_prev) & 0x3) == 0x3; } 6.43 - FreeChunk* next() const { return _next; } 6.44 - FreeChunk* prev() const { return (FreeChunk*)(((intptr_t)_prev) & ~(0x3)); } 6.45 - debug_only(void* prev_addr() const { return (void*)&_prev; }) 6.46 - 6.47 - void linkAfter(FreeChunk* ptr) { 6.48 - linkNext(ptr); 6.49 - if (ptr != NULL) ptr->linkPrev(this); 6.50 - } 6.51 - void linkAfterNonNull(FreeChunk* ptr) { 6.52 - assert(ptr != NULL, "precondition violation"); 6.53 - linkNext(ptr); 6.54 - ptr->linkPrev(this); 6.55 - } 6.56 - void linkNext(FreeChunk* ptr) { _next = ptr; } 6.57 - void linkPrev(FreeChunk* ptr) { _prev = (FreeChunk*)((intptr_t)ptr | 0x1); } 6.58 - void clearPrev() { _prev = NULL; } 6.59 - void clearNext() { _next = NULL; } 6.60 - void dontCoalesce() { 6.61 - // the block should be free 6.62 - assert(isFree(), "Should look like a free block"); 6.63 - _prev = (FreeChunk*)(((intptr_t)_prev) | 0x2); 6.64 - } 6.65 - void markFree() { _prev = (FreeChunk*)((intptr_t)_prev | 0x1); } 6.66 - void markNotFree() { _prev = NULL; } 6.67 - 6.68 - size_t size() const { return _size; } 6.69 - void setSize(size_t size) { _size = size; } 6.70 - 6.71 - // For volatile reads: 6.72 - size_t* size_addr() { return &_size; } 6.73 - 6.74 - // Return the address past the end of this chunk 6.75 - HeapWord* end() const { return ((HeapWord*) this) + _size; } 6.76 - 6.77 - // debugging 6.78 - void verify() const PRODUCT_RETURN; 6.79 - void verifyList() const PRODUCT_RETURN; 6.80 - void mangleAllocated(size_t size) PRODUCT_RETURN; 6.81 - void mangleFreed(size_t size) PRODUCT_RETURN; 6.82 -}; 6.83 - 6.84 -// Alignment helpers etc. 6.85 -#define numQuanta(x,y) ((x+y-1)/y) 6.86 -enum AlignmentConstants { 6.87 - MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment 6.88 -}; 6.89 6.90 // A FreeBlockDictionary is an abstract superclass that will allow 6.91 // a number of alternative implementations in the future.
7.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp Fri Jun 06 11:47:26 2008 -0700 7.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp Mon Jun 09 11:51:19 2008 -0400 7.3 @@ -47,15 +47,15 @@ 7.4 Copy::fill_to_words(addr + hdr, size - hdr, baadbabeHeapWord); 7.5 } 7.6 7.7 -void FreeChunk::mangleFreed(size_t size) { 7.8 +void FreeChunk::mangleFreed(size_t sz) { 7.9 assert(baadbabeHeapWord != deadbeefHeapWord, "Need distinct patterns"); 7.10 // mangle all but the header of a just-freed block of storage 7.11 // just prior to passing it to the storage dictionary 7.12 - assert(size >= MinChunkSize, "smallest size of object"); 7.13 - assert(size == _size, "just checking"); 7.14 + assert(sz >= MinChunkSize, "smallest size of object"); 7.15 + assert(sz == size(), "just checking"); 7.16 HeapWord* addr = (HeapWord*)this; 7.17 size_t hdr = header_size(); 7.18 - Copy::fill_to_words(addr + hdr, size - hdr, deadbeefHeapWord); 7.19 + Copy::fill_to_words(addr + hdr, sz - hdr, deadbeefHeapWord); 7.20 } 7.21 7.22 void FreeChunk::verifyList() const {
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp Mon Jun 09 11:51:19 2008 -0400 8.3 @@ -0,0 +1,137 @@ 8.4 +/* 8.5 + * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 8.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 8.24 + * have any questions. 8.25 + * 8.26 + */ 8.27 + 8.28 +// 8.29 +// Free block maintenance for Concurrent Mark Sweep Generation 8.30 +// 8.31 +// The main data structure for free blocks are 8.32 +// . an indexed array of small free blocks, and 8.33 +// . a dictionary of large free blocks 8.34 +// 8.35 + 8.36 +// No virtuals in FreeChunk (don't want any vtables). 8.37 + 8.38 +// A FreeChunk is merely a chunk that can be in a doubly linked list 8.39 +// and has a size field. NOTE: FreeChunks are distinguished from allocated 8.40 +// objects in two ways (by the sweeper), depending on whether the VM is 32 or 8.41 +// 64 bits. 8.42 +// In 32 bits or 64 bits without CompressedOops, the second word (prev) has the 8.43 +// LSB set to indicate a free chunk; allocated objects' klass() pointers 8.44 +// don't have their LSB set. The corresponding bit in the CMSBitMap is 8.45 +// set when the chunk is allocated. There are also blocks that "look free" 8.46 +// but are not part of the free list and should not be coalesced into larger 8.47 +// free blocks. These free blocks have their two LSB's set. 8.48 + 8.49 +class FreeChunk VALUE_OBJ_CLASS_SPEC { 8.50 + friend class VMStructs; 8.51 + // For 64 bit compressed oops, the markOop encodes both the size and the 8.52 + // indication that this is a FreeChunk and not an object. 8.53 + volatile size_t _size; 8.54 + FreeChunk* _prev; 8.55 + FreeChunk* _next; 8.56 + 8.57 + markOop mark() const volatile { return (markOop)_size; } 8.58 + void set_mark(markOop m) { _size = (size_t)m; } 8.59 + 8.60 + public: 8.61 + NOT_PRODUCT(static const size_t header_size();) 8.62 + 8.63 + // Returns "true" if the address indicates that the block represents 8.64 + // a free chunk. 8.65 + static bool indicatesFreeChunk(const HeapWord* addr) { 8.66 + // Force volatile read from addr because value might change between 8.67 + // calls. We really want the read of _mark and _prev from this pointer 8.68 + // to be volatile but making the fields volatile causes all sorts of 8.69 + // compilation errors. 8.70 + return ((volatile FreeChunk*)addr)->isFree(); 8.71 + } 8.72 + 8.73 + bool isFree() const volatile { 8.74 + LP64_ONLY(if (UseCompressedOops) return mark()->is_cms_free_chunk(); else) 8.75 + return (((intptr_t)_prev) & 0x1) == 0x1; 8.76 + } 8.77 + bool cantCoalesce() const { 8.78 + assert(isFree(), "can't get coalesce bit on not free"); 8.79 + return (((intptr_t)_prev) & 0x2) == 0x2; 8.80 + } 8.81 + void dontCoalesce() { 8.82 + // the block should be free 8.83 + assert(isFree(), "Should look like a free block"); 8.84 + _prev = (FreeChunk*)(((intptr_t)_prev) | 0x2); 8.85 + } 8.86 + FreeChunk* prev() const { 8.87 + return (FreeChunk*)(((intptr_t)_prev) & ~(0x3)); 8.88 + } 8.89 + 8.90 + debug_only(void* prev_addr() const { return (void*)&_prev; }) 8.91 + 8.92 + size_t size() const volatile { 8.93 + LP64_ONLY(if (UseCompressedOops) return mark()->get_size(); else ) 8.94 + return _size; 8.95 + } 8.96 + void setSize(size_t sz) { 8.97 + LP64_ONLY(if (UseCompressedOops) set_mark(markOopDesc::set_size_and_free(sz)); else ) 8.98 + _size = sz; 8.99 + } 8.100 + 8.101 + FreeChunk* next() const { return _next; } 8.102 + 8.103 + void linkAfter(FreeChunk* ptr) { 8.104 + linkNext(ptr); 8.105 + if (ptr != NULL) ptr->linkPrev(this); 8.106 + } 8.107 + void linkAfterNonNull(FreeChunk* ptr) { 8.108 + assert(ptr != NULL, "precondition violation"); 8.109 + linkNext(ptr); 8.110 + ptr->linkPrev(this); 8.111 + } 8.112 + void linkNext(FreeChunk* ptr) { _next = ptr; } 8.113 + void linkPrev(FreeChunk* ptr) { 8.114 + LP64_ONLY(if (UseCompressedOops) _prev = ptr; else) 8.115 + _prev = (FreeChunk*)((intptr_t)ptr | 0x1); 8.116 + } 8.117 + void clearPrev() { _prev = NULL; } 8.118 + void clearNext() { _next = NULL; } 8.119 + void markNotFree() { 8.120 + LP64_ONLY(if (UseCompressedOops) set_mark(markOopDesc::prototype());) 8.121 + // Also set _prev to null 8.122 + _prev = NULL; 8.123 + } 8.124 + 8.125 + // Return the address past the end of this chunk 8.126 + HeapWord* end() const { return ((HeapWord*) this) + size(); } 8.127 + 8.128 + // debugging 8.129 + void verify() const PRODUCT_RETURN; 8.130 + void verifyList() const PRODUCT_RETURN; 8.131 + void mangleAllocated(size_t size) PRODUCT_RETURN; 8.132 + void mangleFreed(size_t size) PRODUCT_RETURN; 8.133 +}; 8.134 + 8.135 +// Alignment helpers etc. 8.136 +#define numQuanta(x,y) ((x+y-1)/y) 8.137 +enum AlignmentConstants { 8.138 + MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment 8.139 +}; 8.140 +
9.1 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Fri Jun 06 11:47:26 2008 -0700 9.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Mon Jun 09 11:51:19 2008 -0400 9.3 @@ -23,6 +23,7 @@ 9.4 */ 9.5 9.6 #define VM_STRUCTS_CMS(nonstatic_field, \ 9.7 + volatile_nonstatic_field, \ 9.8 static_field) \ 9.9 nonstatic_field(CompactibleFreeListSpace, _collector, CMSCollector*) \ 9.10 nonstatic_field(CompactibleFreeListSpace, _bt, BlockOffsetArrayNonContigSpace) \ 9.11 @@ -36,9 +37,9 @@ 9.12 nonstatic_field(CMSCollector, _markBitMap, CMSBitMap) \ 9.13 nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace, CompactibleFreeListSpace*) \ 9.14 static_field(ConcurrentMarkSweepThread, _collector, CMSCollector*) \ 9.15 + volatile_nonstatic_field(FreeChunk, _size, size_t) \ 9.16 nonstatic_field(FreeChunk, _next, FreeChunk*) \ 9.17 - nonstatic_field(FreeChunk, _prev, FreeChunk*) \ 9.18 - nonstatic_field(FreeChunk, _size, size_t) 9.19 + nonstatic_field(FreeChunk, _prev, FreeChunk*) 9.20 9.21 #define VM_TYPES_CMS(declare_type, \ 9.22 declare_toplevel_type) \
10.1 --- a/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep Fri Jun 06 11:47:26 2008 -0700 10.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep Mon Jun 09 11:51:19 2008 -0400 10.3 @@ -206,6 +206,7 @@ 10.4 10.5 freeBlockDictionary.hpp allocation.hpp 10.6 freeBlockDictionary.hpp debug.hpp 10.7 +freeBlockDictionary.hpp freeChunk.hpp 10.8 freeBlockDictionary.hpp globalDefinitions.hpp 10.9 freeBlockDictionary.hpp memRegion.hpp 10.10 freeBlockDictionary.hpp mutex.hpp 10.11 @@ -214,6 +215,14 @@ 10.12 freeChunk.cpp copy.hpp 10.13 freeChunk.cpp freeBlockDictionary.hpp 10.14 10.15 +freeChunk.hpp allocation.hpp 10.16 +freeChunk.hpp debug.hpp 10.17 +freeChunk.hpp globalDefinitions.hpp 10.18 +freeChunk.hpp markOop.hpp 10.19 +freeChunk.hpp memRegion.hpp 10.20 +freeChunk.hpp mutex.hpp 10.21 +freeChunk.hpp ostream.hpp 10.22 + 10.23 freeList.cpp freeBlockDictionary.hpp 10.24 freeList.cpp freeList.hpp 10.25 freeList.cpp globals.hpp
11.1 --- a/src/share/vm/oops/markOop.hpp Fri Jun 06 11:47:26 2008 -0700 11.2 +++ b/src/share/vm/oops/markOop.hpp Mon Jun 09 11:51:19 2008 -0400 11.3 @@ -29,8 +29,10 @@ 11.4 // 11.5 // Bit-format of an object header (most significant first): 11.6 // 11.7 -// 11.8 -// unused:0/25 hash:25/31 age:4 biased_lock:1 lock:2 = 32/64 bits 11.9 +// 32 bits: unused:0 hash:25 age:4 biased_lock:1 lock:2 11.10 +// 64 bits: unused:24 hash:31 cms:2 age:4 biased_lock:1 lock:2 11.11 +// unused:20 size:35 cms:2 age:4 biased_lock:1 lock:2 (if cms 11.12 +// free chunk) 11.13 // 11.14 // - hash contains the identity hash value: largest value is 11.15 // 31 bits, see os::random(). Also, 64-bit vm's require 11.16 @@ -91,6 +93,7 @@ 11.17 biased_lock_bits = 1, 11.18 max_hash_bits = BitsPerWord - age_bits - lock_bits - biased_lock_bits, 11.19 hash_bits = max_hash_bits > 31 ? 31 : max_hash_bits, 11.20 + cms_bits = LP64_ONLY(1) NOT_LP64(0), 11.21 epoch_bits = 2 11.22 }; 11.23 11.24 @@ -106,7 +109,8 @@ 11.25 enum { lock_shift = 0, 11.26 biased_lock_shift = lock_bits, 11.27 age_shift = lock_bits + biased_lock_bits, 11.28 - hash_shift = lock_bits + biased_lock_bits + age_bits, 11.29 + cms_shift = age_shift + age_bits, 11.30 + hash_shift = cms_shift + cms_bits, 11.31 epoch_shift = hash_shift 11.32 }; 11.33 11.34 @@ -118,7 +122,9 @@ 11.35 age_mask = right_n_bits(age_bits), 11.36 age_mask_in_place = age_mask << age_shift, 11.37 epoch_mask = right_n_bits(epoch_bits), 11.38 - epoch_mask_in_place = epoch_mask << epoch_shift 11.39 + epoch_mask_in_place = epoch_mask << epoch_shift, 11.40 + cms_mask = right_n_bits(cms_bits), 11.41 + cms_mask_in_place = cms_mask << cms_shift 11.42 #ifndef _WIN64 11.43 ,hash_mask = right_n_bits(hash_bits), 11.44 hash_mask_in_place = (address_word)hash_mask << hash_shift 11.45 @@ -360,4 +366,40 @@ 11.46 11.47 // see the definition in markOop.cpp for the gory details 11.48 bool should_not_be_cached() const; 11.49 + 11.50 + // These markOops indicate cms free chunk blocks and not objects. 11.51 + // In 64 bit, the markOop is set to distinguish them from oops. 11.52 + // These are defined in 32 bit mode for vmStructs. 11.53 + const static uintptr_t cms_free_chunk_pattern = 0x1; 11.54 + 11.55 + // Constants for the size field. 11.56 + enum { size_shift = cms_shift + cms_bits, 11.57 + size_bits = 35 // need for compressed oops 32G 11.58 + }; 11.59 + // These values are too big for Win64 11.60 + const static uintptr_t size_mask = LP64_ONLY(right_n_bits(size_bits)) 11.61 + NOT_LP64(0); 11.62 + const static uintptr_t size_mask_in_place = 11.63 + (address_word)size_mask << size_shift; 11.64 + 11.65 +#ifdef _LP64 11.66 + static markOop cms_free_prototype() { 11.67 + return markOop(((intptr_t)prototype() & ~cms_mask_in_place) | 11.68 + ((cms_free_chunk_pattern & cms_mask) << cms_shift)); 11.69 + } 11.70 + uintptr_t cms_encoding() const { 11.71 + return mask_bits(value() >> cms_shift, cms_mask); 11.72 + } 11.73 + bool is_cms_free_chunk() const { 11.74 + return is_neutral() && 11.75 + (cms_encoding() & cms_free_chunk_pattern) == cms_free_chunk_pattern; 11.76 + } 11.77 + 11.78 + size_t get_size() const { return (size_t)(value() >> size_shift); } 11.79 + static markOop set_size_and_free(size_t size) { 11.80 + assert((size & ~size_mask) == 0, "shouldn't overflow size field"); 11.81 + return markOop(((intptr_t)cms_free_prototype() & ~size_mask_in_place) | 11.82 + (((intptr_t)size & size_mask) << size_shift)); 11.83 + } 11.84 +#endif // _LP64 11.85 };
12.1 --- a/src/share/vm/runtime/arguments.cpp Fri Jun 06 11:47:26 2008 -0700 12.2 +++ b/src/share/vm/runtime/arguments.cpp Mon Jun 09 11:51:19 2008 -0400 12.3 @@ -1174,7 +1174,7 @@ 12.4 // field offset to determine free list chunk markers. 12.5 // Check that UseCompressedOops can be set with the max heap size allocated 12.6 // by ergonomics. 12.7 - if (!UseConcMarkSweepGC && MaxHeapSize <= max_heap_for_compressed_oops()) { 12.8 + if (MaxHeapSize <= max_heap_for_compressed_oops()) { 12.9 if (FLAG_IS_DEFAULT(UseCompressedOops)) { 12.10 // Leave compressed oops off by default. Uncomment 12.11 // the following line to return it to default status.
13.1 --- a/src/share/vm/runtime/vmStructs.cpp Fri Jun 06 11:47:26 2008 -0700 13.2 +++ b/src/share/vm/runtime/vmStructs.cpp Mon Jun 09 11:51:19 2008 -0400 13.3 @@ -1694,7 +1694,12 @@ 13.4 declare_constant(markOopDesc::no_hash) \ 13.5 declare_constant(markOopDesc::no_hash_in_place) \ 13.6 declare_constant(markOopDesc::no_lock_in_place) \ 13.7 - declare_constant(markOopDesc::max_age) 13.8 + declare_constant(markOopDesc::max_age) \ 13.9 + \ 13.10 + /* Constants in markOop used by CMS. */ \ 13.11 + declare_constant(markOopDesc::cms_shift) \ 13.12 + declare_constant(markOopDesc::cms_mask) \ 13.13 + declare_constant(markOopDesc::size_shift) \ 13.14 13.15 /* NOTE that we do not use the last_entry() macro here; it is used */ 13.16 /* in vmStructs_<os>_<cpu>.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and */ 13.17 @@ -1958,6 +1963,7 @@ 13.18 GENERATE_STATIC_VM_STRUCT_ENTRY) 13.19 13.20 VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ 13.21 + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \ 13.22 GENERATE_STATIC_VM_STRUCT_ENTRY) 13.23 #endif // SERIALGC 13.24 13.25 @@ -2099,6 +2105,7 @@ 13.26 CHECK_STATIC_VM_STRUCT_ENTRY); 13.27 13.28 VM_STRUCTS_CMS(CHECK_NONSTATIC_VM_STRUCT_ENTRY, 13.29 + CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, 13.30 CHECK_STATIC_VM_STRUCT_ENTRY); 13.31 #endif // SERIALGC 13.32 13.33 @@ -2203,6 +2210,7 @@ 13.34 debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, \ 13.35 ENSURE_FIELD_TYPE_PRESENT)); 13.36 debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, \ 13.37 + ENSURE_FIELD_TYPE_PRESENT, \ 13.38 ENSURE_FIELD_TYPE_PRESENT)); 13.39 #endif // SERIALGC 13.40 debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, \