Mercurial > hg > graal-jvmci-8
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. |