mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-13 01:13:10 +00:00
Co-authored-by: Stefan Karlsson <stefank@openjdk.org> Co-authored-by: Erik Österlund <eosterlund@openjdk.org> Co-authored-by: Axel Boldt-Christmas <aboldtch@openjdk.org> Co-authored-by: Per Liden <pliden@openjdk.org> Co-authored-by: Stefan Johansson <sjohanss@openjdk.org> Co-authored-by: Albert Mingkun Yang <ayang@openjdk.org> Co-authored-by: Erik Helin <ehelin@openjdk.org> Co-authored-by: Roberto Castañeda Lozano <rcastanedalo@openjdk.org> Co-authored-by: Nils Eliasson <neliasso@openjdk.org> Co-authored-by: Martin Doerr <mdoerr@openjdk.org> Co-authored-by: Leslie Zhai <lzhai@openjdk.org> Co-authored-by: Fei Yang <fyang@openjdk.org> Co-authored-by: Yadong Wang <yadongwang@openjdk.org> Reviewed-by: eosterlund, aboldtch, rcastanedalo
157 lines
5.8 KiB
C++
157 lines
5.8 KiB
C++
/*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#ifndef SHARE_RUNTIME_STACKWATERMARK_HPP
|
|
#define SHARE_RUNTIME_STACKWATERMARK_HPP
|
|
|
|
#include "memory/allStatic.hpp"
|
|
#include "runtime/mutex.hpp"
|
|
#include "runtime/stackWatermarkKind.hpp"
|
|
#include "utilities/growableArray.hpp"
|
|
|
|
class frame;
|
|
class JavaThread;
|
|
class RegisterMap;
|
|
class StackWatermarkFramesIterator;
|
|
|
|
// The StackWatermark state is a tuple comprising the last epoch in which
|
|
// the watermark has been processed, and a boolean denoting whether the whole
|
|
// processing of the lazy snapshot has been processed or not. It is written
|
|
// in a way that can be used outside of locks, so that fast path checks can
|
|
// be performed without the need for any locking. The boolean can only be
|
|
// trusted if the epoch of the state is the same as the epoch_id() of the
|
|
// watermark. Incrementing the epoch_id() will implicitly initiate a new lazy
|
|
// stack snapshot, and trigger processing on it as needed, due to the cached
|
|
// epoch of the state being outdated. When the snapshot is_done for the current
|
|
// epoch_id(), there is no need to do anything further.
|
|
class StackWatermarkState : public AllStatic {
|
|
public:
|
|
inline static bool is_done(uint32_t state) {
|
|
return state & 1;
|
|
}
|
|
|
|
inline static uint32_t epoch(uint32_t state) {
|
|
return state >> 1;
|
|
}
|
|
|
|
inline static uint32_t create(uint32_t epoch, bool is_done) {
|
|
return (epoch << 1) | (is_done ? 1u : 0u);
|
|
}
|
|
};
|
|
|
|
// The StackWatermark allows lazy incremental concurrent processing of a
|
|
// snapshot of a stack. The lazy and incremental nature is implemented by
|
|
// marking a frame (the watermark) from which returns (or other forms of
|
|
// unwinding) will take a slow path to perform additional processing
|
|
// required when exposing more frames that were part of the snapshot to
|
|
// the system. The watermark pointer always denotes the SP of the watermark.
|
|
// However, active frames can grow and shrink arbitrarily compared to the
|
|
// snapshot view that is being processed, due to things like c2i adapters,
|
|
// and various register saving techniques to get into the runtime. Therefore,
|
|
// in order to cope with the frames growing and shrinking, comparisons
|
|
// against the watermark are performed with the frame pointer of a given
|
|
// frame against the watermark (denoting the SP).
|
|
//
|
|
// ----------
|
|
// | |
|
|
// | caller |
|
|
// | |
|
|
// ----------
|
|
// | | <-- frame fp (always above the watermark of the same frame,
|
|
// | callee | regardless of frame resizing)
|
|
// | |
|
|
// ---------- <-- watermark (callee SP from the snapshot, SP at the
|
|
// point of unwinding, might be above or below
|
|
// due to frame resizing)
|
|
class StackWatermark : public CHeapObj<mtThread> {
|
|
friend class StackWatermarkFramesIterator;
|
|
protected:
|
|
volatile uint32_t _state;
|
|
volatile uintptr_t _watermark;
|
|
StackWatermark* _next;
|
|
JavaThread* _jt;
|
|
StackWatermarkFramesIterator* _iterator;
|
|
Mutex _lock;
|
|
StackWatermarkKind _kind;
|
|
GrowableArrayCHeap<StackWatermark*, mtThread> _linked_watermarks;
|
|
|
|
void process_one();
|
|
|
|
void update_watermark();
|
|
void yield_processing();
|
|
static bool has_barrier(const frame& f);
|
|
void ensure_safe(const frame& f);
|
|
void assert_is_frame_safe(const frame& f) NOT_DEBUG_RETURN;
|
|
bool is_frame_safe(const frame& f);
|
|
|
|
// API for consumers of the stack watermark barrier.
|
|
// The rule for consumers is: do not perform thread transitions
|
|
// or take locks of rank >= special. This is all very special code.
|
|
virtual uint32_t epoch_id() const = 0;
|
|
virtual void process(const frame& f, RegisterMap& register_map, void* context) = 0;
|
|
virtual void start_processing_impl(void* context);
|
|
|
|
// Set process_on_iteration to false if you don't want to move the
|
|
// watermark when new frames are discovered from stack walkers, as
|
|
// opposed to due to frames being unwound by the owning thread.
|
|
virtual bool process_on_iteration() { return true; }
|
|
|
|
void process_linked_watermarks();
|
|
|
|
bool processing_started(uint32_t state) const;
|
|
bool processing_completed(uint32_t state) const;
|
|
|
|
public:
|
|
StackWatermark(JavaThread* jt, StackWatermarkKind kind, uint32_t epoch);
|
|
virtual ~StackWatermark();
|
|
|
|
|
|
// StackWatermarkSet support
|
|
StackWatermarkKind kind() const { return _kind; }
|
|
StackWatermark* next() const { return _next; }
|
|
void set_next(StackWatermark* n) { _next = n; }
|
|
|
|
void push_linked_watermark(StackWatermark* watermark);
|
|
void pop_linked_watermark();
|
|
|
|
uintptr_t watermark();
|
|
uintptr_t last_processed();
|
|
uintptr_t last_processed_raw();
|
|
|
|
bool processing_started() const;
|
|
bool processing_started_acquire() const;
|
|
bool processing_completed() const;
|
|
bool processing_completed_acquire() const;
|
|
|
|
void before_unwind();
|
|
void after_unwind();
|
|
|
|
void on_iteration(const frame& f);
|
|
void on_safepoint();
|
|
void start_processing();
|
|
void finish_processing(void* context);
|
|
};
|
|
|
|
#endif // SHARE_RUNTIME_STACKWATERMARK_HPP
|