Merge
This commit is contained in:
commit
4b8d7ee16c
@ -2027,7 +2027,7 @@ class Assembler : public AbstractAssembler {
|
||||
inline void vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c);
|
||||
inline void vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c);
|
||||
inline void vsl( VectorRegister d, VectorRegister a, VectorRegister b);
|
||||
inline void vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int si4);
|
||||
inline void vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int ui4);
|
||||
inline void vslo( VectorRegister d, VectorRegister a, VectorRegister b);
|
||||
inline void vsr( VectorRegister d, VectorRegister a, VectorRegister b);
|
||||
inline void vsro( VectorRegister d, VectorRegister a, VectorRegister b);
|
||||
|
@ -800,7 +800,7 @@ inline void Assembler::vspltisw(VectorRegister d, int si5)
|
||||
inline void Assembler::vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VPERM_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
|
||||
inline void Assembler::vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VSEL_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
|
||||
inline void Assembler::vsl( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSL_OPCODE | vrt(d) | vra(a) | vrb(b)); }
|
||||
inline void Assembler::vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int si4) { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(simm(si4,4))); }
|
||||
inline void Assembler::vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int ui4) { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(uimm(ui4,4))); }
|
||||
inline void Assembler::vslo( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSLO_OPCODE | vrt(d) | vra(a) | vrb(b)); }
|
||||
inline void Assembler::vsr( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSR_OPCODE | vrt(d) | vra(a) | vrb(b)); }
|
||||
inline void Assembler::vsro( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRO_OPCODE | vrt(d) | vra(a) | vrb(b)); }
|
||||
|
@ -4576,12 +4576,12 @@ void MacroAssembler::kernel_crc32_1word_aligned(Register crc, Register buf, Regi
|
||||
vspltisw(VR0, -1);
|
||||
|
||||
vsldoi(mask_32bit, zeroes, VR0, 4);
|
||||
vsldoi(mask_64bit, zeroes, VR0, -8);
|
||||
vsldoi(mask_64bit, zeroes, VR0, 8);
|
||||
|
||||
// Get the initial value into v8
|
||||
vxor(VR8, VR8, VR8);
|
||||
mtvrd(VR8, crc);
|
||||
vsldoi(VR8, zeroes, VR8, -8); // shift into bottom 32 bits
|
||||
vsldoi(VR8, zeroes, VR8, 8); // shift into bottom 32 bits
|
||||
|
||||
li (rLoaded, 0);
|
||||
|
||||
@ -4930,7 +4930,7 @@ void MacroAssembler::kernel_crc32_1word_aligned(Register crc, Register buf, Regi
|
||||
addi(barretConstants, barretConstants, 16);
|
||||
lvx(const2, barretConstants);
|
||||
|
||||
vsldoi(VR1, VR0, VR0, -8);
|
||||
vsldoi(VR1, VR0, VR0, 8);
|
||||
vxor(VR0, VR0, VR1); // xor two 64 bit results together
|
||||
|
||||
// shift left one bit
|
||||
|
@ -2729,7 +2729,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ vspltisb (vTmp2, -16);
|
||||
__ vrld (keyPerm, keyPerm, vTmp2);
|
||||
__ vrld (keyPerm, keyPerm, vTmp2);
|
||||
__ vsldoi (keyPerm, keyPerm, keyPerm, -8);
|
||||
__ vsldoi (keyPerm, keyPerm, keyPerm, 8);
|
||||
|
||||
// load the 1st round key to vKey1
|
||||
__ li (keypos, 0);
|
||||
@ -2929,7 +2929,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ vspltisb (vTmp2, -16);
|
||||
__ vrld (keyPerm, keyPerm, vTmp2);
|
||||
__ vrld (keyPerm, keyPerm, vTmp2);
|
||||
__ vsldoi (keyPerm, keyPerm, keyPerm, -8);
|
||||
__ vsldoi (keyPerm, keyPerm, keyPerm, 8);
|
||||
|
||||
__ cmpwi (CCR0, keylen, 44);
|
||||
__ beq (CCR0, L_do44);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2017, 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
|
||||
@ -108,13 +108,16 @@ public class ObjectSynchronizer {
|
||||
|
||||
public Object next() {
|
||||
Address addr;
|
||||
if (index > 0) {
|
||||
addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
|
||||
} else {
|
||||
if (index == 0) {
|
||||
// advance to next block
|
||||
blockAddr = block.freeNext();
|
||||
if (blockAddr == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
block = new ObjectMonitor(blockAddr);
|
||||
index = blockSize - 1;
|
||||
addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
|
||||
}
|
||||
addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
|
||||
index --;
|
||||
return new ObjectMonitor(addr);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class HotSpotSpeculationLog implements SpeculationLog {
|
||||
private Set<SpeculationReason> failedSpeculations;
|
||||
|
||||
/** Strong references to all reasons embedded in the current nmethod. */
|
||||
private volatile Collection<SpeculationReason> speculations;
|
||||
private Collection<SpeculationReason> speculations;
|
||||
|
||||
@Override
|
||||
public synchronized void collectFailedSpeculations() {
|
||||
@ -70,14 +70,12 @@ public class HotSpotSpeculationLog implements SpeculationLog {
|
||||
* reason objects that are embedded in nmethods, so we add them to the speculations
|
||||
* collection.
|
||||
*/
|
||||
if (speculations == null) {
|
||||
synchronized (this) {
|
||||
if (speculations == null) {
|
||||
speculations = new ConcurrentLinkedQueue<>();
|
||||
}
|
||||
synchronized (this) {
|
||||
if (speculations == null) {
|
||||
speculations = new ConcurrentLinkedQueue<>();
|
||||
}
|
||||
speculations.add(reason);
|
||||
}
|
||||
speculations.add(reason);
|
||||
|
||||
return HotSpotObjectConstantImpl.forObject(reason);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2017, 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
|
||||
@ -387,7 +387,7 @@ bool os::platform_print_native_stack(outputStream* st, const void* context,
|
||||
intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp!
|
||||
address pc = (address)stk.AddrPC.Offset;
|
||||
|
||||
if (pc != NULL && sp != NULL && fp != NULL) {
|
||||
if (pc != NULL) {
|
||||
if (count == 2 && lastpc == pc) {
|
||||
// Skip it -- StackWalk64() may return the same PC
|
||||
// (but different SP) on the first try.
|
||||
@ -399,8 +399,6 @@ bool os::platform_print_native_stack(outputStream* st, const void* context,
|
||||
st->cr();
|
||||
}
|
||||
lastpc = pc;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
PVOID p = WindowsDbgHelp::SymFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset);
|
||||
|
@ -5185,6 +5185,7 @@ void CMSCollector::refProcessingWork() {
|
||||
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
|
||||
_span, &_markBitMap, &_markStack,
|
||||
&cmsKeepAliveClosure, false /* !preclean */);
|
||||
ReferenceProcessorPhaseTimes pt(_gc_timer_cm, rp->num_q());
|
||||
{
|
||||
GCTraceTime(Debug, gc, phases) t("Reference Processing", _gc_timer_cm);
|
||||
|
||||
@ -5211,16 +5212,16 @@ void CMSCollector::refProcessingWork() {
|
||||
&cmsKeepAliveClosure,
|
||||
&cmsDrainMarkingStackClosure,
|
||||
&task_executor,
|
||||
_gc_timer_cm);
|
||||
&pt);
|
||||
} else {
|
||||
stats = rp->process_discovered_references(&_is_alive_closure,
|
||||
&cmsKeepAliveClosure,
|
||||
&cmsDrainMarkingStackClosure,
|
||||
NULL,
|
||||
_gc_timer_cm);
|
||||
&pt);
|
||||
}
|
||||
_gc_tracer_cm->report_gc_reference_stats(stats);
|
||||
|
||||
pt.print_all_references();
|
||||
}
|
||||
|
||||
// This is the point where the entire marking should have completed.
|
||||
@ -5261,11 +5262,12 @@ void CMSCollector::refProcessingWork() {
|
||||
if (rp->processing_is_mt()) {
|
||||
rp->balance_all_queues();
|
||||
CMSRefProcTaskExecutor task_executor(*this);
|
||||
rp->enqueue_discovered_references(&task_executor);
|
||||
rp->enqueue_discovered_references(&task_executor, &pt);
|
||||
} else {
|
||||
rp->enqueue_discovered_references(NULL);
|
||||
rp->enqueue_discovered_references(NULL, &pt);
|
||||
}
|
||||
rp->verify_no_references_recorded();
|
||||
pt.print_enqueue_phase();
|
||||
assert(!rp->discovery_enabled(), "should have been disabled");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2017, 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
|
||||
@ -984,20 +984,22 @@ void ParNewGeneration::collect(bool full,
|
||||
// Can the mt_degree be set later (at run_task() time would be best)?
|
||||
rp->set_active_mt_degree(active_workers);
|
||||
ReferenceProcessorStats stats;
|
||||
ReferenceProcessorPhaseTimes pt(_gc_timer, rp->num_q());
|
||||
if (rp->processing_is_mt()) {
|
||||
ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set);
|
||||
stats = rp->process_discovered_references(&is_alive, &keep_alive,
|
||||
&evacuate_followers, &task_executor,
|
||||
_gc_timer);
|
||||
&pt);
|
||||
} else {
|
||||
thread_state_set.flush();
|
||||
gch->save_marks();
|
||||
stats = rp->process_discovered_references(&is_alive, &keep_alive,
|
||||
&evacuate_followers, NULL,
|
||||
_gc_timer);
|
||||
&pt);
|
||||
}
|
||||
_gc_tracer.report_gc_reference_stats(stats);
|
||||
_gc_tracer.report_tenuring_threshold(tenuring_threshold());
|
||||
pt.print_all_references();
|
||||
|
||||
if (!promotion_failed()) {
|
||||
// Swap the survivor spaces.
|
||||
@ -1049,14 +1051,16 @@ void ParNewGeneration::collect(bool full,
|
||||
rp->set_enqueuing_is_done(true);
|
||||
if (rp->processing_is_mt()) {
|
||||
ParNewRefProcTaskExecutor task_executor(*this, *_old_gen, thread_state_set);
|
||||
rp->enqueue_discovered_references(&task_executor);
|
||||
rp->enqueue_discovered_references(&task_executor, &pt);
|
||||
} else {
|
||||
rp->enqueue_discovered_references(NULL);
|
||||
rp->enqueue_discovered_references(NULL, &pt);
|
||||
}
|
||||
rp->verify_no_references_recorded();
|
||||
|
||||
gch->trace_heap_after_gc(gc_tracer());
|
||||
|
||||
pt.print_enqueue_phase();
|
||||
|
||||
_gc_timer->register_gc_end();
|
||||
|
||||
_gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
|
||||
|
@ -1260,9 +1260,13 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc,
|
||||
assert(num_free_regions() == 0, "we should not have added any free regions");
|
||||
rebuild_region_sets(false /* free_list_only */);
|
||||
|
||||
ReferenceProcessorPhaseTimes pt(NULL, ref_processor_stw()->num_q());
|
||||
|
||||
// Enqueue any discovered reference objects that have
|
||||
// not been removed from the discovered lists.
|
||||
ref_processor_stw()->enqueue_discovered_references();
|
||||
ref_processor_stw()->enqueue_discovered_references(NULL, &pt);
|
||||
|
||||
pt.print_enqueue_phase();
|
||||
|
||||
#if defined(COMPILER2) || INCLUDE_JVMCI
|
||||
DerivedPointerTable::update_pointers();
|
||||
@ -1667,7 +1671,9 @@ void G1CollectedHeap::shrink(size_t shrink_bytes) {
|
||||
G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
|
||||
CollectedHeap(),
|
||||
_collector_policy(collector_policy),
|
||||
_g1_policy(create_g1_policy()),
|
||||
_gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
|
||||
_gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()),
|
||||
_g1_policy(create_g1_policy(_gc_timer_stw)),
|
||||
_collection_set(this, _g1_policy),
|
||||
_dirty_card_queue_set(false),
|
||||
_is_alive_closure_cm(this),
|
||||
@ -1694,9 +1700,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
|
||||
_expand_heap_after_alloc_failure(true),
|
||||
_old_marking_cycles_started(0),
|
||||
_old_marking_cycles_completed(0),
|
||||
_in_cset_fast_test(),
|
||||
_gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
|
||||
_gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()) {
|
||||
_in_cset_fast_test() {
|
||||
|
||||
_workers = new WorkGang("GC Thread", ParallelGCThreads,
|
||||
/* are_GC_task_threads */true,
|
||||
@ -2015,10 +2019,12 @@ void G1CollectedHeap::ref_processing_init() {
|
||||
|
||||
MemRegion mr = reserved_region();
|
||||
|
||||
bool mt_processing = ParallelRefProcEnabled && (ParallelGCThreads > 1);
|
||||
|
||||
// Concurrent Mark ref processor
|
||||
_ref_processor_cm =
|
||||
new ReferenceProcessor(mr, // span
|
||||
ParallelRefProcEnabled && (ParallelGCThreads > 1),
|
||||
mt_processing,
|
||||
// mt processing
|
||||
ParallelGCThreads,
|
||||
// degree of mt processing
|
||||
@ -2035,7 +2041,7 @@ void G1CollectedHeap::ref_processing_init() {
|
||||
// STW ref processor
|
||||
_ref_processor_stw =
|
||||
new ReferenceProcessor(mr, // span
|
||||
ParallelRefProcEnabled && (ParallelGCThreads > 1),
|
||||
mt_processing,
|
||||
// mt processing
|
||||
ParallelGCThreads,
|
||||
// degree of mt processing
|
||||
@ -4313,6 +4319,8 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per
|
||||
// Setup the soft refs policy...
|
||||
rp->setup_policy(false);
|
||||
|
||||
ReferenceProcessorPhaseTimes* pt = g1_policy()->phase_times()->ref_phase_times();
|
||||
|
||||
ReferenceProcessorStats stats;
|
||||
if (!rp->processing_is_mt()) {
|
||||
// Serial reference processing...
|
||||
@ -4320,7 +4328,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per
|
||||
&keep_alive,
|
||||
&drain_queue,
|
||||
NULL,
|
||||
_gc_timer_stw);
|
||||
pt);
|
||||
} else {
|
||||
uint no_of_gc_workers = workers()->active_workers();
|
||||
|
||||
@ -4334,7 +4342,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per
|
||||
&keep_alive,
|
||||
&drain_queue,
|
||||
&par_task_executor,
|
||||
_gc_timer_stw);
|
||||
pt);
|
||||
}
|
||||
|
||||
_gc_tracer_stw->report_gc_reference_stats(stats);
|
||||
@ -4353,11 +4361,13 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per
|
||||
ReferenceProcessor* rp = _ref_processor_stw;
|
||||
assert(!rp->discovery_enabled(), "should have been disabled as part of processing");
|
||||
|
||||
ReferenceProcessorPhaseTimes* pt = g1_policy()->phase_times()->ref_phase_times();
|
||||
|
||||
// Now enqueue any remaining on the discovered lists on to
|
||||
// the pending list.
|
||||
if (!rp->processing_is_mt()) {
|
||||
// Serial reference processing...
|
||||
rp->enqueue_discovered_references();
|
||||
rp->enqueue_discovered_references(NULL, pt);
|
||||
} else {
|
||||
// Parallel reference enqueueing
|
||||
|
||||
@ -4368,7 +4378,7 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per
|
||||
n_workers, rp->max_num_q());
|
||||
|
||||
G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues, n_workers);
|
||||
rp->enqueue_discovered_references(&par_task_executor);
|
||||
rp->enqueue_discovered_references(&par_task_executor, pt);
|
||||
}
|
||||
|
||||
rp->verify_no_references_recorded();
|
||||
|
@ -298,7 +298,7 @@ private:
|
||||
size_t size,
|
||||
size_t translation_factor);
|
||||
|
||||
static G1Policy* create_g1_policy();
|
||||
static G1Policy* create_g1_policy(STWGCTimer* gc_timer);
|
||||
|
||||
void trace_heap(GCWhen::Type when, const GCTracer* tracer);
|
||||
|
||||
@ -370,6 +370,10 @@ protected:
|
||||
G1EdenRegions _eden;
|
||||
G1SurvivorRegions _survivor;
|
||||
|
||||
STWGCTimer* _gc_timer_stw;
|
||||
|
||||
G1NewTracer* _gc_tracer_stw;
|
||||
|
||||
// The current policy object for the collector.
|
||||
G1Policy* _g1_policy;
|
||||
G1HeapSizingPolicy* _heap_sizing_policy;
|
||||
@ -901,10 +905,6 @@ protected:
|
||||
// The (stw) reference processor...
|
||||
ReferenceProcessor* _ref_processor_stw;
|
||||
|
||||
STWGCTimer* _gc_timer_stw;
|
||||
|
||||
G1NewTracer* _gc_tracer_stw;
|
||||
|
||||
// During reference object discovery, the _is_alive_non_header
|
||||
// closure (if non-null) is applied to the referent object to
|
||||
// determine whether the referent is live. If so then the
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "gc/g1/g1ParScanThreadState.hpp"
|
||||
#include "gc/g1/heapRegion.inline.hpp"
|
||||
|
||||
class STWGCTimer;
|
||||
|
||||
bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts,
|
||||
jlong* totals,
|
||||
jbyte* accuracy,
|
||||
@ -40,6 +42,6 @@ HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
|
||||
return new HeapRegion(hrs_index, bot(), mr);
|
||||
}
|
||||
|
||||
G1Policy* G1CollectedHeap::create_g1_policy() {
|
||||
return new G1DefaultPolicy();
|
||||
G1Policy* G1CollectedHeap::create_g1_policy(STWGCTimer* gc_timer) {
|
||||
return new G1DefaultPolicy(gc_timer);
|
||||
}
|
||||
|
@ -1660,14 +1660,17 @@ void G1ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
|
||||
// Reference lists are balanced (see balance_all_queues() and balance_queues()).
|
||||
rp->set_active_mt_degree(active_workers);
|
||||
|
||||
ReferenceProcessorPhaseTimes pt(_gc_timer_cm, rp->num_q());
|
||||
|
||||
// Process the weak references.
|
||||
const ReferenceProcessorStats& stats =
|
||||
rp->process_discovered_references(&g1_is_alive,
|
||||
&g1_keep_alive,
|
||||
&g1_drain_mark_stack,
|
||||
executor,
|
||||
_gc_timer_cm);
|
||||
&pt);
|
||||
_gc_tracer_cm->report_gc_reference_stats(stats);
|
||||
pt.print_all_references();
|
||||
|
||||
// The do_oop work routines of the keep_alive and drain_marking_stack
|
||||
// oop closures will set the has_overflown flag if we overflow the
|
||||
@ -1678,9 +1681,12 @@ void G1ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
|
||||
|
||||
assert(rp->num_q() == active_workers, "why not");
|
||||
|
||||
rp->enqueue_discovered_references(executor);
|
||||
rp->enqueue_discovered_references(executor, &pt);
|
||||
|
||||
rp->verify_no_references_recorded();
|
||||
|
||||
pt.print_enqueue_phase();
|
||||
|
||||
assert(!rp->discovery_enabled(), "Post condition");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2017, 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
|
||||
@ -47,7 +47,7 @@
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/pair.hpp"
|
||||
|
||||
G1DefaultPolicy::G1DefaultPolicy() :
|
||||
G1DefaultPolicy::G1DefaultPolicy(STWGCTimer* gc_timer) :
|
||||
_predictor(G1ConfidencePercent / 100.0),
|
||||
_analytics(new G1Analytics(&_predictor)),
|
||||
_mmu_tracker(new G1MMUTrackerQueue(GCPauseIntervalMillis / 1000.0, MaxGCPauseMillis / 1000.0)),
|
||||
@ -63,7 +63,7 @@ G1DefaultPolicy::G1DefaultPolicy() :
|
||||
_initial_mark_to_mixed(),
|
||||
_collection_set(NULL),
|
||||
_g1(NULL),
|
||||
_phase_times(new G1GCPhaseTimes(ParallelGCThreads)),
|
||||
_phase_times(new G1GCPhaseTimes(gc_timer, ParallelGCThreads)),
|
||||
_tenuring_threshold(MaxTenuringThreshold),
|
||||
_max_survivor_regions(0),
|
||||
_survivors_age_table(true),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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
|
||||
@ -44,6 +44,7 @@ class G1Analytics;
|
||||
class G1SurvivorRegions;
|
||||
class G1YoungGenSizer;
|
||||
class GCPolicyCounters;
|
||||
class STWGCTimer;
|
||||
|
||||
class G1DefaultPolicy: public G1Policy {
|
||||
private:
|
||||
@ -264,7 +265,7 @@ private:
|
||||
void abort_time_to_mixed_tracking();
|
||||
public:
|
||||
|
||||
G1DefaultPolicy();
|
||||
G1DefaultPolicy(STWGCTimer* gc_timer);
|
||||
|
||||
virtual ~G1DefaultPolicy();
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "gc/g1/g1GCPhaseTimes.hpp"
|
||||
#include "gc/g1/g1HotCardCache.hpp"
|
||||
#include "gc/g1/g1StringDedup.hpp"
|
||||
#include "gc/g1/workerDataArray.inline.hpp"
|
||||
#include "gc/shared/workerDataArray.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
@ -37,10 +37,11 @@
|
||||
|
||||
static const char* Indents[5] = {"", " ", " ", " ", " "};
|
||||
|
||||
G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
|
||||
G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
|
||||
_max_gc_threads(max_gc_threads),
|
||||
_gc_start_counter(0),
|
||||
_gc_pause_time_ms(0.0)
|
||||
_gc_pause_time_ms(0.0),
|
||||
_ref_phase_times((GCTimer*)gc_timer, max_gc_threads)
|
||||
{
|
||||
assert(max_gc_threads > 0, "Must have some GC threads");
|
||||
|
||||
@ -156,6 +157,8 @@ void G1GCPhaseTimes::reset() {
|
||||
_gc_par_phases[i]->reset();
|
||||
}
|
||||
}
|
||||
|
||||
_ref_phase_times.reset();
|
||||
}
|
||||
|
||||
void G1GCPhaseTimes::note_gc_start() {
|
||||
@ -288,6 +291,19 @@ void G1GCPhaseTimes::debug_time(const char* name, double value) const {
|
||||
log_debug(gc, phases)("%s%s: " TIME_FORMAT, Indents[2], name, value);
|
||||
}
|
||||
|
||||
void G1GCPhaseTimes::debug_time_for_reference(const char* name, double value) const {
|
||||
LogTarget(Debug, gc, phases) lt;
|
||||
LogTarget(Debug, gc, phases, ref) lt2;
|
||||
|
||||
if (lt.is_enabled()) {
|
||||
LogStream ls(lt);
|
||||
ls.print_cr("%s%s: " TIME_FORMAT, Indents[2], name, value);
|
||||
} else if (lt2.is_enabled()) {
|
||||
LogStream ls(lt2);
|
||||
ls.print_cr("%s%s: " TIME_FORMAT, Indents[2], name, value);
|
||||
}
|
||||
}
|
||||
|
||||
void G1GCPhaseTimes::trace_time(const char* name, double value) const {
|
||||
log_trace(gc, phases)("%s%s: " TIME_FORMAT, Indents[3], name, value);
|
||||
}
|
||||
@ -374,7 +390,8 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
|
||||
debug_time("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms);
|
||||
trace_phase(_gc_par_phases[PreserveCMReferents]);
|
||||
|
||||
debug_time("Reference Processing", _cur_ref_proc_time_ms);
|
||||
debug_time_for_reference("Reference Processing", _cur_ref_proc_time_ms);
|
||||
_ref_phase_times.print_all_references(2, false);
|
||||
|
||||
if (G1StringDedup::is_enabled()) {
|
||||
debug_time("String Dedup Fixup", _cur_string_dedup_fixup_time_ms);
|
||||
@ -390,7 +407,8 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
|
||||
trace_time("Remove Self Forwards",_cur_evac_fail_remove_self_forwards);
|
||||
}
|
||||
|
||||
debug_time("Reference Enqueuing", _cur_ref_enq_time_ms);
|
||||
debug_time_for_reference("Reference Enqueuing", _cur_ref_enq_time_ms);
|
||||
_ref_phase_times.print_enqueue_phase(2, false);
|
||||
|
||||
debug_time("Merge Per-Thread State", _recorded_merge_pss_time_ms);
|
||||
debug_time("Code Roots Purge", _cur_strong_code_root_purge_time_ms);
|
||||
|
@ -25,11 +25,13 @@
|
||||
#ifndef SHARE_VM_GC_G1_G1GCPHASETIMES_HPP
|
||||
#define SHARE_VM_GC_G1_G1GCPHASETIMES_HPP
|
||||
|
||||
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
|
||||
#include "logging/logLevel.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
class LineBuffer;
|
||||
class STWGCTimer;
|
||||
|
||||
template <class T> class WorkerDataArray;
|
||||
|
||||
@ -159,6 +161,8 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
double _cur_verify_before_time_ms;
|
||||
double _cur_verify_after_time_ms;
|
||||
|
||||
ReferenceProcessorPhaseTimes _ref_phase_times;
|
||||
|
||||
double worker_time(GCParPhases phase, uint worker);
|
||||
void note_gc_end();
|
||||
void reset();
|
||||
@ -172,6 +176,8 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
|
||||
void info_time(const char* name, double value) const;
|
||||
void debug_time(const char* name, double value) const;
|
||||
// This will print logs for both 'gc+phases' and 'gc+phases+ref'.
|
||||
void debug_time_for_reference(const char* name, double value) const;
|
||||
void trace_time(const char* name, double value) const;
|
||||
void trace_count(const char* name, size_t value) const;
|
||||
|
||||
@ -181,7 +187,7 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
void print_other(double accounted_ms) const;
|
||||
|
||||
public:
|
||||
G1GCPhaseTimes(uint max_gc_threads);
|
||||
G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads);
|
||||
void note_gc_start();
|
||||
void print();
|
||||
|
||||
@ -354,6 +360,8 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
double fast_reclaim_humongous_time_ms() {
|
||||
return _cur_fast_reclaim_humongous_time_ms;
|
||||
}
|
||||
|
||||
ReferenceProcessorPhaseTimes* ref_phase_times() { return &_ref_phase_times; }
|
||||
};
|
||||
|
||||
class G1GCParPhaseTimesTracker : public StackObj {
|
||||
|
@ -149,13 +149,16 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
|
||||
assert(rp == g1h->ref_processor_stw(), "Sanity");
|
||||
|
||||
rp->setup_policy(clear_all_softrefs);
|
||||
ReferenceProcessorPhaseTimes pt(gc_timer(), rp->num_q());
|
||||
|
||||
const ReferenceProcessorStats& stats =
|
||||
rp->process_discovered_references(&GenMarkSweep::is_alive,
|
||||
&GenMarkSweep::keep_alive,
|
||||
&GenMarkSweep::follow_stack_closure,
|
||||
NULL,
|
||||
gc_timer());
|
||||
&pt);
|
||||
gc_tracer()->report_gc_reference_stats(stats);
|
||||
pt.print_all_references();
|
||||
}
|
||||
|
||||
// This is the point where the entire marking should have completed.
|
||||
|
@ -254,7 +254,11 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
|
||||
DerivedPointerTable::update_pointers();
|
||||
#endif
|
||||
|
||||
ref_processor()->enqueue_discovered_references(NULL);
|
||||
ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->num_q());
|
||||
|
||||
ref_processor()->enqueue_discovered_references(NULL, &pt);
|
||||
|
||||
pt.print_enqueue_phase();
|
||||
|
||||
// Update time of last GC
|
||||
reset_millis_since_last_gc();
|
||||
@ -528,10 +532,12 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
GCTraceTime(Debug, gc, phases) t("Reference Processing", _gc_timer);
|
||||
|
||||
ref_processor()->setup_policy(clear_all_softrefs);
|
||||
ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->num_q());
|
||||
const ReferenceProcessorStats& stats =
|
||||
ref_processor()->process_discovered_references(
|
||||
is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, _gc_timer);
|
||||
is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, &pt);
|
||||
gc_tracer()->report_gc_reference_stats(stats);
|
||||
pt.print_all_references();
|
||||
}
|
||||
|
||||
// This is the point where the entire marking should have completed.
|
||||
|
@ -1041,7 +1041,11 @@ void PSParallelCompact::post_compact()
|
||||
DerivedPointerTable::update_pointers();
|
||||
#endif
|
||||
|
||||
ref_processor()->enqueue_discovered_references(NULL);
|
||||
ReferenceProcessorPhaseTimes pt(&_gc_timer, ref_processor()->num_q());
|
||||
|
||||
ref_processor()->enqueue_discovered_references(NULL, &pt);
|
||||
|
||||
pt.print_enqueue_phase();
|
||||
|
||||
if (ZapUnusedHeapArea) {
|
||||
heap->gen_mangle_unused_area();
|
||||
@ -2103,18 +2107,20 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
|
||||
GCTraceTime(Debug, gc, phases) tm("Reference Processing", &_gc_timer);
|
||||
|
||||
ReferenceProcessorStats stats;
|
||||
ReferenceProcessorPhaseTimes pt(&_gc_timer, ref_processor()->num_q());
|
||||
if (ref_processor()->processing_is_mt()) {
|
||||
RefProcTaskExecutor task_executor;
|
||||
stats = ref_processor()->process_discovered_references(
|
||||
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
|
||||
&task_executor, &_gc_timer);
|
||||
&task_executor, &pt);
|
||||
} else {
|
||||
stats = ref_processor()->process_discovered_references(
|
||||
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL,
|
||||
&_gc_timer);
|
||||
&pt);
|
||||
}
|
||||
|
||||
gc_tracer->report_gc_reference_stats(stats);
|
||||
pt.print_all_references();
|
||||
}
|
||||
|
||||
// This is the point where the entire marking should have completed.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2017, 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
|
||||
@ -415,25 +415,29 @@ bool PSScavenge::invoke_no_policy() {
|
||||
PSKeepAliveClosure keep_alive(promotion_manager);
|
||||
PSEvacuateFollowersClosure evac_followers(promotion_manager);
|
||||
ReferenceProcessorStats stats;
|
||||
ReferenceProcessorPhaseTimes pt(&_gc_timer, reference_processor()->num_q());
|
||||
if (reference_processor()->processing_is_mt()) {
|
||||
PSRefProcTaskExecutor task_executor;
|
||||
stats = reference_processor()->process_discovered_references(
|
||||
&_is_alive_closure, &keep_alive, &evac_followers, &task_executor,
|
||||
&_gc_timer);
|
||||
&pt);
|
||||
} else {
|
||||
stats = reference_processor()->process_discovered_references(
|
||||
&_is_alive_closure, &keep_alive, &evac_followers, NULL, &_gc_timer);
|
||||
&_is_alive_closure, &keep_alive, &evac_followers, NULL, &pt);
|
||||
}
|
||||
|
||||
_gc_tracer.report_gc_reference_stats(stats);
|
||||
pt.print_all_references();
|
||||
|
||||
// Enqueue reference objects discovered during scavenge.
|
||||
if (reference_processor()->processing_is_mt()) {
|
||||
PSRefProcTaskExecutor task_executor;
|
||||
reference_processor()->enqueue_discovered_references(&task_executor);
|
||||
reference_processor()->enqueue_discovered_references(&task_executor, &pt);
|
||||
} else {
|
||||
reference_processor()->enqueue_discovered_references(NULL);
|
||||
reference_processor()->enqueue_discovered_references(NULL, &pt);
|
||||
}
|
||||
|
||||
pt.print_enqueue_phase();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2017, 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
|
||||
@ -661,11 +661,13 @@ void DefNewGeneration::collect(bool full,
|
||||
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
|
||||
ReferenceProcessor* rp = ref_processor();
|
||||
rp->setup_policy(clear_all_soft_refs);
|
||||
ReferenceProcessorPhaseTimes pt(_gc_timer, rp->num_q());
|
||||
const ReferenceProcessorStats& stats =
|
||||
rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
|
||||
NULL, _gc_timer);
|
||||
NULL, &pt);
|
||||
gc_tracer.report_gc_reference_stats(stats);
|
||||
gc_tracer.report_tenuring_threshold(tenuring_threshold());
|
||||
pt.print_all_references();
|
||||
|
||||
if (!_promotion_failed) {
|
||||
// Swap the survivor spaces.
|
||||
|
@ -210,9 +210,11 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
GCTraceTime(Debug, gc, phases) tm_m("Reference Processing", gc_timer());
|
||||
|
||||
ref_processor()->setup_policy(clear_all_softrefs);
|
||||
ReferenceProcessorPhaseTimes pt(_gc_timer, ref_processor()->num_q());
|
||||
const ReferenceProcessorStats& stats =
|
||||
ref_processor()->process_discovered_references(
|
||||
&is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer);
|
||||
&is_alive, &keep_alive, &follow_stack_closure, NULL, &pt);
|
||||
pt.print_all_references();
|
||||
gc_tracer()->report_gc_reference_stats(stats);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2017, 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
|
||||
@ -78,8 +78,8 @@ class GCPhase {
|
||||
|
||||
class PhasesStack {
|
||||
public:
|
||||
// Set to 5, since Reference processing needs it.
|
||||
static const int PHASE_LEVELS = 5;
|
||||
// Set to 6, since Reference processing needs it.
|
||||
static const int PHASE_LEVELS = 6;
|
||||
|
||||
private:
|
||||
int _phase_indices[PHASE_LEVELS];
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2017, 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
|
||||
@ -428,6 +428,7 @@ class PhaseSender : public PhaseVisitor {
|
||||
case 1: send_phase<EventGCPhasePauseLevel1>(phase); break;
|
||||
case 2: send_phase<EventGCPhasePauseLevel2>(phase); break;
|
||||
case 3: send_phase<EventGCPhasePauseLevel3>(phase); break;
|
||||
case 4: send_phase<EventGCPhasePauseLevel4>(phase); break;
|
||||
default: /* Ignore sending this phase */ break;
|
||||
}
|
||||
}
|
||||
|
@ -387,7 +387,9 @@ void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t siz
|
||||
}
|
||||
gen->collect(full, clear_soft_refs, size, is_tlab);
|
||||
if (!rp->enqueuing_is_done()) {
|
||||
rp->enqueue_discovered_references();
|
||||
ReferenceProcessorPhaseTimes pt(NULL, rp->num_q());
|
||||
rp->enqueue_discovered_references(NULL, &pt);
|
||||
pt.print_enqueue_phase();
|
||||
} else {
|
||||
rp->set_enqueuing_is_done(false);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2017, 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
|
||||
@ -179,7 +179,7 @@ void ReferenceProcessor::update_soft_ref_master_clock() {
|
||||
// past clock value.
|
||||
}
|
||||
|
||||
size_t ReferenceProcessor::total_count(DiscoveredList lists[]) {
|
||||
size_t ReferenceProcessor::total_count(DiscoveredList lists[]) const {
|
||||
size_t total = 0;
|
||||
for (uint i = 0; i < _max_num_q; ++i) {
|
||||
total += lists[i].length();
|
||||
@ -188,11 +188,13 @@ size_t ReferenceProcessor::total_count(DiscoveredList lists[]) {
|
||||
}
|
||||
|
||||
ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
|
||||
BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor,
|
||||
GCTimer* gc_timer) {
|
||||
BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times) {
|
||||
|
||||
double start_time = os::elapsedTime();
|
||||
|
||||
assert(!enqueuing_is_done(), "If here enqueuing should not be complete");
|
||||
// Stop treating discovered references specially.
|
||||
@ -208,40 +210,39 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
|
||||
|
||||
_soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock();
|
||||
|
||||
ReferenceProcessorStats stats(
|
||||
total_count(_discoveredSoftRefs),
|
||||
total_count(_discoveredWeakRefs),
|
||||
total_count(_discoveredFinalRefs),
|
||||
total_count(_discoveredPhantomRefs));
|
||||
ReferenceProcessorStats stats(total_count(_discoveredSoftRefs),
|
||||
total_count(_discoveredWeakRefs),
|
||||
total_count(_discoveredFinalRefs),
|
||||
total_count(_discoveredPhantomRefs));
|
||||
|
||||
// Soft references
|
||||
{
|
||||
GCTraceTime(Debug, gc, ref) tt("SoftReference", gc_timer);
|
||||
RefProcPhaseTimesTracker tt(REF_SOFT, phase_times, this);
|
||||
process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
|
||||
is_alive, keep_alive, complete_gc, task_executor);
|
||||
is_alive, keep_alive, complete_gc, task_executor, phase_times);
|
||||
}
|
||||
|
||||
update_soft_ref_master_clock();
|
||||
|
||||
// Weak references
|
||||
{
|
||||
GCTraceTime(Debug, gc, ref) tt("WeakReference", gc_timer);
|
||||
RefProcPhaseTimesTracker tt(REF_WEAK, phase_times, this);
|
||||
process_discovered_reflist(_discoveredWeakRefs, NULL, true,
|
||||
is_alive, keep_alive, complete_gc, task_executor);
|
||||
is_alive, keep_alive, complete_gc, task_executor, phase_times);
|
||||
}
|
||||
|
||||
// Final references
|
||||
{
|
||||
GCTraceTime(Debug, gc, ref) tt("FinalReference", gc_timer);
|
||||
RefProcPhaseTimesTracker tt(REF_FINAL, phase_times, this);
|
||||
process_discovered_reflist(_discoveredFinalRefs, NULL, false,
|
||||
is_alive, keep_alive, complete_gc, task_executor);
|
||||
is_alive, keep_alive, complete_gc, task_executor, phase_times);
|
||||
}
|
||||
|
||||
// Phantom references
|
||||
{
|
||||
GCTraceTime(Debug, gc, ref) tt("PhantomReference", gc_timer);
|
||||
RefProcPhaseTimesTracker tt(REF_PHANTOM, phase_times, this);
|
||||
process_discovered_reflist(_discoveredPhantomRefs, NULL, true,
|
||||
is_alive, keep_alive, complete_gc, task_executor);
|
||||
is_alive, keep_alive, complete_gc, task_executor, phase_times);
|
||||
}
|
||||
|
||||
// Weak global JNI references. It would make more sense (semantically) to
|
||||
@ -250,15 +251,15 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
|
||||
// thus use JNI weak references to circumvent the phantom references and
|
||||
// resurrect a "post-mortem" object.
|
||||
{
|
||||
GCTraceTime(Debug, gc, ref) tt("JNI Weak Reference", gc_timer);
|
||||
GCTraceTime(Debug, gc, ref) tt("JNI Weak Reference", phase_times->gc_timer());
|
||||
if (task_executor != NULL) {
|
||||
task_executor->set_single_threaded_mode();
|
||||
}
|
||||
process_phaseJNI(is_alive, keep_alive, complete_gc);
|
||||
}
|
||||
|
||||
log_debug(gc, ref)("Ref Counts: Soft: " SIZE_FORMAT " Weak: " SIZE_FORMAT " Final: " SIZE_FORMAT " Phantom: " SIZE_FORMAT,
|
||||
stats.soft_count(), stats.weak_count(), stats.final_count(), stats.phantom_count());
|
||||
phase_times->set_total_time_ms((os::elapsedTime() - start_time) * 1000);
|
||||
|
||||
log_develop_trace(gc, ref)("JNI Weak Reference count: " SIZE_FORMAT, count_jni_refs());
|
||||
|
||||
return stats;
|
||||
@ -289,10 +290,11 @@ void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive,
|
||||
complete_gc->do_void();
|
||||
}
|
||||
|
||||
void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) {
|
||||
void ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times) {
|
||||
// Enqueue references that are not made active again, and
|
||||
// clear the decks for the next collection (cycle).
|
||||
enqueue_discovered_reflists(task_executor);
|
||||
enqueue_discovered_reflists(task_executor, phase_times);
|
||||
|
||||
// Stop treating discovered references specially.
|
||||
disable_discovery();
|
||||
@ -343,13 +345,16 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list) {
|
||||
// Parallel enqueue task
|
||||
class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask {
|
||||
public:
|
||||
RefProcEnqueueTask(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList discovered_refs[],
|
||||
int n_queues)
|
||||
: EnqueueTask(ref_processor, discovered_refs, n_queues)
|
||||
RefProcEnqueueTask(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList discovered_refs[],
|
||||
int n_queues,
|
||||
ReferenceProcessorPhaseTimes* phase_times)
|
||||
: EnqueueTask(ref_processor, discovered_refs, n_queues, phase_times)
|
||||
{ }
|
||||
|
||||
virtual void work(unsigned int work_id) {
|
||||
RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefEnqueue, _phase_times, work_id);
|
||||
|
||||
assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds");
|
||||
// Simplest first cut: static partitioning.
|
||||
int index = work_id;
|
||||
@ -369,10 +374,19 @@ public:
|
||||
};
|
||||
|
||||
// Enqueue references that are not made active again
|
||||
void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor) {
|
||||
void ReferenceProcessor::enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times) {
|
||||
|
||||
ReferenceProcessorStats stats(total_count(_discoveredSoftRefs),
|
||||
total_count(_discoveredWeakRefs),
|
||||
total_count(_discoveredFinalRefs),
|
||||
total_count(_discoveredPhantomRefs));
|
||||
|
||||
RefProcEnqueueTimeTracker tt(phase_times, stats);
|
||||
|
||||
if (_processing_is_mt && task_executor != NULL) {
|
||||
// Parallel code
|
||||
RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q);
|
||||
RefProcEnqueueTask tsk(*this, _discovered_refs, _max_num_q, phase_times);
|
||||
task_executor->execute(tsk);
|
||||
} else {
|
||||
// Serial code: call the parent class's implementation
|
||||
@ -469,7 +483,7 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list,
|
||||
complete_gc->do_void();
|
||||
log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " dead Refs out of " SIZE_FORMAT " discovered Refs by policy, from list " INTPTR_FORMAT,
|
||||
iter.removed(), iter.processed(), p2i(&refs_list));
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse the list and remove any Refs that are not active, or
|
||||
// whose referents are either alive or NULL.
|
||||
@ -598,19 +612,46 @@ void ReferenceProcessor::abandon_partial_discovery() {
|
||||
}
|
||||
}
|
||||
|
||||
size_t ReferenceProcessor::total_reference_count(ReferenceType type) const {
|
||||
DiscoveredList* list = NULL;
|
||||
|
||||
switch (type) {
|
||||
case REF_SOFT:
|
||||
list = _discoveredSoftRefs;
|
||||
break;
|
||||
case REF_WEAK:
|
||||
list = _discoveredWeakRefs;
|
||||
break;
|
||||
case REF_FINAL:
|
||||
list = _discoveredFinalRefs;
|
||||
break;
|
||||
case REF_PHANTOM:
|
||||
list = _discoveredPhantomRefs;
|
||||
break;
|
||||
case REF_OTHER:
|
||||
case REF_NONE:
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
return total_count(list);
|
||||
}
|
||||
|
||||
class RefProcPhase1Task: public AbstractRefProcTaskExecutor::ProcessTask {
|
||||
public:
|
||||
RefProcPhase1Task(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
ReferencePolicy* policy,
|
||||
bool marks_oops_alive)
|
||||
: ProcessTask(ref_processor, refs_lists, marks_oops_alive),
|
||||
RefProcPhase1Task(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
ReferencePolicy* policy,
|
||||
bool marks_oops_alive,
|
||||
ReferenceProcessorPhaseTimes* phase_times)
|
||||
: ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times),
|
||||
_policy(policy)
|
||||
{ }
|
||||
virtual void work(unsigned int i, BoolObjectClosure& is_alive,
|
||||
OopClosure& keep_alive,
|
||||
VoidClosure& complete_gc)
|
||||
{
|
||||
RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase1, _phase_times, i);
|
||||
|
||||
_ref_processor.process_phase1(_refs_lists[i], _policy,
|
||||
&is_alive, &keep_alive, &complete_gc);
|
||||
}
|
||||
@ -620,15 +661,18 @@ private:
|
||||
|
||||
class RefProcPhase2Task: public AbstractRefProcTaskExecutor::ProcessTask {
|
||||
public:
|
||||
RefProcPhase2Task(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
bool marks_oops_alive)
|
||||
: ProcessTask(ref_processor, refs_lists, marks_oops_alive)
|
||||
RefProcPhase2Task(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
bool marks_oops_alive,
|
||||
ReferenceProcessorPhaseTimes* phase_times)
|
||||
: ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times)
|
||||
{ }
|
||||
virtual void work(unsigned int i, BoolObjectClosure& is_alive,
|
||||
OopClosure& keep_alive,
|
||||
VoidClosure& complete_gc)
|
||||
{
|
||||
RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase2, _phase_times, i);
|
||||
|
||||
_ref_processor.process_phase2(_refs_lists[i],
|
||||
&is_alive, &keep_alive, &complete_gc);
|
||||
}
|
||||
@ -636,17 +680,20 @@ public:
|
||||
|
||||
class RefProcPhase3Task: public AbstractRefProcTaskExecutor::ProcessTask {
|
||||
public:
|
||||
RefProcPhase3Task(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
bool clear_referent,
|
||||
bool marks_oops_alive)
|
||||
: ProcessTask(ref_processor, refs_lists, marks_oops_alive),
|
||||
RefProcPhase3Task(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
bool clear_referent,
|
||||
bool marks_oops_alive,
|
||||
ReferenceProcessorPhaseTimes* phase_times)
|
||||
: ProcessTask(ref_processor, refs_lists, marks_oops_alive, phase_times),
|
||||
_clear_referent(clear_referent)
|
||||
{ }
|
||||
virtual void work(unsigned int i, BoolObjectClosure& is_alive,
|
||||
OopClosure& keep_alive,
|
||||
VoidClosure& complete_gc)
|
||||
{
|
||||
RefProcWorkerTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase3, _phase_times, i);
|
||||
|
||||
_ref_processor.process_phase3(_refs_lists[i], _clear_referent,
|
||||
&is_alive, &keep_alive, &complete_gc);
|
||||
}
|
||||
@ -770,15 +817,19 @@ void ReferenceProcessor::balance_all_queues() {
|
||||
}
|
||||
|
||||
void ReferenceProcessor::process_discovered_reflist(
|
||||
DiscoveredList refs_lists[],
|
||||
ReferencePolicy* policy,
|
||||
bool clear_referent,
|
||||
BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor)
|
||||
DiscoveredList refs_lists[],
|
||||
ReferencePolicy* policy,
|
||||
bool clear_referent,
|
||||
BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times)
|
||||
{
|
||||
bool mt_processing = task_executor != NULL && _processing_is_mt;
|
||||
|
||||
phase_times->set_processing_is_mt(mt_processing);
|
||||
|
||||
// If discovery used MT and a dynamic number of GC threads, then
|
||||
// the queues must be balanced for correctness if fewer than the
|
||||
// maximum number of queues were used. The number of queue used
|
||||
@ -789,6 +840,7 @@ void ReferenceProcessor::process_discovered_reflist(
|
||||
|
||||
if ((mt_processing && ParallelRefProcBalancingEnabled) ||
|
||||
must_balance) {
|
||||
RefProcBalanceQueuesTimeTracker tt(phase_times);
|
||||
balance_queues(refs_lists);
|
||||
}
|
||||
|
||||
@ -798,8 +850,10 @@ void ReferenceProcessor::process_discovered_reflist(
|
||||
// policy reasons. Keep alive the transitive closure of all
|
||||
// such referents.
|
||||
if (policy != NULL) {
|
||||
RefProcParPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase1, phase_times);
|
||||
|
||||
if (mt_processing) {
|
||||
RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);
|
||||
RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/, phase_times);
|
||||
task_executor->execute(phase1);
|
||||
} else {
|
||||
for (uint i = 0; i < _max_num_q; i++) {
|
||||
@ -814,24 +868,32 @@ void ReferenceProcessor::process_discovered_reflist(
|
||||
|
||||
// Phase 2:
|
||||
// . Traverse the list and remove any refs whose referents are alive.
|
||||
if (mt_processing) {
|
||||
RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);
|
||||
task_executor->execute(phase2);
|
||||
} else {
|
||||
for (uint i = 0; i < _max_num_q; i++) {
|
||||
process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
|
||||
{
|
||||
RefProcParPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase2, phase_times);
|
||||
|
||||
if (mt_processing) {
|
||||
RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/, phase_times);
|
||||
task_executor->execute(phase2);
|
||||
} else {
|
||||
for (uint i = 0; i < _max_num_q; i++) {
|
||||
process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 3:
|
||||
// . Traverse the list and process referents as appropriate.
|
||||
if (mt_processing) {
|
||||
RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);
|
||||
task_executor->execute(phase3);
|
||||
} else {
|
||||
for (uint i = 0; i < _max_num_q; i++) {
|
||||
process_phase3(refs_lists[i], clear_referent,
|
||||
is_alive, keep_alive, complete_gc);
|
||||
{
|
||||
RefProcParPhaseTimeTracker tt(ReferenceProcessorPhaseTimes::RefPhase3, phase_times);
|
||||
|
||||
if (mt_processing) {
|
||||
RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/, phase_times);
|
||||
task_executor->execute(phase3);
|
||||
} else {
|
||||
for (uint i = 0; i < _max_num_q; i++) {
|
||||
process_phase3(refs_lists[i], clear_referent,
|
||||
is_alive, keep_alive, complete_gc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1196,4 +1258,3 @@ const char* ReferenceProcessor::list_name(uint i) {
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2017, 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,6 +26,7 @@
|
||||
#define SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
|
||||
|
||||
#include "gc/shared/referencePolicy.hpp"
|
||||
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
|
||||
#include "gc/shared/referenceProcessorStats.hpp"
|
||||
#include "memory/referenceType.hpp"
|
||||
#include "oops/instanceRefKlass.hpp"
|
||||
@ -168,7 +169,7 @@ public:
|
||||
class ReferenceProcessor : public CHeapObj<mtGC> {
|
||||
|
||||
private:
|
||||
size_t total_count(DiscoveredList lists[]);
|
||||
size_t total_count(DiscoveredList lists[]) const;
|
||||
|
||||
protected:
|
||||
// The SoftReference master timestamp clock
|
||||
@ -236,13 +237,14 @@ class ReferenceProcessor : public CHeapObj<mtGC> {
|
||||
}
|
||||
|
||||
// Process references with a certain reachability level.
|
||||
void process_discovered_reflist(DiscoveredList refs_lists[],
|
||||
ReferencePolicy* policy,
|
||||
bool clear_referent,
|
||||
BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor);
|
||||
void process_discovered_reflist(DiscoveredList refs_lists[],
|
||||
ReferencePolicy* policy,
|
||||
bool clear_referent,
|
||||
BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times);
|
||||
|
||||
void process_phaseJNI(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
@ -310,7 +312,8 @@ class ReferenceProcessor : public CHeapObj<mtGC> {
|
||||
// occupying the i / _num_q slot.
|
||||
const char* list_name(uint i);
|
||||
|
||||
void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor);
|
||||
void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times);
|
||||
|
||||
protected:
|
||||
// "Preclean" the given discovered reference list
|
||||
@ -416,20 +419,23 @@ class ReferenceProcessor : public CHeapObj<mtGC> {
|
||||
|
||||
// Process references found during GC (called by the garbage collector)
|
||||
ReferenceProcessorStats
|
||||
process_discovered_references(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor,
|
||||
GCTimer *gc_timer);
|
||||
process_discovered_references(BoolObjectClosure* is_alive,
|
||||
OopClosure* keep_alive,
|
||||
VoidClosure* complete_gc,
|
||||
AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times);
|
||||
|
||||
// Enqueue references at end of GC (called by the garbage collector)
|
||||
void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL);
|
||||
void enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor,
|
||||
ReferenceProcessorPhaseTimes* phase_times);
|
||||
|
||||
// If a discovery is in process that is being superceded, abandon it: all
|
||||
// the discovered lists will be empty, and all the objects on them will
|
||||
// have NULL discovered fields. Must be called only at a safepoint.
|
||||
void abandon_partial_discovery();
|
||||
|
||||
size_t total_reference_count(ReferenceType rt) const;
|
||||
|
||||
// debugging
|
||||
void verify_no_references_recorded() PRODUCT_RETURN;
|
||||
void verify_referent(oop obj) PRODUCT_RETURN;
|
||||
@ -584,11 +590,13 @@ public:
|
||||
// Abstract reference processing task to execute.
|
||||
class AbstractRefProcTaskExecutor::ProcessTask {
|
||||
protected:
|
||||
ProcessTask(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
bool marks_oops_alive)
|
||||
ProcessTask(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
bool marks_oops_alive,
|
||||
ReferenceProcessorPhaseTimes* phase_times)
|
||||
: _ref_processor(ref_processor),
|
||||
_refs_lists(refs_lists),
|
||||
_phase_times(phase_times),
|
||||
_marks_oops_alive(marks_oops_alive)
|
||||
{ }
|
||||
|
||||
@ -602,29 +610,33 @@ public:
|
||||
{ return _marks_oops_alive; }
|
||||
|
||||
protected:
|
||||
ReferenceProcessor& _ref_processor;
|
||||
DiscoveredList* _refs_lists;
|
||||
const bool _marks_oops_alive;
|
||||
ReferenceProcessor& _ref_processor;
|
||||
DiscoveredList* _refs_lists;
|
||||
ReferenceProcessorPhaseTimes* _phase_times;
|
||||
const bool _marks_oops_alive;
|
||||
};
|
||||
|
||||
// Abstract reference processing task to execute.
|
||||
class AbstractRefProcTaskExecutor::EnqueueTask {
|
||||
protected:
|
||||
EnqueueTask(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
int n_queues)
|
||||
EnqueueTask(ReferenceProcessor& ref_processor,
|
||||
DiscoveredList refs_lists[],
|
||||
int n_queues,
|
||||
ReferenceProcessorPhaseTimes* phase_times)
|
||||
: _ref_processor(ref_processor),
|
||||
_refs_lists(refs_lists),
|
||||
_n_queues(n_queues)
|
||||
_n_queues(n_queues),
|
||||
_phase_times(phase_times)
|
||||
{ }
|
||||
|
||||
public:
|
||||
virtual void work(unsigned int work_id) = 0;
|
||||
|
||||
protected:
|
||||
ReferenceProcessor& _ref_processor;
|
||||
DiscoveredList* _refs_lists;
|
||||
int _n_queues;
|
||||
ReferenceProcessor& _ref_processor;
|
||||
DiscoveredList* _refs_lists;
|
||||
ReferenceProcessorPhaseTimes* _phase_times;
|
||||
int _n_queues;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_HPP
|
||||
|
475
hotspot/src/share/vm/gc/shared/referenceProcessorPhaseTimes.cpp
Normal file
475
hotspot/src/share/vm/gc/shared/referenceProcessorPhaseTimes.cpp
Normal file
@ -0,0 +1,475 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/gcTimer.hpp"
|
||||
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
|
||||
#include "gc/shared/referenceProcessor.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
|
||||
RefProcWorkerTimeTracker::RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers number,
|
||||
ReferenceProcessorPhaseTimes* phase_times,
|
||||
uint worker_id) :
|
||||
_worker_time(NULL), _start_time(os::elapsedTime()), _worker_id(worker_id) {
|
||||
assert (phase_times != NULL, "Invariant");
|
||||
|
||||
_worker_time = phase_times->worker_time_sec(phase_times->par_phase(number));
|
||||
}
|
||||
|
||||
RefProcWorkerTimeTracker::RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcParPhases phase,
|
||||
ReferenceProcessorPhaseTimes* phase_times,
|
||||
uint worker_id) :
|
||||
_worker_time(NULL), _start_time(os::elapsedTime()), _worker_id(worker_id) {
|
||||
assert (phase_times != NULL, "Invariant");
|
||||
|
||||
_worker_time = phase_times->worker_time_sec(phase);
|
||||
}
|
||||
|
||||
RefProcWorkerTimeTracker::~RefProcWorkerTimeTracker() {
|
||||
_worker_time->set(_worker_id, os::elapsedTime() - _start_time);
|
||||
}
|
||||
|
||||
RefProcPhaseTimeBaseTracker::RefProcPhaseTimeBaseTracker(const char* title,
|
||||
ReferenceProcessorPhaseTimes* phase_times) :
|
||||
_title(title), _phase_times(phase_times), _start_ticks(), _end_ticks() {
|
||||
assert(_phase_times != NULL, "Invariant");
|
||||
|
||||
_start_ticks.stamp();
|
||||
if (_phase_times->gc_timer() != NULL) {
|
||||
_phase_times->gc_timer()->register_gc_phase_start(_title, _start_ticks);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* phase_enum_2_phase_string(ReferenceProcessorPhaseTimes::RefProcParPhases phase) {
|
||||
switch(phase) {
|
||||
case ReferenceProcessorPhaseTimes::SoftRefPhase1:
|
||||
return "Phase1";
|
||||
case ReferenceProcessorPhaseTimes::SoftRefPhase2:
|
||||
case ReferenceProcessorPhaseTimes::WeakRefPhase2:
|
||||
case ReferenceProcessorPhaseTimes::FinalRefPhase2:
|
||||
case ReferenceProcessorPhaseTimes::PhantomRefPhase2:
|
||||
return "Phase2";
|
||||
case ReferenceProcessorPhaseTimes::SoftRefPhase3:
|
||||
case ReferenceProcessorPhaseTimes::WeakRefPhase3:
|
||||
case ReferenceProcessorPhaseTimes::FinalRefPhase3:
|
||||
case ReferenceProcessorPhaseTimes::PhantomRefPhase3:
|
||||
return "Phase3";
|
||||
case ReferenceProcessorPhaseTimes::RefEnqueue:
|
||||
return "Reference Enqueuing";
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* Indents[6] = {"", " ", " ", " ", " ", " "};
|
||||
|
||||
Ticks RefProcPhaseTimeBaseTracker::end_ticks() {
|
||||
// If ASSERT is defined, the default value of Ticks will be -2.
|
||||
if (_end_ticks.value() <= 0) {
|
||||
_end_ticks.stamp();
|
||||
}
|
||||
|
||||
return _end_ticks;
|
||||
}
|
||||
|
||||
double RefProcPhaseTimeBaseTracker::elapsed_time() {
|
||||
jlong end_value = end_ticks().value();
|
||||
|
||||
return TimeHelper::counter_to_millis(end_value - _start_ticks.value());
|
||||
}
|
||||
|
||||
RefProcPhaseTimeBaseTracker::~RefProcPhaseTimeBaseTracker() {
|
||||
if (_phase_times->gc_timer() != NULL) {
|
||||
Ticks ticks = end_ticks();
|
||||
_phase_times->gc_timer()->register_gc_phase_end(ticks);
|
||||
}
|
||||
}
|
||||
|
||||
RefProcBalanceQueuesTimeTracker::RefProcBalanceQueuesTimeTracker(ReferenceProcessorPhaseTimes* phase_times) :
|
||||
RefProcPhaseTimeBaseTracker("Balance queues", phase_times) {}
|
||||
|
||||
RefProcBalanceQueuesTimeTracker::~RefProcBalanceQueuesTimeTracker() {
|
||||
double elapsed = elapsed_time();
|
||||
phase_times()->set_balance_queues_time_ms(phase_times()->processing_ref_type(), elapsed);
|
||||
}
|
||||
|
||||
#define ASSERT_REF_TYPE(ref_type) assert(ref_type >= REF_SOFT && ref_type <= REF_PHANTOM, \
|
||||
"Invariant (%d)", (int)ref_type)
|
||||
|
||||
#define ASSERT_PHASE_NUMBER(phase_number) assert(phase_number >= ReferenceProcessorPhaseTimes::RefPhase1 && \
|
||||
phase_number <= ReferenceProcessorPhaseTimes::RefPhaseMax, \
|
||||
"Invariant (%d)", phase_number);
|
||||
|
||||
static const char* phase_number_2_string(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers phase_number) {
|
||||
ASSERT_PHASE_NUMBER(phase_number);
|
||||
|
||||
switch(phase_number) {
|
||||
case ReferenceProcessorPhaseTimes::RefPhase1:
|
||||
return "Phase1";
|
||||
case ReferenceProcessorPhaseTimes::RefPhase2:
|
||||
return "Phase2";
|
||||
case ReferenceProcessorPhaseTimes::RefPhase3:
|
||||
return "Phase3";
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
RefProcParPhaseTimeTracker::RefProcParPhaseTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers phase_number,
|
||||
ReferenceProcessorPhaseTimes* phase_times) :
|
||||
_phase_number(phase_number),
|
||||
RefProcPhaseTimeBaseTracker(phase_number_2_string(phase_number), phase_times) {}
|
||||
|
||||
RefProcParPhaseTimeTracker::~RefProcParPhaseTimeTracker() {
|
||||
double elapsed = elapsed_time();
|
||||
ReferenceProcessorPhaseTimes::RefProcParPhases phase = phase_times()->par_phase(_phase_number);
|
||||
phase_times()->set_par_phase_time_ms(phase, elapsed);
|
||||
}
|
||||
|
||||
static const char* ref_type_2_string(ReferenceType ref_type) {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
|
||||
switch(ref_type) {
|
||||
case REF_SOFT:
|
||||
return "SoftReference";
|
||||
case REF_WEAK:
|
||||
return "WeakReference";
|
||||
case REF_FINAL:
|
||||
return "FinalReference";
|
||||
case REF_PHANTOM:
|
||||
return "PhantomReference";
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
RefProcPhaseTimesTracker::RefProcPhaseTimesTracker(ReferenceType ref_type,
|
||||
ReferenceProcessorPhaseTimes* phase_times,
|
||||
ReferenceProcessor* rp) :
|
||||
_rp(rp), RefProcPhaseTimeBaseTracker(ref_type_2_string(ref_type), phase_times) {
|
||||
phase_times->set_processing_ref_type(ref_type);
|
||||
|
||||
size_t discovered = rp->total_reference_count(ref_type);
|
||||
phase_times->set_ref_discovered(ref_type, discovered);
|
||||
}
|
||||
|
||||
RefProcPhaseTimesTracker::~RefProcPhaseTimesTracker() {
|
||||
double elapsed = elapsed_time();
|
||||
ReferenceProcessorPhaseTimes* times = phase_times();
|
||||
ReferenceType ref_type = times->processing_ref_type();
|
||||
times->set_ref_proc_time_ms(ref_type, elapsed);
|
||||
|
||||
size_t after_count = _rp->total_reference_count(ref_type);
|
||||
size_t discovered = times->ref_discovered(ref_type);
|
||||
times->set_ref_cleared(ref_type, discovered - after_count);
|
||||
}
|
||||
|
||||
RefProcEnqueueTimeTracker::RefProcEnqueueTimeTracker(ReferenceProcessorPhaseTimes* phase_times,
|
||||
ReferenceProcessorStats& stats) :
|
||||
RefProcPhaseTimeBaseTracker("Reference Enqueuing", phase_times) {
|
||||
phase_times->set_ref_enqueued(REF_SOFT, stats.soft_count());
|
||||
phase_times->set_ref_enqueued(REF_WEAK, stats.weak_count());
|
||||
phase_times->set_ref_enqueued(REF_FINAL, stats.final_count());
|
||||
phase_times->set_ref_enqueued(REF_PHANTOM, stats.phantom_count());
|
||||
}
|
||||
|
||||
RefProcEnqueueTimeTracker::~RefProcEnqueueTimeTracker() {
|
||||
double elapsed = elapsed_time();
|
||||
|
||||
phase_times()->set_par_phase_time_ms(ReferenceProcessorPhaseTimes::RefEnqueue, elapsed);
|
||||
}
|
||||
|
||||
ReferenceProcessorPhaseTimes::ReferenceProcessorPhaseTimes(GCTimer* gc_timer, uint max_gc_threads) :
|
||||
_gc_timer(gc_timer), _processing_is_mt(false) {
|
||||
|
||||
for (int i = 0; i < RefParPhaseMax; i++) {
|
||||
_worker_time_sec[i] = new WorkerDataArray<double>(max_gc_threads, "Process lists (ms)");
|
||||
_par_phase_time_ms[i] = uninitialized();
|
||||
}
|
||||
|
||||
for (int i = 0; i < number_of_subclasses_of_ref; i++) {
|
||||
_ref_proc_time_ms[i] = uninitialized();
|
||||
_balance_queues_time_ms[i] = uninitialized();
|
||||
_ref_cleared[i] = 0;
|
||||
_ref_discovered[i] = 0;
|
||||
_ref_enqueued[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline int ref_type_2_index(ReferenceType ref_type) {
|
||||
return ref_type - REF_SOFT;
|
||||
}
|
||||
|
||||
#define ASSERT_PAR_PHASE(phase) assert(phase >= ReferenceProcessorPhaseTimes::SoftRefPhase1 && \
|
||||
phase < ReferenceProcessorPhaseTimes::RefParPhaseMax, \
|
||||
"Invariant (%d)", (int)phase);
|
||||
|
||||
WorkerDataArray<double>* ReferenceProcessorPhaseTimes::worker_time_sec(RefProcParPhases par_phase) const {
|
||||
ASSERT_PAR_PHASE(par_phase);
|
||||
return _worker_time_sec[par_phase];
|
||||
}
|
||||
|
||||
double ReferenceProcessorPhaseTimes::par_phase_time_ms(RefProcParPhases par_phase) const {
|
||||
ASSERT_PAR_PHASE(par_phase);
|
||||
return _par_phase_time_ms[par_phase];
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::set_par_phase_time_ms(RefProcParPhases par_phase,
|
||||
double par_phase_time_ms) {
|
||||
ASSERT_PAR_PHASE(par_phase);
|
||||
_par_phase_time_ms[par_phase] = par_phase_time_ms;
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::reset() {
|
||||
for (int i = 0; i < RefParPhaseMax; i++) {
|
||||
_worker_time_sec[i]->reset();
|
||||
_par_phase_time_ms[i] = uninitialized();
|
||||
}
|
||||
|
||||
for (int i = 0; i < number_of_subclasses_of_ref; i++) {
|
||||
_ref_proc_time_ms[i] = uninitialized();
|
||||
_balance_queues_time_ms[i] = uninitialized();
|
||||
_ref_cleared[i] = 0;
|
||||
_ref_discovered[i] = 0;
|
||||
_ref_enqueued[i] = 0;
|
||||
}
|
||||
|
||||
_total_time_ms = uninitialized();
|
||||
|
||||
_processing_is_mt = false;
|
||||
}
|
||||
|
||||
ReferenceProcessorPhaseTimes::~ReferenceProcessorPhaseTimes() {
|
||||
for (int i = 0; i < RefParPhaseMax; i++) {
|
||||
delete _worker_time_sec[i];
|
||||
}
|
||||
}
|
||||
|
||||
double ReferenceProcessorPhaseTimes::ref_proc_time_ms(ReferenceType ref_type) const {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
return _par_phase_time_ms[ref_type_2_index(ref_type)];
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::set_ref_proc_time_ms(ReferenceType ref_type,
|
||||
double ref_proc_time_ms) {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
_ref_proc_time_ms[ref_type_2_index(ref_type)] = ref_proc_time_ms;
|
||||
}
|
||||
|
||||
size_t ReferenceProcessorPhaseTimes::ref_cleared(ReferenceType ref_type) const {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
return _ref_cleared[ref_type_2_index(ref_type)];
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::set_ref_cleared(ReferenceType ref_type, size_t count) {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
_ref_cleared[ref_type_2_index(ref_type)] = count;
|
||||
}
|
||||
|
||||
size_t ReferenceProcessorPhaseTimes::ref_discovered(ReferenceType ref_type) const {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
return _ref_discovered[ref_type_2_index(ref_type)];
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::set_ref_discovered(ReferenceType ref_type, size_t count) {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
_ref_discovered[ref_type_2_index(ref_type)] = count;
|
||||
}
|
||||
|
||||
size_t ReferenceProcessorPhaseTimes::ref_enqueued(ReferenceType ref_type) const {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
return _ref_enqueued[ref_type_2_index(ref_type)];
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::set_ref_enqueued(ReferenceType ref_type, size_t count) {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
_ref_enqueued[ref_type_2_index(ref_type)] = count;
|
||||
}
|
||||
|
||||
double ReferenceProcessorPhaseTimes::balance_queues_time_ms(ReferenceType ref_type) const {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
return _balance_queues_time_ms[ref_type_2_index(ref_type)];
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::set_balance_queues_time_ms(ReferenceType ref_type, double time_ms) {
|
||||
ASSERT_REF_TYPE(ref_type);
|
||||
_balance_queues_time_ms[ref_type_2_index(ref_type)] = time_ms;
|
||||
}
|
||||
|
||||
ReferenceProcessorPhaseTimes::RefProcParPhases
|
||||
ReferenceProcessorPhaseTimes::par_phase(RefProcPhaseNumbers phase_number) const {
|
||||
ASSERT_PHASE_NUMBER(phase_number);
|
||||
ASSERT_REF_TYPE(_processing_ref_type);
|
||||
|
||||
int result = SoftRefPhase1;
|
||||
|
||||
switch(_processing_ref_type) {
|
||||
case REF_SOFT:
|
||||
result = (int)SoftRefPhase1;
|
||||
result += phase_number;
|
||||
|
||||
assert((RefProcParPhases)result >= SoftRefPhase1 &&
|
||||
(RefProcParPhases)result <= SoftRefPhase3,
|
||||
"Invariant (%d)", result);
|
||||
break;
|
||||
case REF_WEAK:
|
||||
result = (int)WeakRefPhase2;
|
||||
result += (phase_number - 1);
|
||||
assert((RefProcParPhases)result >= WeakRefPhase2 &&
|
||||
(RefProcParPhases)result <= WeakRefPhase3,
|
||||
"Invariant (%d)", result);
|
||||
break;
|
||||
case REF_FINAL:
|
||||
result = (int)FinalRefPhase2;
|
||||
result += (phase_number - 1);
|
||||
assert((RefProcParPhases)result >= FinalRefPhase2 &&
|
||||
(RefProcParPhases)result <= FinalRefPhase3,
|
||||
"Invariant (%d)", result);
|
||||
break;
|
||||
case REF_PHANTOM:
|
||||
result = (int)PhantomRefPhase2;
|
||||
result += (phase_number - 1);
|
||||
assert((RefProcParPhases)result >= PhantomRefPhase2 &&
|
||||
(RefProcParPhases)result <= PhantomRefPhase3,
|
||||
"Invariant (%d)", result);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
ASSERT_PAR_PHASE(result);
|
||||
|
||||
return (RefProcParPhases)result;
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::print_enqueue_phase(uint base_indent, bool print_total) const {
|
||||
if (print_total) {
|
||||
print_phase(RefEnqueue, base_indent);
|
||||
}
|
||||
|
||||
log_debug(gc, phases, ref)("%sReference Counts: Soft: " SIZE_FORMAT " Weak: " SIZE_FORMAT
|
||||
" Final: " SIZE_FORMAT " Phantom: " SIZE_FORMAT ,
|
||||
Indents[base_indent + 1], ref_enqueued(REF_SOFT), ref_enqueued(REF_WEAK),
|
||||
ref_enqueued(REF_FINAL), ref_enqueued(REF_PHANTOM));
|
||||
}
|
||||
|
||||
#define TIME_FORMAT "%.1lfms"
|
||||
|
||||
void ReferenceProcessorPhaseTimes::print_all_references(uint base_indent, bool print_total) const {
|
||||
if (print_total) {
|
||||
LogTarget(Debug, gc, phases, ref) lt;
|
||||
|
||||
if (lt.is_enabled()) {
|
||||
LogStream ls(lt);
|
||||
ls.print_cr("%s%s: " TIME_FORMAT,
|
||||
Indents[base_indent], "Reference Processing", total_time_ms());
|
||||
}
|
||||
}
|
||||
|
||||
uint next_indent = base_indent + 1;
|
||||
print_reference(REF_SOFT, next_indent);
|
||||
print_reference(REF_WEAK, next_indent);
|
||||
print_reference(REF_FINAL, next_indent);
|
||||
print_reference(REF_PHANTOM, next_indent);
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::print_reference(ReferenceType ref_type, uint base_indent) const {
|
||||
LogTarget(Debug, gc, phases, ref) lt;
|
||||
|
||||
if (lt.is_enabled()) {
|
||||
LogStream ls(lt);
|
||||
uint next_indent = base_indent + 1;
|
||||
ResourceMark rm;
|
||||
|
||||
ls.print_cr("%s%s: " TIME_FORMAT,
|
||||
Indents[base_indent], ref_type_2_string(ref_type), ref_proc_time_ms(ref_type));
|
||||
|
||||
double balance_time = balance_queues_time_ms(ref_type);
|
||||
if (balance_time != uninitialized()) {
|
||||
ls.print_cr("%s%s " TIME_FORMAT, Indents[next_indent], "Balance queues:", balance_time);
|
||||
}
|
||||
|
||||
switch(ref_type) {
|
||||
case REF_SOFT:
|
||||
print_phase(SoftRefPhase1, next_indent);
|
||||
print_phase(SoftRefPhase2, next_indent);
|
||||
print_phase(SoftRefPhase3, next_indent);
|
||||
break;
|
||||
|
||||
case REF_WEAK:
|
||||
print_phase(WeakRefPhase2, next_indent);
|
||||
print_phase(WeakRefPhase3, next_indent);
|
||||
break;
|
||||
|
||||
case REF_FINAL:
|
||||
print_phase(FinalRefPhase2, next_indent);
|
||||
print_phase(FinalRefPhase3, next_indent);
|
||||
break;
|
||||
|
||||
case REF_PHANTOM:
|
||||
print_phase(PhantomRefPhase2, next_indent);
|
||||
print_phase(PhantomRefPhase3, next_indent);
|
||||
break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
ls.print_cr("%s%s " SIZE_FORMAT, Indents[next_indent], "Discovered:", ref_discovered(ref_type));
|
||||
ls.print_cr("%s%s " SIZE_FORMAT, Indents[next_indent], "Cleared:", ref_cleared(ref_type));
|
||||
}
|
||||
}
|
||||
|
||||
void ReferenceProcessorPhaseTimes::print_phase(RefProcParPhases phase, uint indent) const {
|
||||
double phase_time = par_phase_time_ms(phase);
|
||||
if (phase_time != uninitialized()) {
|
||||
LogTarget(Debug, gc, phases, ref) lt;
|
||||
|
||||
LogStream ls(lt);
|
||||
|
||||
ls.print_cr("%s%s%s " TIME_FORMAT,
|
||||
Indents[indent],
|
||||
phase_enum_2_phase_string(phase),
|
||||
indent == 0 ? "" : ":", /* 0 indent logs don't need colon. */
|
||||
phase_time);
|
||||
|
||||
LogTarget(Trace, gc, phases, ref) lt2;
|
||||
if (_processing_is_mt && lt2.is_enabled()) {
|
||||
LogStream ls(lt2);
|
||||
|
||||
ls.print("%s", Indents[indent + 1]);
|
||||
// worker_time_sec is recorded in seconds but it will be printed in milliseconds.
|
||||
worker_time_sec(phase)->print_summary_on(&ls, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef ASSERT_REF_TYPE
|
||||
#undef ASSERT_PHASE_NUMBER
|
||||
#undef ASSERT_PAR_PHASE
|
||||
#undef TIME_FORMAT
|
215
hotspot/src/share/vm/gc/shared/referenceProcessorPhaseTimes.hpp
Normal file
215
hotspot/src/share/vm/gc/shared/referenceProcessorPhaseTimes.hpp
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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_GC_SHARED_REFERENCEPROCESSORPHASETIMES_HPP
|
||||
#define SHARE_VM_GC_SHARED_REFERENCEPROCESSORPHASETIMES_HPP
|
||||
|
||||
#include "gc/shared/referenceProcessorStats.hpp"
|
||||
#include "gc/shared/workerDataArray.inline.hpp"
|
||||
#include "memory/referenceType.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
class DiscoveredList;
|
||||
class GCTimer;
|
||||
|
||||
class ReferenceProcessorPhaseTimes : public CHeapObj<mtGC> {
|
||||
public:
|
||||
// Detailed phases that has parallel work.
|
||||
enum RefProcParPhases {
|
||||
SoftRefPhase1,
|
||||
SoftRefPhase2,
|
||||
SoftRefPhase3,
|
||||
WeakRefPhase2,
|
||||
WeakRefPhase3,
|
||||
FinalRefPhase2,
|
||||
FinalRefPhase3,
|
||||
PhantomRefPhase2,
|
||||
PhantomRefPhase3,
|
||||
RefEnqueue,
|
||||
RefParPhaseMax
|
||||
};
|
||||
|
||||
// Sub-phases that are used when processing each j.l.Reference types.
|
||||
// Only SoftReference has RefPhase1.
|
||||
enum RefProcPhaseNumbers {
|
||||
RefPhase1,
|
||||
RefPhase2,
|
||||
RefPhase3,
|
||||
RefPhaseMax
|
||||
};
|
||||
|
||||
private:
|
||||
static const int number_of_subclasses_of_ref = REF_PHANTOM - REF_OTHER; // 5 - 1 = 4
|
||||
|
||||
// Records per thread information of each phase.
|
||||
WorkerDataArray<double>* _worker_time_sec[RefParPhaseMax];
|
||||
// Records elapsed time of each phase.
|
||||
double _par_phase_time_ms[RefParPhaseMax];
|
||||
|
||||
// Total spent time for references.
|
||||
// e.g. _ref_proc_time_ms[0] = _par_phase_time_ms[SoftRefPhase1] +
|
||||
// _par_phase_time_ms[SoftRefPhase2] +
|
||||
// _par_phase_time_ms[SoftRefPhase3] + extra time.
|
||||
double _ref_proc_time_ms[number_of_subclasses_of_ref];
|
||||
|
||||
double _total_time_ms;
|
||||
|
||||
size_t _ref_cleared[number_of_subclasses_of_ref];
|
||||
size_t _ref_discovered[number_of_subclasses_of_ref];
|
||||
size_t _ref_enqueued[number_of_subclasses_of_ref];
|
||||
double _balance_queues_time_ms[number_of_subclasses_of_ref];
|
||||
|
||||
bool _processing_is_mt;
|
||||
|
||||
// Currently processing reference type.
|
||||
ReferenceType _processing_ref_type;
|
||||
|
||||
GCTimer* _gc_timer;
|
||||
|
||||
double par_phase_time_ms(RefProcParPhases phase) const;
|
||||
double ref_proc_time_ms(ReferenceType ref_type) const;
|
||||
|
||||
double total_time_ms() const { return _total_time_ms; }
|
||||
|
||||
size_t ref_cleared(ReferenceType ref_type) const;
|
||||
size_t ref_enqueued(ReferenceType ref_type) const;
|
||||
|
||||
double balance_queues_time_ms(ReferenceType ref_type) const;
|
||||
|
||||
void print_reference(ReferenceType ref_type, uint base_indent) const;
|
||||
void print_phase(RefProcParPhases phase, uint indent) const;
|
||||
|
||||
public:
|
||||
ReferenceProcessorPhaseTimes(GCTimer* gc_timer, uint max_gc_threads);
|
||||
~ReferenceProcessorPhaseTimes();
|
||||
|
||||
static double uninitialized() { return -1.0; }
|
||||
|
||||
WorkerDataArray<double>* worker_time_sec(RefProcParPhases phase) const;
|
||||
void set_par_phase_time_ms(RefProcParPhases phase, double par_phase_time_ms);
|
||||
|
||||
void set_ref_proc_time_ms(ReferenceType ref_type, double ref_proc_time_ms);
|
||||
|
||||
void set_total_time_ms(double total_time_ms) { _total_time_ms = total_time_ms; }
|
||||
|
||||
void set_ref_cleared(ReferenceType ref_type, size_t count);
|
||||
size_t ref_discovered(ReferenceType ref_type) const;
|
||||
void set_ref_discovered(ReferenceType ref_type, size_t count);
|
||||
void set_ref_enqueued(ReferenceType ref_type, size_t count);
|
||||
|
||||
void set_balance_queues_time_ms(ReferenceType ref_type, double time_ms);
|
||||
|
||||
void set_processing_is_mt(bool processing_is_mt) { _processing_is_mt = processing_is_mt; }
|
||||
|
||||
ReferenceType processing_ref_type() const { return _processing_ref_type; }
|
||||
void set_processing_ref_type(ReferenceType processing_ref_type) { _processing_ref_type = processing_ref_type; }
|
||||
|
||||
// Returns RefProcParPhases calculated from phase_number and _processing_ref_type.
|
||||
RefProcParPhases par_phase(RefProcPhaseNumbers phase_number) const;
|
||||
|
||||
GCTimer* gc_timer() const { return _gc_timer; }
|
||||
|
||||
// Reset all fields. If not reset at next cycle, an assertion will fail.
|
||||
void reset();
|
||||
|
||||
void print_enqueue_phase(uint base_indent = 0, bool print_total = true) const;
|
||||
void print_all_references(uint base_indent = 0, bool print_total = true) const;
|
||||
};
|
||||
|
||||
// Updates working time of each worker thread.
|
||||
class RefProcWorkerTimeTracker : public StackObj {
|
||||
protected:
|
||||
WorkerDataArray<double>* _worker_time;
|
||||
double _start_time;
|
||||
uint _worker_id;
|
||||
|
||||
public:
|
||||
RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers number,
|
||||
ReferenceProcessorPhaseTimes* phase_times,
|
||||
uint worker_id);
|
||||
RefProcWorkerTimeTracker(ReferenceProcessorPhaseTimes::RefProcParPhases phase,
|
||||
ReferenceProcessorPhaseTimes* phase_times,
|
||||
uint worker_id);
|
||||
~RefProcWorkerTimeTracker();
|
||||
};
|
||||
|
||||
class RefProcPhaseTimeBaseTracker : public StackObj {
|
||||
protected:
|
||||
const char* _title;
|
||||
ReferenceProcessorPhaseTimes* _phase_times;
|
||||
Ticks _start_ticks;
|
||||
Ticks _end_ticks;
|
||||
|
||||
Ticks end_ticks();
|
||||
double elapsed_time();
|
||||
ReferenceProcessorPhaseTimes* phase_times() const { return _phase_times; }
|
||||
// Print phase elapsed time with each worker information if MT processed.
|
||||
void print_phase(ReferenceProcessorPhaseTimes::RefProcParPhases phase, uint indent);
|
||||
|
||||
public:
|
||||
RefProcPhaseTimeBaseTracker(const char* title,
|
||||
ReferenceProcessorPhaseTimes* phase_times);
|
||||
~RefProcPhaseTimeBaseTracker();
|
||||
};
|
||||
|
||||
// Updates queue balance time at ReferenceProcessorPhaseTimes and
|
||||
// save it into GCTimer.
|
||||
class RefProcBalanceQueuesTimeTracker : public RefProcPhaseTimeBaseTracker {
|
||||
public:
|
||||
RefProcBalanceQueuesTimeTracker(ReferenceProcessorPhaseTimes* phase_times);
|
||||
~RefProcBalanceQueuesTimeTracker();
|
||||
};
|
||||
|
||||
// Updates phase time at ReferenceProcessorPhaseTimes and save it into GCTimer.
|
||||
class RefProcParPhaseTimeTracker : public RefProcPhaseTimeBaseTracker {
|
||||
ReferenceProcessorPhaseTimes::RefProcPhaseNumbers _phase_number;
|
||||
|
||||
public:
|
||||
RefProcParPhaseTimeTracker(ReferenceProcessorPhaseTimes::RefProcPhaseNumbers phase_number,
|
||||
ReferenceProcessorPhaseTimes* phase_times);
|
||||
~RefProcParPhaseTimeTracker();
|
||||
};
|
||||
|
||||
// Updates phase time related information.
|
||||
// - Each phase processing time, cleared/discovered reference counts and stats for each working threads if MT processed.
|
||||
class RefProcPhaseTimesTracker : public RefProcPhaseTimeBaseTracker {
|
||||
ReferenceProcessor* _rp;
|
||||
|
||||
public:
|
||||
RefProcPhaseTimesTracker(ReferenceType ref_type,
|
||||
ReferenceProcessorPhaseTimes* phase_times,
|
||||
ReferenceProcessor* rp);
|
||||
~RefProcPhaseTimesTracker();
|
||||
};
|
||||
|
||||
// Updates enqueue time related information.
|
||||
// - Enqueueing time, enqueued reference count and stats for each working thread if MT processed.
|
||||
class RefProcEnqueueTimeTracker : public RefProcPhaseTimeBaseTracker {
|
||||
public:
|
||||
RefProcEnqueueTimeTracker(ReferenceProcessorPhaseTimes* phase_times,
|
||||
ReferenceProcessorStats& stats);
|
||||
~RefProcEnqueueTimeTracker();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSORPHASETIMES_HPP
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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
|
||||
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/workerDataArray.inline.hpp"
|
||||
#include "gc/shared/workerDataArray.inline.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
template <>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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_G1_WORKERDATAARRAY_HPP
|
||||
#define SHARE_VM_GC_G1_WORKERDATAARRAY_HPP
|
||||
#ifndef SHARE_VM_GC_SHARED_WORKERDATAARRAY_HPP
|
||||
#define SHARE_VM_GC_SHARED_WORKERDATAARRAY_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
@ -88,4 +88,4 @@ private:
|
||||
void print_details_on(outputStream* out) const;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_HPP
|
||||
#endif // SHARE_VM_GC_SHARED_WORKERDATAARRAY_HPP
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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,10 +22,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP
|
||||
#define SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP
|
||||
#ifndef SHARE_VM_GC_SHARED_WORKERDATAARRAY_INLINE_HPP
|
||||
#define SHARE_VM_GC_SHARED_WORKERDATAARRAY_INLINE_HPP
|
||||
|
||||
#include "gc/g1/workerDataArray.hpp"
|
||||
#include "gc/shared/workerDataArray.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
@ -166,4 +166,4 @@ void WorkerDataArray<T>::reset() {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP
|
||||
#endif // SHARE_VM_GC_SHARED_WORKERDATAARRAY_INLINE_HPP
|
@ -355,131 +355,124 @@ void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_err
|
||||
|
||||
int nof_jsrs = 0;
|
||||
bool has_monitor_bytecodes = false;
|
||||
Bytecodes::Code c;
|
||||
|
||||
{
|
||||
// We cannot tolerate a GC in this block, because we've
|
||||
// cached the bytecodes in 'code_base'. If the Method*
|
||||
// moves, the bytecodes will also move.
|
||||
NoSafepointVerifier nsv;
|
||||
Bytecodes::Code c;
|
||||
// Bytecodes and their length
|
||||
const address code_base = method->code_base();
|
||||
const int code_length = method->code_size();
|
||||
|
||||
// Bytecodes and their length
|
||||
const address code_base = method->code_base();
|
||||
const int code_length = method->code_size();
|
||||
int bc_length;
|
||||
for (int bci = 0; bci < code_length; bci += bc_length) {
|
||||
address bcp = code_base + bci;
|
||||
int prefix_length = 0;
|
||||
c = (Bytecodes::Code)(*bcp);
|
||||
|
||||
int bc_length;
|
||||
for (int bci = 0; bci < code_length; bci += bc_length) {
|
||||
address bcp = code_base + bci;
|
||||
int prefix_length = 0;
|
||||
c = (Bytecodes::Code)(*bcp);
|
||||
// Since we have the code, see if we can get the length
|
||||
// directly. Some more complicated bytecodes will report
|
||||
// a length of zero, meaning we need to make another method
|
||||
// call to calculate the length.
|
||||
bc_length = Bytecodes::length_for(c);
|
||||
if (bc_length == 0) {
|
||||
bc_length = Bytecodes::length_at(method, bcp);
|
||||
|
||||
// Since we have the code, see if we can get the length
|
||||
// directly. Some more complicated bytecodes will report
|
||||
// a length of zero, meaning we need to make another method
|
||||
// call to calculate the length.
|
||||
bc_length = Bytecodes::length_for(c);
|
||||
if (bc_length == 0) {
|
||||
bc_length = Bytecodes::length_at(method, bcp);
|
||||
// length_at will put us at the bytecode after the one modified
|
||||
// by 'wide'. We don't currently examine any of the bytecodes
|
||||
// modified by wide, but in case we do in the future...
|
||||
if (c == Bytecodes::_wide) {
|
||||
prefix_length = 1;
|
||||
c = (Bytecodes::Code)bcp[1];
|
||||
}
|
||||
}
|
||||
|
||||
// length_at will put us at the bytecode after the one modified
|
||||
// by 'wide'. We don't currently examine any of the bytecodes
|
||||
// modified by wide, but in case we do in the future...
|
||||
if (c == Bytecodes::_wide) {
|
||||
prefix_length = 1;
|
||||
c = (Bytecodes::Code)bcp[1];
|
||||
}
|
||||
assert(bc_length != 0, "impossible bytecode length");
|
||||
|
||||
switch (c) {
|
||||
case Bytecodes::_lookupswitch : {
|
||||
#ifndef CC_INTERP
|
||||
Bytecode_lookupswitch bc(method, bcp);
|
||||
(*bcp) = (
|
||||
bc.number_of_pairs() < BinarySwitchThreshold
|
||||
? Bytecodes::_fast_linearswitch
|
||||
: Bytecodes::_fast_binaryswitch
|
||||
);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Bytecodes::_fast_linearswitch:
|
||||
case Bytecodes::_fast_binaryswitch: {
|
||||
#ifndef CC_INTERP
|
||||
(*bcp) = Bytecodes::_lookupswitch;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
assert(bc_length != 0, "impossible bytecode length");
|
||||
case Bytecodes::_invokespecial : {
|
||||
rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case Bytecodes::_lookupswitch : {
|
||||
#ifndef CC_INTERP
|
||||
Bytecode_lookupswitch bc(method, bcp);
|
||||
(*bcp) = (
|
||||
bc.number_of_pairs() < BinarySwitchThreshold
|
||||
? Bytecodes::_fast_linearswitch
|
||||
: Bytecodes::_fast_binaryswitch
|
||||
);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Bytecodes::_fast_linearswitch:
|
||||
case Bytecodes::_fast_binaryswitch: {
|
||||
#ifndef CC_INTERP
|
||||
(*bcp) = Bytecodes::_lookupswitch;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Bytecodes::_putstatic :
|
||||
case Bytecodes::_putfield : {
|
||||
if (!reverse) {
|
||||
// Check if any final field of the class given as parameter is modified
|
||||
// outside of initializer methods of the class. Fields that are modified
|
||||
// are marked with a flag. For marked fields, the compilers do not perform
|
||||
// constant folding (as the field can be changed after initialization).
|
||||
//
|
||||
// The check is performed after verification and only if verification has
|
||||
// succeeded. Therefore, the class is guaranteed to be well-formed.
|
||||
InstanceKlass* klass = method->method_holder();
|
||||
u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
|
||||
constantPoolHandle cp(method->constants());
|
||||
Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
|
||||
|
||||
case Bytecodes::_invokespecial : {
|
||||
rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error);
|
||||
break;
|
||||
}
|
||||
if (klass->name() == ref_class_name) {
|
||||
Symbol* field_name = cp->name_ref_at(bc_index);
|
||||
Symbol* field_sig = cp->signature_ref_at(bc_index);
|
||||
|
||||
case Bytecodes::_putstatic :
|
||||
case Bytecodes::_putfield : {
|
||||
if (!reverse) {
|
||||
// Check if any final field of the class given as parameter is modified
|
||||
// outside of initializer methods of the class. Fields that are modified
|
||||
// are marked with a flag. For marked fields, the compilers do not perform
|
||||
// constant folding (as the field can be changed after initialization).
|
||||
//
|
||||
// The check is performed after verification and only if verification has
|
||||
// succeeded. Therefore, the class is guaranteed to be well-formed.
|
||||
InstanceKlass* klass = method->method_holder();
|
||||
u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
|
||||
constantPoolHandle cp(method->constants());
|
||||
Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
|
||||
|
||||
if (klass->name() == ref_class_name) {
|
||||
Symbol* field_name = cp->name_ref_at(bc_index);
|
||||
Symbol* field_sig = cp->signature_ref_at(bc_index);
|
||||
|
||||
fieldDescriptor fd;
|
||||
if (klass->find_field(field_name, field_sig, &fd) != NULL) {
|
||||
if (fd.access_flags().is_final()) {
|
||||
if (fd.access_flags().is_static()) {
|
||||
if (!method->is_static_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
} else {
|
||||
if (!method->is_object_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
fieldDescriptor fd;
|
||||
if (klass->find_field(field_name, field_sig, &fd) != NULL) {
|
||||
if (fd.access_flags().is_final()) {
|
||||
if (fd.access_flags().is_static()) {
|
||||
if (!method->is_static_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
} else {
|
||||
if (!method->is_object_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fall through
|
||||
case Bytecodes::_getstatic : // fall through
|
||||
case Bytecodes::_getfield : // fall through
|
||||
case Bytecodes::_invokevirtual : // fall through
|
||||
case Bytecodes::_invokestatic :
|
||||
case Bytecodes::_invokeinterface:
|
||||
case Bytecodes::_invokehandle : // if reverse=true
|
||||
rewrite_member_reference(bcp, prefix_length+1, reverse);
|
||||
break;
|
||||
case Bytecodes::_invokedynamic:
|
||||
rewrite_invokedynamic(bcp, prefix_length+1, reverse);
|
||||
break;
|
||||
case Bytecodes::_ldc:
|
||||
case Bytecodes::_fast_aldc: // if reverse=true
|
||||
maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse);
|
||||
break;
|
||||
case Bytecodes::_ldc_w:
|
||||
case Bytecodes::_fast_aldc_w: // if reverse=true
|
||||
maybe_rewrite_ldc(bcp, prefix_length+1, true, reverse);
|
||||
break;
|
||||
case Bytecodes::_jsr : // fall through
|
||||
case Bytecodes::_jsr_w : nof_jsrs++; break;
|
||||
case Bytecodes::_monitorenter : // fall through
|
||||
case Bytecodes::_monitorexit : has_monitor_bytecodes = true; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
// fall through
|
||||
case Bytecodes::_getstatic : // fall through
|
||||
case Bytecodes::_getfield : // fall through
|
||||
case Bytecodes::_invokevirtual : // fall through
|
||||
case Bytecodes::_invokestatic :
|
||||
case Bytecodes::_invokeinterface:
|
||||
case Bytecodes::_invokehandle : // if reverse=true
|
||||
rewrite_member_reference(bcp, prefix_length+1, reverse);
|
||||
break;
|
||||
case Bytecodes::_invokedynamic:
|
||||
rewrite_invokedynamic(bcp, prefix_length+1, reverse);
|
||||
break;
|
||||
case Bytecodes::_ldc:
|
||||
case Bytecodes::_fast_aldc: // if reverse=true
|
||||
maybe_rewrite_ldc(bcp, prefix_length+1, false, reverse);
|
||||
break;
|
||||
case Bytecodes::_ldc_w:
|
||||
case Bytecodes::_fast_aldc_w: // if reverse=true
|
||||
maybe_rewrite_ldc(bcp, prefix_length+1, true, reverse);
|
||||
break;
|
||||
case Bytecodes::_jsr : // fall through
|
||||
case Bytecodes::_jsr_w : nof_jsrs++; break;
|
||||
case Bytecodes::_monitorenter : // fall through
|
||||
case Bytecodes::_monitorexit : has_monitor_bytecodes = true; break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1365,8 +1365,8 @@ C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject
|
||||
ResourceMark rm;
|
||||
|
||||
if (!thread->has_last_Java_frame()) return NULL;
|
||||
Handle result = HotSpotStackFrameReference::klass()->allocate_instance_handle(thread);
|
||||
HotSpotStackFrameReference::klass()->initialize(thread);
|
||||
Handle result = HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
|
||||
HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
|
||||
|
||||
StackFrameStream fst(thread);
|
||||
if (hs_frame != NULL) {
|
||||
@ -1418,13 +1418,13 @@ C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject
|
||||
initialSkip --;
|
||||
} else {
|
||||
ScopeDesc* scope = cvf->scope();
|
||||
// native wrapper do not have a scope
|
||||
// native wrappers do not have a scope
|
||||
if (scope != NULL && scope->objects() != NULL) {
|
||||
bool realloc_failures = Deoptimization::realloc_objects(thread, fst.current(), scope->objects(), THREAD);
|
||||
bool realloc_failures = Deoptimization::realloc_objects(thread, fst.current(), scope->objects(), CHECK_NULL);
|
||||
Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false);
|
||||
|
||||
GrowableArray<ScopeValue*>* local_values = scope->locals();
|
||||
typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), thread);
|
||||
typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), CHECK_NULL);
|
||||
typeArrayHandle array(THREAD, array_oop);
|
||||
for (int i = 0; i < local_values->length(); i++) {
|
||||
ScopeValue* value = local_values->at(i);
|
||||
@ -1543,7 +1543,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame
|
||||
THROW_MSG(vmSymbols::java_lang_NullPointerException(), "stack frame is null")
|
||||
}
|
||||
|
||||
HotSpotStackFrameReference::klass()->initialize(thread);
|
||||
HotSpotStackFrameReference::klass()->initialize(CHECK);
|
||||
|
||||
// look for the given stack frame
|
||||
StackFrameStream fst(thread);
|
||||
@ -1601,7 +1601,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame
|
||||
return;
|
||||
}
|
||||
|
||||
bool realloc_failures = Deoptimization::realloc_objects(thread, fstAfterDeopt.current(), objects, THREAD);
|
||||
bool realloc_failures = Deoptimization::realloc_objects(thread, fstAfterDeopt.current(), objects, CHECK);
|
||||
Deoptimization::reassign_fields(fstAfterDeopt.current(), fstAfterDeopt.register_map(), objects, realloc_failures, false);
|
||||
|
||||
for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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
|
||||
@ -66,6 +66,7 @@ DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);)
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, metaspace)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, mmu)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, ref)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, start)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, task)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, plab)) \
|
||||
|
@ -1700,6 +1700,14 @@ WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
|
||||
return StringTable::shared_string_ignored();
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env))
|
||||
#if INCLUDE_CDS
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
WB_END
|
||||
|
||||
//Some convenience methods to deal with objects from java
|
||||
int WhiteBox::offset_for_field(const char* field_name, oop object,
|
||||
Symbol* signature_symbol) {
|
||||
@ -1993,6 +2001,7 @@ static JNINativeMethod methods[] = {
|
||||
{CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
|
||||
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
|
||||
{CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
|
||||
{CC"isCDSIncludedInVmBuild", CC"()Z", (void*)&WB_IsCDSIncludedInVmBuild },
|
||||
{CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches },
|
||||
{CC"addCompilerDirective", CC"(Ljava/lang/String;)I",
|
||||
(void*)&WB_AddCompilerDirective },
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2012, 2017, 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
|
||||
@ -405,7 +405,7 @@ Declares a structure type that can be used in other events.
|
||||
|
||||
<!-- Promotion events, Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. -->
|
||||
<event id="PromoteObjectInNewPLAB" path="vm/gc/detailed/object_promotion_in_new_PLAB" label="Promotion in new PLAB"
|
||||
description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
|
||||
description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
|
||||
has_thread="true" has_stacktrace="false" is_instant="true">
|
||||
<value type="UINT" field="gcId" label="GC Identifier" relation="GcId" description="Identifier signifying GC during which the object was promoted"/>
|
||||
<value type="CLASS" field="objectClass" label="Object Class" description="Class of promoted object"/>
|
||||
@ -414,9 +414,9 @@ Declares a structure type that can be used in other events.
|
||||
<value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
|
||||
<value type="BYTES64" field="plabSize" label="PLAB Size" description="Size of the allocated PLAB to which the object was copied"/>
|
||||
</event>
|
||||
|
||||
|
||||
<event id="PromoteObjectOutsidePLAB" path="vm/gc/detailed/object_promotion_outside_PLAB" label="Promotion outside PLAB"
|
||||
description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
|
||||
description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
|
||||
has_thread="true" has_stacktrace="false" is_instant="true">
|
||||
<value type="UINT" field="gcId" label="GC Identifier" relation="GcId" description="Identifier signifying GC during which the object was promoted"/>
|
||||
<value type="CLASS" field="objectClass" label="Object Class" description="Class of promoted object"/>
|
||||
@ -463,6 +463,11 @@ Declares a structure type that can be used in other events.
|
||||
<value type="STRING" field="name" label="Name" />
|
||||
</event>
|
||||
|
||||
<event id="GCPhasePauseLevel4" path="vm/gc/phases/pause_level_4" label="GC Phase Pause Level 4" has_thread="true">
|
||||
<value type="UINT" field="gcId" label="GC Identifier" relation="GcId"/>
|
||||
<value type="STRING" field="name" label="Name" />
|
||||
</event>
|
||||
|
||||
<event id="GCPhaseConcurrent" path="vm/gc/phases/concurrent" label="GC Phase Concurrent" has_thread="true">
|
||||
<value type="UINT" field="gcId" label="GC Identifier" relation="GcId"/>
|
||||
<value type="STRING" field="name" label="Name" />
|
||||
|
@ -125,7 +125,6 @@ gc/survivorAlignment/TestPromotionToSurvivor.java 8129886 generic-all
|
||||
gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
|
||||
gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all
|
||||
gc/stress/gclocker/TestGCLockerWithG1.java 8179226 generic-all
|
||||
gc/stress/gclocker/TestGCLockerWithSerial.java 8180311 generic-all
|
||||
|
||||
#############################################################################
|
||||
|
||||
|
@ -51,7 +51,8 @@ requires.properties= \
|
||||
vm.debug \
|
||||
vm.rtm.cpu \
|
||||
vm.rtm.os \
|
||||
vm.aot
|
||||
vm.aot \
|
||||
vm.cds
|
||||
|
||||
# Tests using jtreg 4.2 b07 features
|
||||
requiredVersion=4.2 b07
|
||||
|
@ -142,6 +142,9 @@ public class TestGCLogMessages {
|
||||
// TLAB handling
|
||||
new LogMessageWithLevel("Prepare TLABs", Level.DEBUG),
|
||||
new LogMessageWithLevel("Resize TLABs", Level.DEBUG),
|
||||
// Reference Processing
|
||||
new LogMessageWithLevel("Reference Processing", Level.DEBUG),
|
||||
new LogMessageWithLevel("Reference Enqueuing", Level.DEBUG),
|
||||
|
||||
new LogMessageWithLevelC2OrJVMCIOnly("DerivedPointerTable Update", Level.DEBUG),
|
||||
new LogMessageWithLevel("Start New Collection Set", Level.DEBUG),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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,13 +21,13 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @bug 8169703
|
||||
* @summary Verifies that dumping and loading a CDS archive succeeds with AlwaysPreTouch
|
||||
* @requires vm.gc.G1
|
||||
* @key gc
|
||||
* @key regression
|
||||
* @key gc regression
|
||||
* @requires vm.cds
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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,31 +31,73 @@
|
||||
* java.management
|
||||
*/
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class TestPrintReferences {
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProcessBuilder pb_enabled =
|
||||
ProcessTools.createJavaProcessBuilder("-Xlog:gc+ref=debug", "-Xmx10M", GCTest.class.getName());
|
||||
ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder("-Xlog:gc+phases+ref=debug",
|
||||
"-XX:+UseG1GC",
|
||||
"-Xmx10M",
|
||||
GCTest.class.getName());
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start());
|
||||
|
||||
String countRegex = "[0-9]+ refs";
|
||||
String indent_4 = " ";
|
||||
String indent_6 = " ";
|
||||
String indent_8 = " ";
|
||||
String gcLogTimeRegex = ".* GC\\([0-9]+\\) ";
|
||||
String countRegex = "[0-9]+";
|
||||
String timeRegex = "[0-9]+[.,][0-9]+ms";
|
||||
String totalRegex = gcLogTimeRegex + indent_4 + "Reference Processing: " + timeRegex + "\n";
|
||||
String balanceRegex = gcLogTimeRegex + indent_8 + "Balance queues: " + timeRegex + "\n";
|
||||
String softRefRegex = gcLogTimeRegex + indent_6 + "SoftReference: " + timeRegex + "\n";
|
||||
String weakRefRegex = gcLogTimeRegex + indent_6 + "WeakReference: " + timeRegex + "\n";
|
||||
String finalRefRegex = gcLogTimeRegex + indent_6 + "FinalReference: " + timeRegex + "\n";
|
||||
String phantomRefRegex = gcLogTimeRegex + indent_6 + "PhantomReference: " + timeRegex + "\n";
|
||||
String refDetailRegex = gcLogTimeRegex + indent_8 + "Phase2: " + timeRegex + "\n" +
|
||||
gcLogTimeRegex + indent_8 + "Phase3: " + timeRegex + "\n" +
|
||||
gcLogTimeRegex + indent_8 + "Discovered: " + countRegex + "\n" +
|
||||
gcLogTimeRegex + indent_8 + "Cleared: " + countRegex + "\n";
|
||||
String softRefDetailRegex = gcLogTimeRegex + indent_8 + "Phase1: " + timeRegex + "\n" + refDetailRegex;
|
||||
String enqueueRegex = gcLogTimeRegex + indent_4 + "Reference Enqueuing: " + timeRegex + "\n";
|
||||
String enqueueDetailRegex = gcLogTimeRegex + indent_6 + "Reference Counts: Soft: " + countRegex +
|
||||
" Weak: " + countRegex + " Final: " + countRegex + " Phantom: " + countRegex + "\n";
|
||||
|
||||
output.shouldMatch(".* GC\\([0-9]+\\) SoftReference " + timeRegex + "\n" +
|
||||
".* GC\\([0-9]+\\) WeakReference " + timeRegex + "\n" +
|
||||
".* GC\\([0-9]+\\) FinalReference " + timeRegex + "\n" +
|
||||
".* GC\\([0-9]+\\) PhantomReference " + timeRegex + "\n" +
|
||||
".* GC\\([0-9]+\\) JNI Weak Reference " + timeRegex + "\n" +
|
||||
".* GC\\([0-9]+\\) Ref Counts: Soft: [0-9]+ Weak: [0-9]+ Final: [0-9]+ Phantom: [0-9]+\n");
|
||||
output.shouldMatch(/* Total Reference processing time */
|
||||
totalRegex +
|
||||
/* SoftReference processing */
|
||||
softRefRegex + balanceRegex + softRefDetailRegex +
|
||||
/* WeakReference processing */
|
||||
weakRefRegex + balanceRegex + refDetailRegex +
|
||||
/* FinalReference processing */
|
||||
finalRefRegex + balanceRegex + refDetailRegex +
|
||||
/* PhantomReference processing */
|
||||
phantomRefRegex + balanceRegex + refDetailRegex +
|
||||
/* Total Enqueuing time */
|
||||
enqueueRegex +
|
||||
/* Enqueued Stats */
|
||||
enqueueDetailRegex
|
||||
);
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
static class GCTest {
|
||||
static final int M = 1024 * 1024;
|
||||
|
||||
public static void main(String [] args) {
|
||||
System.gc();
|
||||
|
||||
ArrayList arrSoftRefs = new ArrayList();
|
||||
|
||||
// Populate to triger GC and then Reference related logs will be printed.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
byte[] tmp = new byte[M];
|
||||
|
||||
arrSoftRefs.add(new SoftReference(tmp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @test TestGCLockerWithSerial
|
||||
* @key gc
|
||||
* @requires vm.gc.Serial
|
||||
* @requires vm.flavor != "minimal"
|
||||
* @summary Stress Serial's GC locker by calling GetPrimitiveArrayCritical while concurrently filling up old gen.
|
||||
* @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xmx1500m -Xmx1500m -XX:+UseSerialGC TestGCLockerWithSerial
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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,7 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/workerDataArray.inline.hpp"
|
||||
#include "gc/shared/workerDataArray.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "unittest.hpp"
|
||||
#include "utilities/ostream.hpp"
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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
|
||||
@ -47,7 +47,7 @@ public class BootstrapRedefine {
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("java/lang/Object",
|
||||
InMemoryJavaCompiler.compile("java.lang.Object", source,
|
||||
"-Xmodule:java.base"),
|
||||
"--patch-module=java.base"),
|
||||
"mods/java.base");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.base=mods/java.base", "-version");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2017, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @bug 8003424
|
||||
* @summary Testing UseCompressedClassPointers with CDS
|
||||
* @library /test/lib
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2017, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @bug 8003424
|
||||
* @summary Test that cannot use CDS if UseCompressedClassPointers is turned off.
|
||||
* @library /test/lib
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @bug 8005933
|
||||
* @summary Test that -Xshare:auto uses CDS when explicitly specified with -server.
|
||||
* @library /test/lib
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2017, 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
|
||||
@ -106,6 +106,9 @@ public class CompressedClassPointers {
|
||||
"-XX:+VerifyBeforeGC",
|
||||
"-Xshare:dump");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
if (output.firstMatch("Shared spaces are not supported in this VM") != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
output.shouldContain("Loading classes to share");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2017, 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,15 +21,17 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @bug 8055061
|
||||
* @key nmt
|
||||
* @requires vm.cds
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @run main NMTWithCDS
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test ArchiveDoesNotExist
|
||||
* @requires vm.cds
|
||||
* @summary Test how VM handles "file does not exist" situation while
|
||||
* attempting to use CDS archive. JVM should exit gracefully
|
||||
* when sharing mode is ON, and continue w/o sharing if sharing
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @summary Testing -Xbootclasspath/a support for CDS
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @library /test/lib
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test CdsDifferentCompactStrings
|
||||
* @requires vm.cds
|
||||
* @summary CDS (class data sharing) requires the same -XX:[+-]CompactStrings
|
||||
* setting between archive creation time and load time.
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test CdsDifferentObjectAlignment
|
||||
* @requires vm.cds
|
||||
* @summary Testing CDS (class data sharing) using varying object alignment.
|
||||
* Using different object alignment for each dump/load pair.
|
||||
* This is a negative test; using object alignment for loading that
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test CdsSameObjectAlignment
|
||||
* @requires vm.cds
|
||||
* @summary Testing CDS (class data sharing) using varying object alignment.
|
||||
* Using same object alignment for each dump/load pair
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @bug 8130072
|
||||
* @summary Check that Shared Dictionary is printed out with jcmd
|
||||
* Feature support: compressed oops/kptrs, 64-bit os, not on windows
|
||||
* @requires vm.cds
|
||||
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @library /test/lib
|
||||
@ -62,7 +63,9 @@ public class DumpSharedDictionary {
|
||||
"-Xshare:on", "DumpSharedDictionary", "test");
|
||||
|
||||
out = CDSTestUtils.executeAndLog(pb, "exec");
|
||||
out.shouldHaveExitValue(0);
|
||||
if (!CDSTestUtils.isUnableToMap(out)) {
|
||||
out.shouldHaveExitValue(0);
|
||||
}
|
||||
} else {
|
||||
// Grab my own PID
|
||||
String pid = Long.toString(ProcessTools.getProcessId());
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @bug 8067187
|
||||
* @summary Testing CDS dumping with the -XX:MaxMetaspaceSize=<size> option
|
||||
* @library /test/lib
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @bug 8066670
|
||||
* @summary Testing -XX:+PrintSharedArchiveAndExit option
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test SASymbolTableTest
|
||||
* @requires vm.cds
|
||||
* @summary Walk symbol table using SA, with and without CDS.
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @library /test/lib
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @bug 8014138
|
||||
* @summary Testing new -XX:SharedArchiveFile=<file-name> option
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test SharedBaseAddress
|
||||
* @requires vm.cds
|
||||
* @summary Test variety of values for SharedBaseAddress, making sure
|
||||
* VM handles normal values as well as edge values w/o a crash.
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @summary Check to make sure that shared strings in the bootstrap CDS archive
|
||||
* are actually shared
|
||||
* Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test SharedStringsDedup
|
||||
* @requires vm.cds
|
||||
* @summary Test -Xshare:auto with shared strings and -XX:+UseStringDeduplication
|
||||
* Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
|
||||
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test SharedStringsAuto
|
||||
* @requires vm.cds
|
||||
* @summary Test -Xshare:auto with shared strings.
|
||||
* Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
|
||||
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @bug 8059510
|
||||
* @summary Test SharedSymbolTableBucketSize option
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test SpaceUtilizationCheck
|
||||
* @requires vm.cds
|
||||
* @summary Check if the space utilization for shared spaces is adequate
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @library /test/lib
|
||||
|
@ -21,8 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test InterpreterMethodEntries
|
||||
* @requires vm.cds
|
||||
* @bug 8169711
|
||||
* @summary Test interpreter method entries for intrinsics with CDS (class data sharing)
|
||||
* and different settings of the intrinsic flag during dump/use of the archive.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @summary Exercise initial transformation (ClassFileLoadHook)
|
||||
* with CDS with Interface/Implementor pair
|
||||
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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,9 @@
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @summary Exercise initial transformation (ClassFileLoadHook)
|
||||
* with CDS with SubClass and SuperClass
|
||||
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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,9 @@
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @summary Exercise initial transformation (ClassFileLoadHook)
|
||||
* with CDS with SubClass and SuperClass, each lives in own separate package
|
||||
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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
|
||||
@ -51,11 +51,11 @@ public class PatchModule2Dirs {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source1, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source1, "--patch-module=java.naming"),
|
||||
"mods/java.naming");
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("java/beans/Encoder",
|
||||
InMemoryJavaCompiler.compile("java.beans.Encoder", source2, "-Xmodule:java.desktop"),
|
||||
InMemoryJavaCompiler.compile("java.beans.Encoder", source2, "--patch-module=java.desktop"),
|
||||
"mods2/java.desktop");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @summary test that --patch-module works with CDS
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
@ -61,7 +62,7 @@ public class PatchModuleCDS {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @summary classes which are not useable during run time should not be included in the classlist
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
@ -54,7 +55,7 @@ public class PatchModuleClassList {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk(BOOT_CLASS,
|
||||
InMemoryJavaCompiler.compile(BOOT_CLASS.replace('/', '.'), source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile(BOOT_CLASS.replace('/', '.'), source, "--patch-module=java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Build the jar file that will be used for the module "java.naming".
|
||||
@ -87,7 +88,7 @@ public class PatchModuleClassList {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk(PLATFORM_CLASS,
|
||||
InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "-Xmodule:java.transaction"),
|
||||
InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "--patch-module=java.transaction"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Build the jar file that will be used for the module "java.transaction".
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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
|
||||
@ -46,7 +46,7 @@ public class PatchModuleJavaBase {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("java/lang/NewClass",
|
||||
InMemoryJavaCompiler.compile("java.lang.NewClass", source, "-Xmodule:java.base"),
|
||||
InMemoryJavaCompiler.compile("java.lang.NewClass", source, "--patch-module=java.base"),
|
||||
"mods/java.base");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.base=mods/java.base",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2017, 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
|
||||
@ -46,7 +46,7 @@ public class PatchModuleTest {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
|
||||
"mods/java.naming");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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
|
||||
@ -50,7 +50,7 @@ public class PatchModuleTestJar {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Build the jar file that will be used for the module "java.naming".
|
||||
@ -70,7 +70,7 @@ public class PatchModuleTestJar {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Supply --patch-module with the name of the jar file for the module java.naming.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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
|
||||
@ -52,7 +52,7 @@ public class PatchModuleTestJarDir {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "--patch-module=java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Build the jar file that will be used for the module "java.naming".
|
||||
@ -72,7 +72,7 @@ public class PatchModuleTestJarDir {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager1",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager1", source, "--patch-module=java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Create a second class file in the module java.naming. This class file
|
||||
@ -85,7 +85,7 @@ public class PatchModuleTestJarDir {
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager2",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager2", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager2", source, "--patch-module=java.naming"),
|
||||
(System.getProperty("test.classes") + "/mods/java.naming"));
|
||||
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class PatchModuleTraceCL {
|
||||
|
||||
// Test -Xlog:class+load=info output for --patch-module
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "--patch-module=java.naming"),
|
||||
"mods/java.naming");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming",
|
||||
|
Loading…
x
Reference in New Issue
Block a user