218 if (_special) {
219 // Mark that memory is dirty. If committed again the memory might
220 // need to be cleared explicitly.
221 _dirty.set_range(start_page, end_page);
222 } else {
223 uncommit_internal(start_page, end_page);
224 }
225
226 _committed.clear_range(start_page, end_page);
227 }
228
229 class G1PretouchTask : public AbstractGangTask {
230 private:
231 char* volatile _cur_addr;
232 char* const _start_addr;
233 char* const _end_addr;
234 size_t const _page_size;
235 public:
236 G1PretouchTask(char* start_address, char* end_address, size_t page_size) :
237 AbstractGangTask("G1 PreTouch",
238 Universe::is_fully_initialized() ? GCId::current_raw() :
239 // During VM initialization there is
240 // no GC cycle that this task can be
241 // associated with.
242 GCId::undefined()),
243 _cur_addr(start_address),
244 _start_addr(start_address),
245 _end_addr(end_address),
246 _page_size(page_size) {
247 }
248
249 virtual void work(uint worker_id) {
250 size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
251 while (true) {
252 char* touch_addr = (char*)Atomic::add_ptr((intptr_t)actual_chunk_size, (volatile void*) &_cur_addr) - actual_chunk_size;
253 if (touch_addr < _start_addr || touch_addr >= _end_addr) {
254 break;
255 }
256 char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
257 os::pretouch_memory(touch_addr, end_addr, _page_size);
258 }
259 }
260
261 static size_t chunk_size() { return PreTouchParallelChunkSize; }
262 };
263
264 void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
265 guarantee(pretouch_gang != NULL, "No pretouch gang specified.");
266
267 size_t num_chunks = MAX2((size_t)1, size_in_pages * _page_size / MAX2(G1PretouchTask::chunk_size(), _page_size));
268
269 uint num_workers = MIN2((uint)num_chunks, pretouch_gang->active_workers());
270 G1PretouchTask cl(page_start(start_page), bounded_end_addr(start_page + size_in_pages), _page_size);
271 log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
272 cl.name(), num_workers, num_chunks, size_in_pages * _page_size);
273 pretouch_gang->run_task(&cl, num_workers);
274 }
275
276 bool G1PageBasedVirtualSpace::contains(const void* p) const {
277 return _low_boundary <= (const char*) p && (const char*) p < _high_boundary;
278 }
279
280 #ifndef PRODUCT
281 void G1PageBasedVirtualSpace::print_on(outputStream* out) {
282 out->print ("Virtual space:");
283 if (_special) out->print(" (pinned in memory)");
284 out->cr();
285 out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
286 out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
287 out->print_cr(" - preferred page size: " SIZE_FORMAT, _page_size);
288 out->print_cr(" - [low_b, high_b]: [" PTR_FORMAT ", " PTR_FORMAT "]", p2i(_low_boundary), p2i(_high_boundary));
289 }
290
291 void G1PageBasedVirtualSpace::print() {
292 print_on(tty);
293 }
|
218 if (_special) {
219 // Mark that memory is dirty. If committed again the memory might
220 // need to be cleared explicitly.
221 _dirty.set_range(start_page, end_page);
222 } else {
223 uncommit_internal(start_page, end_page);
224 }
225
226 _committed.clear_range(start_page, end_page);
227 }
228
229 class G1PretouchTask : public AbstractGangTask {
230 private:
231 char* volatile _cur_addr;
232 char* const _start_addr;
233 char* const _end_addr;
234 size_t const _page_size;
235 public:
236 G1PretouchTask(char* start_address, char* end_address, size_t page_size) :
237 AbstractGangTask("G1 PreTouch",
238 Universe::is_fully_initialized() &&
239 Thread::current()->is_Named_thread() ? GCId::current_raw() :
240 // During VM initialization there is
241 // no GC cycle that this task can be
242 // associated with.
243 GCId::undefined()),
244 _cur_addr(start_address),
245 _start_addr(start_address),
246 _end_addr(end_address),
247 _page_size(page_size) {
248 }
249
250 virtual void work(uint worker_id) {
251 size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
252 while (true) {
253 char* touch_addr = (char*)Atomic::add_ptr((intptr_t)actual_chunk_size, (volatile void*) &_cur_addr) - actual_chunk_size;
254 if (touch_addr < _start_addr || touch_addr >= _end_addr) {
255 break;
256 }
257 char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
258 os::pretouch_memory(touch_addr, end_addr, _page_size);
259 }
260 }
261
262 static size_t chunk_size() { return PreTouchParallelChunkSize; }
263 };
264
265 void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
266 G1PretouchTask cl(page_start(start_page), bounded_end_addr(start_page + size_in_pages), _page_size);
267
268 if (pretouch_gang != NULL) {
269 size_t num_chunks = MAX2((size_t)1, size_in_pages * _page_size / MAX2(G1PretouchTask::chunk_size(), _page_size));
270
271 uint num_workers = MIN2((uint)num_chunks, pretouch_gang->active_workers());
272 log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
273 cl.name(), num_workers, num_chunks, size_in_pages * _page_size);
274 pretouch_gang->run_task(&cl, num_workers);
275 } else {
276 log_debug(gc, heap)("Running %s pre-touching " SIZE_FORMAT "B.",
277 cl.name(), size_in_pages * _page_size);
278 cl.work(0);
279 }
280 }
281
282 bool G1PageBasedVirtualSpace::contains(const void* p) const {
283 return _low_boundary <= (const char*) p && (const char*) p < _high_boundary;
284 }
285
286 #ifndef PRODUCT
287 void G1PageBasedVirtualSpace::print_on(outputStream* out) {
288 out->print ("Virtual space:");
289 if (_special) out->print(" (pinned in memory)");
290 out->cr();
291 out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
292 out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
293 out->print_cr(" - preferred page size: " SIZE_FORMAT, _page_size);
294 out->print_cr(" - [low_b, high_b]: [" PTR_FORMAT ", " PTR_FORMAT "]", p2i(_low_boundary), p2i(_high_boundary));
295 }
296
297 void G1PageBasedVirtualSpace::print() {
298 print_on(tty);
299 }
|