/*
 * Copyright (c) 2019, 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 "classfile/classLoaderData.hpp"
#include "jvmci/metadataHandles.hpp"
#include "runtime/atomic.hpp"

jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) {
  assert(obj->is_valid() && obj->is_metadata(), "must be");

  if (_head == nullptr) {
    // This is the first allocation.
    _head = new MetadataHandleBlock();
    _last = _head;
    _num_blocks++;
  }

  HandleRecord* handle = get_handle();

  if (handle != nullptr) {
    handle->set_value(obj);
#ifdef METADATA_TRACK_NAMES
    handle->set_name(obj->print_value_string());
#endif
    return (jmetadata) handle;
  }

  // Check if an unused block follows last
  if (_last->_next != nullptr) {
    // update last and retry
    _last = _last->_next;
    return allocate_metadata_handle(obj);
  }

  // No space available, we have to rebuild free list or expand
  if (_allocate_before_rebuild == 0) {
    rebuild_free_list(); // updates _allocate_before_rebuild counter
  } else {
    // Append new block
    _last->_next = new MetadataHandleBlock();
    _last = _last->_next;
    _allocate_before_rebuild--;
    _num_blocks++;
  }
  return allocate_metadata_handle(obj);  // retry
}


void MetadataHandles::rebuild_free_list() {
  assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
  int free = 0;
  int blocks = 0;
  for (MetadataHandleBlock* current = _head; current != nullptr; current = current->_next) {
    for (int index = 0; index < current->_top; index++) {
      HandleRecord* handle = &(current->_handles)[index];
      if (handle->value() == nullptr) {
        // this handle was cleared out by a delete call, reuse it
        chain_free_list(handle);
        free++;
      }
    }
    // we should not rebuild free list if there are unused handles at the end
    assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking");
    blocks++;
  }
  assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks);
  assert(_num_free_handles == free, "%d != %d", _num_free_handles, free);
  // Heuristic: if more than half of the handles are NOT free we rebuild next time
  // as well, otherwise we append a corresponding number of new blocks before
  // attempting a free list rebuild again.
  int total = blocks * MetadataHandleBlock::block_size_in_handles;
  int extra = total - 2*free;
  if (extra > 0) {
    // Not as many free handles as we would like - compute number of new blocks to append
    _allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles;
  }
}

void MetadataHandles::clear() {
  _free_list = 0;
  _last = _head;
  if (_head != nullptr) {
    for (MetadataHandleBlock* block = _head; block != nullptr; block = block->_next) {
      block->_top = 0;
    }
  }
  _num_handles = 0;
  _num_free_handles = 0;
}

void MetadataHandles::metadata_do(void f(Metadata*)) {
  for (MetadataHandleBlock* current = _head; current != nullptr; current = current->_next) {
    for (int index = 0; index < current->_top; index++) {
      HandleRecord* root = &(current->_handles)[index];
      Metadata* value = root->value();
      // traverse heap pointers only, not deleted handles or free list
      // pointers
      if (value != nullptr && ((intptr_t) value & ptr_tag) == 0) {
        assert(value->is_valid(), "invalid metadata %s", current->get_name(index));
        f(value);
      }
    }
    // the next handle block is valid only if current block is full
    if (current->_top < MetadataHandleBlock::block_size_in_handles) {
      break;
    }
  }
}

// Visit any live metadata handles and clean them up.  Since clearing of these handles is driven by
// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
void MetadataHandles::do_unloading() {
  for (MetadataHandleBlock* current = _head; current != nullptr; current = current->_next) {
    for (int index = 0; index < current->_top; index++) {
      HandleRecord* handle = &(current->_handles)[index];
      Metadata* value = handle->value();
      // traverse heap pointers only, not deleted handles or free list
      // pointers
      if (value != nullptr && ((intptr_t) value & ptr_tag) == 0) {
        Klass* klass = nullptr;
        if (value->is_klass()) {
          klass = (Klass*)value;
        } else if (value->is_method()) {
          Method* m = (Method*)value;
          klass = m->method_holder();
        } else if (value->is_constantPool()) {
          ConstantPool* cp = (ConstantPool*)value;
          klass = cp->pool_holder();
        } else {
          ShouldNotReachHere();
        }
        if (klass->class_loader_data()->is_unloading()) {
          // This needs to be marked so that it's no longer scanned
          // but can't be put on the free list yet. The
          // HandleCleaner will set this to null and
          // put it on the free list.
          jlong old_value = Atomic::cmpxchg((jlong*)handle, (jlong) value, (jlong) (ptr_tag));
          if (old_value == (jlong) value) {
            // Success
          } else {
            guarantee(old_value == 0, "only other possible value");
          }
        }
      }
    }
    // the next handle block is valid only if current block is full
    if (current->_top < MetadataHandleBlock::block_size_in_handles) {
      break;
    }
  }
}
