comparison src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp @ 1546:a00b51b2dda4

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
author ysr
date Mon, 17 May 2010 00:47:28 -0700
parents a8127dc669ba
children c18cbe5936b8
comparison
equal deleted inserted replaced
1545:cc387008223e 1546:a00b51b2dda4
1 /* 1 /*
2 * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. 2 * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
30 enum { 30 enum {
31 promoted_mask = right_n_bits(2), // i.e. 0x3 31 promoted_mask = right_n_bits(2), // i.e. 0x3
32 displaced_mark = nth_bit(2), // i.e. 0x4 32 displaced_mark = nth_bit(2), // i.e. 0x4
33 next_mask = ~(right_n_bits(3)) // i.e. ~(0x7) 33 next_mask = ~(right_n_bits(3)) // i.e. ~(0x7)
34 }; 34 };
35 intptr_t _next; 35
36 // Below, we want _narrow_next in the "higher" 32 bit slot,
37 // whose position will depend on endian-ness of the platform.
38 // This is so that there is no interference with the
39 // cms_free_bit occupying bit position 7 (lsb == 0)
40 // when we are using compressed oops; see FreeChunk::isFree().
41 // We cannot move the cms_free_bit down because currently
42 // biased locking code assumes that age bits are contiguous
43 // with the lock bits. Even if that assumption were relaxed,
44 // the least position we could move this bit to would be
45 // to bit position 3, which would require 16 byte alignment.
46 typedef struct {
47 #ifdef VM_LITTLE_ENDIAN
48 LP64_ONLY(narrowOop _pad;)
49 narrowOop _narrow_next;
50 #else
51 narrowOop _narrow_next;
52 LP64_ONLY(narrowOop _pad;)
53 #endif
54 } Data;
55
56 union {
57 intptr_t _next;
58 Data _data;
59 };
36 public: 60 public:
37 inline PromotedObject* next() const { 61 inline PromotedObject* next() const {
38 return (PromotedObject*)(_next & next_mask); 62 assert(!((FreeChunk*)this)->isFree(), "Error");
63 PromotedObject* res;
64 if (UseCompressedOops) {
65 // The next pointer is a compressed oop stored in the top 32 bits
66 res = (PromotedObject*)oopDesc::decode_heap_oop(_data._narrow_next);
67 } else {
68 res = (PromotedObject*)(_next & next_mask);
69 }
70 assert(oop(res)->is_oop_or_null(true /* ignore mark word */), "Not an oop?");
71 return res;
39 } 72 }
40 inline void setNext(PromotedObject* x) { 73 inline void setNext(PromotedObject* x) {
41 assert(((intptr_t)x & ~next_mask) == 0, 74 assert(((intptr_t)x & ~next_mask) == 0, "Conflict in bit usage, "
42 "Conflict in bit usage, " 75 "or insufficient alignment of objects");
43 " or insufficient alignment of objects"); 76 if (UseCompressedOops) {
44 _next |= (intptr_t)x; 77 assert(_data._narrow_next == 0, "Overwrite?");
78 _data._narrow_next = oopDesc::encode_heap_oop(oop(x));
79 } else {
80 _next |= (intptr_t)x;
81 }
82 assert(!((FreeChunk*)this)->isFree(), "Error");
45 } 83 }
46 inline void setPromotedMark() { 84 inline void setPromotedMark() {
47 _next |= promoted_mask; 85 _next |= promoted_mask;
86 assert(!((FreeChunk*)this)->isFree(), "Error");
48 } 87 }
49 inline bool hasPromotedMark() const { 88 inline bool hasPromotedMark() const {
89 assert(!((FreeChunk*)this)->isFree(), "Error");
50 return (_next & promoted_mask) == promoted_mask; 90 return (_next & promoted_mask) == promoted_mask;
51 } 91 }
52 inline void setDisplacedMark() { 92 inline void setDisplacedMark() {
53 _next |= displaced_mark; 93 _next |= displaced_mark;
94 assert(!((FreeChunk*)this)->isFree(), "Error");
54 } 95 }
55 inline bool hasDisplacedMark() const { 96 inline bool hasDisplacedMark() const {
97 assert(!((FreeChunk*)this)->isFree(), "Error");
56 return (_next & displaced_mark) != 0; 98 return (_next & displaced_mark) != 0;
57 } 99 }
58 inline void clearNext() { _next = 0; } 100 inline void clearNext() {
101 _next = 0;
102 assert(!((FreeChunk*)this)->isFree(), "Error");
103 }
59 debug_only(void *next_addr() { return (void *) &_next; }) 104 debug_only(void *next_addr() { return (void *) &_next; })
60 }; 105 };
61 106
62 class SpoolBlock: public FreeChunk { 107 class SpoolBlock: public FreeChunk {
63 friend class PromotionInfo; 108 friend class PromotionInfo;