Mercurial > hg > graal-compiler
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; |