interfaceSupport.cpp revision 6646:b596a1063e90
1251881Speter/* 2251881Speter * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3251881Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4251881Speter * 5251881Speter * This code is free software; you can redistribute it and/or modify it 6251881Speter * under the terms of the GNU General Public License version 2 only, as 7251881Speter * published by the Free Software Foundation. 8251881Speter * 9251881Speter * This code is distributed in the hope that it will be useful, but WITHOUT 10251881Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11251881Speter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12251881Speter * version 2 for more details (a copy is included in the LICENSE file that 13251881Speter * accompanied this code). 14251881Speter * 15251881Speter * You should have received a copy of the GNU General Public License version 16251881Speter * 2 along with this work; if not, write to the Free Software Foundation, 17251881Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18251881Speter * 19251881Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20251881Speter * or visit www.oracle.com if you need additional information or have any 21251881Speter * questions. 22251881Speter * 23251881Speter */ 24251881Speter 25251881Speter#include "precompiled.hpp" 26251881Speter#include "gc_implementation/shared/markSweep.hpp" 27251881Speter#include "gc_interface/collectedHeap.hpp" 28251881Speter#include "gc_interface/collectedHeap.inline.hpp" 29251881Speter#include "memory/genCollectedHeap.hpp" 30251881Speter#include "memory/resourceArea.hpp" 31251881Speter#include "runtime/atomic.inline.hpp" 32251881Speter#include "runtime/init.hpp" 33251881Speter#include "runtime/interfaceSupport.hpp" 34251881Speter#include "runtime/orderAccess.inline.hpp" 35251881Speter#include "runtime/threadLocalStorage.hpp" 36251881Speter#include "runtime/vframe.hpp" 37251881Speter#include "utilities/preserveException.hpp" 38251881Speter 39251881SpeterPRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC 40251881Speter 41251881Speter// Implementation of InterfaceSupport 42251881Speter 43251881Speter#ifdef ASSERT 44251881Speter 45251881Speterlong InterfaceSupport::_number_of_calls = 0; 46251881Speterlong InterfaceSupport::_scavenge_alot_counter = 1; 47251881Speterlong InterfaceSupport::_fullgc_alot_counter = 1; 48251881Speterlong InterfaceSupport::_fullgc_alot_invocation = 0; 49251881Speter 50251881SpeterHistogram* RuntimeHistogram; 51251881Speter 52251881SpeterRuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) { 53251881Speter static volatile jint RuntimeHistogram_lock = 0; 54251881Speter _name = elementName; 55251881Speter uintx count = 0; 56251881Speter 57251881Speter while (Atomic::cmpxchg(1, &RuntimeHistogram_lock, 0) != 0) { 58251881Speter while (OrderAccess::load_acquire(&RuntimeHistogram_lock) != 0) { 59251881Speter count +=1; 60251881Speter if ( (WarnOnStalledSpinLock > 0) 61251881Speter && (count % WarnOnStalledSpinLock == 0)) { 62251881Speter warning("RuntimeHistogram_lock seems to be stalled"); 63251881Speter } 64251881Speter } 65251881Speter } 66251881Speter 67251881Speter if (RuntimeHistogram == NULL) { 68251881Speter RuntimeHistogram = new Histogram("VM Runtime Call Counts",200); 69251881Speter } 70251881Speter 71251881Speter RuntimeHistogram->add_element(this); 72251881Speter Atomic::dec(&RuntimeHistogram_lock); 73251881Speter} 74251881Speter 75251881Spetervoid InterfaceSupport::trace(const char* result_type, const char* header) { 76251881Speter tty->print_cr("%6d %s", _number_of_calls, header); 77251881Speter} 78251881Speter 79251881Spetervoid InterfaceSupport::gc_alot() { 80251881Speter Thread *thread = Thread::current(); 81251881Speter if (!thread->is_Java_thread()) return; // Avoid concurrent calls 82251881Speter // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC. 83251881Speter JavaThread *current_thread = (JavaThread *)thread; 84251881Speter if (current_thread->active_handles() == NULL) return; 85251881Speter 86251881Speter // Short-circuit any possible re-entrant gc-a-lot attempt 87251881Speter if (thread->skip_gcalot()) return; 88251881Speter 89251881Speter if (is_init_completed()) { 90251881Speter 91251881Speter if (++_fullgc_alot_invocation < FullGCALotStart) { 92251881Speter return; 93251881Speter } 94251881Speter 95251881Speter // Use this line if you want to block at a specific point, 96251881Speter // e.g. one number_of_calls/scavenge/gc before you got into problems 97251881Speter if (FullGCALot) _fullgc_alot_counter--; 98251881Speter 99251881Speter // Check if we should force a full gc 100251881Speter if (_fullgc_alot_counter == 0) { 101251881Speter // Release dummy so objects are forced to move 102251881Speter if (!Universe::release_fullgc_alot_dummy()) { 103251881Speter warning("FullGCALot: Unable to release more dummies at bottom of heap"); 104251881Speter } 105251881Speter HandleMark hm(thread); 106251881Speter Universe::heap()->collect(GCCause::_full_gc_alot); 107251881Speter unsigned int invocations = Universe::heap()->total_full_collections(); 108251881Speter // Compute new interval 109251881Speter if (FullGCALotInterval > 1) { 110251881Speter _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0)); 111251881Speter if (PrintGCDetails && Verbose) { 112251881Speter tty->print_cr("Full gc no: %u\tInterval: %d", invocations, 113251881Speter _fullgc_alot_counter); 114251881Speter } 115251881Speter } else { 116251881Speter _fullgc_alot_counter = 1; 117251881Speter } 118251881Speter // Print progress message 119251881Speter if (invocations % 100 == 0) { 120251881Speter if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations); 121251881Speter } 122251881Speter } else { 123251881Speter if (ScavengeALot) _scavenge_alot_counter--; 124251881Speter // Check if we should force a scavenge 125251881Speter if (_scavenge_alot_counter == 0) { 126251881Speter HandleMark hm(thread); 127251881Speter Universe::heap()->collect(GCCause::_scavenge_alot); 128251881Speter unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections(); 129251881Speter // Compute new interval 130251881Speter if (ScavengeALotInterval > 1) { 131251881Speter _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0)); 132251881Speter if (PrintGCDetails && Verbose) { 133251881Speter tty->print_cr("Scavenge no: %u\tInterval: %d", invocations, 134251881Speter _scavenge_alot_counter); 135251881Speter } 136251881Speter } else { 137251881Speter _scavenge_alot_counter = 1; 138251881Speter } 139251881Speter // Print progress message 140251881Speter if (invocations % 1000 == 0) { 141251881Speter if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations); 142251881Speter } 143251881Speter } 144251881Speter } 145251881Speter } 146251881Speter} 147251881Speter 148251881Speter 149251881Spetervframe* vframe_array[50]; 150251881Speterint walk_stack_counter = 0; 151251881Speter 152251881Spetervoid InterfaceSupport::walk_stack_from(vframe* start_vf) { 153251881Speter // walk 154251881Speter int i = 0; 155251881Speter for (vframe* f = start_vf; f; f = f->sender() ) { 156251881Speter if (i < 50) vframe_array[i++] = f; 157251881Speter } 158251881Speter} 159251881Speter 160251881Speter 161251881Spetervoid InterfaceSupport::walk_stack() { 162251881Speter JavaThread* thread = JavaThread::current(); 163251881Speter walk_stack_counter++; 164251881Speter if (!thread->has_last_Java_frame()) return; 165251881Speter ResourceMark rm(thread); 166251881Speter RegisterMap reg_map(thread); 167251881Speter walk_stack_from(thread->last_java_vframe(®_map)); 168251881Speter} 169251881Speter 170251881Speter 171251881Speter# ifdef ENABLE_ZAP_DEAD_LOCALS 172251881Speter 173251881Speterstatic int zap_traversals = 0; 174251881Speter 175251881Spetervoid InterfaceSupport::zap_dead_locals_old() { 176251881Speter JavaThread* thread = JavaThread::current(); 177251881Speter if (zap_traversals == -1) // edit constant for debugging 178251881Speter warning("I am here"); 179251881Speter int zap_frame_count = 0; // count frames to help debugging 180251881Speter for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) { 181251881Speter sfs.current()->zap_dead_locals(thread, sfs.register_map()); 182251881Speter ++zap_frame_count; 183251881Speter } 184251881Speter ++zap_traversals; 185251881Speter} 186251881Speter 187251881Speter# endif 188251881Speter 189251881Speter 190251881Speterint deoptimizeAllCounter = 0; 191251881Speterint zombieAllCounter = 0; 192251881Speter 193251881Speter 194251881Spetervoid InterfaceSupport::zombieAll() { 195251881Speter if (is_init_completed() && zombieAllCounter > ZombieALotInterval) { 196251881Speter zombieAllCounter = 0; 197251881Speter VM_ZombieAll op; 198251881Speter VMThread::execute(&op); 199251881Speter } else { 200251881Speter zombieAllCounter++; 201251881Speter } 202251881Speter} 203251881Speter 204251881Spetervoid InterfaceSupport::unlinkSymbols() { 205251881Speter VM_UnlinkSymbols op; 206251881Speter VMThread::execute(&op); 207251881Speter} 208251881Speter 209251881Spetervoid InterfaceSupport::deoptimizeAll() { 210251881Speter if (is_init_completed() ) { 211251881Speter if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) { 212251881Speter deoptimizeAllCounter = 0; 213251881Speter VM_DeoptimizeAll op; 214251881Speter VMThread::execute(&op); 215251881Speter } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) { 216251881Speter VM_DeoptimizeAll op; 217251881Speter VMThread::execute(&op); 218251881Speter } 219251881Speter } 220251881Speter deoptimizeAllCounter++; 221251881Speter} 222251881Speter 223251881Speter 224251881Spetervoid InterfaceSupport::stress_derived_pointers() { 225251881Speter#ifdef COMPILER2 226251881Speter JavaThread *thread = JavaThread::current(); 227251881Speter if (!is_init_completed()) return; 228251881Speter ResourceMark rm(thread); 229251881Speter bool found = false; 230251881Speter for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) { 231251881Speter CodeBlob* cb = sfs.current()->cb(); 232251881Speter if (cb != NULL && cb->oop_maps() ) { 233251881Speter // Find oopmap for current method 234251881Speter OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc()); 235251881Speter assert(map != NULL, "no oopmap found for pc"); 236251881Speter found = map->has_derived_pointer(); 237251881Speter } 238251881Speter } 239251881Speter if (found) { 240251881Speter // $$$ Not sure what to do here. 241251881Speter /* 242251881Speter Scavenge::invoke(0); 243251881Speter */ 244251881Speter } 245251881Speter#endif 246251881Speter} 247251881Speter 248251881Speter 249251881Spetervoid InterfaceSupport::verify_stack() { 250251881Speter JavaThread* thread = JavaThread::current(); 251251881Speter ResourceMark rm(thread); 252251881Speter // disabled because it throws warnings that oop maps should only be accessed 253251881Speter // in VM thread or during debugging 254251881Speter 255251881Speter if (!thread->has_pending_exception()) { 256251881Speter // verification does not work if there are pending exceptions 257251881Speter StackFrameStream sfs(thread); 258251881Speter CodeBlob* cb = sfs.current()->cb(); 259251881Speter // In case of exceptions we might not have a runtime_stub on 260251881Speter // top of stack, hence, all callee-saved registers are not going 261251881Speter // to be setup correctly, hence, we cannot do stack verify 262251881Speter if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return; 263251881Speter 264251881Speter for (; !sfs.is_done(); sfs.next()) { 265251881Speter sfs.current()->verify(sfs.register_map()); 266251881Speter } 267251881Speter } 268251881Speter} 269251881Speter 270251881Speter 271251881Spetervoid InterfaceSupport::verify_last_frame() { 272251881Speter JavaThread* thread = JavaThread::current(); 273251881Speter ResourceMark rm(thread); 274251881Speter RegisterMap reg_map(thread); 275251881Speter frame fr = thread->last_frame(); 276251881Speter fr.verify(®_map); 277251881Speter} 278251881Speter 279251881Speter 280251881Speter#endif // ASSERT 281251881Speter 282251881Speter 283251881Spetervoid InterfaceSupport_init() { 284251881Speter#ifdef ASSERT 285251881Speter if (ScavengeALot || FullGCALot) { 286251881Speter srand(ScavengeALotInterval * FullGCALotInterval); 287251881Speter } 288251881Speter#endif 289251881Speter} 290251881Speter