Mercurial > hg > truffle
annotate src/share/vm/runtime/interfaceSupport.cpp @ 1145:e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Wed, 23 Dec 2009 09:23:54 -0800 |
parents | bd02caa94611 |
children | c18cbe5936b8 |
rev | line source |
---|---|
0 | 1 /* |
844 | 2 * Copyright 1997-2009 Sun Microsystems, Inc. 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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_interfaceSupport.cpp.incl" | |
27 | |
28 | |
29 // Implementation of InterfaceSupport | |
30 | |
31 #ifdef ASSERT | |
32 | |
33 long InterfaceSupport::_number_of_calls = 0; | |
34 long InterfaceSupport::_scavenge_alot_counter = 1; | |
35 long InterfaceSupport::_fullgc_alot_counter = 1; | |
36 long InterfaceSupport::_fullgc_alot_invocation = 0; | |
37 | |
38 Histogram* RuntimeHistogram; | |
39 | |
40 RuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) { | |
41 static volatile jint RuntimeHistogram_lock = 0; | |
42 _name = elementName; | |
43 uintx count = 0; | |
44 | |
45 while (Atomic::cmpxchg(1, &RuntimeHistogram_lock, 0) != 0) { | |
46 while (OrderAccess::load_acquire(&RuntimeHistogram_lock) != 0) { | |
47 count +=1; | |
48 if ( (WarnOnStalledSpinLock > 0) | |
49 && (count % WarnOnStalledSpinLock == 0)) { | |
50 warning("RuntimeHistogram_lock seems to be stalled"); | |
51 } | |
52 } | |
53 } | |
54 | |
55 if (RuntimeHistogram == NULL) { | |
56 RuntimeHistogram = new Histogram("VM Runtime Call Counts",200); | |
57 } | |
58 | |
59 RuntimeHistogram->add_element(this); | |
60 Atomic::dec(&RuntimeHistogram_lock); | |
61 } | |
62 | |
63 void InterfaceSupport::trace(const char* result_type, const char* header) { | |
64 tty->print_cr("%6d %s", _number_of_calls, header); | |
65 } | |
66 | |
67 void InterfaceSupport::gc_alot() { | |
68 Thread *thread = Thread::current(); | |
806
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
69 if (!thread->is_Java_thread()) return; // Avoid concurrent calls |
0 | 70 // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC. |
71 JavaThread *current_thread = (JavaThread *)thread; | |
72 if (current_thread->active_handles() == NULL) return; | |
73 | |
806
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
74 // Short-circuit any possible re-entrant gc-a-lot attempt |
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
75 if (thread->skip_gcalot()) return; |
821269eca479
6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM
ysr
parents:
0
diff
changeset
|
76 |
0 | 77 if (is_init_completed()) { |
78 | |
79 if (++_fullgc_alot_invocation < FullGCALotStart) { | |
80 return; | |
81 } | |
82 | |
83 // Use this line if you want to block at a specific point, | |
84 // e.g. one number_of_calls/scavenge/gc before you got into problems | |
85 if (FullGCALot) _fullgc_alot_counter--; | |
86 | |
87 // Check if we should force a full gc | |
88 if (_fullgc_alot_counter == 0) { | |
89 // Release dummy so objects are forced to move | |
90 if (!Universe::release_fullgc_alot_dummy()) { | |
91 warning("FullGCALot: Unable to release more dummies at bottom of heap"); | |
92 } | |
93 HandleMark hm(thread); | |
94 Universe::heap()->collect(GCCause::_full_gc_alot); | |
95 unsigned int invocations = Universe::heap()->total_full_collections(); | |
96 // Compute new interval | |
97 if (FullGCALotInterval > 1) { | |
98 _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0)); | |
99 if (PrintGCDetails && Verbose) { | |
100 tty->print_cr("Full gc no: %u\tInterval: %d", invocations, | |
101 _fullgc_alot_counter); | |
102 } | |
103 } else { | |
104 _fullgc_alot_counter = 1; | |
105 } | |
106 // Print progress message | |
107 if (invocations % 100 == 0) { | |
108 if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations); | |
109 } | |
110 } else { | |
111 if (ScavengeALot) _scavenge_alot_counter--; | |
112 // Check if we should force a scavenge | |
113 if (_scavenge_alot_counter == 0) { | |
114 HandleMark hm(thread); | |
115 Universe::heap()->collect(GCCause::_scavenge_alot); | |
116 unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections(); | |
117 // Compute new interval | |
118 if (ScavengeALotInterval > 1) { | |
119 _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0)); | |
120 if (PrintGCDetails && Verbose) { | |
121 tty->print_cr("Scavenge no: %u\tInterval: %d", invocations, | |
122 _scavenge_alot_counter); | |
123 } | |
124 } else { | |
125 _scavenge_alot_counter = 1; | |
126 } | |
127 // Print progress message | |
128 if (invocations % 1000 == 0) { | |
129 if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations); | |
130 } | |
131 } | |
132 } | |
133 } | |
134 } | |
135 | |
136 | |
137 vframe* vframe_array[50]; | |
138 int walk_stack_counter = 0; | |
139 | |
140 void InterfaceSupport::walk_stack_from(vframe* start_vf) { | |
141 // walk | |
142 int i = 0; | |
143 for (vframe* f = start_vf; f; f = f->sender() ) { | |
144 if (i < 50) vframe_array[i++] = f; | |
145 } | |
146 } | |
147 | |
148 | |
149 void InterfaceSupport::walk_stack() { | |
150 JavaThread* thread = JavaThread::current(); | |
151 walk_stack_counter++; | |
152 if (!thread->has_last_Java_frame()) return; | |
153 ResourceMark rm(thread); | |
154 RegisterMap reg_map(thread); | |
155 walk_stack_from(thread->last_java_vframe(®_map)); | |
156 } | |
157 | |
158 | |
159 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
160 | |
161 static int zap_traversals = 0; | |
162 | |
163 void InterfaceSupport::zap_dead_locals_old() { | |
164 JavaThread* thread = JavaThread::current(); | |
165 if (zap_traversals == -1) // edit constant for debugging | |
166 warning("I am here"); | |
167 int zap_frame_count = 0; // count frames to help debugging | |
168 for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) { | |
169 sfs.current()->zap_dead_locals(thread, sfs.register_map()); | |
170 ++zap_frame_count; | |
171 } | |
172 ++zap_traversals; | |
173 } | |
174 | |
175 # endif | |
176 | |
177 | |
178 int deoptimizeAllCounter = 0; | |
179 int zombieAllCounter = 0; | |
180 | |
181 | |
182 void InterfaceSupport::zombieAll() { | |
183 if (is_init_completed() && zombieAllCounter > ZombieALotInterval) { | |
184 zombieAllCounter = 0; | |
185 VM_ZombieAll op; | |
186 VMThread::execute(&op); | |
187 } else { | |
188 zombieAllCounter++; | |
189 } | |
190 } | |
191 | |
192 void InterfaceSupport::deoptimizeAll() { | |
193 if (is_init_completed() ) { | |
194 if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) { | |
195 deoptimizeAllCounter = 0; | |
196 VM_DeoptimizeAll op; | |
197 VMThread::execute(&op); | |
198 } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) { | |
199 VM_DeoptimizeAll op; | |
200 VMThread::execute(&op); | |
201 } | |
202 } | |
203 deoptimizeAllCounter++; | |
204 } | |
205 | |
206 | |
207 void InterfaceSupport::stress_derived_pointers() { | |
208 #ifdef COMPILER2 | |
209 JavaThread *thread = JavaThread::current(); | |
210 if (!is_init_completed()) return; | |
211 ResourceMark rm(thread); | |
212 bool found = false; | |
213 for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) { | |
214 CodeBlob* cb = sfs.current()->cb(); | |
215 if (cb != NULL && cb->oop_maps() ) { | |
216 // Find oopmap for current method | |
217 OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc()); | |
218 assert(map != NULL, "no oopmap found for pc"); | |
219 found = map->has_derived_pointer(); | |
220 } | |
221 } | |
222 if (found) { | |
223 // $$$ Not sure what to do here. | |
224 /* | |
225 Scavenge::invoke(0); | |
226 */ | |
227 } | |
228 #endif | |
229 } | |
230 | |
231 | |
232 void InterfaceSupport::verify_stack() { | |
233 JavaThread* thread = JavaThread::current(); | |
234 ResourceMark rm(thread); | |
235 // disabled because it throws warnings that oop maps should only be accessed | |
236 // in VM thread or during debugging | |
237 | |
238 if (!thread->has_pending_exception()) { | |
239 // verification does not work if there are pending exceptions | |
240 StackFrameStream sfs(thread); | |
241 CodeBlob* cb = sfs.current()->cb(); | |
242 // In case of exceptions we might not have a runtime_stub on | |
243 // top of stack, hence, all callee-saved registers are not going | |
244 // to be setup correctly, hence, we cannot do stack verify | |
245 if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return; | |
246 | |
247 for (; !sfs.is_done(); sfs.next()) { | |
248 sfs.current()->verify(sfs.register_map()); | |
249 } | |
250 } | |
251 } | |
252 | |
253 | |
254 void InterfaceSupport::verify_last_frame() { | |
255 JavaThread* thread = JavaThread::current(); | |
256 ResourceMark rm(thread); | |
257 RegisterMap reg_map(thread); | |
258 frame fr = thread->last_frame(); | |
259 fr.verify(®_map); | |
260 } | |
261 | |
262 | |
263 #endif // ASSERT | |
264 | |
265 | |
266 void InterfaceSupport_init() { | |
267 #ifdef ASSERT | |
268 if (ScavengeALot || FullGCALot) { | |
269 srand(ScavengeALotInterval * FullGCALotInterval); | |
270 } | |
271 #endif | |
272 } |