interfaceSupport.cpp revision 6412:53a41e7cbe05
1/*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
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/orderAccess.inline.hpp"
34#include "runtime/threadLocalStorage.hpp"
35#include "runtime/vframe.hpp"
36#include "utilities/preserveException.hpp"
37
38PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
39
40// Implementation of InterfaceSupport
41
42#ifdef ASSERT
43
44long InterfaceSupport::_number_of_calls       = 0;
45long InterfaceSupport::_scavenge_alot_counter = 1;
46long InterfaceSupport::_fullgc_alot_counter   = 1;
47long InterfaceSupport::_fullgc_alot_invocation = 0;
48
49Histogram* RuntimeHistogram;
50
51RuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) {
52  static volatile jint RuntimeHistogram_lock = 0;
53  _name = elementName;
54  uintx count = 0;
55
56  while (Atomic::cmpxchg(1, &RuntimeHistogram_lock, 0) != 0) {
57    while (OrderAccess::load_acquire(&RuntimeHistogram_lock) != 0) {
58      count +=1;
59      if ( (WarnOnStalledSpinLock > 0)
60        && (count % WarnOnStalledSpinLock == 0)) {
61        warning("RuntimeHistogram_lock seems to be stalled");
62      }
63    }
64  }
65
66  if (RuntimeHistogram == NULL) {
67    RuntimeHistogram = new Histogram("VM Runtime Call Counts",200);
68  }
69
70  RuntimeHistogram->add_element(this);
71  Atomic::dec(&RuntimeHistogram_lock);
72}
73
74void InterfaceSupport::trace(const char* result_type, const char* header) {
75  tty->print_cr("%6d  %s", _number_of_calls, header);
76}
77
78void InterfaceSupport::gc_alot() {
79  Thread *thread = Thread::current();
80  if (!thread->is_Java_thread()) return; // Avoid concurrent calls
81  // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC.
82  JavaThread *current_thread = (JavaThread *)thread;
83  if (current_thread->active_handles() == NULL) return;
84
85  // Short-circuit any possible re-entrant gc-a-lot attempt
86  if (thread->skip_gcalot()) return;
87
88  if (is_init_completed()) {
89
90    if (++_fullgc_alot_invocation < FullGCALotStart) {
91      return;
92    }
93
94    // Use this line if you want to block at a specific point,
95    // e.g. one number_of_calls/scavenge/gc before you got into problems
96    if (FullGCALot) _fullgc_alot_counter--;
97
98    // Check if we should force a full gc
99    if (_fullgc_alot_counter == 0) {
100      // Release dummy so objects are forced to move
101      if (!Universe::release_fullgc_alot_dummy()) {
102        warning("FullGCALot: Unable to release more dummies at bottom of heap");
103      }
104      HandleMark hm(thread);
105      Universe::heap()->collect(GCCause::_full_gc_alot);
106      unsigned int invocations = Universe::heap()->total_full_collections();
107      // Compute new interval
108      if (FullGCALotInterval > 1) {
109        _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0));
110        if (PrintGCDetails && Verbose) {
111          tty->print_cr("Full gc no: %u\tInterval: %d", invocations,
112                        _fullgc_alot_counter);
113        }
114      } else {
115        _fullgc_alot_counter = 1;
116      }
117      // Print progress message
118      if (invocations % 100 == 0) {
119        if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations);
120      }
121    } else {
122      if (ScavengeALot) _scavenge_alot_counter--;
123      // Check if we should force a scavenge
124      if (_scavenge_alot_counter == 0) {
125        HandleMark hm(thread);
126        Universe::heap()->collect(GCCause::_scavenge_alot);
127        unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections();
128        // Compute new interval
129        if (ScavengeALotInterval > 1) {
130          _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0));
131          if (PrintGCDetails && Verbose) {
132            tty->print_cr("Scavenge no: %u\tInterval: %d", invocations,
133                          _scavenge_alot_counter);
134          }
135        } else {
136          _scavenge_alot_counter = 1;
137        }
138        // Print progress message
139        if (invocations % 1000 == 0) {
140          if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations);
141        }
142      }
143    }
144  }
145}
146
147
148vframe* vframe_array[50];
149int walk_stack_counter = 0;
150
151void InterfaceSupport::walk_stack_from(vframe* start_vf) {
152  // walk
153  int i = 0;
154  for (vframe* f = start_vf; f; f = f->sender() ) {
155    if (i < 50) vframe_array[i++] = f;
156  }
157}
158
159
160void InterfaceSupport::walk_stack() {
161  JavaThread* thread = JavaThread::current();
162  walk_stack_counter++;
163  if (!thread->has_last_Java_frame()) return;
164  ResourceMark rm(thread);
165  RegisterMap reg_map(thread);
166  walk_stack_from(thread->last_java_vframe(&reg_map));
167}
168
169
170# ifdef ENABLE_ZAP_DEAD_LOCALS
171
172static int zap_traversals = 0;
173
174void InterfaceSupport::zap_dead_locals_old() {
175  JavaThread* thread = JavaThread::current();
176  if (zap_traversals == -1) // edit constant for debugging
177    warning("I am here");
178  int zap_frame_count = 0; // count frames to help debugging
179  for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) {
180    sfs.current()->zap_dead_locals(thread, sfs.register_map());
181    ++zap_frame_count;
182  }
183  ++zap_traversals;
184}
185
186# endif
187
188
189int deoptimizeAllCounter = 0;
190int zombieAllCounter = 0;
191
192
193void InterfaceSupport::zombieAll() {
194  if (is_init_completed() && zombieAllCounter > ZombieALotInterval) {
195    zombieAllCounter = 0;
196    VM_ZombieAll op;
197    VMThread::execute(&op);
198  } else {
199    zombieAllCounter++;
200  }
201}
202
203void InterfaceSupport::unlinkSymbols() {
204  VM_UnlinkSymbols op;
205  VMThread::execute(&op);
206}
207
208void InterfaceSupport::deoptimizeAll() {
209  if (is_init_completed() ) {
210    if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) {
211      deoptimizeAllCounter = 0;
212      VM_DeoptimizeAll op;
213      VMThread::execute(&op);
214    } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) {
215      VM_DeoptimizeAll op;
216      VMThread::execute(&op);
217    }
218  }
219  deoptimizeAllCounter++;
220}
221
222
223void InterfaceSupport::stress_derived_pointers() {
224#ifdef COMPILER2
225  JavaThread *thread = JavaThread::current();
226  if (!is_init_completed()) return;
227  ResourceMark rm(thread);
228  bool found = false;
229  for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) {
230    CodeBlob* cb = sfs.current()->cb();
231    if (cb != NULL && cb->oop_maps() ) {
232      // Find oopmap for current method
233      OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc());
234      assert(map != NULL, "no oopmap found for pc");
235      found = map->has_derived_pointer();
236    }
237  }
238  if (found) {
239    // $$$ Not sure what to do here.
240    /*
241    Scavenge::invoke(0);
242    */
243  }
244#endif
245}
246
247
248void InterfaceSupport::verify_stack() {
249  JavaThread* thread = JavaThread::current();
250  ResourceMark rm(thread);
251  // disabled because it throws warnings that oop maps should only be accessed
252  // in VM thread or during debugging
253
254  if (!thread->has_pending_exception()) {
255    // verification does not work if there are pending exceptions
256    StackFrameStream sfs(thread);
257    CodeBlob* cb = sfs.current()->cb();
258      // In case of exceptions we might not have a runtime_stub on
259      // top of stack, hence, all callee-saved registers are not going
260      // to be setup correctly, hence, we cannot do stack verify
261    if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return;
262
263    for (; !sfs.is_done(); sfs.next()) {
264      sfs.current()->verify(sfs.register_map());
265    }
266  }
267}
268
269
270void InterfaceSupport::verify_last_frame() {
271  JavaThread* thread = JavaThread::current();
272  ResourceMark rm(thread);
273  RegisterMap reg_map(thread);
274  frame fr = thread->last_frame();
275  fr.verify(&reg_map);
276}
277
278
279#endif // ASSERT
280
281
282void InterfaceSupport_init() {
283#ifdef ASSERT
284  if (ScavengeALot || FullGCALot) {
285    srand(ScavengeALotInterval * FullGCALotInterval);
286  }
287#endif
288}
289