99 // significantly, and we need functionality that is only in the G1 version. |
99 // significantly, and we need functionality that is only in the G1 version. |
100 // So I copied that code, which led to an alternate G1 version of |
100 // So I copied that code, which led to an alternate G1 version of |
101 // OffsetTableContigSpace. If the two versions of BlockOffsetTable could |
101 // OffsetTableContigSpace. If the two versions of BlockOffsetTable could |
102 // be reconciled, then G1OffsetTableContigSpace could go away. |
102 // be reconciled, then G1OffsetTableContigSpace could go away. |
103 |
103 |
104 // The idea behind time stamps is the following. Doing a save_marks on |
104 // The idea behind time stamps is the following. We want to keep track of |
105 // all regions at every GC pause is time consuming (if I remember |
105 // the highest address where it's safe to scan objects for each region. |
106 // well, 10ms or so). So, we would like to do that only for regions |
106 // This is only relevant for current GC alloc regions so we keep a time stamp |
107 // that are GC alloc regions. To achieve this, we use time |
107 // per region to determine if the region has been allocated during the current |
108 // stamps. For every evacuation pause, G1CollectedHeap generates a |
108 // GC or not. If the time stamp is current we report a scan_top value which |
109 // unique time stamp (essentially a counter that gets |
109 // was saved at the end of the previous GC for retained alloc regions and which is |
110 // incremented). Every time we want to call save_marks on a region, |
110 // equal to the bottom for all other regions. |
111 // we set the saved_mark_word to top and also copy the current GC |
111 // There is a race between card scanners and allocating gc workers where we must ensure |
112 // time stamp to the time stamp field of the space. Reading the |
112 // that card scanners do not read the memory allocated by the gc workers. |
113 // saved_mark_word involves checking the time stamp of the |
113 // In order to enforce that, we must not return a value of _top which is more recent than the |
114 // region. If it is the same as the current GC time stamp, then we |
114 // time stamp. This is due to the fact that a region may become a gc alloc region at |
115 // can safely read the saved_mark_word field, as it is valid. If the |
115 // some point after we've read the timestamp value as being < the current time stamp. |
116 // time stamp of the region is not the same as the current GC time |
116 // The time stamps are re-initialized to zero at cleanup and at Full GCs. |
117 // stamp, then we instead read top, as the saved_mark_word field is |
117 // The current scheme that uses sequential unsigned ints will fail only if we have 4b |
118 // invalid. Time stamps (on the regions and also on the |
|
119 // G1CollectedHeap) are reset at every cleanup (we iterate over |
|
120 // the regions anyway) and at the end of a Full GC. The current scheme |
|
121 // that uses sequential unsigned ints will fail only if we have 4b |
|
122 // evacuation pauses between two cleanups, which is _highly_ unlikely. |
118 // evacuation pauses between two cleanups, which is _highly_ unlikely. |
123 class G1OffsetTableContigSpace: public CompactibleSpace { |
119 class G1OffsetTableContigSpace: public CompactibleSpace { |
124 friend class VMStructs; |
120 friend class VMStructs; |
125 HeapWord* _top; |
121 HeapWord* _top; |
|
122 HeapWord* volatile _scan_top; |
126 protected: |
123 protected: |
127 G1BlockOffsetArrayContigSpace _offsets; |
124 G1BlockOffsetArrayContigSpace _offsets; |
128 Mutex _par_alloc_lock; |
125 Mutex _par_alloc_lock; |
129 volatile unsigned _gc_time_stamp; |
126 volatile unsigned _gc_time_stamp; |
130 // When we need to retire an allocation region, while other threads |
127 // When we need to retire an allocation region, while other threads |
164 void safe_object_iterate(ObjectClosure* blk); |
161 void safe_object_iterate(ObjectClosure* blk); |
165 |
162 |
166 void set_bottom(HeapWord* value); |
163 void set_bottom(HeapWord* value); |
167 void set_end(HeapWord* value); |
164 void set_end(HeapWord* value); |
168 |
165 |
169 virtual HeapWord* saved_mark_word() const; |
166 HeapWord* scan_top() const; |
170 void record_top_and_timestamp(); |
167 void record_timestamp(); |
171 void reset_gc_time_stamp() { _gc_time_stamp = 0; } |
168 void reset_gc_time_stamp() { _gc_time_stamp = 0; } |
172 unsigned get_gc_time_stamp() { return _gc_time_stamp; } |
169 unsigned get_gc_time_stamp() { return _gc_time_stamp; } |
|
170 void record_retained_region(); |
173 |
171 |
174 // See the comment above in the declaration of _pre_dummy_top for an |
172 // See the comment above in the declaration of _pre_dummy_top for an |
175 // explanation of what it is. |
173 // explanation of what it is. |
176 void set_pre_dummy_top(HeapWord* pre_dummy_top) { |
174 void set_pre_dummy_top(HeapWord* pre_dummy_top) { |
177 assert(is_in(pre_dummy_top) && pre_dummy_top <= top(), "pre-condition"); |
175 assert(is_in(pre_dummy_top) && pre_dummy_top <= top(), "pre-condition"); |
190 void prepare_for_compaction(CompactPoint* cp); |
188 void prepare_for_compaction(CompactPoint* cp); |
191 |
189 |
192 // Add offset table update. |
190 // Add offset table update. |
193 virtual HeapWord* allocate(size_t word_size); |
191 virtual HeapWord* allocate(size_t word_size); |
194 HeapWord* par_allocate(size_t word_size); |
192 HeapWord* par_allocate(size_t word_size); |
|
193 |
|
194 HeapWord* saved_mark_word() const { ShouldNotReachHere(); return NULL; } |
195 |
195 |
196 // MarkSweep support phase3 |
196 // MarkSweep support phase3 |
197 virtual HeapWord* initialize_threshold(); |
197 virtual HeapWord* initialize_threshold(); |
198 virtual HeapWord* cross_threshold(HeapWord* start, HeapWord* end); |
198 virtual HeapWord* cross_threshold(HeapWord* start, HeapWord* end); |
199 |
199 |