/*
 * 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.hpp"
#include "runtime/osThread.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/stackFrameStream.inline.hpp"
#include "runtime/stackWatermark.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/preserveException.hpp"

class StackWatermarkFramesIterator : public CHeapObj<mtThread> {
  JavaThread* _jt;
  uintptr_t _caller;
  uintptr_t _callee;
  StackFrameStream _frame_stream;
  StackWatermark& _owner;
  bool _is_done;

  void set_watermark(uintptr_t sp);
  RegisterMap& register_map();
  frame& current();
  void next();

public:
  StackWatermarkFramesIterator(StackWatermark& owner);
  uintptr_t caller() const { return _caller; }
  uintptr_t callee() const { return _callee; }
  void process_one(void* context);
  void process_all(void* context);
  bool has_next() const;
};

void StackWatermarkFramesIterator::set_watermark(uintptr_t sp) {
  assert(sp != 0, "Sanity check");

  if (!has_next()) {
    return;
  }

  if (_callee == 0) {
    _callee = sp;
  } else if (_caller == 0) {
    _caller = sp;
  } else {
    _callee = _caller;
    _caller = sp;
  }
}

// This class encapsulates various marks we need to deal with calling the
// frame processing code from arbitrary points in the runtime. It is mostly
// due to problems that we might want to eventually clean up inside of the
// frame processing code, such as creating random handles even though there
// is no safepoint to protect against, and fiddling around with exceptions.
class StackWatermarkProcessingMark {
  ResetNoHandleMark _rnhm;
  HandleMark _hm;
  PreserveExceptionMark _pem;
  ResourceMark _rm;

public:
  StackWatermarkProcessingMark(Thread* thread) :
      _rnhm(),
      _hm(thread),
      _pem(thread),
      _rm(thread) { }
};

void StackWatermarkFramesIterator::process_one(void* context) {
  StackWatermarkProcessingMark swpm(Thread::current());
  while (has_next()) {
    frame f = current();
    uintptr_t sp = reinterpret_cast<uintptr_t>(f.sp());
    bool frame_has_barrier = StackWatermark::has_barrier(f);
    _owner.process(f, register_map(), context);
    next();
    if (frame_has_barrier) {
      set_watermark(sp);
      break;
    }
  }
}

void StackWatermarkFramesIterator::process_all(void* context) {
  const uintptr_t frames_per_poll_gc = 5;

  ResourceMark rm;
  log_info(stackbarrier)("Processing whole stack for tid %d",
                         _jt->osthread()->thread_id());
  uint i = 0;
  while (has_next()) {
    frame f = current();
    uintptr_t sp = reinterpret_cast<uintptr_t>(f.sp());
    assert(sp >= _caller, "invariant");
    bool frame_has_barrier = StackWatermark::has_barrier(f);
    _owner.process(f, register_map(), context);
    next();
    if (frame_has_barrier) {
      set_watermark(sp);
      if (++i == frames_per_poll_gc) {
        // Yield every N frames so mutator can progress faster.
        i = 0;
        _owner.yield_processing();
      }
    }
  }
}

StackWatermarkFramesIterator::StackWatermarkFramesIterator(StackWatermark& owner) :
    _jt(owner._jt),
    _caller(0),
    _callee(0),
    _frame_stream(owner._jt, true /* update_registers */, false /* process_frames */),
    _owner(owner),
    _is_done(_frame_stream.is_done()) {
}

frame& StackWatermarkFramesIterator::current() {
  return *_frame_stream.current();
}

RegisterMap& StackWatermarkFramesIterator::register_map() {
  return *_frame_stream.register_map();
}

bool StackWatermarkFramesIterator::has_next() const {
  return !_is_done;
}

void StackWatermarkFramesIterator::next() {
  _frame_stream.next();
  _is_done = _frame_stream.is_done();
}

StackWatermark::StackWatermark(JavaThread* jt, StackWatermarkKind kind, uint32_t epoch) :
    _state(StackWatermarkState::create(epoch, true /* is_done */)),
    _watermark(0),
    _next(nullptr),
    _jt(jt),
    _iterator(nullptr),
    _lock(Mutex::stackwatermark, "StackWatermark_lock"),
    _kind(kind),
    _linked_watermarks() {
}

StackWatermark::~StackWatermark() {
  delete _iterator;
}

#ifdef ASSERT
void StackWatermark::assert_is_frame_safe(const frame& f) {
  MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
  assert(is_frame_safe(f), "Frame must be safe");
}
#endif

// A frame is "safe" if it *and* its caller have been processed. This is the invariant
// that allows exposing a frame, and for that frame to directly access its caller frame
// without going through any hooks.
bool StackWatermark::is_frame_safe(const frame& f) {
  assert(_lock.owned_by_self(), "Must be locked");
  uint32_t state = Atomic::load(&_state);
  if (!processing_started(state)) {
    return false;
  }
  if (processing_completed(state)) {
    return true;
  }
  return reinterpret_cast<uintptr_t>(f.sp()) < _iterator->caller();
}

void StackWatermark::start_processing_impl(void* context) {
  log_info(stackbarrier)("Starting stack processing for tid %d",
                         _jt->osthread()->thread_id());
  delete _iterator;
  if (_jt->has_last_Java_frame()) {
    _iterator = new StackWatermarkFramesIterator(*this);
    // Always process three frames when starting an iteration.
    //
    // The three frames corresponds to:
    // 1) The callee frame
    // 2) The caller frame
    // This allows a callee to always be able to read state from its caller
    // without needing any special barriers.
    //
    // 3) An extra frame to deal with unwinding safepointing on the way out.
    // Sometimes, we also call into the runtime to on_unwind(), but then
    // hit a safepoint poll on the way out from the runtime.
    _iterator->process_one(context);
    _iterator->process_one(context);
    _iterator->process_one(context);
  } else {
    _iterator = nullptr;
  }
  update_watermark();
}

void StackWatermark::yield_processing() {
  update_watermark();
  MutexUnlocker mul(&_lock, Mutex::_no_safepoint_check_flag);
}

void StackWatermark::update_watermark() {
  assert(_lock.owned_by_self(), "invariant");
  if (_iterator != nullptr && _iterator->has_next()) {
    assert(_iterator->callee() != 0, "sanity");
    Atomic::release_store(&_watermark, _iterator->callee());
    Atomic::release_store(&_state, StackWatermarkState::create(epoch_id(), false /* is_done */)); // release watermark w.r.t. epoch
  } else {
    Atomic::release_store(&_watermark, uintptr_t(0)); // Release stack data modifications w.r.t. watermark
    Atomic::release_store(&_state, StackWatermarkState::create(epoch_id(), true /* is_done */)); // release watermark w.r.t. epoch
    log_info(stackbarrier)("Finished stack processing iteration for tid %d",
                           _jt->osthread()->thread_id());
  }
}

void StackWatermark::process_one() {
  MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
  if (!processing_started()) {
    start_processing_impl(nullptr /* context */);
  } else if (!processing_completed()) {
    _iterator->process_one(nullptr /* context */);
    update_watermark();
  }
}

void StackWatermark::push_linked_watermark(StackWatermark* watermark) {
  assert(JavaThread::current() == _jt, "This code is not thread safe");
  _linked_watermarks.push(watermark);
}

void StackWatermark::pop_linked_watermark() {
  assert(JavaThread::current() == _jt, "This code is not thread safe");
  assert(_linked_watermarks.length() > 0, "Mismatched push and pop?");
  _linked_watermarks.pop();
}

uintptr_t StackWatermark::watermark() {
  return Atomic::load_acquire(&_watermark);
}

uintptr_t StackWatermark::last_processed() {
  MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
  if (!processing_started()) {
    // Stale state; no last processed
    return 0;
  }
  if (processing_completed()) {
    // Already processed all; no last processed
    return 0;
  }
  return _iterator->caller();
}

uintptr_t StackWatermark::last_processed_raw() {
  return _iterator->caller();
}

bool StackWatermark::processing_started() const {
  return processing_started(Atomic::load(&_state));
}

bool StackWatermark::processing_started_acquire() const {
  return processing_started(Atomic::load_acquire(&_state));
}

bool StackWatermark::processing_completed() const {
  return processing_completed(Atomic::load(&_state));
}

bool StackWatermark::processing_completed_acquire() const {
  return processing_completed(Atomic::load_acquire(&_state));
}

void StackWatermark::process_linked_watermarks() {
  assert(JavaThread::current() == _jt, "This code is not thread safe");

  // Finish processing all linked stack watermarks
  for (StackWatermark* watermark : _linked_watermarks) {
    watermark->finish_processing(nullptr /* context */);
  }
}

void StackWatermark::on_safepoint() {
  start_processing();

  // If the thread waking up from a safepoint expected certain other
  // stack watermarks (potentially from different threads) are processed,
  // then we have to perform processing of said linked watermarks here.
  process_linked_watermarks();
}

void StackWatermark::start_processing() {
  if (!processing_started_acquire()) {
    MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
    if (!processing_started()) {
      start_processing_impl(nullptr /* context */);
    }
  }
}

void StackWatermark::finish_processing(void* context) {
  MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
  if (!processing_started()) {
    start_processing_impl(context);
  }
  if (!processing_completed()) {
    _iterator->process_all(context);
    update_watermark();
  }
}
