/*
 * Copyright (c) 1997, 2020, 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.
 *
 */

#ifndef SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP
#define SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP

#include "gc/g1/heapRegionRemSet.hpp"

#include "gc/g1/g1CardSet.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "runtime/atomic.hpp"
#include "utilities/bitMap.inline.hpp"

void HeapRegionRemSet::set_state_untracked() {
  guarantee(SafepointSynchronize::is_at_safepoint() || !is_tracked(),
            "Should only set to Untracked during safepoint but is %s.", get_state_str());
  if (_state == Untracked) {
    return;
  }
  clear_fcc();
  _state = Untracked;
}

void HeapRegionRemSet::set_state_updating() {
  guarantee(SafepointSynchronize::is_at_safepoint() && !is_tracked(),
            "Should only set to Updating from Untracked during safepoint but is %s", get_state_str());
  clear_fcc();
  _state = Updating;
}

void HeapRegionRemSet::set_state_complete() {
  clear_fcc();
  _state = Complete;
}

template <typename Closure>
class G1ContainerCardsOrRanges {
  Closure& _cl;
  uint _region_idx;
  uint _offset;

public:
  G1ContainerCardsOrRanges(Closure& cl, uint region_idx, uint offset) : _cl(cl), _region_idx(region_idx), _offset(offset) { }

  bool start_iterate(uint tag) {
    return _cl.start_iterate(tag, _region_idx);
  }

  void operator()(uint card_idx) {
    _cl.do_card(card_idx + _offset);
  }

  void operator()(uint card_idx, uint length) {
    _cl.do_card_range(card_idx + _offset, length);
  }
};

template <typename Closure, template <typename> class CardOrRanges>
class G1HeapRegionRemSetMergeCardClosure : public G1CardSet::ContainerPtrClosure {
  G1CardSet* _card_set;
  Closure& _cl;
  uint _log_card_regions_per_region;
  uint _card_regions_per_region_mask;
  uint _log_card_region_size;

public:

  G1HeapRegionRemSetMergeCardClosure(G1CardSet* card_set,
                                      Closure& cl,
                                      uint log_card_regions_per_region,
                                      uint log_card_region_size) :
    _card_set(card_set),
    _cl(cl),
    _log_card_regions_per_region(log_card_regions_per_region),
    _card_regions_per_region_mask((1 << log_card_regions_per_region) - 1),
    _log_card_region_size(log_card_region_size) {
  }

  void do_containerptr(uint card_region_idx, size_t num_occupied, G1CardSet::ContainerPtr container) override {
    CardOrRanges<Closure> cl(_cl,
                             card_region_idx >> _log_card_regions_per_region,
                             (card_region_idx & _card_regions_per_region_mask) << _log_card_region_size);
    _card_set->iterate_cards_or_ranges_in_container(container, cl);
  }
};

template <class CardOrRangeVisitor>
inline void HeapRegionRemSet::iterate_for_merge(CardOrRangeVisitor& cl) {
  G1HeapRegionRemSetMergeCardClosure<CardOrRangeVisitor, G1ContainerCardsOrRanges> cl2(&_card_set,
                                                                                       cl,
                                                                                       _card_set.config()->log2_card_regions_per_heap_region(),
                                                                                       _card_set.config()->log2_cards_per_card_region());
  _card_set.iterate_containers(&cl2, true /* at_safepoint */);
}


uintptr_t HeapRegionRemSet::to_card(OopOrNarrowOopStar from) const {
  return pointer_delta(from, _heap_base_address, 1) >> CardTable::card_shift();
}

void HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, uint tid) {
  assert(_state != Untracked, "must be");

  uint cur_idx = _hr->hrm_index();
  uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift();

  if (G1FromCardCache::contains_or_replace(tid, cur_idx, from_card)) {
    // We can't check whether the card is in the remembered set - the card container
    // may be coarsened just now.
    //assert(contains_reference(from), "We just found " PTR_FORMAT " in the FromCardCache", p2i(from));
   return;
  }

  _card_set.add_card(to_card(from));
}

bool HeapRegionRemSet::contains_reference(OopOrNarrowOopStar from) {
  return _card_set.contains_card(to_card(from));
}

void HeapRegionRemSet::print_info(outputStream* st, OopOrNarrowOopStar from) {
  _card_set.print_info(st, to_card(from));
}

#endif // SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP
