/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_SRC_GC_MOD_UNION_TABLE_H_
#define ART_SRC_GC_MOD_UNION_TABLE_H_

#include "globals.h"
#include "safe_map.h"

#include <set>
#include <vector>

namespace art {
namespace mirror {
class Object;
}
class ContinuousSpace;
class Heap;
class HeapBitmap;
class MarkSweep;
class Space;
class SpaceBitmap;

// Base class
class ModUnionTable {
 public:
  typedef std::vector<const mirror::Object*> ReferenceArray;
  typedef std::set<byte*> ClearedCards;

  ModUnionTable(Heap* heap) : heap_(heap) {

  }

  virtual ~ModUnionTable() {

  }

  // Clear cards which map to a memory range of a space.
  virtual void ClearCards(ContinuousSpace* space) = 0;

  // Update the mod-union table.
  virtual void Update() = 0;

  // Mark all references which are stored in the mod union table.
  virtual void MarkReferences(MarkSweep* mark_sweep) = 0;

  // Verification, sanity checks that we don't have clean cards which conflict with out cached data
  // for said cards. Exclusive lock is required since verify sometimes uses
  // SpaceBitmap::VisitMarkedRange and VisitMarkedRange can't know if the callback will modify the
  // bitmap or not.
  virtual void Verify() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) = 0;

  Heap* GetHeap() {
    return heap_;
  }

 protected:
  Heap* heap_;
};

// Bitmap implementation.
// DEPRECATED, performs strictly less well than merely caching which cards were dirty.
class ModUnionTableBitmap : public ModUnionTable {
 public:
  ModUnionTableBitmap(Heap* heap);
  virtual ~ModUnionTableBitmap();

  // Clear space cards.
  void ClearCards(ContinuousSpace* space);

  // Update table based on cleared cards.
  void Update()
      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Mark all references to the alloc space(s).
  void MarkReferences(MarkSweep* mark_sweep) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);

 protected:
  // Cleared card array, used to update the mod-union table.
  std::vector<byte*> cleared_cards_;

  // One bitmap per image space.
  // TODO: Add support for Zygote spaces?
  typedef SafeMap<ContinuousSpace*, SpaceBitmap*> BitmapMap;
  BitmapMap bitmaps_;
};

// Reference caching implementation. Caches references pointing to alloc space(s) for each card.
class ModUnionTableReferenceCache : public ModUnionTable {
 public:
  typedef SafeMap<const byte*, ReferenceArray > ReferenceMap;

  ModUnionTableReferenceCache(Heap* heap);
  virtual ~ModUnionTableReferenceCache();

  // Clear and store cards for a space.
  void ClearCards(ContinuousSpace* space);

  // Update table based on cleared cards.
  void Update()
      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Mark all references to the alloc space(s).
  void MarkReferences(MarkSweep* mark_sweep)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);

  // Exclusive lock is required since verify uses SpaceBitmap::VisitMarkedRange and
  // VisitMarkedRange can't know if the callback will modify the bitmap or not.
  void Verify() EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);

  // Function that tells whether or not to add a reference to the table.
  virtual bool AddReference(const mirror::Object* obj, const mirror::Object* ref) = 0;

 protected:
  // Cleared card array, used to update the mod-union table.
  ClearedCards cleared_cards_;

  // Maps from dirty cards to their corresponding alloc space references.
  ReferenceMap references_;
};

// Card caching implementation. Keeps track of which cards we cleared and only this information.
class ModUnionTableCardCache : public ModUnionTable {
 public:
  typedef SafeMap<const byte*, ReferenceArray > ReferenceMap;

  ModUnionTableCardCache(Heap* heap);
  virtual ~ModUnionTableCardCache();

  // Clear and store cards for a space.
  void ClearCards(ContinuousSpace* space);

  // Nothing to update.
  void Update() {}

  // Mark all references to the alloc space(s).
  void MarkReferences(MarkSweep* mark_sweep)
      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Nothing to verify.
  void Verify() {}

 protected:
  // Cleared card array, used to update the mod-union table.
  ClearedCards cleared_cards_;
};

}  // namespace art

#endif  // ART_SRC_GC_MOD_UNION_TABLE_H_
