Path: blob/master/src/hotspot/share/runtime/interfaceSupport.cpp
40951 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "gc/shared/collectedHeap.hpp"26#include "gc/shared/collectedHeap.inline.hpp"27#include "logging/log.hpp"28#include "memory/resourceArea.hpp"29#include "memory/universe.hpp"30#include "runtime/atomic.hpp"31#include "runtime/frame.inline.hpp"32#include "runtime/handles.inline.hpp"33#include "runtime/init.hpp"34#include "runtime/interfaceSupport.inline.hpp"35#include "runtime/os.hpp"36#include "runtime/thread.inline.hpp"37#include "runtime/safepointVerifiers.hpp"38#include "runtime/stackFrameStream.inline.hpp"39#include "runtime/vframe.hpp"40#include "runtime/vmOperations.hpp"41#include "runtime/vmThread.hpp"42#include "utilities/preserveException.hpp"4344// Implementation of InterfaceSupport4546#ifdef ASSERT47VMEntryWrapper::VMEntryWrapper() {48if (VerifyLastFrame) {49InterfaceSupport::verify_last_frame();50}51}5253VMEntryWrapper::~VMEntryWrapper() {54InterfaceSupport::check_gc_alot();55if (WalkStackALot) {56InterfaceSupport::walk_stack();57}58if (DeoptimizeALot || DeoptimizeRandom) {59InterfaceSupport::deoptimizeAll();60}61if (ZombieALot) {62InterfaceSupport::zombieAll();63}64// do verification AFTER potential deoptimization65if (VerifyStack) {66InterfaceSupport::verify_stack();67}68}6970VMNativeEntryWrapper::VMNativeEntryWrapper() {71if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();72}7374VMNativeEntryWrapper::~VMNativeEntryWrapper() {75if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();76}7778unsigned int InterfaceSupport::_scavenge_alot_counter = 1;79unsigned int InterfaceSupport::_fullgc_alot_counter = 1;80int InterfaceSupport::_fullgc_alot_invocation = 0;8182void InterfaceSupport::gc_alot() {83Thread *thread = Thread::current();84if (!thread->is_Java_thread()) return; // Avoid concurrent calls85// Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC.86JavaThread *current_thread = thread->as_Java_thread();87if (current_thread->active_handles() == NULL) return;8889// Short-circuit any possible re-entrant gc-a-lot attempt90if (thread->skip_gcalot()) return;9192if (Threads::is_vm_complete()) {9394if (++_fullgc_alot_invocation < FullGCALotStart) {95return;96}9798// Use this line if you want to block at a specific point,99// e.g. one number_of_calls/scavenge/gc before you got into problems100if (FullGCALot) _fullgc_alot_counter--;101102// Check if we should force a full gc103if (_fullgc_alot_counter == 0) {104// Release dummy so objects are forced to move105if (!Universe::release_fullgc_alot_dummy()) {106warning("FullGCALot: Unable to release more dummies at bottom of heap");107}108HandleMark hm(thread);109Universe::heap()->collect(GCCause::_full_gc_alot);110unsigned int invocations = Universe::heap()->total_full_collections();111// Compute new interval112if (FullGCALotInterval > 1) {113_fullgc_alot_counter = 1+(unsigned int)((double)FullGCALotInterval*os::random()/(max_jint+1.0));114log_trace(gc)("Full gc no: %u\tInterval: %u", invocations, _fullgc_alot_counter);115} else {116_fullgc_alot_counter = 1;117}118// Print progress message119if (invocations % 100 == 0) {120log_trace(gc)("Full gc no: %u", invocations);121}122} else {123if (ScavengeALot) _scavenge_alot_counter--;124// Check if we should force a scavenge125if (_scavenge_alot_counter == 0) {126HandleMark hm(thread);127Universe::heap()->collect(GCCause::_scavenge_alot);128unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections();129// Compute new interval130if (ScavengeALotInterval > 1) {131_scavenge_alot_counter = 1+(unsigned int)((double)ScavengeALotInterval*os::random()/(max_jint+1.0));132log_trace(gc)("Scavenge no: %u\tInterval: %u", invocations, _scavenge_alot_counter);133} else {134_scavenge_alot_counter = 1;135}136// Print progress message137if (invocations % 1000 == 0) {138log_trace(gc)("Scavenge no: %u", invocations);139}140}141}142}143}144145146vframe* vframe_array[50];147int walk_stack_counter = 0;148149void InterfaceSupport::walk_stack_from(vframe* start_vf) {150// walk151int i = 0;152for (vframe* f = start_vf; f; f = f->sender() ) {153if (i < 50) vframe_array[i++] = f;154}155}156157158void InterfaceSupport::walk_stack() {159JavaThread* thread = JavaThread::current();160walk_stack_counter++;161if (!thread->has_last_Java_frame()) return;162ResourceMark rm(thread);163RegisterMap reg_map(thread);164walk_stack_from(thread->last_java_vframe(®_map));165}166167// invocation counter for InterfaceSupport::deoptimizeAll/zombieAll functions168int deoptimizeAllCounter = 0;169int zombieAllCounter = 0;170171void InterfaceSupport::zombieAll() {172// This method is called by all threads when a thread make173// transition to VM state (for example, runtime calls).174// Divide number of calls by number of threads to avoid175// dependence of ZombieAll events frequency on number of threads.176int value = zombieAllCounter / Threads::number_of_threads();177if (is_init_completed() && value > ZombieALotInterval) {178zombieAllCounter = 0;179VM_ZombieAll op;180VMThread::execute(&op);181}182zombieAllCounter++;183}184185void InterfaceSupport::deoptimizeAll() {186// This method is called by all threads when a thread make187// transition to VM state (for example, runtime calls).188// Divide number of calls by number of threads to avoid189// dependence of DeoptimizeAll events frequency on number of threads.190int value = deoptimizeAllCounter / Threads::number_of_threads();191if (is_init_completed()) {192if (DeoptimizeALot && value > DeoptimizeALotInterval) {193deoptimizeAllCounter = 0;194VM_DeoptimizeAll op;195VMThread::execute(&op);196} else if (DeoptimizeRandom && (value & 0x1F) == (os::random() & 0x1F)) {197VM_DeoptimizeAll op;198VMThread::execute(&op);199}200}201deoptimizeAllCounter++;202}203204205void InterfaceSupport::verify_stack() {206JavaThread* thread = JavaThread::current();207ResourceMark rm(thread);208// disabled because it throws warnings that oop maps should only be accessed209// in VM thread or during debugging210211if (!thread->has_pending_exception()) {212// verification does not work if there are pending exceptions213StackFrameStream sfs(thread, true /* update */, true /* process_frames */);214CodeBlob* cb = sfs.current()->cb();215// In case of exceptions we might not have a runtime_stub on216// top of stack, hence, all callee-saved registers are not going217// to be setup correctly, hence, we cannot do stack verify218if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return;219220for (; !sfs.is_done(); sfs.next()) {221sfs.current()->verify(sfs.register_map());222}223}224}225226227void InterfaceSupport::verify_last_frame() {228JavaThread* thread = JavaThread::current();229ResourceMark rm(thread);230RegisterMap reg_map(thread);231frame fr = thread->last_frame();232fr.verify(®_map);233}234235236#endif // ASSERT237238239void InterfaceSupport_init() {240#ifdef ASSERT241if (ScavengeALot || FullGCALot) {242srand(ScavengeALotInterval * FullGCALotInterval);243}244#endif245}246247248