87 #endif |
87 #endif |
88 |
88 |
89 class ShenandoahPretouchTask : public AbstractGangTask { |
89 class ShenandoahPretouchTask : public AbstractGangTask { |
90 private: |
90 private: |
91 ShenandoahRegionIterator _regions; |
91 ShenandoahRegionIterator _regions; |
|
92 char* _bitmap_base; |
92 const size_t _bitmap_size; |
93 const size_t _bitmap_size; |
93 const size_t _page_size; |
94 const size_t _heap_page_size; |
94 char* _bitmap_base; |
95 const size_t _bitmap_page_size; |
95 public: |
96 public: |
96 ShenandoahPretouchTask(char* bitmap_base, size_t bitmap_size, size_t page_size) : |
97 ShenandoahPretouchTask(char* bitmap_base, size_t bitmap_size, size_t heap_page_size, size_t bitmap_page_size) : |
97 AbstractGangTask("Shenandoah PreTouch"), |
98 AbstractGangTask("Shenandoah PreTouch"), |
|
99 _bitmap_base(bitmap_base), |
98 _bitmap_size(bitmap_size), |
100 _bitmap_size(bitmap_size), |
99 _page_size(page_size), |
101 _heap_page_size(heap_page_size), |
100 _bitmap_base(bitmap_base) { |
102 _bitmap_page_size(bitmap_page_size) {} |
101 } |
|
102 |
103 |
103 virtual void work(uint worker_id) { |
104 virtual void work(uint worker_id) { |
104 ShenandoahHeapRegion* r = _regions.next(); |
105 ShenandoahHeapRegion* r = _regions.next(); |
105 while (r != NULL) { |
106 while (r != NULL) { |
106 os::pretouch_memory(r->bottom(), r->end(), _page_size); |
107 os::pretouch_memory(r->bottom(), r->end(), _heap_page_size); |
107 |
108 |
108 size_t start = r->region_number() * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor(); |
109 size_t start = r->region_number() * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor(); |
109 size_t end = (r->region_number() + 1) * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor(); |
110 size_t end = (r->region_number() + 1) * ShenandoahHeapRegion::region_size_bytes() / MarkBitMap::heap_map_factor(); |
110 assert (end <= _bitmap_size, "end is sane: " SIZE_FORMAT " < " SIZE_FORMAT, end, _bitmap_size); |
111 assert (end <= _bitmap_size, "end is sane: " SIZE_FORMAT " < " SIZE_FORMAT, end, _bitmap_size); |
111 |
112 |
112 os::pretouch_memory(_bitmap_base + start, _bitmap_base + end, _page_size); |
113 os::pretouch_memory(_bitmap_base + start, _bitmap_base + end, _bitmap_page_size); |
113 |
114 |
114 r = _regions.next(); |
115 r = _regions.next(); |
115 } |
116 } |
116 } |
117 } |
117 }; |
118 }; |
119 jint ShenandoahHeap::initialize() { |
120 jint ShenandoahHeap::initialize() { |
120 ShenandoahBrooksPointer::initial_checks(); |
121 ShenandoahBrooksPointer::initial_checks(); |
121 |
122 |
122 initialize_heuristics(); |
123 initialize_heuristics(); |
123 |
124 |
|
125 // |
|
126 // Figure out heap sizing |
|
127 // |
|
128 |
124 size_t init_byte_size = collector_policy()->initial_heap_byte_size(); |
129 size_t init_byte_size = collector_policy()->initial_heap_byte_size(); |
125 size_t max_byte_size = collector_policy()->max_heap_byte_size(); |
130 size_t max_byte_size = collector_policy()->max_heap_byte_size(); |
126 size_t heap_alignment = collector_policy()->heap_alignment(); |
131 size_t heap_alignment = collector_policy()->heap_alignment(); |
|
132 |
|
133 size_t reg_size_bytes = ShenandoahHeapRegion::region_size_bytes(); |
127 |
134 |
128 if (ShenandoahAlwaysPreTouch) { |
135 if (ShenandoahAlwaysPreTouch) { |
129 // Enabled pre-touch means the entire heap is committed right away. |
136 // Enabled pre-touch means the entire heap is committed right away. |
130 init_byte_size = max_byte_size; |
137 init_byte_size = max_byte_size; |
131 } |
138 } |
132 |
139 |
133 Universe::check_alignment(max_byte_size, |
140 Universe::check_alignment(max_byte_size, reg_size_bytes, "Shenandoah heap"); |
134 ShenandoahHeapRegion::region_size_bytes(), |
141 Universe::check_alignment(init_byte_size, reg_size_bytes, "Shenandoah heap"); |
135 "shenandoah heap"); |
|
136 Universe::check_alignment(init_byte_size, |
|
137 ShenandoahHeapRegion::region_size_bytes(), |
|
138 "shenandoah heap"); |
|
139 |
|
140 ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size, |
|
141 heap_alignment); |
|
142 initialize_reserved_region((HeapWord*)heap_rs.base(), (HeapWord*) (heap_rs.base() + heap_rs.size())); |
|
143 |
|
144 ReservedSpace pgc_rs = heap_rs.first_part(max_byte_size); |
|
145 |
142 |
146 _num_regions = ShenandoahHeapRegion::region_count(); |
143 _num_regions = ShenandoahHeapRegion::region_count(); |
147 |
144 |
148 size_t num_committed_regions = init_byte_size / ShenandoahHeapRegion::region_size_bytes(); |
145 size_t num_committed_regions = init_byte_size / reg_size_bytes; |
149 num_committed_regions = MIN2(num_committed_regions, _num_regions); |
146 num_committed_regions = MIN2(num_committed_regions, _num_regions); |
150 assert(num_committed_regions <= _num_regions, "sanity"); |
147 assert(num_committed_regions <= _num_regions, "sanity"); |
151 |
148 |
152 _initial_size = num_committed_regions * ShenandoahHeapRegion::region_size_bytes(); |
149 _initial_size = num_committed_regions * reg_size_bytes; |
153 _committed = _initial_size; |
150 _committed = _initial_size; |
154 |
151 |
155 log_info(gc, heap)("Initialize Shenandoah heap with initial size " SIZE_FORMAT "%s", |
152 size_t heap_page_size = UseLargePages ? (size_t)os::large_page_size() : (size_t)os::vm_page_size(); |
156 byte_size_in_proper_unit(_initial_size), proper_unit_for_byte_size(_initial_size)); |
153 size_t bitmap_page_size = UseLargePages ? (size_t)os::large_page_size() : (size_t)os::vm_page_size(); |
157 if (!os::commit_memory(pgc_rs.base(), _initial_size, false)) { |
154 |
158 vm_exit_out_of_memory(_initial_size, OOM_MMAP_ERROR, "Shenandoah failed to initialize heap"); |
155 // |
159 } |
156 // Reserve and commit memory for heap |
160 |
157 // |
161 size_t reg_size_words = ShenandoahHeapRegion::region_size_words(); |
158 |
162 size_t reg_size_bytes = ShenandoahHeapRegion::region_size_bytes(); |
159 ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size, heap_alignment); |
163 |
160 initialize_reserved_region((HeapWord*)heap_rs.base(), (HeapWord*) (heap_rs.base() + heap_rs.size())); |
164 _regions = NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, _num_regions, mtGC); |
161 _heap_region = MemRegion((HeapWord*)heap_rs.base(), heap_rs.size() / HeapWordSize); |
165 _free_set = new ShenandoahFreeSet(this, _num_regions); |
|
166 |
|
167 _collection_set = new ShenandoahCollectionSet(this, (HeapWord*)pgc_rs.base()); |
|
168 |
|
169 if (ShenandoahPacing) { |
|
170 _pacer = new ShenandoahPacer(this); |
|
171 _pacer->setup_for_idle(); |
|
172 } else { |
|
173 _pacer = NULL; |
|
174 } |
|
175 |
162 |
176 assert((((size_t) base()) & ShenandoahHeapRegion::region_size_bytes_mask()) == 0, |
163 assert((((size_t) base()) & ShenandoahHeapRegion::region_size_bytes_mask()) == 0, |
177 "misaligned heap: " PTR_FORMAT, p2i(base())); |
164 "Misaligned heap: " PTR_FORMAT, p2i(base())); |
178 |
165 |
179 // The call below uses stuff (the SATB* things) that are in G1, but probably |
166 ReservedSpace sh_rs = heap_rs.first_part(max_byte_size); |
180 // belong into a shared location. |
167 os::commit_memory_or_exit(sh_rs.base(), _initial_size, false, |
181 ShenandoahBarrierSet::satb_mark_queue_set().initialize(this, |
168 "Cannot commit heap memory"); |
182 SATB_Q_CBL_mon, |
169 |
183 20 /* G1SATBProcessCompletedThreshold */, |
170 // |
184 60 /* G1SATBBufferEnqueueingThresholdPercent */); |
171 // Reserve and commit memory for bitmap(s) |
185 |
172 // |
186 // Reserve space for prev and next bitmap. |
173 |
187 size_t bitmap_page_size = UseLargePages ? (size_t)os::large_page_size() : (size_t)os::vm_page_size(); |
|
188 _bitmap_size = MarkBitMap::compute_size(heap_rs.size()); |
174 _bitmap_size = MarkBitMap::compute_size(heap_rs.size()); |
189 _bitmap_size = align_up(_bitmap_size, bitmap_page_size); |
175 _bitmap_size = align_up(_bitmap_size, bitmap_page_size); |
190 _heap_region = MemRegion((HeapWord*) heap_rs.base(), heap_rs.size() / HeapWordSize); |
|
191 |
176 |
192 size_t bitmap_bytes_per_region = reg_size_bytes / MarkBitMap::heap_map_factor(); |
177 size_t bitmap_bytes_per_region = reg_size_bytes / MarkBitMap::heap_map_factor(); |
193 |
178 |
194 guarantee(bitmap_bytes_per_region != 0, |
179 guarantee(bitmap_bytes_per_region != 0, |
195 "Bitmap bytes per region should not be zero"); |
180 "Bitmap bytes per region should not be zero"); |
210 |
195 |
211 guarantee(((_bitmap_bytes_per_slice) % bitmap_page_size) == 0, |
196 guarantee(((_bitmap_bytes_per_slice) % bitmap_page_size) == 0, |
212 "Bitmap slices should be page-granular: bps = " SIZE_FORMAT ", page size = " SIZE_FORMAT, |
197 "Bitmap slices should be page-granular: bps = " SIZE_FORMAT ", page size = " SIZE_FORMAT, |
213 _bitmap_bytes_per_slice, bitmap_page_size); |
198 _bitmap_bytes_per_slice, bitmap_page_size); |
214 |
199 |
215 ReservedSpace bitmap0(_bitmap_size, bitmap_page_size); |
200 ReservedSpace bitmap(_bitmap_size, bitmap_page_size); |
216 MemTracker::record_virtual_memory_type(bitmap0.base(), mtGC); |
201 MemTracker::record_virtual_memory_type(bitmap.base(), mtGC); |
217 _bitmap_region = MemRegion((HeapWord*) bitmap0.base(), bitmap0.size() / HeapWordSize); |
202 _bitmap_region = MemRegion((HeapWord*) bitmap.base(), bitmap.size() / HeapWordSize); |
218 |
203 |
219 size_t bitmap_init_commit = _bitmap_bytes_per_slice * |
204 size_t bitmap_init_commit = _bitmap_bytes_per_slice * |
220 align_up(num_committed_regions, _bitmap_regions_per_slice) / _bitmap_regions_per_slice; |
205 align_up(num_committed_regions, _bitmap_regions_per_slice) / _bitmap_regions_per_slice; |
221 bitmap_init_commit = MIN2(_bitmap_size, bitmap_init_commit); |
206 bitmap_init_commit = MIN2(_bitmap_size, bitmap_init_commit); |
222 os::commit_memory_or_exit((char *) (_bitmap_region.start()), bitmap_init_commit, false, |
207 os::commit_memory_or_exit((char *)_bitmap_region.start(), bitmap_init_commit, false, |
223 "couldn't allocate initial bitmap"); |
208 "Cannot commit bitmap memory"); |
224 |
209 |
225 size_t page_size = UseLargePages ? (size_t)os::large_page_size() : (size_t)os::vm_page_size(); |
210 _marking_context = new ShenandoahMarkingContext(_heap_region, _bitmap_region, _num_regions); |
226 |
211 |
227 if (ShenandoahVerify) { |
212 if (ShenandoahVerify) { |
228 ReservedSpace verify_bitmap(_bitmap_size, page_size); |
213 ReservedSpace verify_bitmap(_bitmap_size, bitmap_page_size); |
229 os::commit_memory_or_exit(verify_bitmap.base(), verify_bitmap.size(), false, |
214 os::commit_memory_or_exit(verify_bitmap.base(), verify_bitmap.size(), false, |
230 "couldn't allocate verification bitmap"); |
215 "Cannot commit verification bitmap memory"); |
231 MemTracker::record_virtual_memory_type(verify_bitmap.base(), mtGC); |
216 MemTracker::record_virtual_memory_type(verify_bitmap.base(), mtGC); |
232 MemRegion verify_bitmap_region = MemRegion((HeapWord *) verify_bitmap.base(), verify_bitmap.size() / HeapWordSize); |
217 MemRegion verify_bitmap_region = MemRegion((HeapWord *) verify_bitmap.base(), verify_bitmap.size() / HeapWordSize); |
233 _verification_bit_map.initialize(_heap_region, verify_bitmap_region); |
218 _verification_bit_map.initialize(_heap_region, verify_bitmap_region); |
234 _verifier = new ShenandoahVerifier(this, &_verification_bit_map); |
219 _verifier = new ShenandoahVerifier(this, &_verification_bit_map); |
235 } |
|
236 |
|
237 _marking_context = new ShenandoahMarkingContext(_heap_region, _bitmap_region, _num_regions); |
|
238 |
|
239 { |
|
240 ShenandoahHeapLocker locker(lock()); |
|
241 for (size_t i = 0; i < _num_regions; i++) { |
|
242 ShenandoahHeapRegion* r = new ShenandoahHeapRegion(this, |
|
243 (HeapWord*) pgc_rs.base() + reg_size_words * i, |
|
244 reg_size_words, |
|
245 i, |
|
246 i < num_committed_regions); |
|
247 |
|
248 _marking_context->initialize_top_at_mark_start(r); |
|
249 _regions[i] = r; |
|
250 assert(!collection_set()->is_in(i), "New region should not be in collection set"); |
|
251 } |
|
252 |
|
253 // Initialize to complete |
|
254 _marking_context->mark_complete(); |
|
255 |
|
256 _free_set->rebuild(); |
|
257 } |
|
258 |
|
259 if (ShenandoahAlwaysPreTouch) { |
|
260 assert (!AlwaysPreTouch, "Should have been overridden"); |
|
261 |
|
262 // For NUMA, it is important to pre-touch the storage under bitmaps with worker threads, |
|
263 // before initialize() below zeroes it with initializing thread. For any given region, |
|
264 // we touch the region and the corresponding bitmaps from the same thread. |
|
265 ShenandoahPushWorkerScope scope(workers(), _max_workers, false); |
|
266 |
|
267 log_info(gc, heap)("Parallel pretouch " SIZE_FORMAT " regions with " SIZE_FORMAT " byte pages", |
|
268 _num_regions, page_size); |
|
269 ShenandoahPretouchTask cl(bitmap0.base(), _bitmap_size, page_size); |
|
270 _workers->run_task(&cl); |
|
271 } |
220 } |
272 |
221 |
273 // Reserve aux bitmap for use in object_iterate(). We don't commit it here. |
222 // Reserve aux bitmap for use in object_iterate(). We don't commit it here. |
274 ReservedSpace aux_bitmap(_bitmap_size, bitmap_page_size); |
223 ReservedSpace aux_bitmap(_bitmap_size, bitmap_page_size); |
275 MemTracker::record_virtual_memory_type(aux_bitmap.base(), mtGC); |
224 MemTracker::record_virtual_memory_type(aux_bitmap.base(), mtGC); |
276 _aux_bitmap_region = MemRegion((HeapWord*) aux_bitmap.base(), aux_bitmap.size() / HeapWordSize); |
225 _aux_bitmap_region = MemRegion((HeapWord*) aux_bitmap.base(), aux_bitmap.size() / HeapWordSize); |
277 _aux_bit_map.initialize(_heap_region, _aux_bitmap_region); |
226 _aux_bit_map.initialize(_heap_region, _aux_bitmap_region); |
278 |
227 |
279 _traversal_gc = heuristics()->can_do_traversal_gc() ? |
228 // |
280 new ShenandoahTraversalGC(this, _num_regions) : |
229 // Create regions and region sets |
281 NULL; |
230 // |
282 |
231 |
283 _monitoring_support = new ShenandoahMonitoringSupport(this); |
232 _regions = NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, _num_regions, mtGC); |
284 |
233 _free_set = new ShenandoahFreeSet(this, _num_regions); |
285 _phase_timings = new ShenandoahPhaseTimings(); |
234 _collection_set = new ShenandoahCollectionSet(this, (HeapWord*)sh_rs.base()); |
286 |
235 |
287 if (ShenandoahAllocationTrace) { |
236 { |
288 _alloc_tracker = new ShenandoahAllocTracker(); |
237 ShenandoahHeapLocker locker(lock()); |
289 } |
238 |
290 |
239 size_t size_words = ShenandoahHeapRegion::region_size_words(); |
291 ShenandoahStringDedup::initialize(); |
240 |
292 |
241 for (size_t i = 0; i < _num_regions; i++) { |
293 _control_thread = new ShenandoahControlThread(); |
242 HeapWord* start = (HeapWord*)sh_rs.base() + size_words * i; |
294 |
243 bool is_committed = i < num_committed_regions; |
295 ShenandoahCodeRoots::initialize(); |
244 ShenandoahHeapRegion* r = new ShenandoahHeapRegion(this, start, size_words, i, is_committed); |
296 |
245 |
297 log_info(gc, init)("Safepointing mechanism: %s", |
246 _marking_context->initialize_top_at_mark_start(r); |
298 SafepointMechanism::uses_thread_local_poll() ? "thread-local poll" : |
247 _regions[i] = r; |
299 (SafepointMechanism::uses_global_page_poll() ? "global-page poll" : "unknown")); |
248 assert(!collection_set()->is_in(i), "New region should not be in collection set"); |
|
249 } |
|
250 |
|
251 // Initialize to complete |
|
252 _marking_context->mark_complete(); |
|
253 |
|
254 _free_set->rebuild(); |
|
255 } |
|
256 |
|
257 if (ShenandoahAlwaysPreTouch) { |
|
258 assert(!AlwaysPreTouch, "Should have been overridden"); |
|
259 |
|
260 // For NUMA, it is important to pre-touch the storage under bitmaps with worker threads, |
|
261 // before initialize() below zeroes it with initializing thread. For any given region, |
|
262 // we touch the region and the corresponding bitmaps from the same thread. |
|
263 ShenandoahPushWorkerScope scope(workers(), _max_workers, false); |
|
264 |
|
265 log_info(gc, init)("Pretouch " SIZE_FORMAT " regions; page sizes: " SIZE_FORMAT " heap, " SIZE_FORMAT " bitmap", |
|
266 _num_regions, heap_page_size, bitmap_page_size); |
|
267 ShenandoahPretouchTask cl(bitmap.base(), _bitmap_size, heap_page_size, bitmap_page_size); |
|
268 _workers->run_task(&cl); |
|
269 } |
|
270 |
|
271 // |
|
272 // Initialize the rest of GC subsystems |
|
273 // |
300 |
274 |
301 _liveness_cache = NEW_C_HEAP_ARRAY(jushort*, _max_workers, mtGC); |
275 _liveness_cache = NEW_C_HEAP_ARRAY(jushort*, _max_workers, mtGC); |
302 for (uint worker = 0; worker < _max_workers; worker++) { |
276 for (uint worker = 0; worker < _max_workers; worker++) { |
303 _liveness_cache[worker] = NEW_C_HEAP_ARRAY(jushort, _num_regions, mtGC); |
277 _liveness_cache[worker] = NEW_C_HEAP_ARRAY(jushort, _num_regions, mtGC); |
304 Copy::fill_to_bytes(_liveness_cache[worker], _num_regions * sizeof(jushort)); |
278 Copy::fill_to_bytes(_liveness_cache[worker], _num_regions * sizeof(jushort)); |
305 } |
279 } |
|
280 |
|
281 // The call below uses stuff (the SATB* things) that are in G1, but probably |
|
282 // belong into a shared location. |
|
283 ShenandoahBarrierSet::satb_mark_queue_set().initialize(this, |
|
284 SATB_Q_CBL_mon, |
|
285 20 /* G1SATBProcessCompletedThreshold */, |
|
286 60 /* G1SATBBufferEnqueueingThresholdPercent */); |
|
287 |
|
288 _monitoring_support = new ShenandoahMonitoringSupport(this); |
|
289 _phase_timings = new ShenandoahPhaseTimings(); |
|
290 ShenandoahStringDedup::initialize(); |
|
291 ShenandoahCodeRoots::initialize(); |
|
292 |
|
293 if (ShenandoahAllocationTrace) { |
|
294 _alloc_tracker = new ShenandoahAllocTracker(); |
|
295 } |
|
296 |
|
297 if (ShenandoahPacing) { |
|
298 _pacer = new ShenandoahPacer(this); |
|
299 _pacer->setup_for_idle(); |
|
300 } else { |
|
301 _pacer = NULL; |
|
302 } |
|
303 |
|
304 _traversal_gc = heuristics()->can_do_traversal_gc() ? |
|
305 new ShenandoahTraversalGC(this, _num_regions) : |
|
306 NULL; |
|
307 |
|
308 _control_thread = new ShenandoahControlThread(); |
|
309 |
|
310 log_info(gc, init)("Initialize Shenandoah heap with initial size " SIZE_FORMAT "%s", |
|
311 byte_size_in_proper_unit(_initial_size), proper_unit_for_byte_size(_initial_size)); |
|
312 |
|
313 log_info(gc, init)("Safepointing mechanism: %s", |
|
314 SafepointMechanism::uses_thread_local_poll() ? "thread-local poll" : |
|
315 (SafepointMechanism::uses_global_page_poll() ? "global-page poll" : "unknown")); |
306 |
316 |
307 return JNI_OK; |
317 return JNI_OK; |
308 } |
318 } |
309 |
319 |
310 void ShenandoahHeap::initialize_heuristics() { |
320 void ShenandoahHeap::initialize_heuristics() { |