comparison src/share/vm/memory/referenceProcessor.cpp @ 3992:d1bdeef3e3e2

7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76 Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing. Reviewed-by: tonyp, brutisso, ysr
author johnc
date Wed, 12 Oct 2011 10:25:51 -0700
parents 4dfb2df418f2
children bf2d2b8b1726
comparison
equal deleted inserted replaced
3991:3f24f946bc2d 3992:d1bdeef3e3e2
34 #include "runtime/jniHandles.hpp" 34 #include "runtime/jniHandles.hpp"
35 35
36 ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; 36 ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
37 ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; 37 ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL;
38 bool ReferenceProcessor::_pending_list_uses_discovered_field = false; 38 bool ReferenceProcessor::_pending_list_uses_discovered_field = false;
39 jlong ReferenceProcessor::_soft_ref_timestamp_clock = 0;
39 40
40 void referenceProcessor_init() { 41 void referenceProcessor_init() {
41 ReferenceProcessor::init_statics(); 42 ReferenceProcessor::init_statics();
42 } 43 }
43 44
44 void ReferenceProcessor::init_statics() { 45 void ReferenceProcessor::init_statics() {
45 // Initialize the master soft ref clock. 46 jlong now = os::javaTimeMillis();
46 java_lang_ref_SoftReference::set_clock(os::javaTimeMillis()); 47
48 // Initialize the soft ref timestamp clock.
49 _soft_ref_timestamp_clock = now;
50 // Also update the soft ref clock in j.l.r.SoftReference
51 java_lang_ref_SoftReference::set_clock(_soft_ref_timestamp_clock);
47 52
48 _always_clear_soft_ref_policy = new AlwaysClearPolicy(); 53 _always_clear_soft_ref_policy = new AlwaysClearPolicy();
49 _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy()) 54 _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
50 NOT_COMPILER2(LRUCurrentHeapPolicy()); 55 NOT_COMPILER2(LRUCurrentHeapPolicy());
51 if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) { 56 if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
53 } 58 }
54 guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || 59 guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
55 RefDiscoveryPolicy == ReferentBasedDiscovery, 60 RefDiscoveryPolicy == ReferentBasedDiscovery,
56 "Unrecongnized RefDiscoveryPolicy"); 61 "Unrecongnized RefDiscoveryPolicy");
57 _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field(); 62 _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field();
63 }
64
65 void ReferenceProcessor::enable_discovery(bool verify_disabled, bool check_no_refs) {
66 #ifdef ASSERT
67 // Verify that we're not currently discovering refs
68 assert(!verify_disabled || !_discovering_refs, "nested call?");
69
70 if (check_no_refs) {
71 // Verify that the discovered lists are empty
72 verify_no_references_recorded();
73 }
74 #endif // ASSERT
75
76 // Someone could have modified the value of the static
77 // field in the j.l.r.SoftReference class that holds the
78 // soft reference timestamp clock using reflection or
79 // Unsafe between GCs. Unconditionally update the static
80 // field in ReferenceProcessor here so that we use the new
81 // value during reference discovery.
82
83 _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock();
84 _discovering_refs = true;
58 } 85 }
59 86
60 ReferenceProcessor::ReferenceProcessor(MemRegion span, 87 ReferenceProcessor::ReferenceProcessor(MemRegion span,
61 bool mt_processing, 88 bool mt_processing,
62 int mt_processing_degree, 89 int mt_processing_degree,
120 147
121 void ReferenceProcessor::update_soft_ref_master_clock() { 148 void ReferenceProcessor::update_soft_ref_master_clock() {
122 // Update (advance) the soft ref master clock field. This must be done 149 // Update (advance) the soft ref master clock field. This must be done
123 // after processing the soft ref list. 150 // after processing the soft ref list.
124 jlong now = os::javaTimeMillis(); 151 jlong now = os::javaTimeMillis();
125 jlong clock = java_lang_ref_SoftReference::clock(); 152 jlong soft_ref_clock = java_lang_ref_SoftReference::clock();
153 assert(soft_ref_clock == _soft_ref_timestamp_clock, "soft ref clocks out of sync");
154
126 NOT_PRODUCT( 155 NOT_PRODUCT(
127 if (now < clock) { 156 if (now < _soft_ref_timestamp_clock) {
128 warning("time warp: %d to %d", clock, now); 157 warning("time warp: "INT64_FORMAT" to "INT64_FORMAT,
158 _soft_ref_timestamp_clock, now);
129 } 159 }
130 ) 160 )
131 // In product mode, protect ourselves from system time being adjusted 161 // In product mode, protect ourselves from system time being adjusted
132 // externally and going backward; see note in the implementation of 162 // externally and going backward; see note in the implementation of
133 // GenCollectedHeap::time_since_last_gc() for the right way to fix 163 // GenCollectedHeap::time_since_last_gc() for the right way to fix
134 // this uniformly throughout the VM; see bug-id 4741166. XXX 164 // this uniformly throughout the VM; see bug-id 4741166. XXX
135 if (now > clock) { 165 if (now > _soft_ref_timestamp_clock) {
166 _soft_ref_timestamp_clock = now;
136 java_lang_ref_SoftReference::set_clock(now); 167 java_lang_ref_SoftReference::set_clock(now);
137 } 168 }
138 // Else leave clock stalled at its old value until time progresses 169 // Else leave clock stalled at its old value until time progresses
139 // past clock value. 170 // past clock value.
140 } 171 }
147 NOT_PRODUCT(verify_ok_to_handle_reflists()); 178 NOT_PRODUCT(verify_ok_to_handle_reflists());
148 179
149 assert(!enqueuing_is_done(), "If here enqueuing should not be complete"); 180 assert(!enqueuing_is_done(), "If here enqueuing should not be complete");
150 // Stop treating discovered references specially. 181 // Stop treating discovered references specially.
151 disable_discovery(); 182 disable_discovery();
183
184 // If discovery was concurrent, someone could have modified
185 // the value of the static field in the j.l.r.SoftReference
186 // class that holds the soft reference timestamp clock using
187 // reflection or Unsafe between when discovery was enabled and
188 // now. Unconditionally update the static field in ReferenceProcessor
189 // here so that we use the new value during processing of the
190 // discovered soft refs.
191
192 _soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock();
152 193
153 bool trace_time = PrintGCDetails && PrintReferenceGC; 194 bool trace_time = PrintGCDetails && PrintReferenceGC;
154 // Soft references 195 // Soft references
155 { 196 {
156 TraceTime tt("SoftReference", trace_time, false, gclog_or_tty); 197 TraceTime tt("SoftReference", trace_time, false, gclog_or_tty);
484 DiscoveredListIterator iter(refs_list, keep_alive, is_alive); 525 DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
485 // Decide which softly reachable refs should be kept alive. 526 // Decide which softly reachable refs should be kept alive.
486 while (iter.has_next()) { 527 while (iter.has_next()) {
487 iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); 528 iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */));
488 bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive(); 529 bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive();
489 if (referent_is_dead && !policy->should_clear_reference(iter.obj())) { 530 if (referent_is_dead &&
531 !policy->should_clear_reference(iter.obj(), _soft_ref_timestamp_clock)) {
490 if (TraceReferenceGC) { 532 if (TraceReferenceGC) {
491 gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", 533 gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy",
492 iter.obj(), iter.obj()->blueprint()->internal_name()); 534 iter.obj(), iter.obj()->blueprint()->internal_name());
493 } 535 }
494 // Remove Reference object from list 536 // Remove Reference object from list
1115 // can mark through them now, rather than delaying that 1157 // can mark through them now, rather than delaying that
1116 // to the reference-processing phase. Since all current 1158 // to the reference-processing phase. Since all current
1117 // time-stamp policies advance the soft-ref clock only 1159 // time-stamp policies advance the soft-ref clock only
1118 // at a major collection cycle, this is always currently 1160 // at a major collection cycle, this is always currently
1119 // accurate. 1161 // accurate.
1120 if (!_current_soft_ref_policy->should_clear_reference(obj)) { 1162 if (!_current_soft_ref_policy->should_clear_reference(obj, _soft_ref_timestamp_clock)) {
1121 return false; 1163 return false;
1122 } 1164 }
1123 } 1165 }
1124 1166
1125 ResourceMark rm; // Needed for tracing. 1167 ResourceMark rm; // Needed for tracing.