/*
 * Copyright (c) 2021, 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 "gc/z/zAddress.inline.hpp"
#include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zGeneration.inline.hpp"
#include "gc/z/zHeap.inline.hpp"
#include "gc/z/zIterator.inline.hpp"
#include "gc/z/zMark.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageTable.hpp"
#include "gc/z/zRemembered.inline.hpp"
#include "gc/z/zRememberedSet.hpp"
#include "gc/z/zTask.hpp"
#include "gc/z/zVerify.hpp"
#include "memory/iterator.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/debug.hpp"

ZRemembered::ZRemembered(ZPageTable* page_table,
                         const ZForwardingTable* old_forwarding_table,
                         ZPageAllocator* page_allocator)
  : _page_table(page_table),
    _old_forwarding_table(old_forwarding_table),
    _page_allocator(page_allocator),
    _found_old() {}

template <typename Function>
void ZRemembered::oops_do_forwarded_via_containing(GrowableArrayView<ZRememberedSetContaining>* array, Function function) const {
  // The array contains duplicated from_addr values. Cache expensive operations.
  zaddress_unsafe from_addr = zaddress_unsafe::null;
  zaddress to_addr = zaddress::null;
  size_t object_size = 0;

  for (const ZRememberedSetContaining containing: *array) {
    if (from_addr != containing._addr) {
      from_addr = containing._addr;

      // Relocate object to new location
      to_addr = ZGeneration::old()->relocate_or_remap_object(from_addr);

      // Figure out size
      object_size = ZUtils::object_size(to_addr);
    }

    // Calculate how far into the from-object the remset entry is
    const uintptr_t field_offset = containing._field_addr - from_addr;

    // The 'containing' could contain mismatched (addr, addr_field).
    // Need to check if the field was within the reported object.
    if (field_offset < object_size) {
      // Calculate the corresponding address in the to-object
      const zaddress to_addr_field = to_addr + field_offset;

      function((volatile zpointer*)untype(to_addr_field));
    }
  }
}

bool ZRemembered::should_scan_page(ZPage* page) const {
  if (!ZGeneration::old()->is_phase_relocate()) {
    // If the old generation collection is not in the relocation phase, then it
    // will not need any synchronization on its forwardings.
    return true;
  }

  ZForwarding* const forwarding = ZGeneration::old()->forwarding(ZOffset::address_unsafe(page->start()));

  if (forwarding == nullptr) {
    // This page was provably not part of the old relocation set
    return true;
  }

  if (!forwarding->relocated_remembered_fields_is_concurrently_scanned()) {
    // Safe to scan
    return true;
  }

  // If we get here, we know that the old collection is concurrently relocating
  // objects. We need to be extremely careful not to scan a page that is
  // concurrently being in-place relocated because it's objects and previous
  // bits could be concurrently be moving around.
  //
  // Before calling this function ZRemembered::scan_forwarding ensures
  // that all forwardings that have not already been fully relocated,
  // will have had their "previous" remembered set bits scanned.
  //
  // The current page we're currently scanning could either be the same page
  // that was found during scan_forwarding, or it could have been replaced
  // by a new "allocating" page. There are two situations we have to consider:
  //
  // 1) If it is a proper new allocating page, then all objects where copied
  // after scan_forwarding ran, and we are guaranteed that no "previous"
  // remembered set bits are set. So, there's no need to scan this page.
  //
  // 2) If this is an in-place relocated page, then the entire page could
  // be concurrently relocated. Meaning that both objects and previous
  // remembered set bits could be moving around. However, if the in-place
  // relocation is ongoing, we've already scanned all relevant "previous"
  // bits when calling scan_forwarding. So, this page *must* not be scanned.
  //
  // Don't scan the page.
  return false;
}

bool ZRemembered::scan_page(ZPage* page) const {
  const bool can_trust_live_bits =
      page->is_relocatable() && !ZGeneration::old()->is_phase_mark();

  bool result = false;

  if (!can_trust_live_bits) {
    // We don't have full liveness info - scan all remset entries
    page->log_msg(" (scan_page_remembered)");
    int count = 0;
    page->oops_do_remembered([&](volatile zpointer* p) {
      result |= scan_field(p);
      count++;
    });
    page->log_msg(" (scan_page_remembered done: %d ignoring: " PTR_FORMAT " )", count, p2i(page->remset_current()));
  } else if (page->is_marked()) {
    // We have full liveness info - Only scan remset entries in live objects
    page->log_msg(" (scan_page_remembered_in_live)");
    page->oops_do_remembered_in_live([&](volatile zpointer* p) {
      result |= scan_field(p);
    });
  } else {
    page->log_msg(" (scan_page_remembered_dead)");
    // All objects are dead - do nothing
  }

  return result;
}

static void fill_containing(GrowableArrayCHeap<ZRememberedSetContaining, mtGC>* array, ZPage* page) {
  page->log_msg(" (fill_remembered_containing)");

  ZRememberedSetContainingIterator iter(page);

  for (ZRememberedSetContaining containing; iter.next(&containing);) {
    array->push(containing);
  }
}

struct ZRememberedScanForwardingContext {
  GrowableArrayCHeap<ZRememberedSetContaining, mtGC> _containing_array;

  struct Where {
    static const int NumRecords = 10;

    Tickspan _duration;
    int      _count;
    Tickspan _max_durations[NumRecords];
    int      _max_count;

    Where()
      : _duration(),
        _count(),
        _max_durations(),
        _max_count() {}

    void report(const Tickspan& duration) {
      _duration += duration;
      _count++;

      // Install into max array
      for (int i = 0; i < NumRecords; i++) {
        if (duration > _max_durations[i]) {
          // Slid to the side
          for (int j = _max_count - 1; i < j; j--) {
            _max_durations[j] = _max_durations[j - 1];
          }

          // Install
          _max_durations[i] = duration;
          if (_max_count < NumRecords) {
            _max_count++;
          }
          break;
        }
      }
    }

    void print(const char* name) {
      log_debug(gc, remset)("Remset forwarding %s: %.3fms count: %d %s",
          name, TimeHelper::counter_to_millis(_duration.value()), _count, Thread::current()->name());
      for (int i = 0; i < _max_count; i++) {
        log_debug(gc, remset)("  %.3fms", TimeHelper::counter_to_millis(_max_durations[i].value()));
      }
    }
  };

  Where _where[2];

  ZRememberedScanForwardingContext()
    : _containing_array(),
      _where() {}

  ~ZRememberedScanForwardingContext() {
    print();
  }

  void report_retained(const Tickspan& duration) {
    _where[0].report(duration);
  }

  void report_released(const Tickspan& duration) {
    _where[1].report(duration);
  }

  void print() {
    _where[0].print("retained");
    _where[1].print("released");
  }
};

struct ZRememberedScanForwardingMeasureRetained {
  ZRememberedScanForwardingContext* _context;
  Ticks                             _start;

  ZRememberedScanForwardingMeasureRetained(ZRememberedScanForwardingContext* context)
    : _context(context),
      _start(Ticks::now()) {
  }

  ~ZRememberedScanForwardingMeasureRetained() {
    const Ticks end = Ticks::now();
    const Tickspan duration = end - _start;
    _context->report_retained(duration);
  }
};

struct ZRememberedScanForwardingMeasureReleased {
  ZRememberedScanForwardingContext* _context;
  Ticks                             _start;

  ZRememberedScanForwardingMeasureReleased(ZRememberedScanForwardingContext* context)
    : _context(context),
      _start(Ticks::now()) {
  }

  ~ZRememberedScanForwardingMeasureReleased() {
    const Ticks end = Ticks::now();
    const Tickspan duration = end - _start;
    _context->report_released(duration);
  }
};

bool ZRemembered::scan_forwarding(ZForwarding* forwarding, void* context_void) const {
  ZRememberedScanForwardingContext* const context = (ZRememberedScanForwardingContext*)context_void;
  bool result = false;

  if (forwarding->retain_page(ZGeneration::old()->relocate_queue())) {
    ZRememberedScanForwardingMeasureRetained measure(context);
    forwarding->page()->log_msg(" (scan_forwarding)");

    // We don't want to wait for the old relocation to finish and publish all
    // relocated remembered fields. Reject its fields and collect enough data
    // up-front.
    forwarding->relocated_remembered_fields_notify_concurrent_scan_of();

    // Collect all remset info while the page is retained
    GrowableArrayCHeap<ZRememberedSetContaining, mtGC>* array = &context->_containing_array;
    array->clear();
    fill_containing(array, forwarding->page());
    forwarding->release_page();

    // Relocate (and mark) while page is released, to prevent
    // retain deadlock when relocation threads in-place relocate.
    oops_do_forwarded_via_containing(array, [&](volatile zpointer* p) {
      result |= scan_field(p);
    });

  } else {
    ZRememberedScanForwardingMeasureReleased measure(context);

    // The page has been released. If the page was relocated while this young
    // generation collection was running, the old generation relocation will
    // have published all addresses of fields that had a remembered set entry.
    forwarding->relocated_remembered_fields_apply_to_published([&](volatile zpointer* p) {
      result |= scan_field(p);
    });
  }

  return result;
}

// When scanning the remembered set during the young generation marking, we
// want to visit all old pages. And we want that to be done in parallel and
// fast.
//
// Walking over the entire page table and letting the workers claim indices
// have been shown to have scalability issues.
//
// So, we have the "found old" optimization, which allows us to perform much
// fewer claims (order of old pages, instead of order of slots in the page
// table), and it allows us to read fewer pages.
//
// The set of "found old pages" isn't precise, and can contain stale entries
// referring to slots of freed pages, or even slots where young pages have
// been installed. However, it will not lack any of the old pages.
//
// The data is maintained very similar to when and how we maintain the
// remembered set bits: We keep two separates sets, one for read-only access
// by the young marking, and a currently active set where we register new
// pages. When pages get relocated, or die, the page table slot for that page
// must be cleared. This clearing is done just like we do with the remset
// scanning: The old entries are not copied to the current active set, only
// slots that were found to actually contain old pages are registered in the
// active set.

ZRemembered::FoundOld::FoundOld()
    // Array initialization requires copy constructors, which CHeapBitMap
    // doesn't provide. Instantiate two instances, and populate an array
    // with pointers to the two instances.
  : _allocated_bitmap_0{ZAddressOffsetMax >> ZGranuleSizeShift, mtGC, true /* clear */},
    _allocated_bitmap_1{ZAddressOffsetMax >> ZGranuleSizeShift, mtGC, true /* clear */},
    _bitmaps{&_allocated_bitmap_0, &_allocated_bitmap_1},
    _current{0} {}

BitMap* ZRemembered::FoundOld::current_bitmap() {
  return _bitmaps[_current];
}

BitMap* ZRemembered::FoundOld::previous_bitmap() {
  return _bitmaps[_current ^ 1];
}

void ZRemembered::FoundOld::flip() {
  _current ^= 1;
}

void ZRemembered::FoundOld::clear_previous() {
  previous_bitmap()->clear_large();
}

void ZRemembered::FoundOld::register_page(ZPage* page) {
  assert(page->is_old(), "Only register old pages");
  current_bitmap()->par_set_bit(untype(page->start()) >> ZGranuleSizeShift, memory_order_relaxed);
}

void ZRemembered::flip_found_old_sets() {
  _found_old.flip();
}

void ZRemembered::clear_found_old_previous_set() {
  _found_old.clear_previous();
}

void ZRemembered::register_found_old(ZPage* page) {
  assert(page->is_old(), "Should only register old pages");
  _found_old.register_page(page);
}

struct ZRemsetTableEntry {
  ZPage* _page;
  ZForwarding* _forwarding;
};

class ZRemsetTableIterator {
private:
  ZRemembered* const            _remembered;
  ZPageTable* const             _page_table;
  const ZForwardingTable* const _old_forwarding_table;
  volatile BitMap::idx_t        _claimed;

public:
  ZRemsetTableIterator(ZRemembered* remembered)
    : _remembered(remembered),
      _page_table(remembered->_page_table),
      _old_forwarding_table(remembered->_old_forwarding_table),
      _claimed(0) {}

  // This iterator uses the "found old" optimization.
  bool next(ZRemsetTableEntry* entry_addr)  {
    BitMap* const bm = _remembered->_found_old.previous_bitmap();

    BitMap::idx_t prev = Atomic::load(&_claimed);

    for (;;) {
      if (prev == bm->size()) {
        return false;
      }

      const BitMap::idx_t page_index = bm->find_first_set_bit(_claimed);
      if (page_index == bm->size()) {
        Atomic::cmpxchg(&_claimed, prev, page_index, memory_order_relaxed);
        return false;
      }

      const BitMap::idx_t res = Atomic::cmpxchg(&_claimed, prev, page_index + 1, memory_order_relaxed);
      if (res != prev) {
        // Someone else claimed
        prev = res;
        continue;
      }

      // Found bit - look around for page or forwarding to scan

      ZForwarding* forwarding = nullptr;
      if (ZGeneration::old()->is_phase_relocate()) {
        forwarding = _old_forwarding_table->at(page_index);
      }

      ZPage* page = _page_table->at(page_index);
      if (page != nullptr && !page->is_old()) {
        page = nullptr;
      }

      if (page == nullptr && forwarding == nullptr) {
        // Nothing to scan
        continue;
      }

      // Found old page or old forwarding
      entry_addr->_forwarding = forwarding;
      entry_addr->_page = page;

      return true;
    }
  }
};

// This task scans the remembered set and follows pointers when possible.
// Interleaving remembered set scanning with marking makes the marking times
// lower and more predictable.
class ZRememberedScanMarkFollowTask : public ZRestartableTask {
private:
  ZRemembered* const   _remembered;
  ZMark* const         _mark;
  ZRemsetTableIterator _remset_table_iterator;

public:
  ZRememberedScanMarkFollowTask(ZRemembered* remembered, ZMark* mark)
    : ZRestartableTask("ZRememberedScanMarkFollowTask"),
      _remembered(remembered),
      _mark(mark),
      _remset_table_iterator(remembered)  {
    _mark->prepare_work();
    _remembered->_page_allocator->enable_safe_destroy();
    _remembered->_page_allocator->enable_safe_recycle();
  }

  ~ZRememberedScanMarkFollowTask() {
    _remembered->_page_allocator->disable_safe_recycle();
    _remembered->_page_allocator->disable_safe_destroy();
    _mark->finish_work();
    // We are done scanning the set of old pages.
    // Clear the set for the next young collection.
    _remembered->clear_found_old_previous_set();
  }

  virtual void work_inner() {
    ZRememberedScanForwardingContext context;

    // Follow initial roots
    if (!_mark->follow_work_partial()) {
      // Bail
      return;
    }

    for (ZRemsetTableEntry entry; _remset_table_iterator.next(&entry);) {
      bool left_marking = false;
      ZForwarding* forwarding = entry._forwarding;
      ZPage* page = entry._page;

      // Scan forwarding
      if (forwarding != nullptr) {
        bool found_roots = _remembered->scan_forwarding(forwarding, &context);
        ZVerify::after_scan(forwarding);
        if (found_roots) {
          // Follow remembered set when possible
          left_marking = !_mark->follow_work_partial();
        }
      }

      // Scan page
      if (page != nullptr) {
        if (_remembered->should_scan_page(page)) {
          // Visit all entries pointing into young gen
          bool found_roots = _remembered->scan_page(page);

          // ... and as a side-effect clear the previous entries
          if (ZVerifyRemembered) {
            // Make sure self healing of pointers is ordered before clearing of
            // the previous bits so that ZVerify::after_scan can detect missing
            // remset entries accurately.
            OrderAccess::storestore();
          }
          page->clear_remset_previous();

          if (found_roots && !left_marking) {
            // Follow remembered set when possible
            left_marking = !_mark->follow_work_partial();
          }
        }

        // The remset scanning maintains the "maybe old" pages optimization.
        //
        // We maintain two sets of old pages: The first is the currently active
        // set, where old pages are registered into. The second is the old
        // read-only copy. The two sets flip during young mark start. This
        // analogous to how we set and clean remembered set bits.
        //
        // The iterator reads from the read-only copy, and then here, we install
        // entries in the current active set.
        _remembered->register_found_old(page);
      }

      SuspendibleThreadSet::yield();
      if (left_marking) {
        // Bail
        return;
      }
    }

    _mark->follow_work_complete();
  }

  virtual void work() {
    SuspendibleThreadSetJoiner sts_joiner;
    work_inner();
    // We might have found pointers into the other generation, and then we want to
    // publish such marking stacks to prevent that generation from getting a mark continue.
    // We also flush in case of a resize where a new worker thread continues the marking
    // work, causing a mark continue for the collected generation.
    ZHeap::heap()->mark_flush_and_free(Thread::current());
  }

  virtual void resize_workers(uint nworkers) {
    _mark->resize_workers(nworkers);
  }
};

void ZRemembered::scan_and_follow(ZMark* mark) {
  {
    // Follow the object graph and lazily scan the remembered set
    ZRememberedScanMarkFollowTask task(this, mark);
    ZGeneration::young()->workers()->run(&task);

    // Try to terminate after following the graph
    if (ZAbort::should_abort() || !mark->try_terminate_flush()) {
      return;
    }
  }

  // If flushing failed, we have to restart marking again, but this time we don't need to
  // scan the remembered set.
  mark->mark_follow();
}

bool ZRemembered::scan_field(volatile zpointer* p) const {
  assert(ZGeneration::young()->is_phase_mark(), "Wrong phase");

  const zaddress addr = ZBarrier::remset_barrier_on_oop_field(p);

  if (!is_null(addr) && ZHeap::heap()->is_young(addr)) {
    remember(p);
    return true;
  }

  return false;
}

void ZRemembered::flip() {
  ZRememberedSet::flip();
  flip_found_old_sets();
}
