< 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 >