/*
 * Copyright (c) 2022, 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/g1/g1ConcurrentRebuildAndScrub.hpp"

#include "gc/g1/g1ConcurrentMark.inline.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1_globals.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/shared/workerThread.hpp"
#include "logging/log.hpp"
#include "memory/memRegion.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"

// Worker task that scans the objects in the old generation to rebuild the remembered
// set and at the same time scrubs dead objects by replacing them with filler objects
// to make them completely parseable.
//
// The remark pause recorded two pointers within the regions:
//
// parsable_bottom (pb): this is the TAMS of the recent marking for that region. Objects
//                       below that may or may not be dead (as per mark bitmap).
//                       This task needs to remove the dead objects, replacing them
//                       with filler objects so that they can be walked through later.
//
// top_at_rebuild_start (tars): at rebuild phase start we record the current top: up to
//                              this address (live) objects need to be scanned for references
//                              that might need to be added to the remembered sets.
//
// Note that bottom <= parsable_bottom <= tars; if there is no tars (i.e. null),
// obviously there can not be a parsable_bottom.
//
// We need to scrub and scan objects to rebuild remembered sets until parsable_bottom;
// we need to scan objects to rebuild remembered sets until tars.
class G1RebuildRSAndScrubTask : public WorkerTask {
  G1ConcurrentMark* _cm;
  HeapRegionClaimer _hr_claimer;

  const bool _should_rebuild_remset;

  class G1RebuildRSAndScrubRegionClosure : public HeapRegionClosure {
    G1ConcurrentMark* _cm;
    const G1CMBitMap* _bitmap;

    G1RebuildRemSetClosure _rebuild_closure;

    const bool _should_rebuild_remset;

    size_t _processed_words;

    const size_t ProcessingYieldLimitInWords = G1RebuildRemSetChunkSize / HeapWordSize;

    void reset_processed_words() {
      _processed_words = 0;
    }

    void add_processed_words(size_t processed) {
      _processed_words += processed;
    }

    // Yield if enough has been processed; returns if the concurrent marking cycle
    // has been aborted for any reason.
    bool yield_if_necessary() {
      if (_processed_words >= ProcessingYieldLimitInWords) {
        reset_processed_words();
        _cm->do_yield_check();
      }
      return _cm->has_aborted();
    }

    // Returns whether the top at rebuild start value for the given region indicates
    // that there is some rebuild or scrubbing work.
    //
    // Based on the results of G1RemSetTrackingPolicy::needs_scan_for_rebuild(),
    // the value may be changed to null during rebuilding if the region has either:
    //  - been allocated after rebuild start, or
    //  - been eagerly reclaimed by a young collection (only humongous)
    bool should_rebuild_or_scrub(HeapRegion* hr) const {
      return _cm->top_at_rebuild_start(hr->hrm_index()) != nullptr;
    }

    // Helper used by both humongous objects and when chunking an object larger than the
    // G1RebuildRemSetChunkSize. The heap region is needed to ensure a humongous object
    // is not eagerly reclaimed during yielding.
    // Returns whether marking has been aborted.
    bool scan_large_object(HeapRegion* hr, const oop obj, MemRegion scan_range) {
      HeapWord* start = scan_range.start();
      HeapWord* limit = scan_range.end();
      do {
        MemRegion mr(start, MIN2(start + ProcessingYieldLimitInWords, limit));
        obj->oop_iterate(&_rebuild_closure, mr);

        // Update processed words and yield, for humongous objects we will yield
        // after each chunk.
        add_processed_words(mr.word_size());
        bool mark_aborted = yield_if_necessary();
        if (mark_aborted) {
          return true;
        } else if (!should_rebuild_or_scrub(hr)) {
          // We need to check should_rebuild_or_scrub() again (for humongous objects)
          // because the region might have been eagerly reclaimed during the yield.
          log_trace(gc, marking)("Rebuild aborted for eagerly reclaimed humongous region: %u", hr->hrm_index());
          return false;
        }

        // Step to next chunk of the humongous object
        start = mr.end();
      } while (start < limit);
      return false;
    }

    // Scan for references into regions that need remembered set update for the given
    // live object. Returns the offset to the next object.
    size_t scan_object(HeapRegion* hr, HeapWord* current) {
      oop obj = cast_to_oop(current);
      size_t obj_size = obj->size();

      if (!_should_rebuild_remset) {
        // Not rebuilding, just step to next object.
        add_processed_words(obj_size);
      } else if (obj_size > ProcessingYieldLimitInWords) {
        // Large object, needs to be chunked to avoid stalling safepoints.
        MemRegion mr(current, obj_size);
        scan_large_object(hr, obj, mr);
        // No need to add to _processed_words, this is all handled by the above call;
        // we also ignore the marking abort result of scan_large_object - we will check
        // again right afterwards.
      } else {
        // Object smaller than yield limit, process it fully.
        obj->oop_iterate(&_rebuild_closure);
        // Update how much we have processed. Yield check in main loop
        // will handle this case.
        add_processed_words(obj_size);
      }

      return obj_size;
    }

    // Scrub a range of dead objects starting at scrub_start. Will never scrub past limit.
    HeapWord* scrub_to_next_live(HeapRegion* hr, HeapWord* scrub_start, HeapWord* limit) {
      assert(!_bitmap->is_marked(scrub_start), "Should not scrub live object");

      HeapWord* scrub_end = _bitmap->get_next_marked_addr(scrub_start, limit);
      hr->fill_range_with_dead_objects(scrub_start, scrub_end);

      // Return the next object to handle.
      return scrub_end;
    }

    // Scan the given region from bottom to parsable_bottom. Returns whether marking has
    // been aborted.
    bool scan_and_scrub_to_pb(HeapRegion* hr, HeapWord* start, HeapWord* const limit) {

      while (start < limit) {
        if (_bitmap->is_marked(start)) {
          //  Live object, need to scan to rebuild remembered sets for this object.
          start += scan_object(hr, start);
        } else {
          // Found dead object (which klass has potentially been unloaded). Scrub to next
          // marked object and continue.
          start = scrub_to_next_live(hr, start, limit);
        }

        bool mark_aborted = yield_if_necessary();
        if (mark_aborted) {
          return true;
        }
      }
      return false;
    }

    // Scan the given region from parsable_bottom to tars. Returns whether marking has
    // been aborted.
    bool scan_from_pb_to_tars(HeapRegion* hr, HeapWord* start, HeapWord* const limit) {

      while (start < limit) {
        start += scan_object(hr, start);
        // Avoid stalling safepoints and stop iteration if mark cycle has been aborted.
        bool mark_aborted = yield_if_necessary();
        if (mark_aborted) {
          return true;
        }
      }
      return false;
    }

    // Scan and scrub the given region to tars. Returns whether marking has
    // been aborted.
    bool scan_and_scrub_region(HeapRegion* hr, HeapWord* const pb) {
      assert(should_rebuild_or_scrub(hr), "must be");

      log_trace(gc, marking)("Scrub and rebuild region: " HR_FORMAT " pb: " PTR_FORMAT " TARS: " PTR_FORMAT,
                             HR_FORMAT_PARAMS(hr), p2i(pb), p2i(_cm->top_at_rebuild_start(hr->hrm_index())));

      if (scan_and_scrub_to_pb(hr, hr->bottom(), pb)) {
        log_trace(gc, marking)("Scan and scrub aborted for region: %u", hr->hrm_index());
        return true;
      }

      // Scrubbing completed for this region - notify that we are done with it, resetting
      // pb to bottom.
      hr->note_end_of_scrubbing();

      // Rebuild from TAMS (= parsable_bottom) to TARS.
      if (scan_from_pb_to_tars(hr, pb, _cm->top_at_rebuild_start(hr->hrm_index()))) {
        log_trace(gc, marking)("Rebuild aborted for region: %u (%s)", hr->hrm_index(), hr->get_short_type_str());
        return true;
      }
      return false;
    }

    // Scan a humongous region for remembered set updates. Scans in chunks to avoid
    // stalling safepoints. Returns whether the concurrent marking phase has been aborted.
    bool scan_humongous_region(HeapRegion* hr, HeapWord* const pb) {
      assert(should_rebuild_or_scrub(hr), "must be");

      if (!_should_rebuild_remset) {
        // When not rebuilding there is nothing to do for humongous objects.
        return false;
      }

      // At this point we should only have live humongous objects, that
      // means it must either be:
      // - marked
      // - or seen as fully parsable, i.e. allocated after the marking started
      oop humongous = cast_to_oop(hr->humongous_start_region()->bottom());
      assert(_bitmap->is_marked(humongous) || pb == hr->bottom(),
             "Humongous object not live");

      log_trace(gc, marking)("Rebuild for humongous region: " HR_FORMAT " pb: " PTR_FORMAT " TARS: " PTR_FORMAT,
                              HR_FORMAT_PARAMS(hr), p2i(pb), p2i(_cm->top_at_rebuild_start(hr->hrm_index())));

      // Scan the humongous object in chunks from bottom to top to rebuild remembered sets.
      HeapWord* humongous_end = hr->humongous_start_region()->bottom() + humongous->size();
      MemRegion mr(hr->bottom(), MIN2(hr->top(), humongous_end));

      bool mark_aborted = scan_large_object(hr, humongous, mr);
      if (mark_aborted) {
        log_trace(gc, marking)("Rebuild aborted for region: %u (%s)", hr->hrm_index(), hr->get_short_type_str());
        return true;
      }
      return false;
    }

  public:
    G1RebuildRSAndScrubRegionClosure(G1ConcurrentMark* cm, bool should_rebuild_remset, uint worker_id) :
      _cm(cm),
      _bitmap(_cm->mark_bitmap()),
      _rebuild_closure(G1CollectedHeap::heap(), worker_id),
      _should_rebuild_remset(should_rebuild_remset),
      _processed_words(0) { }

    bool do_heap_region(HeapRegion* hr) {
      // Avoid stalling safepoints and stop iteration if mark cycle has been aborted.
      _cm->do_yield_check();
      if (_cm->has_aborted()) {
        return true;
      }

      HeapWord* const pb = hr->parsable_bottom_acquire();

      if (!should_rebuild_or_scrub(hr)) {
        // Region has been allocated during this phase, no need to either scrub or
        // scan to rebuild remembered sets.
        log_trace(gc, marking)("Scrub and rebuild region skipped for " HR_FORMAT " pb: " PTR_FORMAT,
                               HR_FORMAT_PARAMS(hr), p2i(pb));
        assert(hr->bottom() == pb, "Region must be fully parsable");
        return false;
      }

      bool mark_aborted;
      if (hr->needs_scrubbing()) {
        // This is a region with potentially unparsable (dead) objects.
        mark_aborted = scan_and_scrub_region(hr, pb);
      } else {
        assert(hr->is_humongous(), "must be, but %u is %s", hr->hrm_index(), hr->get_short_type_str());
        // No need to scrub humongous, but we should scan it to rebuild remsets.
        mark_aborted = scan_humongous_region(hr, pb);
      }

      return mark_aborted;
    }
  };

public:
  G1RebuildRSAndScrubTask(G1ConcurrentMark* cm, bool should_rebuild_remset, uint num_workers) :
    WorkerTask("Scrub dead objects"),
    _cm(cm),
    _hr_claimer(num_workers),
    _should_rebuild_remset(should_rebuild_remset) { }

  void work(uint worker_id) {
    SuspendibleThreadSetJoiner sts_join;

    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    G1RebuildRSAndScrubRegionClosure cl(_cm, _should_rebuild_remset, worker_id);
    g1h->heap_region_par_iterate_from_worker_offset(&cl, &_hr_claimer, worker_id);
  }
};

void G1ConcurrentRebuildAndScrub::rebuild_and_scrub(G1ConcurrentMark* cm, bool should_rebuild_remset, WorkerThreads* workers) {
  uint num_workers = workers->active_workers();

  G1RebuildRSAndScrubTask task(cm, should_rebuild_remset, num_workers);
  workers->run_task(&task, num_workers);
}
