interfaceSupport.cpp revision 1879:f95d63e2154a
11541Srgrimes/*
21541Srgrimes * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
31541Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41541Srgrimes *
51541Srgrimes * This code is free software; you can redistribute it and/or modify it
61541Srgrimes * under the terms of the GNU General Public License version 2 only, as
71541Srgrimes * published by the Free Software Foundation.
81541Srgrimes *
91541Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
101541Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111541Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
121541Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
131541Srgrimes * accompanied this code).
141541Srgrimes *
151541Srgrimes * You should have received a copy of the GNU General Public License version
161541Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
171541Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
181541Srgrimes *
191541Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
201541Srgrimes * or visit www.oracle.com if you need additional information or have any
211541Srgrimes * questions.
221541Srgrimes *
231541Srgrimes */
241541Srgrimes
251541Srgrimes#include "precompiled.hpp"
261541Srgrimes#include "gc_implementation/shared/markSweep.hpp"
271541Srgrimes#include "gc_interface/collectedHeap.hpp"
281541Srgrimes#include "gc_interface/collectedHeap.inline.hpp"
291541Srgrimes#include "memory/genCollectedHeap.hpp"
301541Srgrimes#include "memory/resourceArea.hpp"
311541Srgrimes#include "runtime/init.hpp"
321541Srgrimes#include "runtime/interfaceSupport.hpp"
331541Srgrimes#include "runtime/threadLocalStorage.hpp"
341541Srgrimes#include "runtime/vframe.hpp"
351541Srgrimes#include "utilities/preserveException.hpp"
361541Srgrimes
371541Srgrimes
3844510Swollman// Implementation of InterfaceSupport
3950477Speter
401541Srgrimes#ifdef ASSERT
411541Srgrimes
421541Srgrimeslong InterfaceSupport::_number_of_calls       = 0;
431541Srgrimeslong InterfaceSupport::_scavenge_alot_counter = 1;
4433392Sphklong InterfaceSupport::_fullgc_alot_counter   = 1;
451541Srgrimeslong InterfaceSupport::_fullgc_alot_invocation = 0;
461541Srgrimes
4733392SphkHistogram* RuntimeHistogram;
4833392Sphk
4933392SphkRuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) {
5033392Sphk  static volatile jint RuntimeHistogram_lock = 0;
5133392Sphk  _name = elementName;
5233392Sphk  uintx count = 0;
5329680Sgibbs
5429680Sgibbs  while (Atomic::cmpxchg(1, &RuntimeHistogram_lock, 0) != 0) {
5529680Sgibbs    while (OrderAccess::load_acquire(&RuntimeHistogram_lock) != 0) {
5629680Sgibbs      count +=1;
5733392Sphk      if ( (WarnOnStalledSpinLock > 0)
582112Swollman        && (count % WarnOnStalledSpinLock == 0)) {
5929680Sgibbs        warning("RuntimeHistogram_lock seems to be stalled");
601541Srgrimes      }
611541Srgrimes    }
6229680Sgibbs  }
6329680Sgibbs
6429680Sgibbs  if (RuntimeHistogram == NULL) {
6529680Sgibbs    RuntimeHistogram = new Histogram("VM Runtime Call Counts",200);
6629680Sgibbs  }
6729680Sgibbs
6829680Sgibbs  RuntimeHistogram->add_element(this);
6929680Sgibbs  Atomic::dec(&RuntimeHistogram_lock);
7029680Sgibbs}
7129680Sgibbs
7232388Sphkvoid InterfaceSupport::trace(const char* result_type, const char* header) {
7329680Sgibbs  tty->print_cr("%6d  %s", _number_of_calls, header);
741541Srgrimes}
751541Srgrimes
761541Srgrimesvoid InterfaceSupport::gc_alot() {
771541Srgrimes  Thread *thread = Thread::current();
7832391Sphk  if (!thread->is_Java_thread()) return; // Avoid concurrent calls
791541Srgrimes  // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC.
801541Srgrimes  JavaThread *current_thread = (JavaThread *)thread;
8129805Sgibbs  if (current_thread->active_handles() == NULL) return;
821541Srgrimes
8329805Sgibbs  // Short-circuit any possible re-entrant gc-a-lot attempt
8433392Sphk  if (thread->skip_gcalot()) return;
851541Srgrimes
8633392Sphk  if (is_init_completed()) {
8733392Sphk
8833392Sphk    if (++_fullgc_alot_invocation < FullGCALotStart) {
8929680Sgibbs      return;
9029680Sgibbs    }
911541Srgrimes
9229680Sgibbs    // Use this line if you want to block at a specific point,
9329805Sgibbs    // e.g. one number_of_calls/scavenge/gc before you got into problems
9429805Sgibbs    if (FullGCALot) _fullgc_alot_counter--;
9529805Sgibbs
9629805Sgibbs    // Check if we should force a full gc
9729805Sgibbs    if (_fullgc_alot_counter == 0) {
9829805Sgibbs      // Release dummy so objects are forced to move
9929805Sgibbs      if (!Universe::release_fullgc_alot_dummy()) {
10029805Sgibbs        warning("FullGCALot: Unable to release more dummies at bottom of heap");
10129680Sgibbs      }
10229805Sgibbs      HandleMark hm(thread);
10329680Sgibbs      Universe::heap()->collect(GCCause::_full_gc_alot);
10429680Sgibbs      unsigned int invocations = Universe::heap()->total_full_collections();
10529680Sgibbs      // Compute new interval
10629680Sgibbs      if (FullGCALotInterval > 1) {
10729805Sgibbs        _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0));
10829680Sgibbs        if (PrintGCDetails && Verbose) {
10929680Sgibbs          tty->print_cr("Full gc no: %u\tInterval: %d", invocations,
11029680Sgibbs                        _fullgc_alot_counter);
11129680Sgibbs        }
11229680Sgibbs      } else {
11329680Sgibbs        _fullgc_alot_counter = 1;
11429680Sgibbs      }
11529680Sgibbs      // Print progress message
11629680Sgibbs      if (invocations % 100 == 0) {
11729680Sgibbs        if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations);
11829805Sgibbs      }
11929680Sgibbs    } else {
12029680Sgibbs      if (ScavengeALot) _scavenge_alot_counter--;
12129680Sgibbs      // Check if we should force a scavenge
12244510Swollman      if (_scavenge_alot_counter == 0) {
12344510Swollman        HandleMark hm(thread);
12444510Swollman        Universe::heap()->collect(GCCause::_scavenge_alot);
12544510Swollman        unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections();
12644510Swollman        // Compute new interval
12744510Swollman        if (ScavengeALotInterval > 1) {
12850673Sjlemon          _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0));
12944510Swollman          if (PrintGCDetails && Verbose) {
13029680Sgibbs            tty->print_cr("Scavenge no: %u\tInterval: %d", invocations,
13129680Sgibbs                          _scavenge_alot_counter);
13229680Sgibbs          }
13329680Sgibbs        } else {
13429680Sgibbs          _scavenge_alot_counter = 1;
13529680Sgibbs        }
13629680Sgibbs        // Print progress message
1371541Srgrimes        if (invocations % 1000 == 0) {
13829680Sgibbs          if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations);
1391541Srgrimes        }
1401541Srgrimes      }
1411541Srgrimes    }
1421541Srgrimes  }
1431541Srgrimes}
1441541Srgrimes
1451541Srgrimes
1461541Srgrimesvframe* vframe_array[50];
1471541Srgrimesint walk_stack_counter = 0;
1481541Srgrimes
14929680Sgibbsvoid InterfaceSupport::walk_stack_from(vframe* start_vf) {
15029680Sgibbs  // walk
15129680Sgibbs  int i = 0;
1521541Srgrimes  for (vframe* f = start_vf; f; f = f->sender() ) {
15329680Sgibbs    if (i < 50) vframe_array[i++] = f;
15429680Sgibbs  }
15529680Sgibbs}
15629680Sgibbs
1571541Srgrimes
15829680Sgibbsvoid InterfaceSupport::walk_stack() {
15929680Sgibbs  JavaThread* thread = JavaThread::current();
16033824Sbde  walk_stack_counter++;
1611541Srgrimes  if (!thread->has_last_Java_frame()) return;
16229680Sgibbs  ResourceMark rm(thread);
1631541Srgrimes  RegisterMap reg_map(thread);
16429680Sgibbs  walk_stack_from(thread->last_java_vframe(&reg_map));
16529680Sgibbs}
16629680Sgibbs
1671541Srgrimes
1681541Srgrimes# ifdef ENABLE_ZAP_DEAD_LOCALS
1691541Srgrimes
1701541Srgrimesstatic int zap_traversals = 0;
17129680Sgibbs
17229680Sgibbsvoid InterfaceSupport::zap_dead_locals_old() {
17329680Sgibbs  JavaThread* thread = JavaThread::current();
1741541Srgrimes  if (zap_traversals == -1) // edit constant for debugging
17529680Sgibbs    warning("I am here");
17644510Swollman  int zap_frame_count = 0; // count frames to help debugging
17744510Swollman  for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) {
1781541Srgrimes    sfs.current()->zap_dead_locals(thread, sfs.register_map());
17944510Swollman    ++zap_frame_count;
1801541Srgrimes  }
18129680Sgibbs  ++zap_traversals;
1821541Srgrimes}
1831541Srgrimes
1841541Srgrimes# endif
18529680Sgibbs
18633824Sbde
1871541Srgrimesint deoptimizeAllCounter = 0;
18829680Sgibbsint zombieAllCounter = 0;
1891541Srgrimes
1901541Srgrimes
1911541Srgrimesvoid InterfaceSupport::zombieAll() {
19229680Sgibbs  if (is_init_completed() && zombieAllCounter > ZombieALotInterval) {
19329680Sgibbs    zombieAllCounter = 0;
19429680Sgibbs    VM_ZombieAll op;
19529680Sgibbs    VMThread::execute(&op);
19629680Sgibbs  } else {
19729680Sgibbs    zombieAllCounter++;
19829680Sgibbs  }
19929680Sgibbs}
2001541Srgrimes
20144510Swollmanvoid InterfaceSupport::deoptimizeAll() {
20244510Swollman  if (is_init_completed() ) {
2031541Srgrimes    if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) {
2041541Srgrimes      deoptimizeAllCounter = 0;
2051541Srgrimes      VM_DeoptimizeAll op;
20624101Sbde      VMThread::execute(&op);
20729680Sgibbs    } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) {
20829680Sgibbs      VM_DeoptimizeAll op;
20929680Sgibbs      VMThread::execute(&op);
21029680Sgibbs    }
21129680Sgibbs  }
21244510Swollman  deoptimizeAllCounter++;
21344510Swollman}
21444510Swollman
21544510Swollman
21644510Swollmanvoid InterfaceSupport::stress_derived_pointers() {
21744510Swollman#ifdef COMPILER2
21844510Swollman  JavaThread *thread = JavaThread::current();
21944510Swollman  if (!is_init_completed()) return;
22050673Sjlemon  ResourceMark rm(thread);
22144510Swollman  bool found = false;
22250673Sjlemon  for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) {
22350673Sjlemon    CodeBlob* cb = sfs.current()->cb();
22450673Sjlemon    if (cb != NULL && cb->oop_maps() ) {
22544510Swollman      // Find oopmap for current method
22644510Swollman      OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc());
22744510Swollman      assert(map != NULL, "no oopmap found for pc");
22844510Swollman      found = map->has_derived_pointer();
22944510Swollman    }
23044510Swollman  }
23144510Swollman  if (found) {
23244510Swollman    // $$$ Not sure what to do here.
23344510Swollman    /*
23444510Swollman    Scavenge::invoke(0);
23544510Swollman    */
23644510Swollman  }
23744510Swollman#endif
23844510Swollman}
23944510Swollman
24044510Swollman
24144510Swollmanvoid InterfaceSupport::verify_stack() {
24250673Sjlemon  JavaThread* thread = JavaThread::current();
24344510Swollman  ResourceMark rm(thread);
24444510Swollman  // disabled because it throws warnings that oop maps should only be accessed
24544510Swollman  // in VM thread or during debugging
24644510Swollman
24744510Swollman  if (!thread->has_pending_exception()) {
24850673Sjlemon    // verification does not work if there are pending exceptions
24944510Swollman    StackFrameStream sfs(thread);
25044510Swollman    CodeBlob* cb = sfs.current()->cb();
25144510Swollman      // In case of exceptions we might not have a runtime_stub on
25244510Swollman      // top of stack, hence, all callee-saved registers are not going
25344510Swollman      // to be setup correctly, hence, we cannot do stack verify
25444510Swollman    if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return;
25544510Swollman
25644510Swollman    for (; !sfs.is_done(); sfs.next()) {
25744510Swollman      sfs.current()->verify(sfs.register_map());
25844510Swollman    }
25944510Swollman  }
26044510Swollman}
26144510Swollman
26244510Swollman
26344510Swollmanvoid InterfaceSupport::verify_last_frame() {
26444510Swollman  JavaThread* thread = JavaThread::current();
26544510Swollman  ResourceMark rm(thread);
26644510Swollman  RegisterMap reg_map(thread);
26744510Swollman  frame fr = thread->last_frame();
26850673Sjlemon  fr.verify(&reg_map);
26944510Swollman}
27044510Swollman
27144510Swollman
27250673Sjlemon#endif // ASSERT
27344510Swollman
27444510Swollman
27544510Swollmanvoid InterfaceSupport_init() {
27644510Swollman#ifdef ASSERT
27744510Swollman  if (ScavengeALot || FullGCALot) {
27844510Swollman    srand(ScavengeALotInterval * FullGCALotInterval);
27944510Swollman  }
28044510Swollman#endif
28144510Swollman}
28244510Swollman