Path: blob/master/src/hotspot/share/runtime/interfaceSupport.inline.hpp
40951 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(thread);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(_thread);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(thread);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;245public:246ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr) : ThreadStateTransition(thread), _pr(pr) {247assert(thread->thread_state() == _thread_in_vm, "coming from wrong thread state");248thread->check_possible_safepoint();249// Once we are blocked vm expects stack to be walkable250thread->frame_anchor()->make_walkable(thread);251OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate.252thread->set_thread_state(_thread_blocked);253}254~ThreadBlockInVMPreprocess() {255assert(_thread->thread_state() == _thread_blocked, "coming from wrong thread state");256// Change to transition state and ensure it is seen by the VM thread.257_thread->set_thread_state_fence(_thread_blocked_trans);258259if (SafepointMechanism::should_process(_thread)) {260_pr(_thread);261SafepointMechanism::process_if_requested(_thread);262}263264_thread->set_thread_state(_thread_in_vm);265}266};267268class InFlightMutexRelease {269private:270Mutex** _in_flight_mutex_addr;271public:272InFlightMutexRelease(Mutex** in_flight_mutex_addr) : _in_flight_mutex_addr(in_flight_mutex_addr) {}273void operator()(JavaThread* current) {274if (_in_flight_mutex_addr != NULL && *_in_flight_mutex_addr != NULL) {275(*_in_flight_mutex_addr)->release_for_safepoint();276*_in_flight_mutex_addr = NULL;277}278}279};280281// Parameter in_flight_mutex_addr is only used by class Mutex to avoid certain deadlock282// scenarios while making transitions that might block for a safepoint or handshake.283// It's the address of a pointer to the mutex we are trying to acquire. This will be used to284// access and release said mutex when transitioning back from blocked to vm (destructor) in285// case we need to stop for a safepoint or handshake.286class ThreadBlockInVM {287InFlightMutexRelease _ifmr;288ThreadBlockInVMPreprocess<InFlightMutexRelease> _tbivmpp;289public:290ThreadBlockInVM(JavaThread* thread, Mutex** in_flight_mutex_addr = NULL)291: _ifmr(in_flight_mutex_addr), _tbivmpp(thread, _ifmr) {}292};293294// Debug class instantiated in JRT_ENTRY macro.295// Can be used to verify properties on enter/exit of the VM.296297#ifdef ASSERT298class VMEntryWrapper {299public:300VMEntryWrapper();301~VMEntryWrapper();302};303304305class VMNativeEntryWrapper {306public:307VMNativeEntryWrapper();308~VMNativeEntryWrapper();309};310311#endif // ASSERT312313// LEAF routines do not lock, GC or throw exceptions314315// On macos/aarch64 we need to maintain the W^X state of the thread. So we316// take WXWrite on the enter to VM from the "outside" world, so the rest of JVM317// code can assume writing (but not executing) codecache is always possible318// without preliminary actions.319// JavaThread state should be changed only after taking WXWrite. The state320// change may trigger a safepoint, that would need WXWrite to do bookkeeping321// in the codecache.322323#define VM_LEAF_BASE(result_type, header) \324debug_only(NoHandleMark __hm;) \325MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, \326JavaThread::current())); \327os::verify_stack_alignment(); \328/* begin of body */329330#define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) \331debug_only(ResetNoHandleMark __rnhm;) \332HandleMarkCleaner __hm(thread); \333JavaThread* THREAD = thread; /* For exception macros. */ \334os::verify_stack_alignment(); \335/* begin of body */336337338// ENTRY routines may lock, GC and throw exceptions339340#define VM_ENTRY_BASE(result_type, header, thread) \341HandleMarkCleaner __hm(thread); \342JavaThread* THREAD = thread; /* For exception macros. */ \343os::verify_stack_alignment(); \344/* begin of body */345346347#define JRT_ENTRY(result_type, header) \348result_type header { \349MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \350ThreadInVMfromJava __tiv(current); \351VM_ENTRY_BASE(result_type, header, current) \352debug_only(VMEntryWrapper __vew;)353354// JRT_LEAF currently can be called from either _thread_in_Java or355// _thread_in_native mode.356//357// JRT_LEAF rules:358// A JRT_LEAF method may not interfere with safepointing by359// 1) acquiring or blocking on a Mutex or JavaLock - checked360// 2) allocating heap memory - checked361// 3) executing a VM operation - checked362// 4) executing a system call (including malloc) that could block or grab a lock363// 5) invoking GC364// 6) reaching a safepoint365// 7) running too long366// Nor may any method it calls.367368#define JRT_LEAF(result_type, header) \369result_type header { \370VM_LEAF_BASE(result_type, header) \371debug_only(NoSafepointVerifier __nsv;)372373374#define JRT_ENTRY_NO_ASYNC(result_type, header) \375result_type header { \376MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \377ThreadInVMfromJava __tiv(current, false /* check asyncs */); \378VM_ENTRY_BASE(result_type, header, current) \379debug_only(VMEntryWrapper __vew;)380381// Same as JRT Entry but allows for return value after the safepoint382// to get back into Java from the VM383#define JRT_BLOCK_ENTRY(result_type, header) \384result_type header { \385MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \386HandleMarkCleaner __hm(current);387388#define JRT_BLOCK \389{ \390ThreadInVMfromJava __tiv(current); \391JavaThread* THREAD = current; /* For exception macros. */ \392debug_only(VMEntryWrapper __vew;)393394#define JRT_BLOCK_NO_ASYNC \395{ \396ThreadInVMfromJava __tiv(current, false /* check asyncs */); \397JavaThread* THREAD = current; /* For exception macros. */ \398debug_only(VMEntryWrapper __vew;)399400#define JRT_BLOCK_END }401402#define JRT_END }403404// Definitions for JNI405406#define JNI_ENTRY(result_type, header) \407JNI_ENTRY_NO_PRESERVE(result_type, header) \408WeakPreserveExceptionMark __wem(thread);409410#define JNI_ENTRY_NO_PRESERVE(result_type, header) \411extern "C" { \412result_type JNICALL header { \413JavaThread* thread=JavaThread::thread_from_jni_environment(env); \414assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \415MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \416ThreadInVMfromNative __tiv(thread); \417debug_only(VMNativeEntryWrapper __vew;) \418VM_ENTRY_BASE(result_type, header, thread)419420421#define JNI_LEAF(result_type, header) \422extern "C" { \423result_type JNICALL header { \424JavaThread* thread=JavaThread::thread_from_jni_environment(env); \425assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \426VM_LEAF_BASE(result_type, header)427428429// Close the routine and the extern "C"430#define JNI_END } }431432433434// Definitions for JVM435436#define JVM_ENTRY(result_type, header) \437extern "C" { \438result_type JNICALL header { \439JavaThread* thread=JavaThread::thread_from_jni_environment(env); \440MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \441ThreadInVMfromNative __tiv(thread); \442debug_only(VMNativeEntryWrapper __vew;) \443VM_ENTRY_BASE(result_type, header, thread)444445446#define JVM_ENTRY_NO_ENV(result_type, header) \447extern "C" { \448result_type JNICALL header { \449JavaThread* thread = JavaThread::current(); \450MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \451ThreadInVMfromNative __tiv(thread); \452debug_only(VMNativeEntryWrapper __vew;) \453VM_ENTRY_BASE(result_type, header, thread)454455456#define JVM_LEAF(result_type, header) \457extern "C" { \458result_type JNICALL header { \459VM_Exit::block_if_vm_exited(); \460VM_LEAF_BASE(result_type, header)461462463#define JVM_ENTRY_FROM_LEAF(env, result_type, header) \464{ { \465JavaThread* thread=JavaThread::thread_from_jni_environment(env); \466ThreadInVMfromNative __tiv(thread); \467debug_only(VMNativeEntryWrapper __vew;) \468VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread)469470471#define JVM_END } }472473#endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP474475476