/*
 * Copyright (c) 2013, 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 "classfile/metadataOnStackMark.hpp"
#include "code/codeCache.hpp"
#include "compiler/compileBroker.hpp"
#include "oops/metadata.hpp"
#include "prims/jvmtiImpl.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/synchronizer.hpp"
#include "services/threadService.hpp"
#include "utilities/chunkedList.hpp"
#if INCLUDE_JVMCI
#include "jvmci/jvmci.hpp"
#endif

MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = nullptr;
MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = nullptr;

MetadataOnStackBuffer* MetadataOnStackMark::_current_buffer = nullptr;
NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)

class MetadataOnStackClosure : public MetadataClosure {
  void do_metadata(Metadata* m) { Metadata::mark_on_stack(m); }
};

// Walk metadata on the stack and mark it so that redefinition doesn't delete
// it.  Class unloading only deletes in-error class files, methods created by
// the relocator and dummy constant pools.  None of these appear anywhere except
// in metadata Handles.
MetadataOnStackMark::MetadataOnStackMark(bool walk_all_metadata, bool redefinition_walk) {
  assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
  assert(_used_buffers == nullptr, "sanity check");
  assert(!_is_active, "MetadataOnStackMarks do not nest");
  assert(!redefinition_walk || walk_all_metadata,
         "walk_all_metadata must be true for redefinition_walk");
  NOT_PRODUCT(_is_active = true;)

  Threads::metadata_handles_do(Metadata::mark_on_stack);

  if (walk_all_metadata) {
    MetadataOnStackClosure md_on_stack;
    Threads::metadata_do(&md_on_stack);
    if (redefinition_walk) {
      // We have to walk the whole code cache during redefinition.
      CodeCache::metadata_do(&md_on_stack);
    } else {
      CodeCache::old_nmethods_do(&md_on_stack);
    }
    CompileBroker::mark_on_stack();
    ThreadService::metadata_do(Metadata::mark_on_stack);
#if INCLUDE_JVMCI
    JVMCI::metadata_do(Metadata::mark_on_stack);
#endif
  }
}

MetadataOnStackMark::~MetadataOnStackMark() {
  assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
  // Unmark everything that was marked.   Can't do the same walk because
  // redefine classes messes up the code cache so the set of methods
  // might not be the same.
  retire_current_buffer();

  MetadataOnStackBuffer* buffer = _used_buffers;
  while (buffer != nullptr) {
    // Clear on stack state for all metadata.
    size_t size = buffer->size();
    for (size_t i  = 0; i < size; i++) {
      Metadata* md = buffer->at(i);
      md->set_on_stack(false);
    }

    MetadataOnStackBuffer* next = buffer->next_used();

    // Move the buffer to the free list.
    buffer->clear();
    buffer->set_next_used(nullptr);
    buffer->set_next_free(_free_buffers);
    _free_buffers = buffer;

    // Step to next used buffer.
    buffer = next;
  }

  _used_buffers = nullptr;

  NOT_PRODUCT(_is_active = false;)
}

void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {
  if (buffer == nullptr) {
    return;
  }
  buffer->set_next_used(_used_buffers);
  _used_buffers = buffer;
}

// Current buffer is full or we're ready to walk them, add it to the used list.
void MetadataOnStackMark::retire_current_buffer() {
  retire_buffer(_current_buffer);
  _current_buffer = nullptr;
}

// Get buffer off free list.
MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {
  MetadataOnStackBuffer* allocated = _free_buffers;

  if (allocated != nullptr) {
    _free_buffers = allocated->next_free();
  }

  if (allocated == nullptr) {
    allocated = new MetadataOnStackBuffer();
  }

  assert(!allocated->is_full(), "Should not be full: " PTR_FORMAT, p2i(allocated));

  return allocated;
}

// Record which objects are marked so we can unmark the same objects.
void MetadataOnStackMark::record(Metadata* m) {
  assert(_is_active, "metadata on stack marking is active");

  MetadataOnStackBuffer* buffer = _current_buffer;

  if (buffer != nullptr && buffer->is_full()) {
    retire_buffer(buffer);
    buffer = nullptr;
  }

  if (buffer == nullptr) {
    buffer = allocate_buffer();
    _current_buffer = buffer;
  }

  buffer->push(m);
}
