/*
 * 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;
  }
}
