interfaceSupport.cpp revision 0:a61af66fc99e
1/*
2 * Copyright 1997-2007 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 */
24
25#include "incls/_precompiled.incl"
26#include "incls/_interfaceSupport.cpp.incl"
27
28
29// Implementation of InterfaceSupport
30
31#ifdef ASSERT
32
33long InterfaceSupport::_number_of_calls       = 0;
34long InterfaceSupport::_scavenge_alot_counter = 1;
35long InterfaceSupport::_fullgc_alot_counter   = 1;
36long InterfaceSupport::_fullgc_alot_invocation = 0;
37
38Histogram* RuntimeHistogram;
39
40RuntimeHistogramElement::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
63void InterfaceSupport::trace(const char* result_type, const char* header) {
64  tty->print_cr("%6d  %s", _number_of_calls, header);
65}
66
67void InterfaceSupport::gc_alot() {
68  Thread *thread = Thread::current();
69  if (thread->is_VM_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;
73
74  if (is_init_completed()) {
75
76    if (++_fullgc_alot_invocation < FullGCALotStart) {
77      return;
78    }
79
80    // Use this line if you want to block at a specific point,
81    // e.g. one number_of_calls/scavenge/gc before you got into problems
82    if (FullGCALot) _fullgc_alot_counter--;
83
84    // Check if we should force a full gc
85    if (_fullgc_alot_counter == 0) {
86      // Release dummy so objects are forced to move
87      if (!Universe::release_fullgc_alot_dummy()) {
88        warning("FullGCALot: Unable to release more dummies at bottom of heap");
89      }
90      HandleMark hm(thread);
91      Universe::heap()->collect(GCCause::_full_gc_alot);
92      unsigned int invocations = Universe::heap()->total_full_collections();
93      // Compute new interval
94      if (FullGCALotInterval > 1) {
95        _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0));
96        if (PrintGCDetails && Verbose) {
97          tty->print_cr("Full gc no: %u\tInterval: %d", invocations,
98                        _fullgc_alot_counter);
99        }
100      } else {
101        _fullgc_alot_counter = 1;
102      }
103      // Print progress message
104      if (invocations % 100 == 0) {
105        if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations);
106      }
107    } else {
108      if (ScavengeALot) _scavenge_alot_counter--;
109      // Check if we should force a scavenge
110      if (_scavenge_alot_counter == 0) {
111        HandleMark hm(thread);
112        Universe::heap()->collect(GCCause::_scavenge_alot);
113        unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections();
114        // Compute new interval
115        if (ScavengeALotInterval > 1) {
116          _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0));
117          if (PrintGCDetails && Verbose) {
118            tty->print_cr("Scavenge no: %u\tInterval: %d", invocations,
119                          _scavenge_alot_counter);
120          }
121        } else {
122          _scavenge_alot_counter = 1;
123        }
124        // Print progress message
125        if (invocations % 1000 == 0) {
126          if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations);
127        }
128      }
129    }
130  }
131}
132
133
134vframe* vframe_array[50];
135int walk_stack_counter = 0;
136
137void InterfaceSupport::walk_stack_from(vframe* start_vf) {
138  // walk
139  int i = 0;
140  for (vframe* f = start_vf; f; f = f->sender() ) {
141    if (i < 50) vframe_array[i++] = f;
142  }
143}
144
145
146void InterfaceSupport::walk_stack() {
147  JavaThread* thread = JavaThread::current();
148  walk_stack_counter++;
149  if (!thread->has_last_Java_frame()) return;
150  ResourceMark rm(thread);
151  RegisterMap reg_map(thread);
152  walk_stack_from(thread->last_java_vframe(&reg_map));
153}
154
155
156# ifdef ENABLE_ZAP_DEAD_LOCALS
157
158static int zap_traversals = 0;
159
160void InterfaceSupport::zap_dead_locals_old() {
161  JavaThread* thread = JavaThread::current();
162  if (zap_traversals == -1) // edit constant for debugging
163    warning("I am here");
164  int zap_frame_count = 0; // count frames to help debugging
165  for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) {
166    sfs.current()->zap_dead_locals(thread, sfs.register_map());
167    ++zap_frame_count;
168  }
169  ++zap_traversals;
170}
171
172# endif
173
174
175int deoptimizeAllCounter = 0;
176int zombieAllCounter = 0;
177
178
179void InterfaceSupport::zombieAll() {
180  if (is_init_completed() && zombieAllCounter > ZombieALotInterval) {
181    zombieAllCounter = 0;
182    VM_ZombieAll op;
183    VMThread::execute(&op);
184  } else {
185    zombieAllCounter++;
186  }
187}
188
189void InterfaceSupport::deoptimizeAll() {
190  if (is_init_completed() ) {
191    if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) {
192      deoptimizeAllCounter = 0;
193      VM_DeoptimizeAll op;
194      VMThread::execute(&op);
195    } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) {
196      VM_DeoptimizeAll op;
197      VMThread::execute(&op);
198    }
199  }
200  deoptimizeAllCounter++;
201}
202
203
204void InterfaceSupport::stress_derived_pointers() {
205#ifdef COMPILER2
206  JavaThread *thread = JavaThread::current();
207  if (!is_init_completed()) return;
208  ResourceMark rm(thread);
209  bool found = false;
210  for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) {
211    CodeBlob* cb = sfs.current()->cb();
212    if (cb != NULL && cb->oop_maps() ) {
213      // Find oopmap for current method
214      OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc());
215      assert(map != NULL, "no oopmap found for pc");
216      found = map->has_derived_pointer();
217    }
218  }
219  if (found) {
220    // $$$ Not sure what to do here.
221    /*
222    Scavenge::invoke(0);
223    */
224  }
225#endif
226}
227
228
229void InterfaceSupport::verify_stack() {
230  JavaThread* thread = JavaThread::current();
231  ResourceMark rm(thread);
232  // disabled because it throws warnings that oop maps should only be accessed
233  // in VM thread or during debugging
234
235  if (!thread->has_pending_exception()) {
236    // verification does not work if there are pending exceptions
237    StackFrameStream sfs(thread);
238    CodeBlob* cb = sfs.current()->cb();
239      // In case of exceptions we might not have a runtime_stub on
240      // top of stack, hence, all callee-saved registers are not going
241      // to be setup correctly, hence, we cannot do stack verify
242    if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return;
243
244    for (; !sfs.is_done(); sfs.next()) {
245      sfs.current()->verify(sfs.register_map());
246    }
247  }
248}
249
250
251void InterfaceSupport::verify_last_frame() {
252  JavaThread* thread = JavaThread::current();
253  ResourceMark rm(thread);
254  RegisterMap reg_map(thread);
255  frame fr = thread->last_frame();
256  fr.verify(&reg_map);
257}
258
259
260#endif // ASSERT
261
262
263void InterfaceSupport_init() {
264#ifdef ASSERT
265  if (ScavengeALot || FullGCALot) {
266    srand(ScavengeALotInterval * FullGCALotInterval);
267  }
268#endif
269}
270