30 class BlkClosure; |
30 class BlkClosure; |
31 class BlkClosureCareful; |
31 class BlkClosureCareful; |
32 class UpwardsObjectClosure; |
32 class UpwardsObjectClosure; |
33 class ObjectClosureCareful; |
33 class ObjectClosureCareful; |
34 class Klass; |
34 class Klass; |
35 |
|
36 class PromotedObject VALUE_OBJ_CLASS_SPEC { |
|
37 private: |
|
38 enum { |
|
39 promoted_mask = right_n_bits(2), // i.e. 0x3 |
|
40 displaced_mark = nth_bit(2), // i.e. 0x4 |
|
41 next_mask = ~(right_n_bits(3)) // i.e. ~(0x7) |
|
42 }; |
|
43 intptr_t _next; |
|
44 public: |
|
45 inline PromotedObject* next() const { |
|
46 return (PromotedObject*)(_next & next_mask); |
|
47 } |
|
48 inline void setNext(PromotedObject* x) { |
|
49 assert(((intptr_t)x & ~next_mask) == 0, |
|
50 "Conflict in bit usage, " |
|
51 " or insufficient alignment of objects"); |
|
52 _next |= (intptr_t)x; |
|
53 } |
|
54 inline void setPromotedMark() { |
|
55 _next |= promoted_mask; |
|
56 } |
|
57 inline bool hasPromotedMark() const { |
|
58 return (_next & promoted_mask) == promoted_mask; |
|
59 } |
|
60 inline void setDisplacedMark() { |
|
61 _next |= displaced_mark; |
|
62 } |
|
63 inline bool hasDisplacedMark() const { |
|
64 return (_next & displaced_mark) != 0; |
|
65 } |
|
66 inline void clearNext() { _next = 0; } |
|
67 debug_only(void *next_addr() { return (void *) &_next; }) |
|
68 }; |
|
69 |
|
70 class SpoolBlock: public FreeChunk { |
|
71 friend class PromotionInfo; |
|
72 protected: |
|
73 SpoolBlock* nextSpoolBlock; |
|
74 size_t bufferSize; // number of usable words in this block |
|
75 markOop* displacedHdr; // the displaced headers start here |
|
76 |
|
77 // Note about bufferSize: it denotes the number of entries available plus 1; |
|
78 // legal indices range from 1 through BufferSize - 1. See the verification |
|
79 // code verify() that counts the number of displaced headers spooled. |
|
80 size_t computeBufferSize() { |
|
81 return (size() * sizeof(HeapWord) - sizeof(*this)) / sizeof(markOop); |
|
82 } |
|
83 |
|
84 public: |
|
85 void init() { |
|
86 bufferSize = computeBufferSize(); |
|
87 displacedHdr = (markOop*)&displacedHdr; |
|
88 nextSpoolBlock = NULL; |
|
89 } |
|
90 |
|
91 void print_on(outputStream* st) const; |
|
92 void print() const { print_on(gclog_or_tty); } |
|
93 }; |
|
94 |
|
95 class PromotionInfo VALUE_OBJ_CLASS_SPEC { |
|
96 bool _tracking; // set if tracking |
|
97 CompactibleFreeListSpace* _space; // the space to which this belongs |
|
98 PromotedObject* _promoHead; // head of list of promoted objects |
|
99 PromotedObject* _promoTail; // tail of list of promoted objects |
|
100 SpoolBlock* _spoolHead; // first spooling block |
|
101 SpoolBlock* _spoolTail; // last non-full spooling block or null |
|
102 SpoolBlock* _splice_point; // when _spoolTail is null, holds list tail |
|
103 SpoolBlock* _spareSpool; // free spool buffer |
|
104 size_t _firstIndex; // first active index in |
|
105 // first spooling block (_spoolHead) |
|
106 size_t _nextIndex; // last active index + 1 in last |
|
107 // spooling block (_spoolTail) |
|
108 private: |
|
109 // ensure that spooling space exists; return true if there is spooling space |
|
110 bool ensure_spooling_space_work(); |
|
111 |
|
112 public: |
|
113 PromotionInfo() : |
|
114 _tracking(0), _space(NULL), |
|
115 _promoHead(NULL), _promoTail(NULL), |
|
116 _spoolHead(NULL), _spoolTail(NULL), |
|
117 _spareSpool(NULL), _firstIndex(1), |
|
118 _nextIndex(1) {} |
|
119 |
|
120 bool noPromotions() const { |
|
121 assert(_promoHead != NULL || _promoTail == NULL, "list inconsistency"); |
|
122 return _promoHead == NULL; |
|
123 } |
|
124 void startTrackingPromotions(); |
|
125 void stopTrackingPromotions(uint worker_id = 0); |
|
126 bool tracking() const { return _tracking; } |
|
127 void track(PromotedObject* trackOop); // keep track of a promoted oop |
|
128 // The following variant must be used when trackOop is not fully |
|
129 // initialized and has a NULL klass: |
|
130 void track(PromotedObject* trackOop, klassOop klassOfOop); // keep track of a promoted oop |
|
131 void setSpace(CompactibleFreeListSpace* sp) { _space = sp; } |
|
132 CompactibleFreeListSpace* space() const { return _space; } |
|
133 markOop nextDisplacedHeader(); // get next header & forward spool pointer |
|
134 void saveDisplacedHeader(markOop hdr); |
|
135 // save header and forward spool |
|
136 |
|
137 inline size_t refillSize() const; |
|
138 |
|
139 SpoolBlock* getSpoolBlock(); // return a free spooling block |
|
140 inline bool has_spooling_space() { |
|
141 return _spoolTail != NULL && _spoolTail->bufferSize > _nextIndex; |
|
142 } |
|
143 // ensure that spooling space exists |
|
144 bool ensure_spooling_space() { |
|
145 return has_spooling_space() || ensure_spooling_space_work(); |
|
146 } |
|
147 #define PROMOTED_OOPS_ITERATE_DECL(OopClosureType, nv_suffix) \ |
|
148 void promoted_oops_iterate##nv_suffix(OopClosureType* cl); |
|
149 ALL_SINCE_SAVE_MARKS_CLOSURES(PROMOTED_OOPS_ITERATE_DECL) |
|
150 #undef PROMOTED_OOPS_ITERATE_DECL |
|
151 void promoted_oops_iterate(OopsInGenClosure* cl) { |
|
152 promoted_oops_iterate_v(cl); |
|
153 } |
|
154 void verify() const; |
|
155 void reset() { |
|
156 _promoHead = NULL; |
|
157 _promoTail = NULL; |
|
158 _spoolHead = NULL; |
|
159 _spoolTail = NULL; |
|
160 _spareSpool = NULL; |
|
161 _firstIndex = 0; |
|
162 _nextIndex = 0; |
|
163 |
|
164 } |
|
165 |
|
166 void print_on(outputStream* st) const; |
|
167 void print_statistics(uint worker_id) const; |
|
168 }; |
|
169 |
35 |
170 class LinearAllocBlock VALUE_OBJ_CLASS_SPEC { |
36 class LinearAllocBlock VALUE_OBJ_CLASS_SPEC { |
171 public: |
37 public: |
172 LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), |
38 LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), |
173 _allocation_size_limit(0) {} |
39 _allocation_size_limit(0) {} |
555 // For an object in this space, the mark-word's two |
421 // For an object in this space, the mark-word's two |
556 // LSB's having the value [11] indicates that it has been |
422 // LSB's having the value [11] indicates that it has been |
557 // promoted since the most recent call to save_marks() on |
423 // promoted since the most recent call to save_marks() on |
558 // this generation and has not subsequently been iterated |
424 // this generation and has not subsequently been iterated |
559 // over (using oop_since_save_marks_iterate() above). |
425 // over (using oop_since_save_marks_iterate() above). |
|
426 // This property holds only for single-threaded collections, |
|
427 // and is typically used for Cheney scans; for MT scavenges, |
|
428 // the property holds for all objects promoted during that |
|
429 // scavenge for the duration of the scavenge and is used |
|
430 // by card-scanning to avoid scanning objects (being) promoted |
|
431 // during that scavenge. |
560 bool obj_allocated_since_save_marks(const oop obj) const { |
432 bool obj_allocated_since_save_marks(const oop obj) const { |
561 assert(is_in_reserved(obj), "Wrong space?"); |
433 assert(is_in_reserved(obj), "Wrong space?"); |
562 return ((PromotedObject*)obj)->hasPromotedMark(); |
434 return ((PromotedObject*)obj)->hasPromotedMark(); |
563 } |
435 } |
564 |
436 |