Path: blob/master/src/hotspot/share/runtime/interfaceSupport.inline.hpp
64440 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2021, Azul Systems, 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 it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 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 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#ifndef SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP26#define SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP2728// No interfaceSupport.hpp2930#include "gc/shared/gc_globals.hpp"31#include "runtime/handles.inline.hpp"32#include "runtime/mutexLocker.hpp"33#include "runtime/orderAccess.hpp"34#include "runtime/os.hpp"35#include "runtime/safepointMechanism.inline.hpp"36#include "runtime/safepointVerifiers.hpp"37#include "runtime/thread.hpp"38#include "runtime/threadWXSetters.inline.hpp"39#include "runtime/vmOperations.hpp"40#include "utilities/globalDefinitions.hpp"41#include "utilities/macros.hpp"42#include "utilities/preserveException.hpp"4344// Wrapper for all entry points to the virtual machine.4546// InterfaceSupport provides functionality used by the VM_LEAF_BASE and47// VM_ENTRY_BASE macros. These macros are used to guard entry points into48// the VM and perform checks upon leave of the VM.495051class InterfaceSupport: AllStatic {52# ifdef ASSERT53public:54static unsigned int _scavenge_alot_counter;55static unsigned int _fullgc_alot_counter;56static int _fullgc_alot_invocation;5758// Helper methods used to implement +ScavengeALot and +FullGCALot59static void check_gc_alot() { if (ScavengeALot || FullGCALot) gc_alot(); }60static void gc_alot();6162static void walk_stack_from(vframe* start_vf);63static void walk_stack();6465static void zombieAll();66static void deoptimizeAll();67static void verify_stack();68static void verify_last_frame();69# endif70};717273// Basic class for all thread transition classes.7475class ThreadStateTransition : public StackObj {76protected:77JavaThread* _thread;78public:79ThreadStateTransition(JavaThread *thread) {80_thread = thread;81assert(thread != NULL, "must be active Java thread");82assert(thread == Thread::current(), "must be current thread");83}8485// Change threadstate in a manner, so safepoint can detect changes.86// Time-critical: called on exit from every runtime routine87static inline void transition(JavaThread *thread, JavaThreadState from, JavaThreadState to) {88assert(from != _thread_in_Java, "use transition_from_java");89assert(from != _thread_in_native, "use transition_from_native");90assert((from & 1) == 0 && (to & 1) == 0, "odd numbers are transitions states");91assert(thread->thread_state() == from, "coming from wrong thread state");9293// Check NoSafepointVerifier94// This also clears unhandled oops if CheckUnhandledOops is used.95thread->check_possible_safepoint();9697// Change to transition state and ensure it is seen by the VM thread.98thread->set_thread_state_fence((JavaThreadState)(from + 1));99100SafepointMechanism::process_if_requested(thread);101thread->set_thread_state(to);102}103104// Same as above, but assumes from = _thread_in_Java. This is simpler, since we105// never block on entry to the VM. This will break the code, since e.g. preserve arguments106// have not been setup.107static inline void transition_from_java(JavaThread *thread, JavaThreadState to) {108assert(thread->thread_state() == _thread_in_Java, "coming from wrong thread state");109thread->set_thread_state(to);110}111112static inline void transition_from_native(JavaThread *thread, JavaThreadState to) {113assert((to & 1) == 0, "odd numbers are transitions states");114assert(thread->thread_state() == _thread_in_native, "coming from wrong thread state");115assert(!thread->has_last_Java_frame() || thread->frame_anchor()->walkable(), "Unwalkable stack in native->vm transition");116117// Change to transition state and ensure it is seen by the VM thread.118thread->set_thread_state_fence(_thread_in_native_trans);119120// We never install asynchronous exceptions when coming (back) in121// to the runtime from native code because the runtime is not set122// up to handle exceptions floating around at arbitrary points.123SafepointMechanism::process_if_requested_with_exit_check(thread, false /* check asyncs */);124thread->set_thread_state(to);125}126127protected:128void trans(JavaThreadState from, JavaThreadState to) { transition(_thread, from, to); }129void trans_from_java(JavaThreadState to) { transition_from_java(_thread, to); }130void trans_from_native(JavaThreadState to) { transition_from_native(_thread, to); }131};132133class ThreadInVMForHandshake : public ThreadStateTransition {134const JavaThreadState _original_state;135public:136ThreadInVMForHandshake(JavaThread* thread) : ThreadStateTransition(thread),137_original_state(thread->thread_state()) {138139if (thread->has_last_Java_frame()) {140thread->frame_anchor()->make_walkable();141}142143thread->set_thread_state(_thread_in_vm);144145// Threads shouldn't block if they are in the middle of printing, but...146ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id());147}148149~ThreadInVMForHandshake() {150assert(_thread->thread_state() == _thread_in_vm, "should only call when leaving VM after handshake");151_thread->set_thread_state(_original_state);152}153154};155156class ThreadInVMfromJava : public ThreadStateTransition {157bool _check_asyncs;158public:159ThreadInVMfromJava(JavaThread* thread, bool check_asyncs = true) : ThreadStateTransition(thread), _check_asyncs(check_asyncs) {160trans_from_java(_thread_in_vm);161}162~ThreadInVMfromJava() {163if (_thread->stack_overflow_state()->stack_yellow_reserved_zone_disabled()) {164_thread->stack_overflow_state()->enable_stack_yellow_reserved_zone();165}166trans(_thread_in_vm, _thread_in_Java);167// We prevent asynchronous exceptions from being installed on return to Java in situations168// where we can't tolerate them. See bugs: 4324348, 4854693, 4998314, 5040492, 5050705.169if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(_check_asyncs);170}171};172173174class ThreadInVMfromUnknown {175JavaThread* _thread;176public:177ThreadInVMfromUnknown() : _thread(NULL) {178Thread* t = Thread::current();179if (t->is_Java_thread()) {180JavaThread* t2 = t->as_Java_thread();181if (t2->thread_state() == _thread_in_native) {182_thread = t2;183ThreadStateTransition::transition_from_native(t2, _thread_in_vm);184// Used to have a HandleMarkCleaner but that is dangerous as185// it could free a handle in our (indirect, nested) caller.186// We expect any handles will be short lived and figure we187// don't need an actual HandleMark.188}189}190}191~ThreadInVMfromUnknown() {192if (_thread) {193ThreadStateTransition::transition(_thread, _thread_in_vm, _thread_in_native);194}195}196};197198199class ThreadInVMfromNative : public ThreadStateTransition {200ResetNoHandleMark __rnhm;201public:202ThreadInVMfromNative(JavaThread* thread) : ThreadStateTransition(thread) {203trans_from_native(_thread_in_vm);204}205~ThreadInVMfromNative() {206assert(_thread->thread_state() == _thread_in_vm, "coming from wrong thread state");207// We cannot assert !_thread->owns_locks() since we have valid cases where208// we call known native code using this wrapper holding locks.209_thread->check_possible_safepoint();210// Once we are in native vm expects stack to be walkable211_thread->frame_anchor()->make_walkable();212OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate.213_thread->set_thread_state(_thread_in_native);214}215};216217218class ThreadToNativeFromVM : public ThreadStateTransition {219public:220ThreadToNativeFromVM(JavaThread *thread) : ThreadStateTransition(thread) {221// We are leaving the VM at this point and going directly to native code.222// Block, if we are in the middle of a safepoint synchronization.223assert(!thread->owns_locks(), "must release all locks when leaving VM");224thread->frame_anchor()->make_walkable();225trans(_thread_in_vm, _thread_in_native);226// Check for pending. async. exceptions or suspends.227if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(false);228}229230~ThreadToNativeFromVM() {231trans_from_native(_thread_in_vm);232assert(!_thread->is_pending_jni_exception_check(), "Pending JNI Exception Check");233// We don't need to clear_walkable because it will happen automagically when we return to java234}235};236237// Perform a transition to _thread_blocked and take a call-back to be executed before238// SafepointMechanism::process_if_requested when returning to the VM. This allows us239// to perform an "undo" action if we might block processing a safepoint/handshake operation240// (such as thread suspension).241template <typename PRE_PROC>242class ThreadBlockInVMPreprocess : public ThreadStateTransition {243private:244PRE_PROC& _pr;245bool _allow_suspend;246public:247ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr, bool allow_suspend = true)248: ThreadStateTransition(thread), _pr(pr), _allow_suspend(allow_suspend) {249assert(thread->thread_state() == _thread_in_vm, "coming from wrong thread state");250thread->check_possible_safepoint();251// Once we are blocked vm expects stack to be walkable252thread->frame_anchor()->make_walkable();253OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate.254thread->set_thread_state(_thread_blocked);255}256~ThreadBlockInVMPreprocess() {257assert(_thread->thread_state() == _thread_blocked, "coming from wrong thread state");258// Change to transition state and ensure it is seen by the VM thread.259_thread->set_thread_state_fence(_thread_blocked_trans);260261if (SafepointMechanism::should_process(_thread, _allow_suspend)) {262_pr(_thread);263SafepointMechanism::process_if_requested(_thread, _allow_suspend);264}265266_thread->set_thread_state(_thread_in_vm);267}268};269270class InFlightMutexRelease {271private:272Mutex** _in_flight_mutex_addr;273public:274InFlightMutexRelease(Mutex** in_flight_mutex_addr) : _in_flight_mutex_addr(in_flight_mutex_addr) {}275void operator()(JavaThread* current) {276if (_in_flight_mutex_addr != NULL && *_in_flight_mutex_addr != NULL) {277(*_in_flight_mutex_addr)->release_for_safepoint();278*_in_flight_mutex_addr = NULL;279}280}281};282283// Parameter in_flight_mutex_addr is only used by class Mutex to avoid certain deadlock284// scenarios while making transitions that might block for a safepoint or handshake.285// It's the address of a pointer to the mutex we are trying to acquire. This will be used to286// access and release said mutex when transitioning back from blocked to vm (destructor) in287// case we need to stop for a safepoint or handshake.288class ThreadBlockInVM {289InFlightMutexRelease _ifmr;290ThreadBlockInVMPreprocess<InFlightMutexRelease> _tbivmpp;291public:292ThreadBlockInVM(JavaThread* thread, Mutex** in_flight_mutex_addr = NULL)293: _ifmr(in_flight_mutex_addr), _tbivmpp(thread, _ifmr, /* allow_suspend= */ false) {}294};295296// Debug class instantiated in JRT_ENTRY macro.297// Can be used to verify properties on enter/exit of the VM.298299#ifdef ASSERT300class VMEntryWrapper {301public:302VMEntryWrapper();303~VMEntryWrapper();304};305306307class VMNativeEntryWrapper {308public:309VMNativeEntryWrapper();310~VMNativeEntryWrapper();311};312313#endif // ASSERT314315// LEAF routines do not lock, GC or throw exceptions316317// On macos/aarch64 we need to maintain the W^X state of the thread. So we318// take WXWrite on the enter to VM from the "outside" world, so the rest of JVM319// code can assume writing (but not executing) codecache is always possible320// without preliminary actions.321// JavaThread state should be changed only after taking WXWrite. The state322// change may trigger a safepoint, that would need WXWrite to do bookkeeping323// in the codecache.324325#define VM_LEAF_BASE(result_type, header) \326debug_only(NoHandleMark __hm;) \327MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, \328JavaThread::current())); \329os::verify_stack_alignment(); \330/* begin of body */331332#define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) \333debug_only(ResetNoHandleMark __rnhm;) \334HandleMarkCleaner __hm(thread); \335JavaThread* THREAD = thread; /* For exception macros. */ \336os::verify_stack_alignment(); \337/* begin of body */338339340// ENTRY routines may lock, GC and throw exceptions341342#define VM_ENTRY_BASE(result_type, header, thread) \343HandleMarkCleaner __hm(thread); \344JavaThread* THREAD = thread; /* For exception macros. */ \345os::verify_stack_alignment(); \346/* begin of body */347348349#define JRT_ENTRY(result_type, header) \350result_type header { \351MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \352ThreadInVMfromJava __tiv(current); \353VM_ENTRY_BASE(result_type, header, current) \354debug_only(VMEntryWrapper __vew;)355356// JRT_LEAF currently can be called from either _thread_in_Java or357// _thread_in_native mode.358//359// JRT_LEAF rules:360// A JRT_LEAF method may not interfere with safepointing by361// 1) acquiring or blocking on a Mutex or JavaLock - checked362// 2) allocating heap memory - checked363// 3) executing a VM operation - checked364// 4) executing a system call (including malloc) that could block or grab a lock365// 5) invoking GC366// 6) reaching a safepoint367// 7) running too long368// Nor may any method it calls.369370#define JRT_LEAF(result_type, header) \371result_type header { \372VM_LEAF_BASE(result_type, header) \373debug_only(NoSafepointVerifier __nsv;)374375376#define JRT_ENTRY_NO_ASYNC(result_type, header) \377result_type header { \378MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \379ThreadInVMfromJava __tiv(current, false /* check asyncs */); \380VM_ENTRY_BASE(result_type, header, current) \381debug_only(VMEntryWrapper __vew;)382383// Same as JRT Entry but allows for return value after the safepoint384// to get back into Java from the VM385#define JRT_BLOCK_ENTRY(result_type, header) \386result_type header { \387MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \388HandleMarkCleaner __hm(current);389390#define JRT_BLOCK \391{ \392ThreadInVMfromJava __tiv(current); \393JavaThread* THREAD = current; /* For exception macros. */ \394debug_only(VMEntryWrapper __vew;)395396#define JRT_BLOCK_NO_ASYNC \397{ \398ThreadInVMfromJava __tiv(current, false /* check asyncs */); \399JavaThread* THREAD = current; /* For exception macros. */ \400debug_only(VMEntryWrapper __vew;)401402#define JRT_BLOCK_END }403404#define JRT_END }405406// Definitions for JNI407408#define JNI_ENTRY(result_type, header) \409JNI_ENTRY_NO_PRESERVE(result_type, header) \410WeakPreserveExceptionMark __wem(thread);411412#define JNI_ENTRY_NO_PRESERVE(result_type, header) \413extern "C" { \414result_type JNICALL header { \415JavaThread* thread=JavaThread::thread_from_jni_environment(env); \416assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \417MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \418ThreadInVMfromNative __tiv(thread); \419debug_only(VMNativeEntryWrapper __vew;) \420VM_ENTRY_BASE(result_type, header, thread)421422423#define JNI_LEAF(result_type, header) \424extern "C" { \425result_type JNICALL header { \426JavaThread* thread=JavaThread::thread_from_jni_environment(env); \427assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \428VM_LEAF_BASE(result_type, header)429430431// Close the routine and the extern "C"432#define JNI_END } }433434435436// Definitions for JVM437438#define JVM_ENTRY(result_type, header) \439extern "C" { \440result_type JNICALL header { \441JavaThread* thread=JavaThread::thread_from_jni_environment(env); \442MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \443ThreadInVMfromNative __tiv(thread); \444debug_only(VMNativeEntryWrapper __vew;) \445VM_ENTRY_BASE(result_type, header, thread)446447448#define JVM_ENTRY_NO_ENV(result_type, header) \449extern "C" { \450result_type JNICALL header { \451JavaThread* thread = JavaThread::current(); \452MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \453ThreadInVMfromNative __tiv(thread); \454debug_only(VMNativeEntryWrapper __vew;) \455VM_ENTRY_BASE(result_type, header, thread)456457458#define JVM_LEAF(result_type, header) \459extern "C" { \460result_type JNICALL header { \461VM_Exit::block_if_vm_exited(); \462VM_LEAF_BASE(result_type, header)463464465#define JVM_ENTRY_FROM_LEAF(env, result_type, header) \466{ { \467JavaThread* thread=JavaThread::thread_from_jni_environment(env); \468ThreadInVMfromNative __tiv(thread); \469debug_only(VMNativeEntryWrapper __vew;) \470VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread)471472473#define JVM_END } }474475#endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP476477478