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; |