blob: a49b1bfc307948921706cf8e9a8b93719020bac1 [file] [log] [blame]
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "logging/log.hpp"
#include "runtime/atomic.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/javaThread.inline.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/safepointMechanism.inline.hpp"
#include "runtime/stackWatermark.inline.hpp"
#include "runtime/stackWatermarkSet.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/preserveException.hpp"
#include "utilities/vmError.hpp"
StackWatermarks::StackWatermarks() :
_head(nullptr) {}
StackWatermarks::~StackWatermarks() {
StackWatermark* current = _head;
while (current != nullptr) {
StackWatermark* next = current->next();
delete current;
current = next;
}
}
StackWatermark* StackWatermarkSet::head(JavaThread* jt) {
return jt->stack_watermarks()->_head;
}
void StackWatermarkSet::set_head(JavaThread* jt, StackWatermark* watermark) {
jt->stack_watermarks()->_head = watermark;
}
void StackWatermarkSet::add_watermark(JavaThread* jt, StackWatermark* watermark) {
assert(!has_watermark(jt, watermark->kind()), "Two instances of same kind");
StackWatermark* prev = head(jt);
watermark->set_next(prev);
set_head(jt, watermark);
}
static void verify_processing_context() {
#ifdef ASSERT
Thread* thread = Thread::current();
if (thread->is_Java_thread()) {
JavaThread* jt = JavaThread::cast(thread);
JavaThreadState state = jt->thread_state();
assert(state != _thread_in_native, "unsafe thread state");
assert(state != _thread_blocked, "unsafe thread state");
} else if (thread->is_VM_thread()) {
} else {
assert_locked_or_safepoint(Threads_lock);
}
#endif
}
void StackWatermarkSet::before_unwind(JavaThread* jt) {
verify_processing_context();
assert(jt->has_last_Java_frame(), "must have a Java frame");
for (StackWatermark* current = head(jt); current != nullptr; current = current->next()) {
current->before_unwind();
}
SafepointMechanism::update_poll_values(jt);
}
void StackWatermarkSet::after_unwind(JavaThread* jt) {
verify_processing_context();
assert(jt->has_last_Java_frame(), "must have a Java frame");
for (StackWatermark* current = head(jt); current != nullptr; current = current->next()) {
current->after_unwind();
}
SafepointMechanism::update_poll_values(jt);
}
void StackWatermarkSet::on_iteration(JavaThread* jt, const frame& fr) {
if (VMError::is_error_reported()) {
// Don't perform barrier when error reporting walks the stack.
return;
}
verify_processing_context();
for (StackWatermark* current = head(jt); current != nullptr; current = current->next()) {
current->on_iteration(fr);
}
// We don't call SafepointMechanism::update_poll_values here, because the thread
// calling this might not be Thread::current().
}
void StackWatermarkSet::on_safepoint(JavaThread* jt) {
StackWatermark* watermark = get(jt, StackWatermarkKind::gc);
if (watermark != nullptr) {
watermark->on_safepoint();
}
}
void StackWatermarkSet::start_processing(JavaThread* jt, StackWatermarkKind kind) {
verify_processing_context();
assert(!jt->is_terminated(), "Poll after termination is a bug");
StackWatermark* watermark = get(jt, kind);
if (watermark != nullptr) {
watermark->start_processing();
}
// We don't call SafepointMechanism::update_poll_values here, because the thread
// calling this might not be Thread::current(). The thread the stack belongs to
// will always update the poll values when waking up from a safepoint.
}
bool StackWatermarkSet::processing_started(JavaThread* jt) {
for (StackWatermark* current = head(jt); current != nullptr; current = current->next()) {
if (!current->processing_started()) {
return false;
}
}
return true;
}
void StackWatermarkSet::finish_processing(JavaThread* jt, void* context, StackWatermarkKind kind) {
StackWatermark* watermark = get(jt, kind);
if (watermark != nullptr) {
watermark->finish_processing(context);
}
// We don't call SafepointMechanism::update_poll_values here, because the thread
// calling this might not be Thread::current().
}
uintptr_t StackWatermarkSet::lowest_watermark(JavaThread* jt) {
uintptr_t max_watermark = uintptr_t(0) - 1;
uintptr_t watermark = max_watermark;
for (StackWatermark* current = head(jt); current != nullptr; current = current->next()) {
watermark = MIN2(watermark, current->watermark());
}
if (watermark == max_watermark) {
return 0;
} else {
return watermark;
}
}