< prev index next >
src/share/vm/gc_implementation/g1/satbQueue.cpp
Print this page
rev 7327 : 8075215: SATB buffer processing found reclaimed humongous object
Summary: Don't assume SATB buffer entries are valid objects
Reviewed-by: brutisso, ecaspole
*** 27,36 ****
--- 27,37 ----
#include "gc_implementation/g1/satbQueue.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/sharedHeap.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/mutexLocker.hpp"
+ #include "runtime/safepoint.hpp"
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
*** 160,173 ****
bool ObjPtrQueue::should_enqueue_buffer() {
assert(_lock == NULL || _lock->owned_by_self(),
"we should have taken the lock before calling this");
! // Even if G1SATBBufferEnqueueingThresholdPercent == 0 we have to
! // filter the buffer given that this will remove any references into
! // the CSet as we currently assume that no such refs will appear in
! // enqueued buffers.
// This method should only be called if there is a non-NULL buffer
// that is full.
assert(_index == 0, "pre-condition");
assert(_buf != NULL, "pre-condition");
--- 161,171 ----
bool ObjPtrQueue::should_enqueue_buffer() {
assert(_lock == NULL || _lock->owned_by_self(),
"we should have taken the lock before calling this");
! // If G1SATBBufferEnqueueingThresholdPercent == 0 we could skip filtering.
// This method should only be called if there is a non-NULL buffer
// that is full.
assert(_index == 0, "pre-condition");
assert(_buf != NULL, "pre-condition");
*** 180,208 ****
size_t perc = retained_entries * 100 / all_entries;
bool should_enqueue = perc > (size_t) G1SATBBufferEnqueueingThresholdPercent;
return should_enqueue;
}
! void ObjPtrQueue::apply_closure_and_empty(ObjectClosure* cl) {
if (_buf != NULL) {
! apply_closure_to_buffer(cl, _buf, _index, _sz);
_index = _sz;
}
}
- void ObjPtrQueue::apply_closure_to_buffer(ObjectClosure* cl,
- void** buf, size_t index, size_t sz) {
- if (cl == NULL) return;
- for (size_t i = index; i < sz; i += oopSize) {
- oop obj = (oop)buf[byte_index_to_index((int)i)];
- // There can be NULL entries because of destructors.
- if (obj != NULL) {
- cl->do_object(obj);
- }
- }
- }
-
#ifndef PRODUCT
// Helpful for debugging
void ObjPtrQueue::print(const char* name) {
print(name, _buf, _index, _sz);
--- 178,200 ----
size_t perc = retained_entries * 100 / all_entries;
bool should_enqueue = perc > (size_t) G1SATBBufferEnqueueingThresholdPercent;
return should_enqueue;
}
! void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
! assert(SafepointSynchronize::is_at_safepoint(),
! "SATB queues must only be processed at safepoints");
if (_buf != NULL) {
! assert(_index % sizeof(void*) == 0, "invariant");
! assert(_sz % sizeof(void*) == 0, "invariant");
! assert(_index <= _sz, "invariant");
! cl->do_buffer(_buf + byte_index_to_index((int)_index),
! byte_index_to_index((int)(_sz - _index)));
_index = _sz;
}
}
#ifndef PRODUCT
// Helpful for debugging
void ObjPtrQueue::print(const char* name) {
print(name, _buf, _index, _sz);
*** 289,299 ****
t->satb_mark_queue().filter();
}
shared_satb_queue()->filter();
}
! bool SATBMarkQueueSet::apply_closure_to_completed_buffer(ObjectClosure* cl) {
BufferNode* nd = NULL;
{
MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
if (_completed_buffers_head != NULL) {
nd = _completed_buffers_head;
--- 281,291 ----
t->satb_mark_queue().filter();
}
shared_satb_queue()->filter();
}
! bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
BufferNode* nd = NULL;
{
MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
if (_completed_buffers_head != NULL) {
nd = _completed_buffers_head;
*** 303,313 ****
if (_n_completed_buffers == 0) _process_completed = false;
}
}
if (nd != NULL) {
void **buf = BufferNode::make_buffer_from_node(nd);
! ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz);
deallocate_buffer(buf);
return true;
} else {
return false;
}
--- 295,316 ----
if (_n_completed_buffers == 0) _process_completed = false;
}
}
if (nd != NULL) {
void **buf = BufferNode::make_buffer_from_node(nd);
! // Skip over NULL entries at beginning (e.g. push end) of buffer.
! // Filtering can result in non-full completed buffers; see
! // should_enqueue_buffer.
! assert(_sz % sizeof(void*) == 0, "invariant");
! size_t limit = ObjPtrQueue::byte_index_to_index((int)_sz);
! for (size_t i = 0; i < limit; ++i) {
! if (buf[i] != NULL) {
! // Found the end of the block of NULLs; process the remainder.
! cl->do_buffer(buf + i, limit - i);
! break;
! }
! }
deallocate_buffer(buf);
return true;
} else {
return false;
}
< prev index next >