Mercurial > hg > truffle
comparison src/share/vm/gc_interface/collectedHeap.cpp @ 1027:39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
6889757: G1: enable card mark elision for initializing writes from compiled code (ReduceInitialCardMarks)
Summary: Defer the (compiler-elided) card-mark upon a slow-path allocation until after the store and before the next subsequent safepoint; G1 now answers yes to can_elide_tlab_write_barriers().
Reviewed-by: jcoomes, kvn, never
author | ysr |
---|---|
date | Fri, 16 Oct 2009 02:05:46 -0700 |
parents | 7bb995fbd3c0 |
children | 4ce7240d622c |
comparison
equal
deleted
inserted
replaced
1025:1ee412f7fec9 | 1027:39b01ab7035a |
---|---|
135 } | 135 } |
136 thread->tlab().fill(obj, obj + size, new_tlab_size); | 136 thread->tlab().fill(obj, obj + size, new_tlab_size); |
137 return obj; | 137 return obj; |
138 } | 138 } |
139 | 139 |
140 void CollectedHeap::flush_deferred_store_barrier(JavaThread* thread) { | |
141 MemRegion deferred = thread->deferred_card_mark(); | |
142 if (!deferred.is_empty()) { | |
143 { | |
144 // Verify that the storage points to a parsable object in heap | |
145 DEBUG_ONLY(oop old_obj = oop(deferred.start());) | |
146 assert(is_in(old_obj), "Not in allocated heap"); | |
147 assert(!can_elide_initializing_store_barrier(old_obj), | |
148 "Else should have been filtered in defer_store_barrier()"); | |
149 assert(!is_in_permanent(old_obj), "Sanity: not expected"); | |
150 assert(old_obj->is_oop(true), "Not an oop"); | |
151 assert(old_obj->is_parsable(), "Will not be concurrently parsable"); | |
152 assert(deferred.word_size() == (size_t)(old_obj->size()), | |
153 "Mismatch: multiple objects?"); | |
154 } | |
155 BarrierSet* bs = barrier_set(); | |
156 assert(bs->has_write_region_opt(), "No write_region() on BarrierSet"); | |
157 bs->write_region(deferred); | |
158 // "Clear" the deferred_card_mark field | |
159 thread->set_deferred_card_mark(MemRegion()); | |
160 } | |
161 assert(thread->deferred_card_mark().is_empty(), "invariant"); | |
162 } | |
163 | |
164 // Helper for ReduceInitialCardMarks. For performance, | |
165 // compiled code may elide card-marks for initializing stores | |
166 // to a newly allocated object along the fast-path. We | |
167 // compensate for such elided card-marks as follows: | |
168 // (a) Generational, non-concurrent collectors, such as | |
169 // GenCollectedHeap(ParNew,DefNew,Tenured) and | |
170 // ParallelScavengeHeap(ParallelGC, ParallelOldGC) | |
171 // need the card-mark if and only if the region is | |
172 // in the old gen, and do not care if the card-mark | |
173 // succeeds or precedes the initializing stores themselves, | |
174 // so long as the card-mark is completed before the next | |
175 // scavenge. For all these cases, we can do a card mark | |
176 // at the point at which we do a slow path allocation | |
177 // in the old gen. For uniformity, however, we end | |
178 // up using the same scheme (see below) for all three | |
179 // cases (deferring the card-mark appropriately). | |
180 // (b) GenCollectedHeap(ConcurrentMarkSweepGeneration) requires | |
181 // in addition that the card-mark for an old gen allocated | |
182 // object strictly follow any associated initializing stores. | |
183 // In these cases, the memRegion remembered below is | |
184 // used to card-mark the entire region either just before the next | |
185 // slow-path allocation by this thread or just before the next scavenge or | |
186 // CMS-associated safepoint, whichever of these events happens first. | |
187 // (The implicit assumption is that the object has been fully | |
188 // initialized by this point, a fact that we assert when doing the | |
189 // card-mark.) | |
190 // (c) G1CollectedHeap(G1) uses two kinds of write barriers. When a | |
191 // G1 concurrent marking is in progress an SATB (pre-write-)barrier is | |
192 // is used to remember the pre-value of any store. Initializing | |
193 // stores will not need this barrier, so we need not worry about | |
194 // compensating for the missing pre-barrier here. Turning now | |
195 // to the post-barrier, we note that G1 needs a RS update barrier | |
196 // which simply enqueues a (sequence of) dirty cards which may | |
197 // optionally be refined by the concurrent update threads. Note | |
198 // that this barrier need only be applied to a non-young write, | |
199 // but, like in CMS, because of the presence of concurrent refinement | |
200 // (much like CMS' precleaning), must strictly follow the oop-store. | |
201 // Thus, using the same protocol for maintaining the intended | |
202 // invariants turns out, serendepitously, to be the same for all | |
203 // three collectors/heap types above. | |
204 // | |
205 // For each future collector, this should be reexamined with | |
206 // that specific collector in mind. | |
207 oop CollectedHeap::defer_store_barrier(JavaThread* thread, oop new_obj) { | |
208 // If a previous card-mark was deferred, flush it now. | |
209 flush_deferred_store_barrier(thread); | |
210 if (can_elide_initializing_store_barrier(new_obj)) { | |
211 // The deferred_card_mark region should be empty | |
212 // following the flush above. | |
213 assert(thread->deferred_card_mark().is_empty(), "Error"); | |
214 } else { | |
215 // Remember info for the newly deferred store barrier | |
216 MemRegion deferred = MemRegion((HeapWord*)new_obj, new_obj->size()); | |
217 assert(!deferred.is_empty(), "Error"); | |
218 thread->set_deferred_card_mark(deferred); | |
219 } | |
220 return new_obj; | |
221 } | |
222 | |
140 size_t CollectedHeap::filler_array_hdr_size() { | 223 size_t CollectedHeap::filler_array_hdr_size() { |
141 return size_t(arrayOopDesc::header_size(T_INT)); | 224 return size_t(arrayOopDesc::header_size(T_INT)); |
142 } | 225 } |
143 | 226 |
144 size_t CollectedHeap::filler_array_min_size() { | 227 size_t CollectedHeap::filler_array_min_size() { |
221 words -= cur; | 304 words -= cur; |
222 } | 305 } |
223 #endif | 306 #endif |
224 | 307 |
225 fill_with_object_impl(start, words); | 308 fill_with_object_impl(start, words); |
226 } | |
227 | |
228 oop CollectedHeap::new_store_barrier(oop new_obj) { | |
229 // %%% This needs refactoring. (It was imported from the server compiler.) | |
230 guarantee(can_elide_tlab_store_barriers(), "store barrier elision not supported"); | |
231 BarrierSet* bs = this->barrier_set(); | |
232 assert(bs->has_write_region_opt(), "Barrier set does not have write_region"); | |
233 int new_size = new_obj->size(); | |
234 bs->write_region(MemRegion((HeapWord*)new_obj, new_size)); | |
235 return new_obj; | |
236 } | 309 } |
237 | 310 |
238 HeapWord* CollectedHeap::allocate_new_tlab(size_t size) { | 311 HeapWord* CollectedHeap::allocate_new_tlab(size_t size) { |
239 guarantee(false, "thread-local allocation buffers not supported"); | 312 guarantee(false, "thread-local allocation buffers not supported"); |
240 return NULL; | 313 return NULL; |