8273143: Transition to _thread_in_vm when handling a polling page exception
Reviewed-by: rehn, dcubed, coleenp, rrich
This commit is contained in:
parent
9209e6d6ae
commit
237f861e82
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -99,6 +99,9 @@
|
|||||||
#undef PREFETCH_OPCCODE
|
#undef PREFETCH_OPCCODE
|
||||||
#define PREFETCH_OPCCODE
|
#define PREFETCH_OPCCODE
|
||||||
|
|
||||||
|
JRT_ENTRY(void, at_safepoint(JavaThread* current)) {}
|
||||||
|
JRT_END
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Interpreter safepoint: it is expected that the interpreter will have no live
|
Interpreter safepoint: it is expected that the interpreter will have no live
|
||||||
handles of its own creation live at an interpreter safepoint. Therefore we
|
handles of its own creation live at an interpreter safepoint. Therefore we
|
||||||
@ -107,12 +110,10 @@
|
|||||||
There really shouldn't be any handles remaining to trash but this is cheap
|
There really shouldn't be any handles remaining to trash but this is cheap
|
||||||
in relation to a safepoint.
|
in relation to a safepoint.
|
||||||
*/
|
*/
|
||||||
#define RETURN_SAFEPOINT \
|
#define RETURN_SAFEPOINT \
|
||||||
if (SafepointMechanism::should_process(THREAD)) { \
|
if (SafepointMechanism::should_process(THREAD)) { \
|
||||||
HandleMarkCleaner __hmc(THREAD); \
|
CALL_VM(at_safepoint(THREAD), handle_exception); \
|
||||||
CALL_VM(SafepointMechanism::process_if_requested_with_exit_check(THREAD, true /* check asyncs */), \
|
}
|
||||||
handle_exception); \
|
|
||||||
} \
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VM_JAVA_ERROR - Macro for throwing a java exception from
|
* VM_JAVA_ERROR - Macro for throwing a java exception from
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -488,10 +488,11 @@ void HandshakeState::remove_op(HandshakeOperation* op) {
|
|||||||
bool HandshakeState::process_by_self(bool allow_suspend) {
|
bool HandshakeState::process_by_self(bool allow_suspend) {
|
||||||
assert(Thread::current() == _handshakee, "should call from _handshakee");
|
assert(Thread::current() == _handshakee, "should call from _handshakee");
|
||||||
assert(!_handshakee->is_terminated(), "should not be a terminated thread");
|
assert(!_handshakee->is_terminated(), "should not be a terminated thread");
|
||||||
assert(_handshakee->thread_state() != _thread_blocked, "should not be in a blocked state");
|
|
||||||
assert(_handshakee->thread_state() != _thread_in_native, "should not be in native");
|
|
||||||
|
|
||||||
ThreadInVMForHandshake tivm(_handshakee);
|
_handshakee->frame_anchor()->make_walkable(_handshakee);
|
||||||
|
// Threads shouldn't block if they are in the middle of printing, but...
|
||||||
|
ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id());
|
||||||
|
|
||||||
// Handshakes cannot safely safepoint.
|
// Handshakes cannot safely safepoint.
|
||||||
// The exception to this rule is the asynchronous suspension handshake.
|
// The exception to this rule is the asynchronous suspension handshake.
|
||||||
// It by-passes the NSV by manually doing the transition.
|
// It by-passes the NSV by manually doing the transition.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
|
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -120,29 +120,6 @@ class ThreadStateTransition : public StackObj {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadInVMForHandshake : public ThreadStateTransition {
|
|
||||||
const JavaThreadState _original_state;
|
|
||||||
public:
|
|
||||||
ThreadInVMForHandshake(JavaThread* thread) : ThreadStateTransition(thread),
|
|
||||||
_original_state(thread->thread_state()) {
|
|
||||||
|
|
||||||
if (thread->has_last_Java_frame()) {
|
|
||||||
thread->frame_anchor()->make_walkable(thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread->set_thread_state(_thread_in_vm);
|
|
||||||
|
|
||||||
// Threads shouldn't block if they are in the middle of printing, but...
|
|
||||||
ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id());
|
|
||||||
}
|
|
||||||
|
|
||||||
~ThreadInVMForHandshake() {
|
|
||||||
assert(_thread->thread_state() == _thread_in_vm, "should only call when leaving VM after handshake");
|
|
||||||
_thread->set_thread_state(_original_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class ThreadInVMfromJava : public ThreadStateTransition {
|
class ThreadInVMfromJava : public ThreadStateTransition {
|
||||||
bool _check_asyncs;
|
bool _check_asyncs;
|
||||||
public:
|
public:
|
||||||
@ -222,7 +199,7 @@ class ThreadBlockInVMPreprocess : public ThreadStateTransition {
|
|||||||
PRE_PROC& _pr;
|
PRE_PROC& _pr;
|
||||||
bool _allow_suspend;
|
bool _allow_suspend;
|
||||||
public:
|
public:
|
||||||
ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr = emptyOp, bool allow_suspend = false)
|
ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr, bool allow_suspend = false)
|
||||||
: ThreadStateTransition(thread), _pr(pr), _allow_suspend(allow_suspend) {
|
: ThreadStateTransition(thread), _pr(pr), _allow_suspend(allow_suspend) {
|
||||||
transition_from_vm(thread, _thread_blocked);
|
transition_from_vm(thread, _thread_blocked);
|
||||||
}
|
}
|
||||||
@ -236,11 +213,15 @@ class ThreadBlockInVMPreprocess : public ThreadStateTransition {
|
|||||||
SafepointMechanism::process_if_requested(_thread, _allow_suspend);
|
SafepointMechanism::process_if_requested(_thread, _allow_suspend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emptyOp(JavaThread* current) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ThreadBlockInVMPreprocess<> ThreadBlockInVM;
|
class ThreadBlockInVM : public ThreadBlockInVMPreprocess<> {
|
||||||
|
public:
|
||||||
|
ThreadBlockInVM(JavaThread* thread, bool allow_suspend = false)
|
||||||
|
: ThreadBlockInVMPreprocess(thread, emptyOp, allow_suspend) {}
|
||||||
|
private:
|
||||||
|
static void emptyOp(JavaThread* current) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Debug class instantiated in JRT_ENTRY macro.
|
// Debug class instantiated in JRT_ENTRY macro.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -754,6 +754,7 @@ void SafepointSynchronize::block(JavaThread *thread) {
|
|||||||
|
|
||||||
void SafepointSynchronize::handle_polling_page_exception(JavaThread *thread) {
|
void SafepointSynchronize::handle_polling_page_exception(JavaThread *thread) {
|
||||||
assert(thread->thread_state() == _thread_in_Java, "should come from Java code");
|
assert(thread->thread_state() == _thread_in_Java, "should come from Java code");
|
||||||
|
thread->set_thread_state(_thread_in_vm);
|
||||||
|
|
||||||
// Enable WXWrite: the function is called implicitly from java code.
|
// Enable WXWrite: the function is called implicitly from java code.
|
||||||
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread));
|
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread));
|
||||||
@ -765,6 +766,8 @@ void SafepointSynchronize::handle_polling_page_exception(JavaThread *thread) {
|
|||||||
ThreadSafepointState* state = thread->safepoint_state();
|
ThreadSafepointState* state = thread->safepoint_state();
|
||||||
|
|
||||||
state->handle_polling_page_exception();
|
state->handle_polling_page_exception();
|
||||||
|
|
||||||
|
thread->set_thread_state(_thread_in_Java);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -970,7 +973,6 @@ void ThreadSafepointState::handle_polling_page_exception() {
|
|||||||
// If we have a pending async exception deoptimize the frame
|
// If we have a pending async exception deoptimize the frame
|
||||||
// as otherwise we may never deliver it.
|
// as otherwise we may never deliver it.
|
||||||
if (self->has_async_exception_condition()) {
|
if (self->has_async_exception_condition()) {
|
||||||
ThreadInVMfromJava __tiv(self, false /* check asyncs */);
|
|
||||||
Deoptimization::deoptimize_frame(self, caller_fr.id());
|
Deoptimization::deoptimize_frame(self, caller_fr.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -126,10 +126,6 @@ class SafepointSynchronize : AllStatic {
|
|||||||
JavaThread *thread,
|
JavaThread *thread,
|
||||||
uint64_t safepoint_count);
|
uint64_t safepoint_count);
|
||||||
|
|
||||||
static bool is_a_block_safe_state(JavaThreadState state) {
|
|
||||||
// Check that we have a valid thread_state before blocking for safepoints
|
|
||||||
return state == _thread_in_vm || state == _thread_in_Java;
|
|
||||||
}
|
|
||||||
// Called when a thread voluntarily blocks
|
// Called when a thread voluntarily blocks
|
||||||
static void block(JavaThread *thread);
|
static void block(JavaThread *thread);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -119,7 +119,7 @@ void SafepointMechanism::process(JavaThread *thread, bool allow_suspend) {
|
|||||||
bool need_rechecking;
|
bool need_rechecking;
|
||||||
do {
|
do {
|
||||||
JavaThreadState state = thread->thread_state();
|
JavaThreadState state = thread->thread_state();
|
||||||
guarantee(SafepointSynchronize::is_a_block_safe_state(state), "Illegal threadstate encountered: %d", state);
|
guarantee(state == _thread_in_vm, "Illegal threadstate encountered: %d", state);
|
||||||
if (global_poll()) {
|
if (global_poll()) {
|
||||||
// Any load in ::block() must not pass the global poll load.
|
// Any load in ::block() must not pass the global poll load.
|
||||||
// Otherwise we might load an old safepoint counter (for example).
|
// Otherwise we might load an old safepoint counter (for example).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
|
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -1646,24 +1646,10 @@ void JavaThread::check_and_handle_async_exceptions() {
|
|||||||
|
|
||||||
// We may be at method entry which requires we save the do-not-unlock flag.
|
// We may be at method entry which requires we save the do-not-unlock flag.
|
||||||
UnlockFlagSaver fs(this);
|
UnlockFlagSaver fs(this);
|
||||||
switch (thread_state()) {
|
Exceptions::throw_unsafe_access_internal_error(this, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation");
|
||||||
case _thread_in_vm: {
|
// We might have blocked in a ThreadBlockInVM wrapper in the call above so make sure we process pending
|
||||||
JavaThread* THREAD = this;
|
// suspend requests and object reallocation operations if any since we might be going to Java after this.
|
||||||
Exceptions::throw_unsafe_access_internal_error(THREAD, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation");
|
SafepointMechanism::process_if_requested_with_exit_check(this, true /* check asyncs */);
|
||||||
// We might have blocked in a ThreadBlockInVM wrapper in the call above so make sure we process pending
|
|
||||||
// suspend requests and object reallocation operations if any since we might be going to Java after this.
|
|
||||||
SafepointMechanism::process_if_requested_with_exit_check(this, true /* check asyncs */);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case _thread_in_Java: {
|
|
||||||
ThreadInVMfromJava tiv(this);
|
|
||||||
JavaThread* THREAD = this;
|
|
||||||
Exceptions::throw_unsafe_access_internal_error(THREAD, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation in compiled Java code");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1770,27 +1756,19 @@ bool JavaThread::java_resume() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for another thread to perform object reallocation and relocking on behalf of
|
// Wait for another thread to perform object reallocation and relocking on behalf of
|
||||||
// this thread.
|
// this thread. The current thread is required to change to _thread_blocked in order
|
||||||
// Raw thread state transition to _thread_blocked and back again to the original
|
// to be seen to be safepoint/handshake safe whilst suspended and only after becoming
|
||||||
// state before returning are performed. The current thread is required to
|
// handshake safe, the other thread can complete the handshake used to synchronize
|
||||||
// change to _thread_blocked in order to be seen to be safepoint/handshake safe
|
// with this thread and then perform the reallocation and relocking.
|
||||||
// whilst suspended and only after becoming handshake safe, the other thread can
|
// See EscapeBarrier::sync_and_suspend_*()
|
||||||
// complete the handshake used to synchronize with this thread and then perform
|
|
||||||
// the reallocation and relocking. We cannot use the thread state transition
|
|
||||||
// helpers because we arrive here in various states and also because the helpers
|
|
||||||
// indirectly call this method. After leaving _thread_blocked we have to check
|
|
||||||
// for safepoint/handshake, except if _thread_in_native. The thread is safe
|
|
||||||
// without blocking then. Allowed states are enumerated in
|
|
||||||
// SafepointSynchronize::block(). See also EscapeBarrier::sync_and_suspend_*()
|
|
||||||
|
|
||||||
void JavaThread::wait_for_object_deoptimization() {
|
void JavaThread::wait_for_object_deoptimization() {
|
||||||
assert(!has_last_Java_frame() || frame_anchor()->walkable(), "should have walkable stack");
|
assert(!has_last_Java_frame() || frame_anchor()->walkable(), "should have walkable stack");
|
||||||
assert(this == Thread::current(), "invariant");
|
assert(this == Thread::current(), "invariant");
|
||||||
JavaThreadState state = thread_state();
|
|
||||||
|
|
||||||
bool spin_wait = os::is_MP();
|
bool spin_wait = os::is_MP();
|
||||||
do {
|
do {
|
||||||
set_thread_state(_thread_blocked);
|
ThreadBlockInVM tbivm(this, true /* allow_suspend */);
|
||||||
// Wait for object deoptimization if requested.
|
// Wait for object deoptimization if requested.
|
||||||
if (spin_wait) {
|
if (spin_wait) {
|
||||||
// A single deoptimization is typically very short. Microbenchmarks
|
// A single deoptimization is typically very short. Microbenchmarks
|
||||||
@ -1808,14 +1786,6 @@ void JavaThread::wait_for_object_deoptimization() {
|
|||||||
ml.wait();
|
ml.wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The current thread could have been suspended again. We have to check for
|
|
||||||
// suspend after restoring the saved state. Without this the current thread
|
|
||||||
// might return to _thread_in_Java and execute bytecode.
|
|
||||||
set_thread_state_fence(state);
|
|
||||||
|
|
||||||
if (state != _thread_in_native) {
|
|
||||||
SafepointMechanism::process_if_requested(this);
|
|
||||||
}
|
|
||||||
// A handshake for obj. deoptimization suspend could have been processed so
|
// A handshake for obj. deoptimization suspend could have been processed so
|
||||||
// we must check after processing.
|
// we must check after processing.
|
||||||
} while (is_obj_deopt_suspend());
|
} while (is_obj_deopt_suspend());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user