Wed, 13 Jan 2010 23:05:52 -0800
6912065: final fields in objects need to support inlining optimizations for JSR 292
Reviewed-by: twisti, kvn
1 /*
2 * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
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 */
25 #include "incls/_precompiled.incl"
26 #include "incls/_interfaceSupport.cpp.incl"
29 // Implementation of InterfaceSupport
31 #ifdef ASSERT
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;
38 Histogram* RuntimeHistogram;
40 RuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) {
41 static volatile jint RuntimeHistogram_lock = 0;
42 _name = elementName;
43 uintx count = 0;
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 }
55 if (RuntimeHistogram == NULL) {
56 RuntimeHistogram = new Histogram("VM Runtime Call Counts",200);
57 }
59 RuntimeHistogram->add_element(this);
60 Atomic::dec(&RuntimeHistogram_lock);
61 }
63 void InterfaceSupport::trace(const char* result_type, const char* header) {
64 tty->print_cr("%6d %s", _number_of_calls, header);
65 }
67 void InterfaceSupport::gc_alot() {
68 Thread *thread = Thread::current();
69 if (!thread->is_Java_thread()) return; // Avoid concurrent calls
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;
74 // Short-circuit any possible re-entrant gc-a-lot attempt
75 if (thread->skip_gcalot()) return;
77 if (is_init_completed()) {
79 if (++_fullgc_alot_invocation < FullGCALotStart) {
80 return;
81 }
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--;
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 }
137 vframe* vframe_array[50];
138 int walk_stack_counter = 0;
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 }
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 }
159 # ifdef ENABLE_ZAP_DEAD_LOCALS
161 static int zap_traversals = 0;
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 }
175 # endif
178 int deoptimizeAllCounter = 0;
179 int zombieAllCounter = 0;
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 }
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 }
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 }
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
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;
247 for (; !sfs.is_done(); sfs.next()) {
248 sfs.current()->verify(sfs.register_map());
249 }
250 }
251 }
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 }
263 #endif // ASSERT
266 void InterfaceSupport_init() {
267 #ifdef ASSERT
268 if (ScavengeALot || FullGCALot) {
269 srand(ScavengeALotInterval * FullGCALotInterval);
270 }
271 #endif
272 }