Mercurial > hg > graal-jvmci-8
annotate src/share/vm/runtime/interfaceSupport.cpp @ 3979:4dfb2df418f2
6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
author | johnc |
---|---|
date | Thu, 22 Sep 2011 10:57:37 -0700 |
parents | 1d1603768966 |
children | 78bbf4d43a14 |
rev | line source |
---|---|
0 | 1 /* |
2426
1d1603768966
7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents:
2177
diff
changeset
|
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/shared/markSweep.hpp" | |
27 #include "gc_interface/collectedHeap.hpp" | |
28 #include "gc_interface/collectedHeap.inline.hpp" | |
29 #include "memory/genCollectedHeap.hpp" | |
30 #include "memory/resourceArea.hpp" | |
31 #include "runtime/init.hpp" | |
32 #include "runtime/interfaceSupport.hpp" | |
33 #include "runtime/threadLocalStorage.hpp" | |
34 #include "runtime/vframe.hpp" | |
35 #include "utilities/preserveException.hpp" | |
0 | 36 |
37 | |
38 // Implementation of InterfaceSupport | |
39 | |
40 #ifdef ASSERT | |
41 | |
42 long InterfaceSupport::_number_of_calls = 0; | |
43 long InterfaceSupport::_scavenge_alot_counter = 1; | |
44 long InterfaceSupport::_fullgc_alot_counter = 1; | |
45 long InterfaceSupport::_fullgc_alot_invocation = 0; | |
46 | |
47 Histogram* RuntimeHistogram; | |
48 | |
49 RuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) { | |
50 static volatile jint RuntimeHistogram_lock = 0; | |
51 _name = elementName; | |
52 uintx count = 0; | |
53 | |
54 while (Atomic::cmpxchg(1, &RuntimeHistogram_lock, 0) != 0) { | |
55 while (OrderAccess::load_acquire(&RuntimeHistogram_lock) != 0) { | |
56 count +=1; | |
57 if ( (WarnOnStalledSpinLock > 0) | |
58 && (count % WarnOnStalledSpinLock == 0)) { | |
59 warning("RuntimeHistogram_lock seems to be stalled"); | |
60 } | |
61 } | |
62 } | |
63 | |
64 if (RuntimeHistogram == NULL) { | |
65 RuntimeHistogram = new Histogram("VM Runtime Call Counts",200); | |
66 } | |
67 | |
68 RuntimeHistogram->add_element(this); | |
69 Atomic::dec(&RuntimeHistogram_lock); | |
70 } | |
71 | |
72 void InterfaceSupport::trace(const char* result_type, const char* header) { | |
73 tty->print_cr("%6d %s", _number_of_calls, header); | |
74 } | |
75 | |
76 void InterfaceSupport::gc_alot() { | |
77 Thread *thread = Thread::current(); | |
806
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
78 if (!thread->is_Java_thread()) return; // Avoid concurrent calls |
0 | 79 // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC. |
80 JavaThread *current_thread = (JavaThread *)thread; | |
81 if (current_thread->active_handles() == NULL) return; | |
82 | |
806
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
83 // Short-circuit any possible re-entrant gc-a-lot attempt |
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
84 if (thread->skip_gcalot()) return; |
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
85 |
0 | 86 if (is_init_completed()) { |
87 | |
88 if (++_fullgc_alot_invocation < FullGCALotStart) { | |
89 return; | |
90 } | |
91 | |
92 // Use this line if you want to block at a specific point, | |
93 // e.g. one number_of_calls/scavenge/gc before you got into problems | |
94 if (FullGCALot) _fullgc_alot_counter--; | |
95 | |
96 // Check if we should force a full gc | |
97 if (_fullgc_alot_counter == 0) { | |
98 // Release dummy so objects are forced to move | |
99 if (!Universe::release_fullgc_alot_dummy()) { | |
100 warning("FullGCALot: Unable to release more dummies at bottom of heap"); | |
101 } | |
102 HandleMark hm(thread); | |
103 Universe::heap()->collect(GCCause::_full_gc_alot); | |
104 unsigned int invocations = Universe::heap()->total_full_collections(); | |
105 // Compute new interval | |
106 if (FullGCALotInterval > 1) { | |
107 _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0)); | |
108 if (PrintGCDetails && Verbose) { | |
109 tty->print_cr("Full gc no: %u\tInterval: %d", invocations, | |
110 _fullgc_alot_counter); | |
111 } | |
112 } else { | |
113 _fullgc_alot_counter = 1; | |
114 } | |
115 // Print progress message | |
116 if (invocations % 100 == 0) { | |
117 if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations); | |
118 } | |
119 } else { | |
120 if (ScavengeALot) _scavenge_alot_counter--; | |
121 // Check if we should force a scavenge | |
122 if (_scavenge_alot_counter == 0) { | |
123 HandleMark hm(thread); | |
124 Universe::heap()->collect(GCCause::_scavenge_alot); | |
125 unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections(); | |
126 // Compute new interval | |
127 if (ScavengeALotInterval > 1) { | |
128 _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0)); | |
129 if (PrintGCDetails && Verbose) { | |
130 tty->print_cr("Scavenge no: %u\tInterval: %d", invocations, | |
131 _scavenge_alot_counter); | |
132 } | |
133 } else { | |
134 _scavenge_alot_counter = 1; | |
135 } | |
136 // Print progress message | |
137 if (invocations % 1000 == 0) { | |
138 if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations); | |
139 } | |
140 } | |
141 } | |
142 } | |
143 } | |
144 | |
145 | |
146 vframe* vframe_array[50]; | |
147 int walk_stack_counter = 0; | |
148 | |
149 void InterfaceSupport::walk_stack_from(vframe* start_vf) { | |
150 // walk | |
151 int i = 0; | |
152 for (vframe* f = start_vf; f; f = f->sender() ) { | |
153 if (i < 50) vframe_array[i++] = f; | |
154 } | |
155 } | |
156 | |
157 | |
158 void InterfaceSupport::walk_stack() { | |
159 JavaThread* thread = JavaThread::current(); | |
160 walk_stack_counter++; | |
161 if (!thread->has_last_Java_frame()) return; | |
162 ResourceMark rm(thread); | |
163 RegisterMap reg_map(thread); | |
164 walk_stack_from(thread->last_java_vframe(®_map)); | |
165 } | |
166 | |
167 | |
168 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
169 | |
170 static int zap_traversals = 0; | |
171 | |
172 void InterfaceSupport::zap_dead_locals_old() { | |
173 JavaThread* thread = JavaThread::current(); | |
174 if (zap_traversals == -1) // edit constant for debugging | |
175 warning("I am here"); | |
176 int zap_frame_count = 0; // count frames to help debugging | |
177 for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) { | |
178 sfs.current()->zap_dead_locals(thread, sfs.register_map()); | |
179 ++zap_frame_count; | |
180 } | |
181 ++zap_traversals; | |
182 } | |
183 | |
184 # endif | |
185 | |
186 | |
187 int deoptimizeAllCounter = 0; | |
188 int zombieAllCounter = 0; | |
189 | |
190 | |
191 void InterfaceSupport::zombieAll() { | |
192 if (is_init_completed() && zombieAllCounter > ZombieALotInterval) { | |
193 zombieAllCounter = 0; | |
194 VM_ZombieAll op; | |
195 VMThread::execute(&op); | |
196 } else { | |
197 zombieAllCounter++; | |
198 } | |
199 } | |
200 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
201 void InterfaceSupport::unlinkSymbols() { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
202 VM_UnlinkSymbols op; |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
203 VMThread::execute(&op); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
204 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
205 |
0 | 206 void InterfaceSupport::deoptimizeAll() { |
207 if (is_init_completed() ) { | |
208 if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) { | |
209 deoptimizeAllCounter = 0; | |
210 VM_DeoptimizeAll op; | |
211 VMThread::execute(&op); | |
212 } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) { | |
213 VM_DeoptimizeAll op; | |
214 VMThread::execute(&op); | |
215 } | |
216 } | |
217 deoptimizeAllCounter++; | |
218 } | |
219 | |
220 | |
221 void InterfaceSupport::stress_derived_pointers() { | |
222 #ifdef COMPILER2 | |
223 JavaThread *thread = JavaThread::current(); | |
224 if (!is_init_completed()) return; | |
225 ResourceMark rm(thread); | |
226 bool found = false; | |
227 for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) { | |
228 CodeBlob* cb = sfs.current()->cb(); | |
229 if (cb != NULL && cb->oop_maps() ) { | |
230 // Find oopmap for current method | |
231 OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc()); | |
232 assert(map != NULL, "no oopmap found for pc"); | |
233 found = map->has_derived_pointer(); | |
234 } | |
235 } | |
236 if (found) { | |
237 // $$$ Not sure what to do here. | |
238 /* | |
239 Scavenge::invoke(0); | |
240 */ | |
241 } | |
242 #endif | |
243 } | |
244 | |
245 | |
246 void InterfaceSupport::verify_stack() { | |
247 JavaThread* thread = JavaThread::current(); | |
248 ResourceMark rm(thread); | |
249 // disabled because it throws warnings that oop maps should only be accessed | |
250 // in VM thread or during debugging | |
251 | |
252 if (!thread->has_pending_exception()) { | |
253 // verification does not work if there are pending exceptions | |
254 StackFrameStream sfs(thread); | |
255 CodeBlob* cb = sfs.current()->cb(); | |
256 // In case of exceptions we might not have a runtime_stub on | |
257 // top of stack, hence, all callee-saved registers are not going | |
258 // to be setup correctly, hence, we cannot do stack verify | |
259 if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return; | |
260 | |
261 for (; !sfs.is_done(); sfs.next()) { | |
262 sfs.current()->verify(sfs.register_map()); | |
263 } | |
264 } | |
265 } | |
266 | |
267 | |
268 void InterfaceSupport::verify_last_frame() { | |
269 JavaThread* thread = JavaThread::current(); | |
270 ResourceMark rm(thread); | |
271 RegisterMap reg_map(thread); | |
272 frame fr = thread->last_frame(); | |
273 fr.verify(®_map); | |
274 } | |
275 | |
276 | |
277 #endif // ASSERT | |
278 | |
279 | |
280 void InterfaceSupport_init() { | |
281 #ifdef ASSERT | |
282 if (ScavengeALot || FullGCALot) { | |
283 srand(ScavengeALotInterval * FullGCALotInterval); | |
284 } | |
285 #endif | |
286 } |