< prev index next >
src/share/vm/gc/g1/g1ConcurrentMark.hpp
Print this page
rev 11974 : imported patch 8159422-high-mark-stack-contention
rev 11975 : imported patch 8159422-mikael-review
rev 11977 : imported patch 8159422-kim-review
rev 11978 : imported patch 8159422-kim-review2
*** 150,160 ****
// Stores oops in a huge buffer in virtual memory that is always fully committed.
// Resizing may only happen during a STW pause when the stack is empty.
//
// Memory is allocated on a "chunk" basis, i.e. a set of oops. For this, the mark
// stack memory is split into evenly sized chunks of oops. Users can only
! // add an remove entries on that basis.
// Chunks are filled in increasing address order. Not completely filled chunks
// have a NULL element as a terminating element.
//
// Every chunk has a header containing a single pointer element used for memory
// management. This wastes some space, but is negligible (< .1% with current sizing).
--- 150,160 ----
// Stores oops in a huge buffer in virtual memory that is always fully committed.
// Resizing may only happen during a STW pause when the stack is empty.
//
// Memory is allocated on a "chunk" basis, i.e. a set of oops. For this, the mark
// stack memory is split into evenly sized chunks of oops. Users can only
! // add or remove entries on that basis.
// Chunks are filled in increasing address order. Not completely filled chunks
// have a NULL element as a terminating element.
//
// Every chunk has a header containing a single pointer element used for memory
// management. This wastes some space, but is negligible (< .1% with current sizing).
*** 181,207 ****
OopChunk* volatile _free_list; // Linked list of free chunks that can be allocated by users.
char _pad1[DEFAULT_CACHE_LINE_SIZE - sizeof(OopChunk*)];
OopChunk* volatile _chunk_list; // List of chunks currently containing data.
char _pad2[DEFAULT_CACHE_LINE_SIZE - sizeof(OopChunk*)];
- size_t volatile _chunks_in_chunk_list;
- char _pad3[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)];
-
volatile size_t _hwm; // High water mark within the reserved space.
char _pad4[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)];
// Allocate a new chunk from the reserved memory, using the high water mark. Returns
// NULL if out of memory.
OopChunk* allocate_new_chunk();
! bool _out_of_memory;
// Atomically add the given chunk to the list.
void add_chunk_to_list(OopChunk* volatile* list, OopChunk* elem);
// Atomically remove and return a chunk from the given list. Returns NULL if the
// list is empty.
! OopChunk* remove_chunk_from_list(OopChunk* volatile* list); bool _should_expand;
// Resizes the mark stack to the given new capacity. Releases any previous
// memory if successful.
bool resize(size_t new_capacity);
--- 181,214 ----
OopChunk* volatile _free_list; // Linked list of free chunks that can be allocated by users.
char _pad1[DEFAULT_CACHE_LINE_SIZE - sizeof(OopChunk*)];
OopChunk* volatile _chunk_list; // List of chunks currently containing data.
char _pad2[DEFAULT_CACHE_LINE_SIZE - sizeof(OopChunk*)];
volatile size_t _hwm; // High water mark within the reserved space.
char _pad4[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)];
// Allocate a new chunk from the reserved memory, using the high water mark. Returns
// NULL if out of memory.
OopChunk* allocate_new_chunk();
! volatile size_t _chunks_in_chunk_list;
!
! volatile bool _out_of_memory;
// Atomically add the given chunk to the list.
void add_chunk_to_list(OopChunk* volatile* list, OopChunk* elem);
// Atomically remove and return a chunk from the given list. Returns NULL if the
// list is empty.
! OopChunk* remove_chunk_from_list(OopChunk* volatile* list);
!
! void add_chunk_to_chunk_list(OopChunk* elem);
! void add_chunk_to_free_list(OopChunk* elem);
!
! OopChunk* remove_chunk_from_chunk_list();
! OopChunk* remove_chunk_from_free_list();
!
! bool _should_expand;
// Resizes the mark stack to the given new capacity. Releases any previous
// memory if successful.
bool resize(size_t new_capacity);
*** 216,233 ****
bool initialize(size_t initial_capacity, size_t max_capacity);
// Pushes the given buffer containing at most OopsPerChunk elements on the mark
// stack. If less than OopsPerChunk elements are to be pushed, the array must
// be terminated with a NULL.
! void par_push_chunk(oop* buffer);
// Pops a chunk from this mark stack, copying them into the given buffer. This
// chunk may contain up to OopsPerChunk elements. If there are less, the last
// element in the array is a NULL pointer.
bool par_pop_chunk(oop* buffer);
! bool is_empty() const { return _chunk_list == NULL && _chunks_in_chunk_list == 0; }
size_t capacity() const { return _chunk_capacity; }
bool is_out_of_memory() const { return _out_of_memory; }
void clear_out_of_memory() { _out_of_memory = false; }
--- 223,244 ----
bool initialize(size_t initial_capacity, size_t max_capacity);
// Pushes the given buffer containing at most OopsPerChunk elements on the mark
// stack. If less than OopsPerChunk elements are to be pushed, the array must
// be terminated with a NULL.
! // Returns whether the buffer contents were successfully pushed to the global mark
! // stack.
! bool par_push_chunk(oop* buffer);
// Pops a chunk from this mark stack, copying them into the given buffer. This
// chunk may contain up to OopsPerChunk elements. If there are less, the last
// element in the array is a NULL pointer.
bool par_pop_chunk(oop* buffer);
! // Return whether the chunk list is empty. Racy due to unsynchronized access to
! // _chunk_list.
! bool is_empty() const { return _chunk_list == NULL; }
size_t capacity() const { return _chunk_capacity; }
bool is_out_of_memory() const { return _out_of_memory; }
void clear_out_of_memory() { _out_of_memory = false; }
*** 244,254 ****
void set_empty();
// Apply Fn to every oop on the mark stack. The mark stack must not
// be modified while iterating.
! template<typename Fn> void iterate(Fn fn) PRODUCT_RETURN;
};
// Root Regions are regions that are not empty at the beginning of a
// marking cycle and which we might collect during an evacuation pause
// while the cycle is active. Given that, during evacuation pauses, we
--- 255,265 ----
void set_empty();
// Apply Fn to every oop on the mark stack. The mark stack must not
// be modified while iterating.
! template<typename Fn> void iterate(Fn fn) const PRODUCT_RETURN;
};
// Root Regions are regions that are not empty at the beginning of a
// marking cycle and which we might collect during an evacuation pause
// while the cycle is active. Given that, during evacuation pauses, we
*** 519,530 ****
public:
// Manipulation of the global mark stack.
// The push and pop operations are used by tasks for transfers
// between task-local queues and the global mark stack.
bool mark_stack_push(oop* arr) {
! _global_mark_stack.par_push_chunk(arr);
! if (_global_mark_stack.is_out_of_memory()) {
set_has_overflown();
return false;
}
return true;
}
--- 530,540 ----
public:
// Manipulation of the global mark stack.
// The push and pop operations are used by tasks for transfers
// between task-local queues and the global mark stack.
bool mark_stack_push(oop* arr) {
! if (!_global_mark_stack.par_push_chunk(arr)) {
set_has_overflown();
return false;
}
return true;
}
< prev index next >