--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu May 07 11:28:03 2015 -0700
@@ -1631,36 +1631,22 @@
NOT_LP64(__ get_thread(thread);)
- Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
- PtrQueue::byte_offset_of_active()));
-
Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_index()));
Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_buf()));
-
Label done;
Label runtime;
// Can we store original value in the thread's buffer?
-#ifdef _LP64
- __ movslq(tmp, queue_index);
- __ cmpq(tmp, 0);
-#else
- __ cmpl(queue_index, 0);
-#endif
- __ jcc(Assembler::equal, runtime);
-#ifdef _LP64
- __ subq(tmp, wordSize);
- __ movl(queue_index, tmp);
- __ addq(tmp, buffer);
-#else
- __ subl(queue_index, wordSize);
- __ movl(tmp, buffer);
- __ addl(tmp, queue_index);
-#endif
+ __ movptr(tmp, queue_index);
+ __ testptr(tmp, tmp);
+ __ jcc(Assembler::zero, runtime);
+ __ subptr(tmp, wordSize);
+ __ movptr(queue_index, tmp);
+ __ addptr(tmp, buffer);
// prev_val (rax)
f.load_argument(0, pre_val);
@@ -1713,6 +1699,7 @@
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
Label done;
+ Label enqueued;
Label runtime;
// At this point we know new_value is non-NULL and the new_value crosses regions.
@@ -1752,28 +1739,19 @@
__ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
- __ cmpl(queue_index, 0);
- __ jcc(Assembler::equal, runtime);
- __ subl(queue_index, wordSize);
-
- const Register buffer_addr = rbx;
- __ push(rbx);
-
- __ movptr(buffer_addr, buffer);
+ const Register tmp = rdx;
+ __ push(rdx);
-#ifdef _LP64
- __ movslq(rscratch1, queue_index);
- __ addptr(buffer_addr, rscratch1);
-#else
- __ addptr(buffer_addr, queue_index);
-#endif
- __ movptr(Address(buffer_addr, 0), card_addr);
-
- __ pop(rbx);
- __ jmp(done);
+ __ movptr(tmp, queue_index);
+ __ testptr(tmp, tmp);
+ __ jcc(Assembler::zero, runtime);
+ __ subptr(tmp, wordSize);
+ __ movptr(queue_index, tmp);
+ __ addptr(tmp, buffer);
+ __ movptr(Address(tmp, 0), card_addr);
+ __ jmp(enqueued);
__ bind(runtime);
- __ push(rdx);
#ifdef _LP64
__ push(r8);
__ push(r9);
@@ -1795,12 +1773,12 @@
__ pop(r9);
__ pop(r8);
#endif
+ __ bind(enqueued);
__ pop(rdx);
+
__ bind(done);
-
__ pop(rcx);
__ pop(rax);
-
}
break;
#endif // INCLUDE_ALL_GCS
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
-#define SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
#include "memory/freeList.hpp"
#include "gc_implementation/shared/allocationStats.hpp"
@@ -226,4 +226,4 @@
#endif // NOT PRODUCT
};
-#endif // SHARE_VM_MEMORY_ADAPTIVEFREELIST_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_ADAPTIVEFREELIST_HPP
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -28,6 +28,7 @@
#include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
#include "oops/oop.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
// Trim our work_queue so its length is below max at return
inline void Par_MarkRefsIntoAndScanClosure::trim_queue(uint max) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Thu May 07 11:28:03 2015 -0700
@@ -1082,17 +1082,6 @@
bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const {
FreeChunk* fc = (FreeChunk*)p;
assert(is_in_reserved(p), "Should be in space");
- // When doing a mark-sweep-compact of the CMS generation, this
- // assertion may fail because prepare_for_compaction() uses
- // space that is garbage to maintain information on ranges of
- // live objects so that these live ranges can be moved as a whole.
- // Comment out this assertion until that problem can be solved
- // (i.e., that the block start calculation may look at objects
- // at address below "p" in finding the object that contains "p"
- // and those objects (if garbage) may have been modified to hold
- // live range information.
- // assert(CollectedHeap::use_parallel_gc_threads() || _bt.block_start(p) == p,
- // "Should be a block boundary");
if (FreeChunk::indicatesFreeChunk(p)) return false;
Klass* k = oop(p)->klass_or_null();
if (k != NULL) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu May 07 11:28:03 2015 -0700
@@ -66,6 +66,7 @@
#include "services/memoryService.hpp"
#include "services/runtimeService.hpp"
#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
// statics
CMSCollector* ConcurrentMarkSweepGeneration::_collector = NULL;
@@ -224,16 +225,12 @@
"Offset of FreeChunk::_prev within FreeChunk must match"
" that of OopDesc::_klass within OopDesc");
)
- if (CollectedHeap::use_parallel_gc_threads()) {
- typedef CMSParGCThreadState* CMSParGCThreadStatePtr;
- _par_gc_thread_states =
- NEW_C_HEAP_ARRAY(CMSParGCThreadStatePtr, ParallelGCThreads, mtGC);
- for (uint i = 0; i < ParallelGCThreads; i++) {
- _par_gc_thread_states[i] = new CMSParGCThreadState(cmsSpace());
- }
- } else {
- _par_gc_thread_states = NULL;
- }
+
+ _par_gc_thread_states = NEW_C_HEAP_ARRAY(CMSParGCThreadState*, ParallelGCThreads, mtGC);
+ for (uint i = 0; i < ParallelGCThreads; i++) {
+ _par_gc_thread_states[i] = new CMSParGCThreadState(cmsSpace());
+ }
+
_incremental_collection_failed = false;
// The "dilatation_factor" is the expansion that can occur on
// account of the fact that the minimum object size in the CMS
@@ -459,7 +456,6 @@
_markBitMap(0, Mutex::leaf + 1, "CMS_markBitMap_lock"),
_modUnionTable((CardTableModRefBS::card_shift - LogHeapWordSize),
-1 /* lock-free */, "No_lock" /* dummy */),
- _modUnionClosure(&_modUnionTable),
_modUnionClosurePar(&_modUnionTable),
// Adjust my span to cover old (cms) gen
_span(cmsGen->reserved()),
@@ -2129,10 +2125,7 @@
bool registerClosure = duringMarking;
- ModUnionClosure* muc = CollectedHeap::use_parallel_gc_threads() ?
- &_modUnionClosurePar
- : &_modUnionClosure;
- _cmsGen->gc_prologue_work(full, registerClosure, muc);
+ _cmsGen->gc_prologue_work(full, registerClosure, &_modUnionClosurePar);
if (!full) {
stats().record_gc0_begin();
@@ -2905,8 +2898,8 @@
class CMSParMarkTask : public AbstractGangTask {
protected:
CMSCollector* _collector;
- int _n_workers;
- CMSParMarkTask(const char* name, CMSCollector* collector, int n_workers) :
+ uint _n_workers;
+ CMSParMarkTask(const char* name, CMSCollector* collector, uint n_workers) :
AbstractGangTask(name),
_collector(collector),
_n_workers(n_workers) {}
@@ -2920,7 +2913,7 @@
// Parallel initial mark task
class CMSParInitialMarkTask: public CMSParMarkTask {
public:
- CMSParInitialMarkTask(CMSCollector* collector, int n_workers) :
+ CMSParInitialMarkTask(CMSCollector* collector, uint n_workers) :
CMSParMarkTask("Scan roots and young gen for initial mark in parallel",
collector, n_workers) {}
void work(uint worker_id);
@@ -3005,11 +2998,11 @@
{
COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
- if (CMSParallelInitialMarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
+ if (CMSParallelInitialMarkEnabled) {
// The parallel version.
FlexibleWorkGang* workers = gch->workers();
assert(workers != NULL, "Need parallel worker threads.");
- int n_workers = workers->active_workers();
+ uint n_workers = workers->active_workers();
CMSParInitialMarkTask tsk(this, n_workers);
gch->set_par_threads(n_workers);
initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
@@ -3150,7 +3143,7 @@
// MT Concurrent Marking Task
class CMSConcMarkingTask: public YieldingFlexibleGangTask {
CMSCollector* _collector;
- int _n_workers; // requested/desired # workers
+ uint _n_workers; // requested/desired # workers
bool _result;
CompactibleFreeListSpace* _cms_space;
char _pad_front[64]; // padding to ...
@@ -3196,7 +3189,7 @@
CMSConcMarkingTerminator* terminator() { return &_term; }
- virtual void set_for_termination(int active_workers) {
+ virtual void set_for_termination(uint active_workers) {
terminator()->reset_for_reuse(active_workers);
}
@@ -3642,10 +3635,9 @@
bool CMSCollector::do_marking_mt() {
assert(ConcGCThreads > 0 && conc_workers() != NULL, "precondition");
- int num_workers = AdaptiveSizePolicy::calc_active_conc_workers(
- conc_workers()->total_workers(),
- conc_workers()->active_workers(),
- Threads::number_of_non_daemon_threads());
+ uint num_workers = AdaptiveSizePolicy::calc_active_conc_workers(conc_workers()->total_workers(),
+ conc_workers()->active_workers(),
+ Threads::number_of_non_daemon_threads());
conc_workers()->set_active_workers(num_workers);
CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();
@@ -4347,7 +4339,7 @@
// dirtied since the first checkpoint in this GC cycle and prior to
// the most recent young generation GC, minus those cleaned up by the
// concurrent precleaning.
- if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
+ if (CMSParallelRemarkEnabled) {
GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
do_remark_parallel();
} else {
@@ -4491,7 +4483,7 @@
// workers to be taken from the active workers in the work gang.
CMSParRemarkTask(CMSCollector* collector,
CompactibleFreeListSpace* cms_space,
- int n_workers, FlexibleWorkGang* workers,
+ uint n_workers, FlexibleWorkGang* workers,
OopTaskQueueSet* task_queues):
CMSParMarkTask("Rescan roots and grey objects in parallel",
collector, n_workers),
@@ -4504,7 +4496,7 @@
OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
ParallelTaskTerminator* terminator() { return &_term; }
- int n_workers() { return _n_workers; }
+ uint n_workers() { return _n_workers; }
void work(uint worker_id);
@@ -5067,7 +5059,7 @@
// Choose to use the number of GC workers most recently set
// into "active_workers". If active_workers is not set, set it
// to ParallelGCThreads.
- int n_workers = workers->active_workers();
+ uint n_workers = workers->active_workers();
if (n_workers == 0) {
assert(n_workers > 0, "Should have been set during scavenge");
n_workers = ParallelGCThreads;
@@ -5433,7 +5425,7 @@
// That is OK as long as the Reference lists are balanced (see
// balance_all_queues() and balance_queues()).
GenCollectedHeap* gch = GenCollectedHeap::heap();
- int active_workers = ParallelGCThreads;
+ uint active_workers = ParallelGCThreads;
FlexibleWorkGang* workers = gch->workers();
if (workers != NULL) {
active_workers = workers->active_workers();
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu May 07 11:28:03 2015 -0700
@@ -647,7 +647,6 @@
// Keep this textually after _markBitMap and _span; c'tor dependency.
ConcurrentMarkSweepThread* _cmsThread; // The thread doing the work
- ModUnionClosure _modUnionClosure;
ModUnionClosurePar _modUnionClosurePar;
// CMS abstract state machine
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu May 07 11:28:03 2015 -0700
@@ -54,6 +54,7 @@
#include "runtime/atomic.inline.hpp"
#include "runtime/prefetch.inline.hpp"
#include "services/memTracker.hpp"
+#include "utilities/taskqueue.inline.hpp"
// Concurrent marking bit map wrapper
@@ -2314,13 +2315,13 @@
G1CollectedHeap* _g1h;
ConcurrentMark* _cm;
WorkGang* _workers;
- int _active_workers;
+ uint _active_workers;
public:
G1CMRefProcTaskExecutor(G1CollectedHeap* g1h,
- ConcurrentMark* cm,
- WorkGang* workers,
- int n_workers) :
+ ConcurrentMark* cm,
+ WorkGang* workers,
+ uint n_workers) :
_g1h(g1h), _cm(cm),
_workers(workers), _active_workers(n_workers) { }
@@ -2551,31 +2552,50 @@
_nextMarkBitMap = (CMBitMap*) temp;
}
-class CMObjectClosure;
-
-// Closure for iterating over objects, currently only used for
-// processing SATB buffers.
-class CMObjectClosure : public ObjectClosure {
+// Closure for marking entries in SATB buffers.
+class CMSATBBufferClosure : public SATBBufferClosure {
private:
CMTask* _task;
+ G1CollectedHeap* _g1h;
+
+ // This is very similar to CMTask::deal_with_reference, but with
+ // more relaxed requirements for the argument, so this must be more
+ // circumspect about treating the argument as an object.
+ void do_entry(void* entry) const {
+ _task->increment_refs_reached();
+ HeapRegion* hr = _g1h->heap_region_containing_raw(entry);
+ if (entry < hr->next_top_at_mark_start()) {
+ // Until we get here, we don't know whether entry refers to a valid
+ // object; it could instead have been a stale reference.
+ oop obj = static_cast<oop>(entry);
+ assert(obj->is_oop(true /* ignore mark word */),
+ err_msg("Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj)));
+ _task->make_reference_grey(obj, hr);
+ }
+ }
public:
- void do_object(oop obj) {
- _task->deal_with_reference(obj);
+ CMSATBBufferClosure(CMTask* task, G1CollectedHeap* g1h)
+ : _task(task), _g1h(g1h) { }
+
+ virtual void do_buffer(void** buffer, size_t size) {
+ for (size_t i = 0; i < size; ++i) {
+ do_entry(buffer[i]);
+ }
}
-
- CMObjectClosure(CMTask* task) : _task(task) { }
};
class G1RemarkThreadsClosure : public ThreadClosure {
- CMObjectClosure _cm_obj;
+ CMSATBBufferClosure _cm_satb_cl;
G1CMOopClosure _cm_cl;
MarkingCodeBlobClosure _code_cl;
int _thread_parity;
public:
G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task) :
- _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
+ _cm_satb_cl(task, g1h),
+ _cm_cl(g1h, g1h->concurrent_mark(), task),
+ _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
_thread_parity(Threads::thread_claim_parity()) {}
void do_thread(Thread* thread) {
@@ -2591,11 +2611,11 @@
// live by the SATB invariant but other oops recorded in nmethods may behave differently.
jt->nmethods_do(&_code_cl);
- jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj);
+ jt->satb_mark_queue().apply_closure_and_empty(&_cm_satb_cl);
}
} else if (thread->is_VM_thread()) {
if (thread->claim_oops_do(true, _thread_parity)) {
- JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj);
+ JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
}
}
}
@@ -2630,7 +2650,7 @@
}
}
- CMRemarkTask(ConcurrentMark* cm, int active_workers) :
+ CMRemarkTask(ConcurrentMark* cm, uint active_workers) :
AbstractGangTask("Par Remark"), _cm(cm) {
_cm->terminator()->reset_for_reuse(active_workers);
}
@@ -3008,7 +3028,7 @@
ConcurrentMark* _cm;
BitMap* _cm_card_bm;
uint _max_worker_id;
- int _active_workers;
+ uint _active_workers;
HeapRegionClaimer _hrclaimer;
public:
@@ -3016,7 +3036,7 @@
ConcurrentMark* cm,
BitMap* cm_card_bm,
uint max_worker_id,
- int n_workers) :
+ uint n_workers) :
AbstractGangTask("Count Aggregation"),
_g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
_max_worker_id(max_worker_id),
@@ -3033,7 +3053,7 @@
void ConcurrentMark::aggregate_count_data() {
- int n_workers = _g1h->workers()->active_workers();
+ uint n_workers = _g1h->workers()->active_workers();
G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm,
_max_worker_id, n_workers);
@@ -3693,13 +3713,13 @@
// very counter productive if it did that. :-)
_draining_satb_buffers = true;
- CMObjectClosure oc(this);
+ CMSATBBufferClosure satb_cl(this, _g1h);
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
// This keeps claiming and applying the closure to completed buffers
// until we run out of buffers or we need to abort.
while (!has_aborted() &&
- satb_mq_set.apply_closure_to_completed_buffer(&oc)) {
+ satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)) {
if (_cm->verbose_medium()) {
gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id);
}
@@ -3758,6 +3778,10 @@
#endif // _MARKING_STATS_
}
+bool ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) {
+ return _task_queues->steal(worker_id, hash_seed, obj);
+}
+
/*****************************************************************************
The do_marking_step(time_target_ms, ...) method is the building
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu May 07 11:28:03 2015 -0700
@@ -139,6 +139,11 @@
static size_t compute_size(size_t heap_size);
// Returns the amount of bytes on the heap between two marks in the bitmap.
static size_t mark_distance();
+ // Returns how many bytes (or bits) of the heap a single byte (or bit) of the
+ // mark bitmap corresponds to. This is the same as the mark distance above.
+ static size_t heap_map_factor() {
+ return mark_distance();
+ }
CMBitMap() : CMBitMapRO(LogMinObjAlignment), _listener() { _listener.set_bitmap(this); }
@@ -671,9 +676,7 @@
}
// Attempts to steal an object from the task queues of other tasks
- bool try_stealing(uint worker_id, int* hash_seed, oop& obj) {
- return _task_queues->steal(worker_id, hash_seed, obj);
- }
+ bool try_stealing(uint worker_id, int* hash_seed, oop& obj);
ConcurrentMark(G1CollectedHeap* g1h,
G1RegionToSpaceMapper* prev_bitmap_storage,
@@ -1095,9 +1098,9 @@
void regular_clock_call();
bool concurrent() { return _concurrent; }
- // Test whether objAddr might have already been passed over by the
+ // Test whether obj might have already been passed over by the
// mark bitmap scan, and so needs to be pushed onto the mark stack.
- bool is_below_finger(HeapWord* objAddr, HeapWord* global_finger) const;
+ bool is_below_finger(oop obj, HeapWord* global_finger) const;
template<bool scan> void process_grey_object(oop obj);
@@ -1148,8 +1151,18 @@
void set_cm_oop_closure(G1CMOopClosure* cm_oop_closure);
- // It grays the object by marking it and, if necessary, pushing it
- // on the local queue
+ // Increment the number of references this task has visited.
+ void increment_refs_reached() { ++_refs_reached; }
+
+ // Grey the object by marking it. If not already marked, push it on
+ // the local queue if below the finger.
+ // Precondition: obj is in region.
+ // Precondition: obj is below region's NTAMS.
+ inline void make_reference_grey(oop obj, HeapRegion* region);
+
+ // Grey the object (by calling make_grey_reference) if required,
+ // e.g. obj is below its containing region's NTAMS.
+ // Precondition: obj is a valid heap object.
inline void deal_with_reference(oop obj);
// It scans an object and visits its children.
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -27,6 +27,7 @@
#include "gc_implementation/g1/concurrentMark.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
// Utility routine to set an exclusive range of cards on the given
// card liveness bitmap
@@ -259,15 +260,15 @@
++_local_pushes );
}
-inline bool CMTask::is_below_finger(HeapWord* objAddr,
- HeapWord* global_finger) const {
- // If objAddr is above the global finger, then the mark bitmap scan
+inline bool CMTask::is_below_finger(oop obj, HeapWord* global_finger) const {
+ // If obj is above the global finger, then the mark bitmap scan
// will find it later, and no push is needed. Similarly, if we have
- // a current region and objAddr is between the local finger and the
+ // a current region and obj is between the local finger and the
// end of the current region, then no push is needed. The tradeoff
// of checking both vs only checking the global finger is that the
// local check will be more accurate and so result in fewer pushes,
// but may also be a little slower.
+ HeapWord* objAddr = (HeapWord*)obj;
if (_finger != NULL) {
// We have a current region.
@@ -277,7 +278,7 @@
assert(_region_limit != NULL, "invariant");
assert(_region_limit <= global_finger, "invariant");
- // True if objAddr is less than the local finger, or is between
+ // True if obj is less than the local finger, or is between
// the region limit and the global finger.
if (objAddr < _finger) {
return true;
@@ -289,13 +290,65 @@
return objAddr < global_finger;
}
+inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) {
+ if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) {
+
+ if (_cm->verbose_high()) {
+ gclog_or_tty->print_cr("[%u] marked object " PTR_FORMAT,
+ _worker_id, p2i(obj));
+ }
+
+ // No OrderAccess:store_load() is needed. It is implicit in the
+ // CAS done in CMBitMap::parMark() call in the routine above.
+ HeapWord* global_finger = _cm->finger();
+
+ // We only need to push a newly grey object on the mark
+ // stack if it is in a section of memory the mark bitmap
+ // scan has already examined. Mark bitmap scanning
+ // maintains progress "fingers" for determining that.
+ //
+ // Notice that the global finger might be moving forward
+ // concurrently. This is not a problem. In the worst case, we
+ // mark the object while it is above the global finger and, by
+ // the time we read the global finger, it has moved forward
+ // past this object. In this case, the object will probably
+ // be visited when a task is scanning the region and will also
+ // be pushed on the stack. So, some duplicate work, but no
+ // correctness problems.
+ if (is_below_finger(obj, global_finger)) {
+ if (obj->is_typeArray()) {
+ // Immediately process arrays of primitive types, rather
+ // than pushing on the mark stack. This keeps us from
+ // adding humongous objects to the mark stack that might
+ // be reclaimed before the entry is processed - see
+ // selection of candidates for eager reclaim of humongous
+ // objects. The cost of the additional type test is
+ // mitigated by avoiding a trip through the mark stack,
+ // by only doing a bookkeeping update and avoiding the
+ // actual scan of the object - a typeArray contains no
+ // references, and the metadata is built-in.
+ process_grey_object<false>(obj);
+ } else {
+ if (_cm->verbose_high()) {
+ gclog_or_tty->print_cr("[%u] below a finger (local: " PTR_FORMAT
+ ", global: " PTR_FORMAT ") pushing "
+ PTR_FORMAT " on mark stack",
+ _worker_id, p2i(_finger),
+ p2i(global_finger), p2i(obj));
+ }
+ push(obj);
+ }
+ }
+ }
+}
+
inline void CMTask::deal_with_reference(oop obj) {
if (_cm->verbose_high()) {
gclog_or_tty->print_cr("[%u] we're dealing with reference = "PTR_FORMAT,
_worker_id, p2i((void*) obj));
}
- ++_refs_reached;
+ increment_refs_reached();
HeapWord* objAddr = (HeapWord*) obj;
assert(obj->is_oop_or_null(true /* ignore mark word */), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(obj)));
@@ -307,55 +360,7 @@
// anything with it).
HeapRegion* hr = _g1h->heap_region_containing_raw(obj);
if (!hr->obj_allocated_since_next_marking(obj)) {
- if (_cm->verbose_high()) {
- gclog_or_tty->print_cr("[%u] "PTR_FORMAT" is not considered marked",
- _worker_id, p2i((void*) obj));
- }
-
- // we need to mark it first
- if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) {
- // No OrderAccess:store_load() is needed. It is implicit in the
- // CAS done in CMBitMap::parMark() call in the routine above.
- HeapWord* global_finger = _cm->finger();
-
- // We only need to push a newly grey object on the mark
- // stack if it is in a section of memory the mark bitmap
- // scan has already examined. Mark bitmap scanning
- // maintains progress "fingers" for determining that.
- //
- // Notice that the global finger might be moving forward
- // concurrently. This is not a problem. In the worst case, we
- // mark the object while it is above the global finger and, by
- // the time we read the global finger, it has moved forward
- // past this object. In this case, the object will probably
- // be visited when a task is scanning the region and will also
- // be pushed on the stack. So, some duplicate work, but no
- // correctness problems.
- if (is_below_finger(objAddr, global_finger)) {
- if (obj->is_typeArray()) {
- // Immediately process arrays of primitive types, rather
- // than pushing on the mark stack. This keeps us from
- // adding humongous objects to the mark stack that might
- // be reclaimed before the entry is processed - see
- // selection of candidates for eager reclaim of humongous
- // objects. The cost of the additional type test is
- // mitigated by avoiding a trip through the mark stack,
- // by only doing a bookkeeping update and avoiding the
- // actual scan of the object - a typeArray contains no
- // references, and the metadata is built-in.
- process_grey_object<false>(obj);
- } else {
- if (_cm->verbose_high()) {
- gclog_or_tty->print_cr("[%u] below a finger (local: " PTR_FORMAT
- ", global: " PTR_FORMAT ") pushing "
- PTR_FORMAT " on mark stack",
- _worker_id, p2i(_finger),
- p2i(global_finger), p2i(objAddr));
- }
- push(obj);
- }
- }
- }
+ make_reference_grey(obj, hr);
}
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/evacuationInfo.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
#include "memory/allocation.hpp"
@@ -78,4 +78,4 @@
uint regions_freed() { return _regions_freed; }
};
-#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_EVACUATIONINFO_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_EVACUATIONINFO_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp Thu May 07 11:28:03 2015 -0700
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "gc_implementation/g1/g1Allocator.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/heapRegion.inline.hpp"
#include "gc_implementation/g1/heapRegionSet.inline.hpp"
@@ -119,7 +119,6 @@
size_t gclab_word_size = _g1h->desired_plab_sz(dest);
if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
G1PLAB* alloc_buf = alloc_buffer(dest, context);
- add_to_alloc_buffer_waste(alloc_buf->words_remaining());
alloc_buf->retire();
HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context);
@@ -153,8 +152,19 @@
for (uint state = 0; state < InCSetState::Num; state++) {
G1PLAB* const buf = _alloc_buffers[state];
if (buf != NULL) {
- add_to_alloc_buffer_waste(buf->words_remaining());
buf->flush_and_retire_stats(_g1h->alloc_buffer_stats(state));
}
}
}
+
+void G1DefaultParGCAllocator::waste(size_t& wasted, size_t& undo_wasted) {
+ wasted = 0;
+ undo_wasted = 0;
+ for (uint state = 0; state < InCSetState::Num; state++) {
+ G1PLAB * const buf = _alloc_buffers[state];
+ if (buf != NULL) {
+ wasted += buf->waste();
+ undo_wasted += buf->undo_waste();
+ }
+ }
+}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp Thu May 07 11:28:03 2015 -0700
@@ -188,12 +188,6 @@
// architectures have a special compare against zero instructions.
const uint _survivor_alignment_bytes;
- size_t _alloc_buffer_waste;
- size_t _undo_waste;
-
- void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
- void add_to_undo_waste(size_t waste) { _undo_waste += waste; }
-
virtual void retire_alloc_buffers() = 0;
virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
@@ -213,15 +207,12 @@
public:
G1ParGCAllocator(G1CollectedHeap* g1h) :
- _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()),
- _alloc_buffer_waste(0), _undo_waste(0) {
- }
+ _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { }
virtual ~G1ParGCAllocator() { }
static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h);
- size_t alloc_buffer_waste() { return _alloc_buffer_waste; }
- size_t undo_waste() {return _undo_waste; }
+ virtual void waste(size_t& wasted, size_t& undo_wasted) = 0;
// Allocate word_sz words in dest, either directly into the regions or by
// allocating a new PLAB. Returns the address of the allocated memory, NULL if
@@ -253,14 +244,7 @@
}
void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
- if (alloc_buffer(dest, context)->contains(obj)) {
- assert(alloc_buffer(dest, context)->contains(obj + word_sz - 1),
- "should contain whole object");
- alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
- } else {
- CollectedHeap::fill_with_object(obj, word_sz);
- add_to_undo_waste(word_sz);
- }
+ alloc_buffer(dest, context)->undo_allocation(obj, word_sz);
}
};
@@ -280,7 +264,9 @@
return _alloc_buffers[dest.value()];
}
- virtual void retire_alloc_buffers() ;
+ virtual void retire_alloc_buffers();
+
+ virtual void waste(size_t& wasted, size_t& undo_wasted);
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ALLOCATOR_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Thu May 07 11:28:03 2015 -0700
@@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.hpp"
#include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/heapRegion.hpp"
#include "memory/space.hpp"
#include "oops/oop.inline.hpp"
@@ -66,6 +66,20 @@
return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
}
+#ifdef ASSERT
+void G1BlockOffsetSharedArray::check_index(size_t index, const char* msg) const {
+ assert((index) < (_reserved.word_size() >> LogN_words),
+ err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT,
+ msg, (index), (_reserved.word_size() >> LogN_words)));
+ assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)),
+ err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT
+ " (%u) is not in committed area.",
+ (index),
+ p2i(address_for_index_raw(index)),
+ G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
+}
+#endif // ASSERT
+
//////////////////////////////////////////////////////////////////////
// G1BlockOffsetArray
//////////////////////////////////////////////////////////////////////
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Thu May 07 11:28:03 2015 -0700
@@ -170,6 +170,8 @@
bool is_card_boundary(HeapWord* p) const;
+ void check_index(size_t index, const char* msg) const NOT_DEBUG_RETURN;
+
public:
// Return the number of slots needed for an offset array
@@ -179,6 +181,11 @@
return ReservedSpace::allocation_align_size_up(number_of_slots);
}
+ // Returns how many bytes of the heap a single byte of the BOT corresponds to.
+ static size_t heap_map_factor() {
+ return N_bytes;
+ }
+
enum SomePublicConstants {
LogN = 9,
LogN_words = LogN - LogHeapWordSize,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
#include "gc_implementation/g1/g1BlockOffsetTable.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/heapRegion.inline.hpp"
#include "memory/space.hpp"
@@ -47,17 +46,6 @@
}
}
-#define check_index(index, msg) \
- assert((index) < (_reserved.word_size() >> LogN_words), \
- err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, \
- msg, (index), (_reserved.word_size() >> LogN_words))); \
- assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)), \
- err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT \
- " (%u) is not in committed area.", \
- (index), \
- p2i(address_for_index_raw(index)), \
- G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
-
u_char G1BlockOffsetSharedArray::offset_array(size_t index) const {
check_index(index, "index out of range");
return _offset_array[index];
@@ -119,8 +107,6 @@
return result;
}
-#undef check_index
-
inline size_t
G1BlockOffsetArray::block_size(const HeapWord* p) const {
return gsp()->block_size(p);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,17 @@
_counts->clear_range(mr);
}
+size_t G1CardCounts::compute_size(size_t mem_region_size_in_words) {
+ // We keep card counts for every card, so the size of the card counts table must
+ // be the same as the card table.
+ return G1SATBCardTableLoggingModRefBS::compute_size(mem_region_size_in_words);
+}
+
+size_t G1CardCounts::heap_map_factor() {
+ // See G1CardCounts::compute_size() why we reuse the card table value.
+ return G1SATBCardTableLoggingModRefBS::heap_map_factor();
+}
+
void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) {
if (has_count_table()) {
assert(from_card_num < to_card_num,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Thu May 07 11:28:03 2015 -0700
@@ -101,6 +101,14 @@
public:
G1CardCounts(G1CollectedHeap* g1h);
+ // Return the number of slots needed for a card counts table
+ // that covers mem_region_words words.
+ static size_t compute_size(size_t mem_region_size_in_words);
+
+ // Returns how many bytes of the heap a single byte of the card counts table
+ // corresponds to.
+ static size_t heap_map_factor();
+
void initialize(G1RegionToSpaceMapper* mapper);
// Increments the refinement count for the given card.
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu May 07 11:28:03 2015 -0700
@@ -66,6 +66,7 @@
#include "runtime/vmThread.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
@@ -1083,11 +1084,9 @@
class RebuildRSOutOfRegionClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h;
UpdateRSOopClosure _cl;
- int _worker_i;
public:
- RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, int worker_i = 0) :
+ RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, uint worker_i = 0) :
_cl(g1->g1_rem_set(), worker_i),
- _worker_i(worker_i),
_g1h(g1)
{ }
@@ -1166,6 +1165,7 @@
SvcGCMarker sgcm(SvcGCMarker::FULL);
ResourceMark rm;
+ G1Log::update_level();
print_heap_before_gc();
trace_heap_before_gc(gc_tracer);
@@ -1890,24 +1890,24 @@
G1RegionToSpaceMapper* bot_storage =
create_aux_memory_mapper("Block offset table",
G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize),
- G1BlockOffsetSharedArray::N_bytes);
+ G1BlockOffsetSharedArray::heap_map_factor());
ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize));
G1RegionToSpaceMapper* cardtable_storage =
create_aux_memory_mapper("Card table",
G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize),
- G1BlockOffsetSharedArray::N_bytes);
+ G1SATBCardTableLoggingModRefBS::heap_map_factor());
G1RegionToSpaceMapper* card_counts_storage =
create_aux_memory_mapper("Card counts table",
- G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize),
- G1BlockOffsetSharedArray::N_bytes);
+ G1CardCounts::compute_size(g1_rs.size() / HeapWordSize),
+ G1CardCounts::heap_map_factor());
size_t bitmap_size = CMBitMap::compute_size(g1_rs.size());
G1RegionToSpaceMapper* prev_bitmap_storage =
- create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::mark_distance());
+ create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::heap_map_factor());
G1RegionToSpaceMapper* next_bitmap_storage =
- create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::mark_distance());
+ create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::heap_map_factor());
_hrm.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage);
g1_barrier_set()->initialize(cardtable_storage);
@@ -3039,7 +3039,7 @@
assert(UseDynamicNumberOfGCThreads ||
workers()->active_workers() == workers()->total_workers(),
"If not dynamic should be using all the workers");
- int n_workers = workers()->active_workers();
+ uint n_workers = workers()->active_workers();
set_par_threads(n_workers);
workers()->run_task(&task);
set_par_threads(0);
@@ -3577,9 +3577,9 @@
print_taskqueue_stats_hdr(st);
TaskQueueStats totals;
- const int n = workers()->total_workers();
- for (int i = 0; i < n; ++i) {
- st->print("%3d ", i); task_queue(i)->stats.print(st); st->cr();
+ const uint n = workers()->total_workers();
+ for (uint i = 0; i < n; ++i) {
+ st->print("%3u ", i); task_queue(i)->stats.print(st); st->cr();
totals += task_queue(i)->stats;
}
st->print_raw("tot "); totals.print(st); st->cr();
@@ -3588,8 +3588,8 @@
}
void G1CollectedHeap::reset_taskqueue_stats() {
- const int n = workers()->total_workers();
- for (int i = 0; i < n; ++i) {
+ const uint n = workers()->total_workers();
+ for (uint i = 0; i < n; ++i) {
task_queue(i)->stats.reset();
}
}
@@ -3648,6 +3648,7 @@
SvcGCMarker sgcm(SvcGCMarker::MINOR);
ResourceMark rm;
+ G1Log::update_level();
print_heap_before_gc();
trace_heap_before_gc(_gc_tracer_stw);
@@ -4318,7 +4319,7 @@
ParallelTaskTerminator* terminator() { return &_terminator; }
- virtual void set_for_termination(int active_workers) {
+ virtual void set_for_termination(uint active_workers) {
_root_processor->set_num_workers(active_workers);
terminator()->reset_for_reuse(active_workers);
_n_workers = active_workers;
@@ -4997,13 +4998,13 @@
G1CollectedHeap* _g1h;
RefToScanQueueSet* _queues;
FlexibleWorkGang* _workers;
- int _active_workers;
+ uint _active_workers;
public:
G1STWRefProcTaskExecutor(G1CollectedHeap* g1h,
- FlexibleWorkGang* workers,
- RefToScanQueueSet *task_queues,
- int n_workers) :
+ FlexibleWorkGang* workers,
+ RefToScanQueueSet *task_queues,
+ uint n_workers) :
_g1h(g1h),
_queues(task_queues),
_workers(workers),
@@ -5136,7 +5137,7 @@
uint _n_workers;
public:
- G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h,int workers, RefToScanQueueSet *task_queues) :
+ G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, uint workers, RefToScanQueueSet *task_queues) :
AbstractGangTask("ParPreserveCMReferents"),
_g1h(g1h),
_queues(task_queues),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu May 07 11:28:03 2015 -0700
@@ -979,7 +979,7 @@
void set_refine_cte_cl_concurrency(bool concurrent);
- RefToScanQueue *task_queue(int i) const;
+ RefToScanQueue *task_queue(uint i) const;
// A set of cards where updates happened during the GC
DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -210,7 +210,7 @@
g1_barrier_set()->g1_mark_as_young(mr);
}
-inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
+inline RefToScanQueue* G1CollectedHeap::task_queue(uint i) const {
return _task_queues->queue(i);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Thu May 07 11:28:03 2015 -0700
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
#include "memory/allocation.hpp"
@@ -286,4 +286,4 @@
~G1GCParPhaseTimesTracker();
};
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMES_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Log.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Log.cpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,34 @@
#include "precompiled.hpp"
#include "gc_implementation/g1/g1_globals.hpp"
#include "gc_implementation/g1/g1Log.hpp"
-#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
G1Log::LogLevel G1Log::_level = G1Log::LevelNone;
+
+// Updates _level based on PrintGC and PrintGCDetails values (unless
+// G1LogLevel is set explicitly)
+// - PrintGC maps to "fine".
+// - PrintGCDetails maps to "finer".
+void G1Log::update_level() {
+ if (FLAG_IS_DEFAULT(G1LogLevel)) {
+ _level = LevelNone;
+ if (PrintGCDetails) {
+ _level = LevelFiner;
+ } else if (PrintGC) {
+ _level = LevelFine;
+ }
+ }
+}
+
+
// If G1LogLevel has not been set up we will use the values of PrintGC
// and PrintGCDetails for the logging level.
-// - PrintGC maps to "fine".
-// - PrintGCDetails maps to "finer".
void G1Log::init() {
- if (G1LogLevel != NULL && G1LogLevel[0] != '\0') {
- if (strncmp("none", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
+ if (!FLAG_IS_DEFAULT(G1LogLevel)) {
+ // PrintGC flags change won't have any affect, because G1LogLevel
+ // is set explicitly
+ if (G1LogLevel[0] == '\0' || strncmp("none", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
_level = LevelNone;
} else if (strncmp("fine", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
_level = LevelFine;
@@ -47,10 +64,7 @@
warning("Unknown logging level '%s', should be one of 'fine', 'finer' or 'finest'.", G1LogLevel);
}
} else {
- if (PrintGCDetails) {
- _level = LevelFiner;
- } else if (PrintGC) {
- _level = LevelFine;
- }
+ update_level();
}
}
+
--- a/hotspot/src/share/vm/gc_implementation/g1/g1Log.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1Log.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,9 @@
}
static void init();
+
+ // Update to log level to reflect runtime changes to manageable flags
+ static void update_level();
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1LOG_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -76,9 +76,6 @@
}
void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) {
- double longest_allowed = longest_pause_internal(start);
- if (longest_allowed < 0.0)
- longest_allowed = 0.0;
double duration = end - start;
remove_expired_entries(end);
@@ -111,41 +108,6 @@
// this is for trying things out in the future and a couple
// of other places (debugging)
-double G1MMUTrackerQueue::longest_pause(double current_time) {
- if (_DISABLE_MMU)
- return _max_gc_time;
-
- MutexLockerEx x(MMUTracker_lock, Mutex::_no_safepoint_check_flag);
- remove_expired_entries(current_time);
-
- return longest_pause_internal(current_time);
-}
-
-double G1MMUTrackerQueue::longest_pause_internal(double current_time) {
- double target_time = _max_gc_time;
-
- while( 1 ) {
- double gc_time =
- calculate_gc_time(current_time + target_time);
- double diff = target_time + gc_time - _max_gc_time;
- if (!is_double_leq_0(diff)) {
- target_time -= diff;
- if (is_double_leq_0(target_time)) {
- target_time = -1.0;
- break;
- }
- } else {
- break;
- }
- }
-
- return target_time;
-}
-
-// basically the _internal call does not remove expired entries
-// this is for trying things out in the future and a couple
-// of other places (debugging)
-
double G1MMUTrackerQueue::when_sec(double current_time, double pause_time) {
if (_DISABLE_MMU)
return 0.0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,6 @@
G1MMUTracker(double time_slice, double max_gc_time);
virtual void add_pause(double start, double end, bool gc_thread) = 0;
- virtual double longest_pause(double current_time) = 0;
virtual double when_sec(double current_time, double pause_time) = 0;
double max_gc_time() {
@@ -122,7 +121,6 @@
void remove_expired_entries(double current_time);
double calculate_gc_time(double current_time);
- double longest_pause_internal(double current_time);
double when_internal(double current_time, double pause_time);
public:
@@ -130,7 +128,6 @@
virtual void add_pause(double start, double end, bool gc_thread);
- virtual double longest_pause(double current_time);
virtual double when_sec(double current_time, double pause_time);
};
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Thu May 07 11:28:03 2015 -0700
@@ -29,7 +29,7 @@
#include "gc_implementation/g1/g1StringDedup.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/prefetch.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
: _g1h(g1h),
@@ -95,8 +95,9 @@
const double elapsed_ms = elapsed_time() * 1000.0;
const double s_roots_ms = strong_roots_time() * 1000.0;
const double term_ms = term_time() * 1000.0;
- const size_t alloc_buffer_waste = _g1_par_allocator->alloc_buffer_waste();
- const size_t undo_waste = _g1_par_allocator->undo_waste();
+ size_t alloc_buffer_waste = 0;
+ size_t undo_waste = 0;
+ _g1_par_allocator->waste(alloc_buffer_waste, undo_waste);
st->print_cr("%3d %9.2f %9.2f %6.2f "
"%9.2f %6.2f " SIZE_FORMAT_W(8) " "
SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,9 +54,6 @@
uint _tenuring_threshold;
G1ParScanClosure _scanner;
- size_t _alloc_buffer_waste;
- size_t _undo_waste;
-
OopsInHeapRegionClosure* _evac_failure_cl;
int _hash_seed;
@@ -78,9 +75,6 @@
#define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
- void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
- void add_to_undo_waste(size_t waste) { _undo_waste += waste; }
-
DirtyCardQueue& dirty_card_queue() { return _dcq; }
G1SATBCardTableModRefBS* ctbs() { return _ct_bs; }
@@ -106,10 +100,7 @@
bool verify_task(StarTask ref) const;
#endif // ASSERT
- template <class T> void push_on_queue(T* ref) {
- assert(verify_ref(ref), "sanity");
- _refs->push(ref);
- }
+ template <class T> void push_on_queue(T* ref);
template <class T> void update_rs(HeapRegion* from, T* p, uint tid) {
// If the new value of the field points to the same region or
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -59,6 +59,11 @@
update_rs(from, p, queue_num());
}
+template <class T> inline void G1ParScanThreadState::push_on_queue(T* ref) {
+ assert(verify_ref(ref), "sanity");
+ _refs->push(ref);
+}
+
inline void G1ParScanThreadState::do_oop_partial_array(oop* p) {
assert(has_partial_array_mask(p), "invariant");
oop from_obj = clear_partial_array_mask(p);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp Thu May 07 11:28:03 2015 -0700
@@ -329,6 +329,6 @@
_g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
}
-void G1RootProcessor::set_num_workers(int active_workers) {
+void G1RootProcessor::set_num_workers(uint active_workers) {
_process_strong_tasks->set_n_threads(active_workers);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp Thu May 07 11:28:03 2015 -0700
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
#include "memory/allocation.hpp"
#include "memory/strongRootsScope.hpp"
@@ -115,7 +115,7 @@
uint worker_i);
// Inform the root processor about the number of worker threads
- void set_num_workers(int active_workers);
+ void set_num_workers(uint active_workers);
};
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_ROOTPROCESSOR_HPP
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ROOTPROCESSOR_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Thu May 07 11:28:03 2015 -0700
@@ -153,6 +153,11 @@
return ReservedSpace::allocation_align_size_up(number_of_slots);
}
+ // Returns how many bytes of the heap a single byte of the Card Table corresponds to.
+ static size_t heap_map_factor() {
+ return CardTableModRefBS::card_size;
+ }
+
G1SATBCardTableLoggingModRefBS(MemRegion whole_heap);
virtual void initialize() { }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionBounds.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionBounds.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,9 @@
*
*/
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
+
#include "gc_implementation/g1/heapRegionBounds.hpp"
size_t HeapRegionBounds::min_size() {
@@ -35,3 +38,5 @@
size_t HeapRegionBounds::target_number() {
return TARGET_REGION_NUMBER;
}
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONBOUNDS_INLINE_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Thu May 07 11:28:03 2015 -0700
@@ -29,6 +29,7 @@
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/mutexLocker.hpp"
+#include "runtime/safepoint.hpp"
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
@@ -160,10 +161,7 @@
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.
+ // If G1SATBBufferEnqueueingThresholdPercent == 0 we could skip filtering.
// This method should only be called if there is a non-NULL buffer
// that is full.
@@ -180,25 +178,19 @@
return should_enqueue;
}
-void ObjPtrQueue::apply_closure_and_empty(ObjectClosure* cl) {
+void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) {
+ assert(SafepointSynchronize::is_at_safepoint(),
+ "SATB queues must only be processed at safepoints");
if (_buf != NULL) {
- apply_closure_to_buffer(cl, _buf, _index, _sz);
+ 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;
}
}
-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
@@ -289,7 +281,7 @@
shared_satb_queue()->filter();
}
-bool SATBMarkQueueSet::apply_closure_to_completed_buffer(ObjectClosure* cl) {
+bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
BufferNode* nd = NULL;
{
MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
@@ -303,7 +295,18 @@
}
if (nd != NULL) {
void **buf = BufferNode::make_buffer_from_node(nd);
- ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz);
+ // 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 {
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Thu May 07 11:28:03 2015 -0700
@@ -25,29 +25,30 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_SATBQUEUE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_SATBQUEUE_HPP
+#include "memory/allocation.hpp"
#include "gc_implementation/g1/ptrQueue.hpp"
-class ObjectClosure;
class JavaThread;
class SATBMarkQueueSet;
+// Base class for processing the contents of a SATB buffer.
+class SATBBufferClosure : public StackObj {
+protected:
+ ~SATBBufferClosure() { }
+
+public:
+ // Process the SATB entries in the designated buffer range.
+ virtual void do_buffer(void** buffer, size_t size) = 0;
+};
+
// A ptrQueue whose elements are "oops", pointers to object heads.
class ObjPtrQueue: public PtrQueue {
- friend class Threads;
friend class SATBMarkQueueSet;
- friend class G1RemarkThreadsClosure;
private:
// Filter out unwanted entries from the buffer.
void filter();
- // Apply the closure to all elements and empty the buffer;
- void apply_closure_and_empty(ObjectClosure* cl);
-
- // Apply the closure to all elements of "buf", down to "index" (inclusive.)
- static void apply_closure_to_buffer(ObjectClosure* cl,
- void** buf, size_t index, size_t sz);
-
public:
ObjPtrQueue(PtrQueueSet* qset, bool perm = false) :
// SATB queues are only active during marking cycles. We create
@@ -60,6 +61,10 @@
// Process queue entries and free resources.
void flush();
+ // Apply cl to the active part of the buffer.
+ // Prerequisite: Must be at a safepoint.
+ void apply_closure_and_empty(SATBBufferClosure* cl);
+
// Overrides PtrQueue::should_enqueue_buffer(). See the method's
// definition for more information.
virtual bool should_enqueue_buffer();
@@ -97,10 +102,12 @@
// Filter all the currently-active SATB buffers.
void filter_thread_buffers();
- // If there exists some completed buffer, pop it, then apply the
- // closure to all its elements, and return true. If no
- // completed buffers exist, return false.
- bool apply_closure_to_completed_buffer(ObjectClosure* closure);
+ // If there exists some completed buffer, pop and process it, and
+ // return true. Otherwise return false. Processing a buffer
+ // consists of applying the closure to the buffer range starting
+ // with the first non-NULL entry to the end of the buffer; the
+ // leading entries may be NULL due to filtering.
+ bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
#ifndef PRODUCT
// Helpful for debugging
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu May 07 11:28:03 2015 -0700
@@ -54,6 +54,7 @@
#include "utilities/copy.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
#include "utilities/workgroup.hpp"
#ifdef _MSC_VER
@@ -272,16 +273,8 @@
}
-void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
- size_t word_sz) {
- // Is the alloc in the current alloc buffer?
- if (to_space_alloc_buffer()->contains(obj)) {
- assert(to_space_alloc_buffer()->contains(obj + word_sz - 1),
- "Should contain whole object.");
- to_space_alloc_buffer()->undo_allocation(obj, word_sz);
- } else {
- CollectedHeap::fill_with_object(obj, word_sz);
- }
+void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, size_t word_sz) {
+ to_space_alloc_buffer()->undo_allocation(obj, word_sz);
}
void ParScanThreadState::print_promotion_failure_size() {
@@ -308,7 +301,7 @@
inline ParScanThreadState& thread_state(int i);
void trace_promotion_failed(const YoungGCTracer* gc_tracer);
- void reset(int active_workers, bool promotion_failed);
+ void reset(uint active_workers, bool promotion_failed);
void flush();
#if TASKQUEUE_STATS
@@ -365,7 +358,7 @@
}
}
-void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
+void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed)
{
_term.reset_for_reuse(active_threads);
if (promotion_failed) {
@@ -583,7 +576,7 @@
// Reset the terminator for the given number of
// active threads.
-void ParNewGenTask::set_for_termination(int active_workers) {
+void ParNewGenTask::set_for_termination(uint active_workers) {
_state_set->reset(active_workers, _gen->promotion_failed());
// Should the heap be passed in? There's only 1 for now so
// grab it instead.
@@ -766,7 +759,7 @@
private:
virtual void work(uint worker_id);
- virtual void set_for_termination(int active_workers) {
+ virtual void set_for_termination(uint active_workers) {
_state_set.terminator()->reset_for_reuse(active_workers);
}
private:
@@ -912,10 +905,10 @@
AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
FlexibleWorkGang* workers = gch->workers();
assert(workers != NULL, "Need workgang for parallel work");
- int active_workers =
- AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
- workers->active_workers(),
- Threads::number_of_non_daemon_threads());
+ uint active_workers =
+ AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
+ workers->active_workers(),
+ Threads::number_of_non_daemon_threads());
workers->set_active_workers(active_workers);
_old_gen = gch->old_gen();
@@ -947,7 +940,7 @@
gch->save_marks();
assert(workers != NULL, "Need parallel worker threads.");
- int n_workers = active_workers;
+ uint n_workers = active_workers;
// Set the correct parallelism (number of queues) in the reference processor
ref_processor()->set_active_mt_degree(n_workers);
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Thu May 07 11:28:03 2015 -0700
@@ -250,7 +250,7 @@
// Reset the terminator in ParScanThreadStateSet for
// "active_workers" threads.
- virtual void set_for_termination(int active_workers);
+ virtual void set_for_termination(uint active_workers);
};
class KeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Thu May 07 11:28:03 2015 -0700
@@ -57,7 +57,7 @@
ParCompactionManager* cm =
ParCompactionManager::gc_thread_compaction_manager(which);
- PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
+ ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
CLDToOopClosure mark_and_push_from_clds(&mark_and_push_closure, true);
MarkingCodeBlobClosure mark_and_push_in_blobs(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
@@ -85,8 +85,8 @@
PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
ParCompactionManager* cm =
ParCompactionManager::gc_thread_compaction_manager(which);
- PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
- PSParallelCompact::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
+ ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+ ParCompactionManager::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
switch (_root_type) {
case universe:
@@ -156,8 +156,8 @@
PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
ParCompactionManager* cm =
ParCompactionManager::gc_thread_compaction_manager(which);
- PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
- PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
+ ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+ ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
_rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
mark_and_push_closure, follow_stack_closure);
}
@@ -213,7 +213,7 @@
ParCompactionManager* cm =
ParCompactionManager::gc_thread_compaction_manager(which);
- PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
+ ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
oop obj = NULL;
ObjArrayTask task;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Thu May 07 11:28:03 2015 -0700
@@ -37,7 +37,7 @@
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
PSOldGen* ParCompactionManager::_old_gen = NULL;
ParCompactionManager** ParCompactionManager::_manager_array = NULL;
@@ -179,11 +179,11 @@
void InstanceKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
assert(obj != NULL, "can't follow the content of NULL object");
- PSParallelCompact::follow_klass(cm, this);
+ cm->follow_klass(this);
// Only mark the header and let the scan of the meta-data mark
// everything else.
- PSParallelCompact::MarkAndPushClosure cl(cm);
+ ParCompactionManager::MarkAndPushClosure cl(cm);
InstanceKlass::oop_oop_iterate_oop_maps<true>(obj, &cl);
}
@@ -201,9 +201,9 @@
// the call to follow_class_loader is made when the class loader itself
// is handled.
if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
- PSParallelCompact::follow_class_loader(cm, klass->class_loader_data());
+ cm->follow_class_loader(klass->class_loader_data());
} else {
- PSParallelCompact::follow_klass(cm, klass);
+ cm->follow_klass(klass);
}
} else {
// If klass is NULL then this a mirror for a primitive type.
@@ -212,7 +212,7 @@
assert(java_lang_Class::is_primitive(obj), "Sanity check");
}
- PSParallelCompact::MarkAndPushClosure cl(cm);
+ ParCompactionManager::MarkAndPushClosure cl(cm);
oop_oop_iterate_statics<true>(obj, &cl);
}
@@ -221,7 +221,7 @@
ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
if (loader_data != NULL) {
- PSParallelCompact::follow_class_loader(cm, loader_data);
+ cm->follow_class_loader(loader_data);
}
}
@@ -253,37 +253,24 @@
gclog_or_tty->print_cr(" Non NULL normal " PTR_FORMAT, p2i(obj));
}
)
- PSParallelCompact::mark_and_push(cm, referent_addr);
+ cm->mark_and_push(referent_addr);
}
}
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
- if (ReferenceProcessor::pending_list_uses_discovered_field()) {
- // Treat discovered as normal oop, if ref is not "active",
- // i.e. if next is non-NULL.
- T next_oop = oopDesc::load_heap_oop(next_addr);
- if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
- T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Process discovered as normal "
- PTR_FORMAT, p2i(discovered_addr));
- }
- )
- PSParallelCompact::mark_and_push(cm, discovered_addr);
- }
- } else {
-#ifdef ASSERT
- // In the case of older JDKs which do not use the discovered
- // field for the pending list, an inactive ref (next != NULL)
- // must always have a NULL discovered field.
- T next = oopDesc::load_heap_oop(next_addr);
- oop discovered = java_lang_ref_Reference::discovered(obj);
- assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
- err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
- p2i(obj)));
-#endif
+ // Treat discovered as normal oop, if ref is not "active",
+ // i.e. if next is non-NULL.
+ T next_oop = oopDesc::load_heap_oop(next_addr);
+ if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+ T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+ debug_only(
+ if(TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" Process discovered as normal "
+ PTR_FORMAT, p2i(discovered_addr));
+ }
+ )
+ cm->mark_and_push(discovered_addr);
}
- PSParallelCompact::mark_and_push(cm, next_addr);
+ cm->mark_and_push(next_addr);
klass->InstanceKlass::oop_pc_follow_contents(obj, cm);
}
@@ -297,7 +284,7 @@
}
void ObjArrayKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
- PSParallelCompact::follow_klass(cm, this);
+ cm->follow_klass(this);
if (UseCompressedOops) {
oop_pc_follow_contents_specialized<narrowOop>(objArrayOop(obj), 0, cm);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Thu May 07 11:28:03 2015 -0700
@@ -29,11 +29,6 @@
#include "utilities/stack.hpp"
#include "utilities/taskqueue.hpp"
-// Move to some global location
-#define HAS_BEEN_MOVED 0x1501d01d
-// End move to some global location
-
-
class MutableSpace;
class PSOldGen;
class ParCompactionManager;
@@ -170,24 +165,23 @@
bool should_copy();
// Save for later processing. Must not fail.
- inline void push(oop obj) { _marking_stack.push(obj); }
+ inline void push(oop obj);
inline void push_objarray(oop objarray, size_t index);
inline void push_region(size_t index);
+ // Check mark and maybe push on marking stack.
+ template <typename T> inline void mark_and_push(T* p);
+
+ inline void follow_klass(Klass* klass);
+
+ void follow_class_loader(ClassLoaderData* klass);
+
// Access function for compaction managers
static ParCompactionManager* gc_thread_compaction_manager(int index);
- static bool steal(int queue_num, int* seed, oop& t) {
- return stack_array()->steal(queue_num, seed, t);
- }
-
- static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t) {
- return _objarray_queues->steal(queue_num, seed, t);
- }
-
- static bool steal(int queue_num, int* seed, size_t& region) {
- return region_array()->steal(queue_num, seed, region);
- }
+ static bool steal(int queue_num, int* seed, oop& t);
+ static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t);
+ static bool steal(int queue_num, int* seed, size_t& region);
// Process tasks remaining on any marking stack
void follow_marking_stacks();
@@ -200,6 +194,39 @@
void follow_contents(objArrayOop array, int index);
void update_contents(oop obj);
+
+ class MarkAndPushClosure: public ExtendedOopClosure {
+ private:
+ ParCompactionManager* _compaction_manager;
+ public:
+ MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
+
+ template <typename T> void do_oop_nv(T* p);
+ virtual void do_oop(oop* p);
+ virtual void do_oop(narrowOop* p);
+
+ // This closure provides its own oop verification code.
+ debug_only(virtual bool should_verify_oops() { return false; })
+ };
+
+ class FollowStackClosure: public VoidClosure {
+ private:
+ ParCompactionManager* _compaction_manager;
+ public:
+ FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
+ virtual void do_void();
+ };
+
+ // The one and only place to start following the classes.
+ // Should only be applied to the ClassLoaderData klasses list.
+ class FollowKlassClosure : public KlassClosure {
+ private:
+ MarkAndPushClosure* _mark_and_push_closure;
+ public:
+ FollowKlassClosure(MarkAndPushClosure* mark_and_push_closure) :
+ _mark_and_push_closure(mark_and_push_closure) { }
+ void do_klass(Klass* klass);
+ };
};
inline ParCompactionManager* ParCompactionManager::manager_array(int index) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -31,6 +31,23 @@
#include "oops/oop.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
+#include "utilities/taskqueue.inline.hpp"
+
+inline bool ParCompactionManager::steal(int queue_num, int* seed, oop& t) {
+ return stack_array()->steal(queue_num, seed, t);
+}
+
+inline bool ParCompactionManager::steal_objarray(int queue_num, int* seed, ObjArrayTask& t) {
+ return _objarray_queues->steal(queue_num, seed, t);
+}
+
+inline bool ParCompactionManager::steal(int queue_num, int* seed, size_t& region) {
+ return region_array()->steal(queue_num, seed, region);
+}
+
+inline void ParCompactionManager::push(oop obj) {
+ _marking_stack.push(obj);
+}
void ParCompactionManager::push_objarray(oop obj, size_t index)
{
@@ -50,6 +67,47 @@
region_stack()->push(index);
}
+template <typename T>
+inline void ParCompactionManager::mark_and_push(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap");
+
+ if (mark_bitmap()->is_unmarked(obj) && PSParallelCompact::mark_obj(obj)) {
+ push(obj);
+ }
+ }
+}
+
+template <typename T>
+inline void ParCompactionManager::MarkAndPushClosure::do_oop_nv(T* p) {
+ _compaction_manager->mark_and_push(p);
+}
+
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(oop* p) { do_oop_nv(p); }
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+
+inline void ParCompactionManager::follow_klass(Klass* klass) {
+ oop holder = klass->klass_holder();
+ mark_and_push(&holder);
+}
+
+inline void ParCompactionManager::FollowStackClosure::do_void() {
+ _compaction_manager->follow_marking_stacks();
+}
+
+inline void ParCompactionManager::FollowKlassClosure::do_klass(Klass* klass) {
+ klass->oops_do(_mark_and_push_closure);
+}
+
+inline void ParCompactionManager::follow_class_loader(ClassLoaderData* cld) {
+ MarkAndPushClosure mark_and_push_closure(this);
+ FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
+
+ cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
+}
+
inline void ParCompactionManager::follow_contents(oop obj) {
assert(PSParallelCompact::mark_bitmap()->is_marked(obj), "should be marked");
obj->pc_follow_contents(this);
@@ -69,7 +127,7 @@
// Push the non-NULL elements of the next stride on the marking stack.
for (T* e = beg; e < end; e++) {
- PSParallelCompact::mark_and_push<T>(cm, e);
+ cm->mark_and_push<T>(e);
}
if (end_index < len) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu May 07 11:28:03 2015 -0700
@@ -108,7 +108,6 @@
bool PSParallelCompact::_print_phases = false;
ReferenceProcessor* PSParallelCompact::_ref_processor = NULL;
-Klass* PSParallelCompact::_updated_int_array_klass_obj = NULL;
double PSParallelCompact::_dwl_mean;
double PSParallelCompact::_dwl_std_dev;
@@ -820,17 +819,9 @@
bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); }
-void PSParallelCompact::KeepAliveClosure::do_oop(oop* p) { PSParallelCompact::KeepAliveClosure::do_oop_work(p); }
-void PSParallelCompact::KeepAliveClosure::do_oop(narrowOop* p) { PSParallelCompact::KeepAliveClosure::do_oop_work(p); }
-
PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_pointer_closure;
PSParallelCompact::AdjustKlassClosure PSParallelCompact::_adjust_klass_closure;
-void PSParallelCompact::FollowStackClosure::do_void() { _compaction_manager->follow_marking_stacks(); }
-
-void PSParallelCompact::FollowKlassClosure::do_klass(Klass* klass) {
- klass->oops_do(_mark_and_push_closure);
-}
void PSParallelCompact::AdjustKlassClosure::do_klass(Klass* klass) {
klass->oops_do(&PSParallelCompact::_adjust_pointer_closure);
}
@@ -2350,8 +2341,8 @@
TaskQueueSetSuper* qset = ParCompactionManager::region_array();
ParallelTaskTerminator terminator(active_gc_threads, qset);
- PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
- PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
+ ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
+ ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
// Need new claim bits before marking starts.
ClassLoaderDataGraph::clear_claimed_marks();
@@ -2425,14 +2416,6 @@
_gc_tracer.report_object_count_after_gc(is_alive_closure());
}
-void PSParallelCompact::follow_class_loader(ParCompactionManager* cm,
- ClassLoaderData* cld) {
- PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
- PSParallelCompact::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
-
- cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
-}
-
// This should be moved to the shared markSweep code!
class PSAlwaysTrueClosure: public BoolObjectClosure {
public:
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Thu May 07 11:28:03 2015 -0700
@@ -28,7 +28,6 @@
#include "gc_implementation/parallelScavenge/objectStartArray.hpp"
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
#include "gc_implementation/parallelScavenge/parMarkBitMap.hpp"
-#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
#include "gc_implementation/shared/collectorCounters.hpp"
#include "gc_implementation/shared/mutableSpace.hpp"
#include "gc_interface/collectedHeap.hpp"
@@ -933,25 +932,6 @@
virtual bool do_object_b(oop p);
};
- class KeepAliveClosure: public OopClosure {
- private:
- ParCompactionManager* _compaction_manager;
- protected:
- template <class T> inline void do_oop_work(T* p);
- public:
- KeepAliveClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
- virtual void do_oop(oop* p);
- virtual void do_oop(narrowOop* p);
- };
-
- class FollowStackClosure: public VoidClosure {
- private:
- ParCompactionManager* _compaction_manager;
- public:
- FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
- virtual void do_void();
- };
-
class AdjustPointerClosure: public ExtendedOopClosure {
public:
template <typename T> void do_oop_nv(T* p);
@@ -967,12 +947,8 @@
void do_klass(Klass* klass);
};
- friend class KeepAliveClosure;
- friend class FollowStackClosure;
friend class AdjustPointerClosure;
friend class AdjustKlassClosure;
- friend class FollowKlassClosure;
- friend class InstanceClassLoaderKlass;
friend class RefProcTaskProxy;
private:
@@ -994,9 +970,6 @@
// Reference processing (used in ...follow_contents)
static ReferenceProcessor* _ref_processor;
- // Updated location of intArrayKlassObj.
- static Klass* _updated_int_array_klass_obj;
-
// Values computed at initialization and used by dead_wood_limiter().
static double _dwl_mean;
static double _dwl_std_dev;
@@ -1142,30 +1115,6 @@
static void reset_millis_since_last_gc();
public:
- class MarkAndPushClosure: public ExtendedOopClosure {
- private:
- ParCompactionManager* _compaction_manager;
- public:
- MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
-
- template <typename T> void do_oop_nv(T* p);
- virtual void do_oop(oop* p);
- virtual void do_oop(narrowOop* p);
-
- // This closure provides its own oop verification code.
- debug_only(virtual bool should_verify_oops() { return false; })
- };
-
- // The one and only place to start following the classes.
- // Should only be applied to the ClassLoaderData klasses list.
- class FollowKlassClosure : public KlassClosure {
- private:
- MarkAndPushClosure* _mark_and_push_closure;
- public:
- FollowKlassClosure(MarkAndPushClosure* mark_and_push_closure) :
- _mark_and_push_closure(mark_and_push_closure) { }
- void do_klass(Klass* klass);
- };
PSParallelCompact();
@@ -1193,23 +1142,13 @@
// Used to add tasks
static GCTaskManager* const gc_task_manager();
- static Klass* updated_int_array_klass_obj() {
- return _updated_int_array_klass_obj;
- }
// Marking support
static inline bool mark_obj(oop obj);
static inline bool is_marked(oop obj);
- // Check mark and maybe push on marking stack
- template <class T> static inline void mark_and_push(ParCompactionManager* cm,
- T* p);
+
template <class T> static inline void adjust_pointer(T* p);
- static inline void follow_klass(ParCompactionManager* cm, Klass* klass);
-
- static void follow_class_loader(ParCompactionManager* cm,
- ClassLoaderData* klass);
-
// Compaction support.
// Return true if p is in the range [beg_addr, end_addr).
static inline bool is_in(HeapWord* p, HeapWord* beg_addr, HeapWord* end_addr);
@@ -1337,11 +1276,6 @@
return mark_bitmap()->is_marked(obj);
}
-template <class T>
-inline void PSParallelCompact::KeepAliveClosure::do_oop_work(T* p) {
- mark_and_push(_compaction_manager, p);
-}
-
inline bool PSParallelCompact::print_phases() {
return _print_phases;
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -26,38 +26,11 @@
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPARALLELCOMPACT_INLINE_HPP
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
-#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "oops/klass.hpp"
#include "oops/oop.inline.hpp"
-template <typename T>
-inline void PSParallelCompact::mark_and_push(ParCompactionManager* cm, T* p) {
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop)) {
- oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap");
-
- if (mark_bitmap()->is_unmarked(obj) && mark_obj(obj)) {
- cm->push(obj);
- }
- }
-}
-
-template <typename T>
-inline void PSParallelCompact::MarkAndPushClosure::do_oop_nv(T* p) {
- mark_and_push(_compaction_manager, p);
-}
-
-inline void PSParallelCompact::MarkAndPushClosure::do_oop(oop* p) { do_oop_nv(p); }
-inline void PSParallelCompact::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
-
-inline void PSParallelCompact::follow_klass(ParCompactionManager* cm, Klass* klass) {
- oop holder = klass->klass_holder();
- mark_and_push(cm, &holder);
-}
-
template <class T>
inline void PSParallelCompact::adjust_pointer(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Thu May 07 11:28:03 2015 -0700
@@ -36,7 +36,7 @@
#include "oops/instanceMirrorKlass.inline.hpp"
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "utilities/stack.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = NULL;
OopStarTaskQueueSet* PSPromotionManager::_stack_array_depth = NULL;
@@ -365,33 +365,19 @@
// Treat discovered as normal oop, if ref is not "active",
// i.e. if next is non-NULL.
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
- if (ReferenceProcessor::pending_list_uses_discovered_field()) {
- T next_oop = oopDesc::load_heap_oop(next_addr);
- if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
- T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Process discovered as normal "
- PTR_FORMAT, p2i(discovered_addr));
- }
- )
- if (PSScavenge::should_scavenge(discovered_addr)) {
- pm->claim_or_forward_depth(discovered_addr);
+ T next_oop = oopDesc::load_heap_oop(next_addr);
+ if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+ T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+ debug_only(
+ if(TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" Process discovered as normal "
+ PTR_FORMAT, p2i(discovered_addr));
}
+ )
+ if (PSScavenge::should_scavenge(discovered_addr)) {
+ pm->claim_or_forward_depth(discovered_addr);
}
- } else {
-#ifdef ASSERT
- // In the case of older JDKs which do not use the discovered
- // field for the pending list, an inactive ref (next != NULL)
- // must always have a NULL discovered field.
- oop next = oopDesc::load_decode_heap_oop(next_addr);
- oop discovered = java_lang_ref_Reference::discovered(obj);
- assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
- err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
- p2i(obj)));
-#endif
}
-
// Treat next as normal oop; next is a link in the reference queue.
if (PSScavenge::should_scavenge(next_addr)) {
pm->claim_or_forward_depth(next_addr);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Thu May 07 11:28:03 2015 -0700
@@ -45,10 +45,6 @@
// FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate!
//
-// Move to some global location
-#define HAS_BEEN_MOVED 0x1501d01d
-// End move to some global location
-
class MutableSpace;
class PSOldGen;
class ParCompactionManager;
@@ -143,9 +139,7 @@
int start, int end);
void process_array_chunk(oop old);
- template <class T> void push_depth(T* p) {
- claimed_stack_depth()->push(p);
- }
+ template <class T> void push_depth(T* p);
inline void promotion_trace_event(oop new_obj, oop old_obj, size_t obj_size,
uint age, bool tenured,
@@ -163,9 +157,7 @@
static PSPromotionManager* gc_thread_promotion_manager(int index);
static PSPromotionManager* vm_thread_promotion_manager();
- static bool steal_depth(int queue_num, int* seed, StarTask& t) {
- return stack_array_depth()->steal(queue_num, seed, t);
- }
+ static bool steal_depth(int queue_num, int* seed, StarTask& t);
PSPromotionManager();
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -31,6 +31,7 @@
#include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
#include "oops/oop.inline.hpp"
+#include "utilities/taskqueue.inline.hpp"
inline PSPromotionManager* PSPromotionManager::manager_array(int index) {
assert(_manager_array != NULL, "access of NULL manager_array");
@@ -39,6 +40,11 @@
}
template <class T>
+inline void PSPromotionManager::push_depth(T* p) {
+ claimed_stack_depth()->push(p);
+}
+
+template <class T>
inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) {
if (p != NULL) { // XXX: error if p != NULL here
oop o = oopDesc::load_decode_heap_oop_not_null(p);
@@ -99,7 +105,7 @@
// performance.
//
template<bool promote_immediately>
-oop PSPromotionManager::copy_to_survivor_space(oop o) {
+inline oop PSPromotionManager::copy_to_survivor_space(oop o) {
assert(should_scavenge(&o), "Sanity");
oop new_obj = NULL;
@@ -317,6 +323,10 @@
}
}
+inline bool PSPromotionManager::steal_depth(int queue_num, int* seed, StarTask& t) {
+ return stack_array_depth()->steal(queue_num, seed, t);
+}
+
#if TASKQUEUE_STATS
void PSPromotionManager::record_steal(StarTask& p) {
if (is_oop_masked(p)) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Thu May 07 11:28:03 2015 -0700
@@ -39,8 +39,7 @@
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
#include "services/management.hpp"
-#include "utilities/stack.inline.hpp"
-#include "utilities/taskqueue.hpp"
+#include "utilities/taskqueue.inline.hpp"
//
// ScavengeRootsTask
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -97,10 +97,10 @@
// Calculate the number of GC threads based on the size of the heap.
// Use the larger.
-int AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
- const uintx min_workers,
- uintx active_workers,
- uintx application_workers) {
+uint AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
+ const uintx min_workers,
+ uintx active_workers,
+ uintx application_workers) {
// If the user has specifically set the number of
// GC threads, use them.
@@ -178,9 +178,9 @@
return new_active_workers;
}
-int AdaptiveSizePolicy::calc_active_workers(uintx total_workers,
- uintx active_workers,
- uintx application_workers) {
+uint AdaptiveSizePolicy::calc_active_workers(uintx total_workers,
+ uintx active_workers,
+ uintx application_workers) {
// If the user has specifically set the number of
// GC threads, use them.
@@ -188,13 +188,14 @@
// or the users has requested a specific number, set the active
// number of workers to all the workers.
- int new_active_workers;
+ uint new_active_workers;
if (!UseDynamicNumberOfGCThreads ||
(!FLAG_IS_DEFAULT(ParallelGCThreads) && !ForceDynamicNumberOfGCThreads)) {
new_active_workers = total_workers;
} else {
+ uintx min_workers = (total_workers == 1) ? 1 : 2;
new_active_workers = calc_default_active_workers(total_workers,
- 2, /* Minimum number of workers */
+ min_workers,
active_workers,
application_workers);
}
@@ -202,18 +203,17 @@
return new_active_workers;
}
-int AdaptiveSizePolicy::calc_active_conc_workers(uintx total_workers,
- uintx active_workers,
- uintx application_workers) {
+uint AdaptiveSizePolicy::calc_active_conc_workers(uintx total_workers,
+ uintx active_workers,
+ uintx application_workers) {
if (!UseDynamicNumberOfGCThreads ||
(!FLAG_IS_DEFAULT(ConcGCThreads) && !ForceDynamicNumberOfGCThreads)) {
return ConcGCThreads;
} else {
- int no_of_gc_threads = calc_default_active_workers(
- total_workers,
- 1, /* Minimum number of workers */
- active_workers,
- application_workers);
+ uint no_of_gc_threads = calc_default_active_workers(total_workers,
+ 1, /* Minimum number of workers */
+ active_workers,
+ application_workers);
return no_of_gc_threads;
}
}
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -343,10 +343,10 @@
uint gc_cost_ratio);
// Return number default GC threads to use in the next GC.
- static int calc_default_active_workers(uintx total_workers,
- const uintx min_workers,
- uintx active_workers,
- uintx application_workers);
+ static uint calc_default_active_workers(uintx total_workers,
+ const uintx min_workers,
+ uintx active_workers,
+ uintx application_workers);
// Return number of GC threads to use in the next GC.
// This is called sparingly so as not to change the
@@ -358,14 +358,14 @@
// GC workers from the calls above. For example,
// a CMS parallel remark uses the same number of GC
// workers as the most recent ParNew collection.
- static int calc_active_workers(uintx total_workers,
- uintx active_workers,
- uintx application_workers);
+ static uint calc_active_workers(uintx total_workers,
+ uintx active_workers,
+ uintx application_workers);
// Return number of GC threads to use in the next concurrent GC phase.
- static int calc_active_conc_workers(uintx total_workers,
- uintx active_workers,
- uintx application_workers);
+ static uint calc_active_conc_workers(uintx total_workers,
+ uintx active_workers,
+ uintx application_workers);
bool is_gc_cms_adaptive_size_policy() {
return kind() == _gc_cms_adaptive_size_policy;
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Thu May 07 11:28:03 2015 -0700
@@ -145,31 +145,18 @@
}
}
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
- if (ReferenceProcessor::pending_list_uses_discovered_field()) {
- // Treat discovered as normal oop, if ref is not "active",
- // i.e. if next is non-NULL.
- T next_oop = oopDesc::load_heap_oop(next_addr);
- if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
- T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Process discovered as normal "
- PTR_FORMAT, p2i(discovered_addr));
- }
- )
- MarkSweep::mark_and_push(discovered_addr);
- }
- } else {
-#ifdef ASSERT
- // In the case of older JDKs which do not use the discovered
- // field for the pending list, an inactive ref (next != NULL)
- // must always have a NULL discovered field.
- oop next = oopDesc::load_decode_heap_oop(next_addr);
- oop discovered = java_lang_ref_Reference::discovered(obj);
- assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
- err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
- p2i(obj)));
-#endif
+ // Treat discovered as normal oop, if ref is not "active",
+ // i.e. if next is non-NULL.
+ T next_oop = oopDesc::load_heap_oop(next_addr);
+ if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
+ T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
+ debug_only(
+ if(TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" Process discovered as normal "
+ PTR_FORMAT, p2i(discovered_addr));
+ }
+ )
+ MarkSweep::mark_and_push(discovered_addr);
}
// treat next as normal oop. next is a link in the reference queue.
debug_only(
--- a/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP
-#define SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
#include "gc_implementation/shared/gcTrace.hpp"
#include "memory/allocation.hpp"
@@ -42,4 +42,4 @@
#endif // INCLUDE_SERVICES
-#endif // SHARE_VM_OBJECT_COUNT_EVENT_SENDER
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_OBJECTCOUNTEVENTSENDER_HPP
--- a/hotspot/src/share/vm/gc_implementation/shared/plab.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.cpp Thu May 07 11:28:03 2015 -0700
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc_implementation/shared/plab.hpp"
+#include "gc_interface/collectedHeap.hpp"
#include "memory/threadLocalAllocBuffer.hpp"
#include "oops/arrayOop.hpp"
#include "oops/oop.inline.hpp"
@@ -39,7 +40,7 @@
PLAB::PLAB(size_t desired_plab_sz_) :
_word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL),
- _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0)
+ _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0), _undo_wasted(0)
{
// ArrayOopDesc::header_size depends on command line initialization.
AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0;
@@ -62,13 +63,15 @@
// Now flush the statistics.
stats->add_allocated(_allocated);
stats->add_wasted(_wasted);
+ stats->add_undo_wasted(_undo_wasted);
stats->add_unused(unused);
// Since we have flushed the stats we need to clear the _allocated and _wasted
// fields in case somebody retains an instance of this over GCs. Not doing so
// will artifically inflate the values in the statistics.
- _allocated = 0;
- _wasted = 0;
+ _allocated = 0;
+ _wasted = 0;
+ _undo_wasted = 0;
}
void PLAB::retire() {
@@ -84,6 +87,28 @@
return result;
}
+void PLAB::add_undo_waste(HeapWord* obj, size_t word_sz) {
+ CollectedHeap::fill_with_object(obj, word_sz);
+ _undo_wasted += word_sz;
+}
+
+void PLAB::undo_last_allocation(HeapWord* obj, size_t word_sz) {
+ assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
+ assert(pointer_delta(_top, obj) == word_sz, "Bad undo");
+ _top = obj;
+}
+
+void PLAB::undo_allocation(HeapWord* obj, size_t word_sz) {
+ // Is the alloc in the current alloc buffer?
+ if (contains(obj)) {
+ assert(contains(obj + word_sz - 1),
+ "should contain whole object");
+ undo_last_allocation(obj, word_sz);
+ } else {
+ add_undo_waste(obj, word_sz);
+ }
+}
+
// Compute desired plab size and latch result for later
// use. This should be called once at the end of parallel
// scavenge; it clears the sensor accumulators.
@@ -98,8 +123,9 @@
err_msg("Inconsistency in PLAB stats: "
"_allocated: "SIZE_FORMAT", "
"_wasted: "SIZE_FORMAT", "
- "_unused: "SIZE_FORMAT,
- _allocated, _wasted, _unused));
+ "_unused: "SIZE_FORMAT", "
+ "_undo_wasted: "SIZE_FORMAT,
+ _allocated, _wasted, _unused, _undo_wasted));
_allocated = 1;
}
--- a/hotspot/src/share/vm/gc_implementation/shared/plab.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/plab.hpp Thu May 07 11:28:03 2015 -0700
@@ -45,6 +45,7 @@
// In support of ergonomic sizing of PLAB's
size_t _allocated; // in HeapWord units
size_t _wasted; // in HeapWord units
+ size_t _undo_wasted;
char tail[32];
static size_t AlignmentReserve;
@@ -62,6 +63,12 @@
// the amount of remaining space.
size_t retire_internal();
+ void add_undo_waste(HeapWord* obj, size_t word_sz);
+
+ // Undo the last allocation in the buffer, which is required to be of the
+ // "obj" of the given "word_sz".
+ void undo_last_allocation(HeapWord* obj, size_t word_sz);
+
public:
// Initializes the buffer to be empty, but with the given "word_sz".
// Must get initialized with "set_buf" for an allocation to succeed.
@@ -90,18 +97,17 @@
// Allocate the object aligned to "alignment_in_bytes".
HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
- // Undo the last allocation in the buffer, which is required to be of the
+ // Undo any allocation in the buffer, which is required to be of the
// "obj" of the given "word_sz".
- void undo_allocation(HeapWord* obj, size_t word_sz) {
- assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo");
- assert(pointer_delta(_top, obj) == word_sz, "Bad undo");
- _top = obj;
- }
+ void undo_allocation(HeapWord* obj, size_t word_sz);
// The total (word) size of the buffer, including both allocated and
// unallocated space.
size_t word_sz() { return _word_sz; }
+ size_t waste() { return _wasted; }
+ size_t undo_waste() { return _undo_wasted; }
+
// Should only be done if we are about to reset with a new buffer of the
// given size.
void set_word_size(size_t new_word_sz) {
@@ -146,20 +152,23 @@
class PLABStats VALUE_OBJ_CLASS_SPEC {
size_t _allocated; // Total allocated
size_t _wasted; // of which wasted (internal fragmentation)
+ size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size)
size_t _unused; // Unused in last buffer
size_t _desired_plab_sz;// Output of filter (below), suitably trimmed and quantized
AdaptiveWeightedAverage
_filter; // Integrator with decay
void reset() {
- _allocated = 0;
- _wasted = 0;
- _unused = 0;
+ _allocated = 0;
+ _wasted = 0;
+ _undo_wasted = 0;
+ _unused = 0;
}
public:
PLABStats(size_t desired_plab_sz_, unsigned wt) :
_allocated(0),
_wasted(0),
+ _undo_wasted(0),
_unused(0),
_desired_plab_sz(desired_plab_sz_),
_filter(wt)
@@ -192,6 +201,10 @@
void add_wasted(size_t v) {
Atomic::add_ptr(v, &_wasted);
}
+
+ void add_undo_wasted(size_t v) {
+ Atomic::add_ptr(v, &_undo_wasted);
+ }
};
#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PLAB_HPP
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Thu May 07 11:28:03 2015 -0700
@@ -598,13 +598,6 @@
#endif
public:
- // This is a convenience method that is used in cases where
- // the actual number of GC worker threads is not pertinent but
- // only whether there more than 0. Use of this method helps
- // reduce the occurrence of ParallelGCThreads to uses where the
- // actual number may be germane.
- static bool use_parallel_gc_threads() { return ParallelGCThreads > 0; }
-
// Copy the current allocation context statistics for the specified contexts.
// For each context in contexts, set the corresponding entries in the totals
// and accuracy arrays to the current values held by the statistics. Each
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu May 07 11:28:03 2015 -0700
@@ -640,7 +640,7 @@
// All threads execute the following. A specific chunk of buckets
// from the StringTable are the individual tasks.
if (weak_roots != NULL) {
- if (CollectedHeap::use_parallel_gc_threads()) {
+ if (is_par) {
StringTable::possibly_parallel_oops_do(weak_roots);
} else {
StringTable::oops_do(weak_roots);
--- a/hotspot/src/share/vm/memory/guardedMemory.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/guardedMemory.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
-#define SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+#ifndef SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
+#define SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -323,4 +323,4 @@
#endif
}; // GuardedMemory
-#endif // SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+#endif // SHARE_VM_MEMORY_GUARDEDMEMORY_HPP
--- a/hotspot/src/share/vm/memory/metaspace.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Thu May 07 11:28:03 2015 -0700
@@ -252,7 +252,7 @@
// Used to manage the free list of Metablocks (a block corresponds
// to the allocation of a quantum of metadata).
class BlockFreelist VALUE_OBJ_CLASS_SPEC {
- BlockTreeDictionary* _dictionary;
+ BlockTreeDictionary* const _dictionary;
// Only allocate and split from freelist if the size of the allocation
// is at least 1/4th the size of the available block.
@@ -269,13 +269,7 @@
MetaWord* get_block(size_t word_size);
void return_block(MetaWord* p, size_t word_size);
- size_t total_size() {
- if (dictionary() == NULL) {
- return 0;
- } else {
- return dictionary()->total_size();
- }
-}
+ size_t total_size() { return dictionary()->total_size(); }
void print_on(outputStream* st) const;
};
@@ -814,30 +808,21 @@
// BlockFreelist methods
-BlockFreelist::BlockFreelist() : _dictionary(NULL) {}
+BlockFreelist::BlockFreelist() : _dictionary(new BlockTreeDictionary()) {}
BlockFreelist::~BlockFreelist() {
- if (_dictionary != NULL) {
- if (Verbose && TraceMetadataChunkAllocation) {
- _dictionary->print_free_lists(gclog_or_tty);
- }
- delete _dictionary;
+ if (Verbose && TraceMetadataChunkAllocation) {
+ dictionary()->print_free_lists(gclog_or_tty);
}
+ delete _dictionary;
}
void BlockFreelist::return_block(MetaWord* p, size_t word_size) {
Metablock* free_chunk = ::new (p) Metablock(word_size);
- if (dictionary() == NULL) {
- _dictionary = new BlockTreeDictionary();
- }
dictionary()->return_chunk(free_chunk);
}
MetaWord* BlockFreelist::get_block(size_t word_size) {
- if (dictionary() == NULL) {
- return NULL;
- }
-
if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
// Dark matter. Too small for dictionary.
return NULL;
@@ -866,9 +851,6 @@
}
void BlockFreelist::print_on(outputStream* st) const {
- if (dictionary() == NULL) {
- return;
- }
dictionary()->print_free_lists(st);
}
--- a/hotspot/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,9 @@
* questions.
*
*/
-#ifndef SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
-#define SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+
+#ifndef SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
+#define SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
#include "memory/allocation.hpp"
@@ -100,4 +101,4 @@
}
};
-#endif // SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP
+#endif // SHARE_VM_MEMORY_METASPACECHUNKFREELISTSUMMARY_HPP
--- a/hotspot/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
-#define SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#ifndef SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
+#define SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
@@ -49,4 +49,4 @@
}
};
-#endif // SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP
+#endif // SHARE_VM_MEMORY_METASPACEGCTHRESHOLDUPDATER_HPP
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp Thu May 07 11:28:03 2015 -0700
@@ -21,8 +21,9 @@
* questions.
*
*/
-#ifndef SHARE_VM_MEMORY_METASPACE_SHARED_HPP
-#define SHARE_VM_MEMORY_METASPACE_SHARED_HPP
+
+#ifndef SHARE_VM_MEMORY_METASPACESHARED_HPP
+#define SHARE_VM_MEMORY_METASPACESHARED_HPP
#include "classfile/compactHashtable.hpp"
#include "memory/allocation.hpp"
@@ -153,4 +154,4 @@
static int count_class(const char* classlist_file);
static void estimate_regions_size() NOT_CDS_RETURN;
};
-#endif // SHARE_VM_MEMORY_METASPACE_SHARED_HPP
+#endif // SHARE_VM_MEMORY_METASPACESHARED_HPP
--- a/hotspot/src/share/vm/memory/metaspaceTracer.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspaceTracer.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_MEMORY_METASPACE_TRACER_HPP
-#define SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+#ifndef SHARE_VM_MEMORY_METASPACETRACER_HPP
+#define SHARE_VM_MEMORY_METASPACETRACER_HPP
#include "memory/allocation.hpp"
#include "memory/metaspace.hpp"
@@ -52,4 +52,4 @@
};
-#endif // SHARE_VM_MEMORY_METASPACE_TRACER_HPP
+#endif // SHARE_VM_MEMORY_METASPACETRACER_HPP
--- a/hotspot/src/share/vm/memory/padded.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/padded.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,9 @@
*
*/
+#ifndef SHARE_VM_MEMORY_PADDED_INLINE_HPP
+#define SHARE_VM_MEMORY_PADDED_INLINE_HPP
+
#include "memory/allocation.inline.hpp"
#include "memory/padded.hpp"
#include "utilities/debug.hpp"
@@ -86,3 +89,5 @@
return (T*)align_pointer_up(chunk, alignment);
}
+
+#endif // SHARE_VM_MEMORY_PADDED_INLINE_HPP
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu May 07 11:28:03 2015 -0700
@@ -37,7 +37,6 @@
ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL;
-bool ReferenceProcessor::_pending_list_uses_discovered_field = false;
jlong ReferenceProcessor::_soft_ref_timestamp_clock = 0;
void referenceProcessor_init() {
@@ -63,7 +62,6 @@
guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
RefDiscoveryPolicy == ReferentBasedDiscovery,
"Unrecognized RefDiscoveryPolicy");
- _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field();
}
void ReferenceProcessor::enable_discovery(bool check_no_refs) {
@@ -353,10 +351,6 @@
// all linked Reference objects. Note that it is important to not dirty any
// cards during reference processing since this will cause card table
// verification to fail for G1.
- //
- // BKWRD COMPATIBILITY NOTE: For older JDKs (prior to the fix for 4956777),
- // the "next" field is used to chain the pending list, not the discovered
- // field.
if (TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list "
INTPTR_FORMAT, p2i(refs_list.head()));
@@ -364,64 +358,30 @@
oop obj = NULL;
oop next_d = refs_list.head();
- if (pending_list_uses_discovered_field()) { // New behavior
- // Walk down the list, self-looping the next field
- // so that the References are not considered active.
- while (obj != next_d) {
- obj = next_d;
- assert(obj->is_instanceRef(), "should be reference object");
- next_d = java_lang_ref_Reference::discovered(obj);
- if (TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
- p2i(obj), p2i(next_d));
- }
- assert(java_lang_ref_Reference::next(obj) == NULL,
- "Reference not active; should not be discovered");
- // Self-loop next, so as to make Ref not active.
- java_lang_ref_Reference::set_next_raw(obj, obj);
- if (next_d != obj) {
- oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
- } else {
- // This is the last object.
- // Swap refs_list into pending_list_addr and
- // set obj's discovered to what we read from pending_list_addr.
- oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
- // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above.
- java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL
- oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
- }
+ // Walk down the list, self-looping the next field
+ // so that the References are not considered active.
+ while (obj != next_d) {
+ obj = next_d;
+ assert(obj->is_instanceRef(), "should be reference object");
+ next_d = java_lang_ref_Reference::discovered(obj);
+ if (TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
+ p2i(obj), p2i(next_d));
}
- } else { // Old behavior
- // Walk down the list, copying the discovered field into
- // the next field and clearing the discovered field.
- while (obj != next_d) {
- obj = next_d;
- assert(obj->is_instanceRef(), "should be reference object");
- next_d = java_lang_ref_Reference::discovered(obj);
- if (TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
- p2i(obj), p2i(next_d));
- }
- assert(java_lang_ref_Reference::next(obj) == NULL,
- "The reference should not be enqueued");
- if (next_d == obj) { // obj is last
- // Swap refs_list into pending_list_addr and
- // set obj's next to what we read from pending_list_addr.
- oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
- // Need oop_check on pending_list_addr above;
- // see special oop-check code at the end of
- // enqueue_discovered_reflists() further below.
- if (old == NULL) {
- // obj should be made to point to itself, since
- // pending list was empty.
- java_lang_ref_Reference::set_next(obj, obj);
- } else {
- java_lang_ref_Reference::set_next(obj, old);
- }
- } else {
- java_lang_ref_Reference::set_next(obj, next_d);
- }
- java_lang_ref_Reference::set_discovered(obj, (oop) NULL);
+ assert(java_lang_ref_Reference::next(obj) == NULL,
+ "Reference not active; should not be discovered");
+ // Self-loop next, so as to make Ref not active.
+ java_lang_ref_Reference::set_next_raw(obj, obj);
+ if (next_d != obj) {
+ oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), next_d);
+ } else {
+ // This is the last object.
+ // Swap refs_list into pending_list_addr and
+ // set obj's discovered to what we read from pending_list_addr.
+ oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr);
+ // Need post-barrier on pending_list_addr. See enqueue_discovered_ref_helper() above.
+ java_lang_ref_Reference::set_discovered_raw(obj, old); // old may be NULL
+ oopDesc::bs()->write_ref_field(java_lang_ref_Reference::discovered_addr(obj), old);
}
}
}
@@ -515,22 +475,6 @@
_refs_list.dec_length(1);
}
-// Make the Reference object active again.
-void DiscoveredListIterator::make_active() {
- // The pre barrier for G1 is probably just needed for the old
- // reference processing behavior. Should we guard this with
- // ReferenceProcessor::pending_list_uses_discovered_field() ?
- if (UseG1GC) {
- HeapWord* next_addr = java_lang_ref_Reference::next_addr(_ref);
- if (UseCompressedOops) {
- oopDesc::bs()->write_ref_field_pre((narrowOop*)next_addr, NULL);
- } else {
- oopDesc::bs()->write_ref_field_pre((oop*)next_addr, NULL);
- }
- }
- java_lang_ref_Reference::set_next_raw(_ref, NULL);
-}
-
void DiscoveredListIterator::clear_referent() {
oop_store_raw(_referent_addr, NULL);
}
@@ -567,8 +511,6 @@
}
// Remove Reference object from list
iter.remove();
- // Make the Reference object active again
- iter.make_active();
// keep the referent around
iter.make_referent_alive();
iter.move_to_next();
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu May 07 11:28:03 2015 -0700
@@ -161,9 +161,6 @@
// Remove the current reference from the list
void remove();
- // Make the Reference object active again.
- void make_active();
-
// Make the referent alive.
inline void make_referent_alive() {
if (UseCompressedOops) {
@@ -200,9 +197,6 @@
size_t total_count(DiscoveredList lists[]);
protected:
- // Compatibility with pre-4965777 JDK's
- static bool _pending_list_uses_discovered_field;
-
// The SoftReference master timestamp clock
static jlong _soft_ref_timestamp_clock;
@@ -421,13 +415,6 @@
bool discovery_is_atomic() const { return _discovery_is_atomic; }
void set_atomic_discovery(bool atomic) { _discovery_is_atomic = atomic; }
- // whether the JDK in which we are embedded is a pre-4965777 JDK,
- // and thus whether or not it uses the discovered field to chain
- // the entries in the pending list.
- static bool pending_list_uses_discovered_field() {
- return _pending_list_uses_discovered_field;
- }
-
// whether discovery is done by multiple threads same-old-timeously
bool discovery_is_mt() const { return _discovery_is_mt; }
void set_mt_discovery(bool mt) { _discovery_is_mt = mt; }
--- a/hotspot/src/share/vm/memory/referenceType.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/memory/referenceType.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,8 @@
*
*/
-#ifndef SHARE_VM_MEMORY_REFRERENCETYPE_HPP
-#define SHARE_VM_MEMORY_REFRERENCETYPE_HPP
+#ifndef SHARE_VM_MEMORY_REFERENCETYPE_HPP
+#define SHARE_VM_MEMORY_REFERENCETYPE_HPP
#include "utilities/debug.hpp"
@@ -39,4 +39,4 @@
REF_CLEANER // Subclass of sun/misc/Cleaner
};
-#endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP
+#endif // SHARE_VM_MEMORY_REFERENCETYPE_HPP
--- a/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -55,30 +55,17 @@
}
}
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
- if (ReferenceProcessor::pending_list_uses_discovered_field()) {
- T next_oop = oopDesc::load_heap_oop(next_addr);
- // Treat discovered as normal oop, if ref is not "active" (next non-NULL)
- if (!oopDesc::is_null(next_oop) && contains(disc_addr)) {
- // i.e. ref is not "active"
- debug_only(
- if(TraceReferenceGC && PrintGCDetails) {
- gclog_or_tty->print_cr(" Process discovered as normal "
- PTR_FORMAT, p2i(disc_addr));
- }
- )
- Devirtualizer<nv>::do_oop(closure, disc_addr);
- }
- } else {
- // In the case of older JDKs which do not use the discovered field for
- // the pending list, an inactive ref (next != NULL) must always have a
- // NULL discovered field.
+ T next_oop = oopDesc::load_heap_oop(next_addr);
+ // Treat discovered as normal oop, if ref is not "active" (next non-NULL)
+ if (!oopDesc::is_null(next_oop) && contains(disc_addr)) {
+ // i.e. ref is not "active"
debug_only(
- T next_oop = oopDesc::load_heap_oop(next_addr);
- T disc_oop = oopDesc::load_heap_oop(disc_addr);
- assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop),
- err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL"
- "discovered field", p2i(obj)));
+ if(TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" Process discovered as normal "
+ PTR_FORMAT, p2i(disc_addr));
+ }
)
+ Devirtualizer<nv>::do_oop(closure, disc_addr);
}
// treat next as normal oop
if (contains(next_addr)) {
--- a/hotspot/src/share/vm/runtime/java.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp Thu May 07 11:28:03 2015 -0700
@@ -651,11 +651,15 @@
minor = micro;
micro = 0;
}
+ // Incompatible with pre-4243978 JDK.
+ if (info.pending_list_uses_discovered_field == 0) {
+ vm_exit_during_initialization(
+ "Incompatible JDK is not using Reference.discovered field for pending list");
+ }
_current = JDK_Version(major, minor, micro, info.update_version,
info.special_update_version, build,
info.thread_park_blocker == 1,
- info.post_vm_init_hook_enabled == 1,
- info.pending_list_uses_discovered_field == 1);
+ info.post_vm_init_hook_enabled == 1);
}
}
--- a/hotspot/src/share/vm/runtime/java.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/java.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,6 @@
bool _partially_initialized;
bool _thread_park_blocker;
- bool _pending_list_uses_discovered_field;
bool _post_vm_init_hook_enabled;
bool is_valid() const {
@@ -114,18 +113,17 @@
JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
_special(0), _build(0), _partially_initialized(false),
- _thread_park_blocker(false), _post_vm_init_hook_enabled(false),
- _pending_list_uses_discovered_field(false) {}
+ _thread_park_blocker(false), _post_vm_init_hook_enabled(false)
+ {}
JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
- bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false,
- bool pending_list_uses_discovered_field = false) :
+ bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) :
_major(major), _minor(minor), _micro(micro), _update(update),
_special(special), _build(build), _partially_initialized(false),
_thread_park_blocker(thread_park_blocker),
- _post_vm_init_hook_enabled(post_vm_init_hook_enabled),
- _pending_list_uses_discovered_field(pending_list_uses_discovered_field) {}
+ _post_vm_init_hook_enabled(post_vm_init_hook_enabled)
+ {}
// Returns the current running JDK version
static JDK_Version current() { return _current; }
@@ -152,10 +150,6 @@
bool post_vm_init_hook_enabled() const {
return _post_vm_init_hook_enabled;
}
- // For compatibility wrt pre-4965777 JDK's
- bool pending_list_uses_discovered_field() const {
- return _pending_list_uses_discovered_field;
- }
// Performs a full ordering comparison using all fields (update, build, etc.)
int compare(const JDK_Version& other) const;
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Thu May 07 11:28:03 2015 -0700
@@ -4210,13 +4210,13 @@
Abstract_VM_Version::vm_info_string());
st->cr();
-#if INCLUDE_ALL_GCS
+#if INCLUDE_SERVICES
// Dump concurrent locks
ConcurrentLocksDump concurrent_locks;
if (print_concurrent_locks) {
concurrent_locks.dump_at_safepoint();
}
-#endif // INCLUDE_ALL_GCS
+#endif // INCLUDE_SERVICES
ALL_JAVA_THREADS(p) {
ResourceMark rm;
@@ -4229,11 +4229,11 @@
}
}
st->cr();
-#if INCLUDE_ALL_GCS
+#if INCLUDE_SERVICES
if (print_concurrent_locks) {
concurrent_locks.print_locks_on(p, st);
}
-#endif // INCLUDE_ALL_GCS
+#endif // INCLUDE_SERVICES
}
VMThread::vm_thread()->print_on(st);
--- a/hotspot/src/share/vm/runtime/vm_version.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp Thu May 07 11:28:03 2015 -0700
@@ -78,7 +78,7 @@
int Abstract_VM_Version::_vm_micro_version = 0;
int Abstract_VM_Version::_vm_build_number = 0;
bool Abstract_VM_Version::_initialized = false;
-int Abstract_VM_Version::_parallel_worker_threads = 0;
+unsigned int Abstract_VM_Version::_parallel_worker_threads = 0;
bool Abstract_VM_Version::_parallel_worker_threads_initialized = false;
#ifdef ASSERT
--- a/hotspot/src/share/vm/runtime/vm_version.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/runtime/vm_version.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
static int _vm_micro_version;
static int _vm_build_number;
static bool _initialized;
- static int _parallel_worker_threads;
+ static unsigned int _parallel_worker_threads;
static bool _parallel_worker_threads_initialized;
static int _reserve_for_allocation_prefetch;
--- a/hotspot/src/share/vm/utilities/taskqueue.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.cpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,8 +31,6 @@
#include "utilities/stack.inline.hpp"
#include "utilities/taskqueue.hpp"
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
#ifdef TRACESPINNING
uint ParallelTaskTerminator::_total_yields = 0;
uint ParallelTaskTerminator::_total_spins = 0;
@@ -131,7 +129,7 @@
}
ParallelTaskTerminator::
-ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set) :
+ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set) :
_n_threads(n_threads),
_queue_set(queue_set),
_offered_termination(0) {}
@@ -154,7 +152,7 @@
ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
assert(_n_threads > 0, "Initialization is incorrect");
assert(_offered_termination < _n_threads, "Invariant");
- Atomic::inc(&_offered_termination);
+ Atomic::inc((int *)&_offered_termination);
uint yield_count = 0;
// Number of hard spin loops done since last yield
@@ -216,8 +214,8 @@
} else {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() "
- "thread %d sleeps after %d yields",
- Thread::current(), yield_count);
+ "thread " PTR_FORMAT " sleeps after %u yields",
+ p2i(Thread::current()), yield_count);
}
yield_count = 0;
// A sleep will cause this processor to seek work on another processor's
@@ -232,7 +230,7 @@
#endif
if (peek_in_queue_set() ||
(terminator != NULL && terminator->should_exit_termination())) {
- Atomic::dec(&_offered_termination);
+ Atomic::dec((int *)&_offered_termination);
assert(_offered_termination < _n_threads, "Invariant");
return false;
}
@@ -265,7 +263,7 @@
}
#endif // ASSERT
-void ParallelTaskTerminator::reset_for_reuse(int n_threads) {
+void ParallelTaskTerminator::reset_for_reuse(uint n_threads) {
reset_for_reuse();
_n_threads = n_threads;
}
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,6 @@
#define SHARE_VM_UTILITIES_TASKQUEUE_HPP
#include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/orderAccess.inline.hpp"
#include "utilities/stack.hpp"
// Simple TaskQueue stats that are collected by default in debug builds.
@@ -134,11 +131,7 @@
if (_fields._top == 0) ++_fields._tag;
}
- Age cmpxchg(const Age new_age, const Age old_age) volatile {
- return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
- (volatile intptr_t *)&_data,
- (intptr_t)old_age._data);
- }
+ Age cmpxchg(const Age new_age, const Age old_age) volatile;
bool operator ==(const Age& other) const { return _data == other._data; }
@@ -315,121 +308,6 @@
assert(sizeof(Age) == sizeof(size_t), "Depends on this.");
}
-template<class E, MEMFLAGS F, unsigned int N>
-void GenericTaskQueue<E, F, N>::initialize() {
- _elems = _array_allocator.allocate(N);
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
- // tty->print_cr("START OopTaskQueue::oops_do");
- uint iters = size();
- uint index = _bottom;
- for (uint i = 0; i < iters; ++i) {
- index = decrement_index(index);
- // tty->print_cr(" doing entry %d," INTPTR_T " -> " INTPTR_T,
- // index, &_elems[index], _elems[index]);
- E* t = (E*)&_elems[index]; // cast away volatility
- oop* p = (oop*)t;
- assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
- f->do_oop(p);
- }
- // tty->print_cr("END OopTaskQueue::oops_do");
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
- if (dirty_n_elems == N - 1) {
- // Actually means 0, so do the push.
- uint localBot = _bottom;
- // g++ complains if the volatile result of the assignment is
- // unused, so we cast the volatile away. We cannot cast directly
- // to void, because gcc treats that as not using the result of the
- // assignment. However, casting to E& means that we trigger an
- // unused-value warning. So, we cast the E& to void.
- (void)const_cast<E&>(_elems[localBot] = t);
- OrderAccess::release_store(&_bottom, increment_index(localBot));
- TASKQUEUE_STATS_ONLY(stats.record_push());
- return true;
- }
- return false;
-}
-
-// pop_local_slow() is done by the owning thread and is trying to
-// get the last task in the queue. It will compete with pop_global()
-// that will be used by other threads. The tag age is incremented
-// whenever the queue goes empty which it will do here if this thread
-// gets the last task or in pop_global() if the queue wraps (top == 0
-// and pop_global() succeeds, see pop_global()).
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
- // This queue was observed to contain exactly one element; either this
- // thread will claim it, or a competing "pop_global". In either case,
- // the queue will be logically empty afterwards. Create a new Age value
- // that represents the empty queue for the given value of "_bottom". (We
- // must also increment "tag" because of the case where "bottom == 1",
- // "top == 0". A pop_global could read the queue element in that case,
- // then have the owner thread do a pop followed by another push. Without
- // the incrementing of "tag", the pop_global's CAS could succeed,
- // allowing it to believe it has claimed the stale element.)
- Age newAge((idx_t)localBot, oldAge.tag() + 1);
- // Perhaps a competing pop_global has already incremented "top", in which
- // case it wins the element.
- if (localBot == oldAge.top()) {
- // No competing pop_global has yet incremented "top"; we'll try to
- // install new_age, thus claiming the element.
- Age tempAge = _age.cmpxchg(newAge, oldAge);
- if (tempAge == oldAge) {
- // We win.
- assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
- TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
- return true;
- }
- }
- // We lose; a completing pop_global gets the element. But the queue is empty
- // and top is greater than bottom. Fix this representation of the empty queue
- // to become the canonical one.
- _age.set(newAge);
- assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
- return false;
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
- Age oldAge = _age.get();
- // Architectures with weak memory model require a barrier here
- // to guarantee that bottom is not older than age,
- // which is crucial for the correctness of the algorithm.
-#if !(defined SPARC || defined IA32 || defined AMD64)
- OrderAccess::fence();
-#endif
- uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
- uint n_elems = size(localBot, oldAge.top());
- if (n_elems == 0) {
- return false;
- }
-
- // g++ complains if the volatile result of the assignment is
- // unused, so we cast the volatile away. We cannot cast directly
- // to void, because gcc treats that as not using the result of the
- // assignment. However, casting to E& means that we trigger an
- // unused-value warning. So, we cast the E& to void.
- (void) const_cast<E&>(t = _elems[oldAge.top()]);
- Age newAge(oldAge);
- newAge.increment();
- Age resAge = _age.cmpxchg(newAge, oldAge);
-
- // Note that using "_bottom" here might fail, since a pop_local might
- // have decremented it.
- assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
- return resAge == oldAge;
-}
-
-template<class E, MEMFLAGS F, unsigned int N>
-GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
- FREE_C_HEAP_ARRAY(E, _elems);
-}
-
// OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
// elements that do not fit in the TaskQueue.
//
@@ -468,24 +346,6 @@
overflow_t _overflow_stack;
};
-template <class E, MEMFLAGS F, unsigned int N>
-bool OverflowTaskQueue<E, F, N>::push(E t)
-{
- if (!taskqueue_t::push(t)) {
- overflow_stack()->push(t);
- TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size()));
- }
- return true;
-}
-
-template <class E, MEMFLAGS F, unsigned int N>
-bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
-{
- if (overflow_empty()) return false;
- t = overflow_stack()->pop();
- return true;
-}
-
class TaskQueueSetSuper {
protected:
static int randomParkAndMiller(int* seed0);
@@ -506,13 +366,7 @@
public:
typedef typename T::element_type E;
- GenericTaskQueueSet(int n) : _n(n) {
- typedef T* GenericTaskQueuePtr;
- _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
- for (int i = 0; i < n; i++) {
- _queues[i] = NULL;
- }
- }
+ GenericTaskQueueSet(int n);
bool steal_best_of_2(uint queue_num, int* seed, E& t);
@@ -541,40 +395,6 @@
return _queues[i];
}
-template<class T, MEMFLAGS F> bool
-GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
- for (uint i = 0; i < 2 * _n; i++) {
- if (steal_best_of_2(queue_num, seed, t)) {
- TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
- return true;
- }
- }
- TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
- return false;
-}
-
-template<class T, MEMFLAGS F> bool
-GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
- if (_n > 2) {
- uint k1 = queue_num;
- while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
- uint k2 = queue_num;
- while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
- // Sample both and try the larger.
- uint sz1 = _queues[k1]->size();
- uint sz2 = _queues[k2]->size();
- if (sz2 > sz1) return _queues[k2]->pop_global(t);
- else return _queues[k1]->pop_global(t);
- } else if (_n == 2) {
- // Just try the other one.
- uint k = (queue_num + 1) % 2;
- return _queues[k]->pop_global(t);
- } else {
- assert(_n == 1, "can't be zero.");
- return false;
- }
-}
-
template<class T, MEMFLAGS F>
bool GenericTaskQueueSet<T, F>::peek() {
// Try all the queues.
@@ -598,9 +418,9 @@
class ParallelTaskTerminator: public StackObj {
private:
- int _n_threads;
+ uint _n_threads;
TaskQueueSetSuper* _queue_set;
- int _offered_termination;
+ uint _offered_termination;
#ifdef TRACESPINNING
static uint _total_yields;
@@ -617,7 +437,7 @@
// "n_threads" is the number of threads to be terminated. "queue_set" is a
// queue sets of work queues of other threads.
- ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set);
+ ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set);
// The current thread has no work, and is ready to terminate if everyone
// else is. If returns "true", all threads are terminated. If returns
@@ -639,7 +459,7 @@
void reset_for_reuse();
// Same as above but the number of parallel threads is set to the
// given number.
- void reset_for_reuse(int n_threads);
+ void reset_for_reuse(uint n_threads);
#ifdef TRACESPINNING
static uint total_yields() { return _total_yields; }
@@ -649,65 +469,6 @@
#endif
};
-template<class E, MEMFLAGS F, unsigned int N> inline bool
-GenericTaskQueue<E, F, N>::push(E t) {
- uint localBot = _bottom;
- assert(localBot < N, "_bottom out of range.");
- idx_t top = _age.top();
- uint dirty_n_elems = dirty_size(localBot, top);
- assert(dirty_n_elems < N, "n_elems out of range.");
- if (dirty_n_elems < max_elems()) {
- // g++ complains if the volatile result of the assignment is
- // unused, so we cast the volatile away. We cannot cast directly
- // to void, because gcc treats that as not using the result of the
- // assignment. However, casting to E& means that we trigger an
- // unused-value warning. So, we cast the E& to void.
- (void) const_cast<E&>(_elems[localBot] = t);
- OrderAccess::release_store(&_bottom, increment_index(localBot));
- TASKQUEUE_STATS_ONLY(stats.record_push());
- return true;
- } else {
- return push_slow(t, dirty_n_elems);
- }
-}
-
-template<class E, MEMFLAGS F, unsigned int N> inline bool
-GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
- uint localBot = _bottom;
- // This value cannot be N-1. That can only occur as a result of
- // the assignment to bottom in this method. If it does, this method
- // resets the size to 0 before the next call (which is sequential,
- // since this is pop_local.)
- uint dirty_n_elems = dirty_size(localBot, _age.top());
- assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
- if (dirty_n_elems == 0) return false;
- localBot = decrement_index(localBot);
- _bottom = localBot;
- // This is necessary to prevent any read below from being reordered
- // before the store just above.
- OrderAccess::fence();
- // g++ complains if the volatile result of the assignment is
- // unused, so we cast the volatile away. We cannot cast directly
- // to void, because gcc treats that as not using the result of the
- // assignment. However, casting to E& means that we trigger an
- // unused-value warning. So, we cast the E& to void.
- (void) const_cast<E&>(t = _elems[localBot]);
- // This is a second read of "age"; the "size()" above is the first.
- // If there's still at least one element in the queue, based on the
- // "_bottom" and "age" we've read, then there can be no interference with
- // a "pop_global" operation, and we're done.
- idx_t tp = _age.top(); // XXX
- if (size(localBot, tp) > 0) {
- assert(dirty_size(localBot, tp) != N - 1, "sanity");
- TASKQUEUE_STATS_ONLY(stats.record_pop());
- return true;
- } else {
- // Otherwise, the queue contained exactly one element; we take the slow
- // path.
- return pop_local_slow(localBot, _age.get());
- }
-}
-
typedef GenericTaskQueue<oop, mtGC> OopTaskQueue;
typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/taskqueue.inline.hpp Thu May 07 11:28:03 2015 -0700
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
+#define SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
+
+#include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/taskqueue.hpp"
+#include "utilities/stack.inline.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
+
+template <class T, MEMFLAGS F>
+inline GenericTaskQueueSet<T, F>::GenericTaskQueueSet(int n) : _n(n) {
+ typedef T* GenericTaskQueuePtr;
+ _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
+ for (int i = 0; i < n; i++) {
+ _queues[i] = NULL;
+ }
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline void GenericTaskQueue<E, F, N>::initialize() {
+ _elems = _array_allocator.allocate(N);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
+ FREE_C_HEAP_ARRAY(E, _elems);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
+ if (dirty_n_elems == N - 1) {
+ // Actually means 0, so do the push.
+ uint localBot = _bottom;
+ // g++ complains if the volatile result of the assignment is
+ // unused, so we cast the volatile away. We cannot cast directly
+ // to void, because gcc treats that as not using the result of the
+ // assignment. However, casting to E& means that we trigger an
+ // unused-value warning. So, we cast the E& to void.
+ (void)const_cast<E&>(_elems[localBot] = t);
+ OrderAccess::release_store(&_bottom, increment_index(localBot));
+ TASKQUEUE_STATS_ONLY(stats.record_push());
+ return true;
+ }
+ return false;
+}
+
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::push(E t) {
+ uint localBot = _bottom;
+ assert(localBot < N, "_bottom out of range.");
+ idx_t top = _age.top();
+ uint dirty_n_elems = dirty_size(localBot, top);
+ assert(dirty_n_elems < N, "n_elems out of range.");
+ if (dirty_n_elems < max_elems()) {
+ // g++ complains if the volatile result of the assignment is
+ // unused, so we cast the volatile away. We cannot cast directly
+ // to void, because gcc treats that as not using the result of the
+ // assignment. However, casting to E& means that we trigger an
+ // unused-value warning. So, we cast the E& to void.
+ (void) const_cast<E&>(_elems[localBot] = t);
+ OrderAccess::release_store(&_bottom, increment_index(localBot));
+ TASKQUEUE_STATS_ONLY(stats.record_push());
+ return true;
+ } else {
+ return push_slow(t, dirty_n_elems);
+ }
+}
+
+template <class E, MEMFLAGS F, unsigned int N>
+inline bool OverflowTaskQueue<E, F, N>::push(E t)
+{
+ if (!taskqueue_t::push(t)) {
+ overflow_stack()->push(t);
+ TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->size()));
+ }
+ return true;
+}
+
+// pop_local_slow() is done by the owning thread and is trying to
+// get the last task in the queue. It will compete with pop_global()
+// that will be used by other threads. The tag age is incremented
+// whenever the queue goes empty which it will do here if this thread
+// gets the last task or in pop_global() if the queue wraps (top == 0
+// and pop_global() succeeds, see pop_global()).
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
+ // This queue was observed to contain exactly one element; either this
+ // thread will claim it, or a competing "pop_global". In either case,
+ // the queue will be logically empty afterwards. Create a new Age value
+ // that represents the empty queue for the given value of "_bottom". (We
+ // must also increment "tag" because of the case where "bottom == 1",
+ // "top == 0". A pop_global could read the queue element in that case,
+ // then have the owner thread do a pop followed by another push. Without
+ // the incrementing of "tag", the pop_global's CAS could succeed,
+ // allowing it to believe it has claimed the stale element.)
+ Age newAge((idx_t)localBot, oldAge.tag() + 1);
+ // Perhaps a competing pop_global has already incremented "top", in which
+ // case it wins the element.
+ if (localBot == oldAge.top()) {
+ // No competing pop_global has yet incremented "top"; we'll try to
+ // install new_age, thus claiming the element.
+ Age tempAge = _age.cmpxchg(newAge, oldAge);
+ if (tempAge == oldAge) {
+ // We win.
+ assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
+ TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
+ return true;
+ }
+ }
+ // We lose; a completing pop_global gets the element. But the queue is empty
+ // and top is greater than bottom. Fix this representation of the empty queue
+ // to become the canonical one.
+ _age.set(newAge);
+ assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
+ return false;
+}
+
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
+ uint localBot = _bottom;
+ // This value cannot be N-1. That can only occur as a result of
+ // the assignment to bottom in this method. If it does, this method
+ // resets the size to 0 before the next call (which is sequential,
+ // since this is pop_local.)
+ uint dirty_n_elems = dirty_size(localBot, _age.top());
+ assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
+ if (dirty_n_elems == 0) return false;
+ localBot = decrement_index(localBot);
+ _bottom = localBot;
+ // This is necessary to prevent any read below from being reordered
+ // before the store just above.
+ OrderAccess::fence();
+ // g++ complains if the volatile result of the assignment is
+ // unused, so we cast the volatile away. We cannot cast directly
+ // to void, because gcc treats that as not using the result of the
+ // assignment. However, casting to E& means that we trigger an
+ // unused-value warning. So, we cast the E& to void.
+ (void) const_cast<E&>(t = _elems[localBot]);
+ // This is a second read of "age"; the "size()" above is the first.
+ // If there's still at least one element in the queue, based on the
+ // "_bottom" and "age" we've read, then there can be no interference with
+ // a "pop_global" operation, and we're done.
+ idx_t tp = _age.top(); // XXX
+ if (size(localBot, tp) > 0) {
+ assert(dirty_size(localBot, tp) != N - 1, "sanity");
+ TASKQUEUE_STATS_ONLY(stats.record_pop());
+ return true;
+ } else {
+ // Otherwise, the queue contained exactly one element; we take the slow
+ // path.
+ return pop_local_slow(localBot, _age.get());
+ }
+}
+
+template <class E, MEMFLAGS F, unsigned int N>
+bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
+{
+ if (overflow_empty()) return false;
+ t = overflow_stack()->pop();
+ return true;
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
+ Age oldAge = _age.get();
+ // Architectures with weak memory model require a barrier here
+ // to guarantee that bottom is not older than age,
+ // which is crucial for the correctness of the algorithm.
+#if !(defined SPARC || defined IA32 || defined AMD64)
+ OrderAccess::fence();
+#endif
+ uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
+ uint n_elems = size(localBot, oldAge.top());
+ if (n_elems == 0) {
+ return false;
+ }
+
+ // g++ complains if the volatile result of the assignment is
+ // unused, so we cast the volatile away. We cannot cast directly
+ // to void, because gcc treats that as not using the result of the
+ // assignment. However, casting to E& means that we trigger an
+ // unused-value warning. So, we cast the E& to void.
+ (void) const_cast<E&>(t = _elems[oldAge.top()]);
+ Age newAge(oldAge);
+ newAge.increment();
+ Age resAge = _age.cmpxchg(newAge, oldAge);
+
+ // Note that using "_bottom" here might fail, since a pop_local might
+ // have decremented it.
+ assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
+ return resAge == oldAge;
+}
+
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
+ if (_n > 2) {
+ uint k1 = queue_num;
+ while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
+ uint k2 = queue_num;
+ while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
+ // Sample both and try the larger.
+ uint sz1 = _queues[k1]->size();
+ uint sz2 = _queues[k2]->size();
+ if (sz2 > sz1) return _queues[k2]->pop_global(t);
+ else return _queues[k1]->pop_global(t);
+ } else if (_n == 2) {
+ // Just try the other one.
+ uint k = (queue_num + 1) % 2;
+ return _queues[k]->pop_global(t);
+ } else {
+ assert(_n == 1, "can't be zero.");
+ return false;
+ }
+}
+
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
+ for (uint i = 0; i < 2 * _n; i++) {
+ if (steal_best_of_2(queue_num, seed, t)) {
+ TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
+ return true;
+ }
+ }
+ TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false));
+ return false;
+}
+
+template <unsigned int N, MEMFLAGS F>
+inline typename TaskQueueSuper<N, F>::Age TaskQueueSuper<N, F>::Age::cmpxchg(const Age new_age, const Age old_age) volatile {
+ return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data,
+ (volatile intptr_t *)&_data,
+ (intptr_t)old_age._data);
+}
+
+template<class E, MEMFLAGS F, unsigned int N>
+inline void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
+ // tty->print_cr("START OopTaskQueue::oops_do");
+ uint iters = size();
+ uint index = _bottom;
+ for (uint i = 0; i < iters; ++i) {
+ index = decrement_index(index);
+ // tty->print_cr(" doing entry %d," INTPTR_T " -> " INTPTR_T,
+ // index, &_elems[index], _elems[index]);
+ E* t = (E*)&_elems[index]; // cast away volatility
+ oop* p = (oop*)t;
+ assert((*t)->is_oop_or_null(), err_msg("Expected an oop or NULL at " PTR_FORMAT, p2i(*t)));
+ f->do_oop(p);
+ }
+ // tty->print_cr("END OopTaskQueue::oops_do");
+}
+
+
+#endif // SHARE_VM_UTILITIES_TASKQUEUE_INLINE_HPP
--- a/hotspot/src/share/vm/utilities/workgroup.cpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/workgroup.cpp Thu May 07 11:28:03 2015 -0700
@@ -29,8 +29,6 @@
#include "runtime/os.hpp"
#include "utilities/workgroup.hpp"
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
// Definitions of WorkGang methods.
AbstractWorkGang::AbstractWorkGang(const char* name,
@@ -155,7 +153,7 @@
// Wait for them to be finished
while (finished_workers() < no_of_parallel_workers) {
if (TraceWorkGang) {
- tty->print_cr("Waiting in work gang %s: %d/%d finished sequence %d",
+ tty->print_cr("Waiting in work gang %s: %u/%u finished sequence %d",
name(), finished_workers(), no_of_parallel_workers,
_sequence_number);
}
@@ -163,11 +161,11 @@
}
_task = NULL;
if (TraceWorkGang) {
- tty->print_cr("\nFinished work gang %s: %d/%d sequence %d",
+ tty->print_cr("\nFinished work gang %s: %u/%u sequence %d",
name(), finished_workers(), no_of_parallel_workers,
_sequence_number);
Thread* me = Thread::current();
- tty->print_cr(" T: 0x%x VM_thread: %d", me, me->is_VM_thread());
+ tty->print_cr(" T: " PTR_FORMAT " VM_thread: %d", p2i(me), me->is_VM_thread());
}
}
@@ -190,7 +188,7 @@
monitor()->notify_all();
while (finished_workers() < active_workers()) {
if (TraceWorkGang) {
- tty->print_cr("Waiting in work gang %s: %d/%d finished",
+ tty->print_cr("Waiting in work gang %s: %u/%u finished",
name(), finished_workers(), active_workers());
}
monitor()->wait(/* no_safepoint_check */ true);
@@ -251,7 +249,7 @@
assert(_gang != NULL, "No gang to run in");
os::set_priority(this, NearMaxPriority);
if (TraceWorkGang) {
- tty->print_cr("Running gang worker for gang %s id %d",
+ tty->print_cr("Running gang worker for gang %s id %u",
gang()->name(), id());
}
// The VM thread should not execute here because MutexLocker's are used
@@ -274,7 +272,7 @@
// in the outer loop.
gang()->internal_worker_poll(&data);
if (TraceWorkGang) {
- tty->print("Polled outside for work in gang %s worker %d",
+ tty->print("Polled outside for work in gang %s worker %u",
gang()->name(), id());
tty->print(" terminate: %s",
data.terminate() ? "true" : "false");
@@ -308,7 +306,7 @@
gang_monitor->wait(/* no_safepoint_check */ true);
gang()->internal_worker_poll(&data);
if (TraceWorkGang) {
- tty->print("Polled inside for work in gang %s worker %d",
+ tty->print("Polled inside for work in gang %s worker %u",
gang()->name(), id());
tty->print(" terminate: %s",
data.terminate() ? "true" : "false");
@@ -325,14 +323,14 @@
// Drop gang mutex.
}
if (TraceWorkGang) {
- tty->print("Work for work gang %s id %d task %s part %d",
+ tty->print("Work for work gang %s id %u task %s part %d",
gang()->name(), id(), data.task()->name(), part);
}
assert(data.task() != NULL, "Got null task");
data.task()->work(part);
{
if (TraceWorkGang) {
- tty->print("Finish for work gang %s id %d task %s part %d",
+ tty->print("Finish for work gang %s id %u task %s part %d",
gang()->name(), id(), data.task()->name(), part);
}
// Grab the gang mutex.
--- a/hotspot/src/share/vm/utilities/workgroup.hpp Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/src/share/vm/utilities/workgroup.hpp Thu May 07 11:28:03 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@
// and may inherit this method that does nothing. Some
// tasks do some coordination on termination and override
// this method to implement that coordination.
- virtual void set_for_termination(int active_workers) {};
+ virtual void set_for_termination(uint active_workers) {};
// Debugging accessor for the name.
const char* name() const PRODUCT_RETURN_(return NULL;);
@@ -102,7 +102,7 @@
AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues) :
AbstractGangTask(name), _queues(queues), _terminator(0, _queues) {}
ParallelTaskTerminator* terminator() { return &_terminator; }
- virtual void set_for_termination(int active_workers) {
+ virtual void set_for_termination(uint active_workers) {
terminator()->reset_for_reuse(active_workers);
}
OopTaskQueueSet* queues() { return _queues; }
--- a/hotspot/test/Makefile Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/Makefile Thu May 07 11:28:03 2015 -0700
@@ -28,8 +28,6 @@
ALT_MAKE ?= closed
--include $(ALT_MAKE)/Makefile
-
GETMIXEDPATH=echo
# Utilities used
@@ -306,6 +304,8 @@
endif
JTREG_BASIC_OPTIONS += $(JTREG_KEY_OPTION)
+-include $(ALT_MAKE)/Makefile
+
# Make sure jtreg exists
$(JTREG): $(JT_HOME)
@@ -405,15 +405,6 @@
################################################################
-# internalvmtests (run internal unit tests inside the VM)
-
-hotspot_internalvmtests internalvmtests: prep $(PRODUCT_HOME)
- $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -XX:+ExecuteInternalVMTests -version
-
-PHONY_LIST += hotspot_internalvmtests internalvmtests
-
-################################################################
-
# Phony targets (e.g. these are not filenames)
.PHONY: all clean prep $(PHONY_LIST)
--- a/hotspot/test/TEST.groups Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/TEST.groups Thu May 07 11:28:03 2015 -0700
@@ -233,6 +233,7 @@
gc/arguments/TestParallelGCThreads.java \
gc/arguments/TestUseCompressedOopsErgo.java \
gc/class_unloading/TestG1ClassUnloadingHWM.java \
+ gc/ergonomics/TestDynamicNumberOfGCThreads.java
gc/g1/ \
gc/metaspace/G1AddMetaspaceDependency.java \
gc/metaspace/TestMetaspacePerfCounters.java \
@@ -262,6 +263,7 @@
gc/arguments/TestMinInitialErgonomics.java \
gc/arguments/TestParallelGCThreads.java \
gc/arguments/TestUseCompressedOopsErgo.java \
+ gc/ergonomics/TestDynamicNumberOfGCThreads.java
gc/metaspace/TestMetaspacePerfCounters.java \
gc/parallelScavenge/ \
gc/startup_warnings/TestParallelGC.java \
@@ -279,6 +281,7 @@
gc/arguments/TestUseCompressedOopsErgo.java \
gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java \
gc/concurrentMarkSweep/ \
+ gc/ergonomics/TestDynamicNumberOfGCThreads.java
gc/startup_warnings/TestCMS.java \
gc/startup_warnings/TestDefNewCMS.java \
gc/startup_warnings/TestParNewCMS.java
--- a/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/TestSoftReferencesBehaviorOnOOME.java Thu May 07 11:28:03 2015 -0700
@@ -28,29 +28,30 @@
* @library /testlibrary
* @modules java.base/sun.misc
* java.management
- * @ignore 8073669
* @build TestSoftReferencesBehaviorOnOOME
* @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 512 2k
* @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 128k 256k
- * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k 10
+ * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k
*/
import com.oracle.java.testlibrary.Utils;
+import com.oracle.java.testlibrary.Asserts;
import java.lang.ref.SoftReference;
import java.util.LinkedList;
import java.util.Random;
public class TestSoftReferencesBehaviorOnOOME {
- private static final Random rndGenerator = Utils.getRandomInstance();
-
+ /**
+ * Test generates a lot of soft references to objects with random payloads.
+ * Then it provokes OOME and checks that all SoftReferences has been gone
+ * @param args - [minSize] [maxSize] [freq]
+ * where
+ * - minSize - min size of random objects
+ * - maxSize - max size of random objects
+ */
public static void main(String[] args) {
- int semiRefAllocFrequency = DEFAULT_FREQUENCY;
- long minSize = DEFAULT_MIN_SIZE,
- maxSize = DEFAULT_MAX_SIZE;
-
- if ( args.length >= 3 ) {
- semiRefAllocFrequency = Integer.parseInt(args[2]);
- }
+ long minSize = DEFAULT_MIN_SIZE;
+ long maxSize = DEFAULT_MAX_SIZE;
if ( args.length >= 2) {
maxSize = getBytesCount(args[1]);
@@ -60,46 +61,49 @@
minSize = getBytesCount(args[0]);
}
- new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize, semiRefAllocFrequency);
+ new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize);
}
/**
* Test that all SoftReferences has been cleared at time of OOM.
*/
- void softReferencesOom(long minSize, long maxSize, int semiRefAllocFrequency) {
- System.out.format( "minSize = %d, maxSize = %d, freq = %d%n", minSize, maxSize, semiRefAllocFrequency );
- long counter = 0;
+ void softReferencesOom(long minSize, long maxSize) {
+ System.out.format( "minSize = %d, maxSize = %d%n", minSize, maxSize );
+
+ LinkedList<SoftReference> arrSoftRefs = new LinkedList();
+ staticRef = arrSoftRefs;
+ LinkedList arrObjects = new LinkedList();
+ staticRef = arrObjects;
long multiplier = maxSize - minSize;
- LinkedList<SoftReference> arrSoftRefs = new LinkedList();
- LinkedList arrObjects = new LinkedList();
long numberOfNotNulledObjects = 0;
- long oomSoftArraySize = 0;
try {
- while (true) {
- // Keep every Xth object to make sure we hit OOM pretty fast
- if (counter % semiRefAllocFrequency != 0) {
- long allocationSize = ((int) (rndGenerator.nextDouble() * multiplier))
- + minSize;
- arrObjects.add(new byte[(int)allocationSize]);
- } else {
- arrSoftRefs.add(new SoftReference(new Object()));
- }
+
+ // Lets allocate as many as we can - taking size of all SoftRerefences
+ // by minimum. So it can provoke some GC but we surely will allocate enough.
+ long numSofts = (long) ((0.95 * Runtime.getRuntime().totalMemory()) / minSize);
+ System.out.println("num Soft: " + numSofts);
+
+ while (numSofts-- > 0) {
+ int allocationSize = ((int) (RND_GENERATOR.nextDouble() * multiplier))
+ + (int)minSize;
+ arrSoftRefs.add(new SoftReference(new byte[allocationSize]));
+ }
- counter++;
- if (counter == Long.MAX_VALUE) {
- counter = 0;
- }
+ System.out.println("free: " + Runtime.getRuntime().freeMemory());
+
+ // provoke OOME.
+ while (true) {
+ arrObjects.add(new byte[(int) Runtime.getRuntime().totalMemory()]);
}
+
} catch (OutOfMemoryError oome) {
+
// Clear allocated ballast, so we don't get another OOM.
-
+ staticRef = null;
arrObjects = null;
-
- // Get the number of soft refs first, so we don't trigger
- // another OOM.
- oomSoftArraySize = arrSoftRefs.size();
+ long oomSoftArraySize = arrSoftRefs.size();
for (SoftReference sr : arrSoftRefs) {
Object o = sr.get();
@@ -111,15 +115,14 @@
// Make sure we clear all refs before we return failure
arrSoftRefs = null;
-
- if (numberOfNotNulledObjects > 0) {
- throw new RuntimeException(numberOfNotNulledObjects + " out of "
- + oomSoftArraySize + " SoftReferences was not "
- + "null at time of OutOfMemoryError");
- }
+ Asserts.assertFalse(numberOfNotNulledObjects > 0,
+ "" + numberOfNotNulledObjects + " out of "
+ + oomSoftArraySize + " SoftReferences was not "
+ + "null at time of OutOfMemoryError"
+ );
} finally {
- arrSoftRefs = null;
- arrObjects = null;
+ Asserts.assertTrue(arrObjects == null, "OOME hasn't been provoked");
+ Asserts.assertTrue(arrSoftRefs == null, "OOME hasn't been provoked");
}
}
@@ -128,9 +131,7 @@
long mod = 1;
if (arg.trim().length() >= 2) {
- mod = postfixes.indexOf(
- arg.trim().charAt(arg.length() - 1)
- );
+ mod = postfixes.indexOf(arg.trim().charAt(arg.length() - 1));
if (mod != -1) {
mod = (long) Math.pow(1024, mod+1);
@@ -143,7 +144,8 @@
return Long.parseLong(arg) * mod;
}
+ private static final Random RND_GENERATOR = Utils.getRandomInstance();
private static final long DEFAULT_MIN_SIZE = 512;
private static final long DEFAULT_MAX_SIZE = 1024;
- private static final int DEFAULT_FREQUENCY = 4;
+ private static Object staticRef; // to prevent compile optimisations
}
--- a/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java Thu May 07 11:28:03 2015 -0700
@@ -44,14 +44,24 @@
}
private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output) {
+ output.shouldHaveExitValue(0); // test should run succesfully
output.shouldContain("new_active_workers");
- output.shouldHaveExitValue(0);
}
private static void testDynamicNumberOfGCThreads(String gcFlag) throws Exception {
// UseDynamicNumberOfGCThreads and TraceDynamicGCThreads enabled
- ProcessBuilder pb_enabled =
- ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-Xmx10M", "-XX:+PrintGCDetails", "-XX:+UseDynamicNumberOfGCThreads", "-XX:+TraceDynamicGCThreads", GCTest.class.getName());
+ String[] baseArgs = {"-XX:+" + gcFlag, "-Xmx10M", "-XX:+PrintGCDetails", "-XX:+UseDynamicNumberOfGCThreads", "-XX:+TraceDynamicGCThreads", GCTest.class.getName()};
+
+ // Base test with gc and +UseDynamicNumberOfGCThreads:
+ ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(baseArgs);
+ verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
+
+ // Ensure it also works on uniprocessors or if user specifies -XX:ParallelGCThreads=1:
+ String[] extraArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+ForceDynamicNumberOfGCThreads", "-XX:ParallelGCThreads=1"};
+ String[] finalArgs = new String[baseArgs.length + extraArgs.length];
+ System.arraycopy(extraArgs, 0, finalArgs, 0, extraArgs.length);
+ System.arraycopy(baseArgs, 0, finalArgs, extraArgs.length, baseArgs.length);
+ pb_enabled = ProcessTools.createJavaProcessBuilder(finalArgs);
verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
}
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java Thu May 07 11:28:03 2015 -0700
@@ -76,7 +76,6 @@
printTestInfo(maxCacheSize);
vmOpts.add("-XX:G1ConcRSLogCacheSize=" + hotCardTableSize);
- vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
// for 32 bits ObjectAlignmentInBytes is not a option
if (Platform.is32bit()) {
@@ -98,7 +97,7 @@
private void performTest(List<String> opts) throws Exception {
ProcessBuilder pb
- = ProcessTools.createJavaProcessBuilder(
+ = ProcessTools.createJavaProcessBuilder(true,
opts.toArray(new String[opts.size()])
);
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
/**
* @test TestShrinkAuxiliaryData05
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
* @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
/**
* @test TestShrinkAuxiliaryData10
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
* @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
/**
* @test TestShrinkAuxiliaryData15
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
* @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
/**
* @test TestShrinkAuxiliaryData20
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
* @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
/**
* @test TestShrinkAuxiliaryData25
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
* @requires vm.gc=="G1" | vm.gc=="null"
--- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java Wed May 06 17:42:24 2015 -0700
+++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java Thu May 07 11:28:03 2015 -0700
@@ -23,7 +23,7 @@
/**
* @test TestShrinkAuxiliaryData30
- * @bug 8038423 8061715
+ * @bug 8038423 8061715 8078405
* @summary Checks that decommitment occurs for JVM with different
* G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values
* @requires vm.gc=="G1" | vm.gc=="null"