/*
 * Copyright (c) 2020, 2025, 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 "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 "runtime/threadSMR.hpp"
#include "runtime/vmOperation.hpp"
#include "runtime/vmThread.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();
  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;
  }
}

void StackWatermarkSet::safepoint_synchronize_begin() {
  if (VMThread::vm_operation()->skip_thread_oop_barriers()) {
    return;
  }

  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
    StackWatermarkSet::start_processing(thread, StackWatermarkKind::gc);
  }
}
