/*
 * Copyright (C) 2008 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_SPACE_BITMAP_INL_H_
#define ART_SRC_GC_SPACE_BITMAP_INL_H_

#include "base/logging.h"
#include "cutils/atomic.h"

namespace art {

inline bool SpaceBitmap::AtomicTestAndSet(const mirror::Object* obj) {
  uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
  DCHECK_GE(addr, heap_begin_);
  const uintptr_t offset = addr - heap_begin_;
  const size_t index = OffsetToIndex(offset);
  const word mask = OffsetToMask(offset);
  word* const address = &bitmap_begin_[index];
  DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_;
  word old_word;
  do {
    old_word = *address;
    // Fast path: The bit is already set.
    if ((old_word & mask) != 0) {
      return true;
    }
  } while (UNLIKELY(android_atomic_cas(old_word, old_word | mask, address) != 0));
  return false;
}

inline bool SpaceBitmap::Test(const mirror::Object* obj) const {
  uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
  DCHECK(HasAddress(obj)) << obj;
  DCHECK(bitmap_begin_ != NULL);
  DCHECK_GE(addr, heap_begin_);
  const uintptr_t offset = addr - heap_begin_;
  return (bitmap_begin_[OffsetToIndex(offset)] & OffsetToMask(offset)) != 0;
}

template <typename Visitor, typename FingerVisitor>
void SpaceBitmap::VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end,
                                   const Visitor& visitor,
                                   const FingerVisitor& finger_visitor) const {
  DCHECK_LT(visit_begin, visit_end);

  const size_t word_span = kAlignment * kBitsPerWord; // Equals IndexToOffset(1).
  const size_t bit_index_start = (visit_begin - heap_begin_) / kAlignment;
  const size_t bit_index_end = (visit_end - heap_begin_ - 1) / kAlignment;

  size_t word_start = bit_index_start / kBitsPerWord;
  size_t word_end = bit_index_end / kBitsPerWord;
  DCHECK_LT(word_end * kWordSize, Size());

  // Trim off left_bits of left bits.
  size_t edge_word = bitmap_begin_[word_start];

  // Handle bits on the left first as a special case
  size_t left_bits = bit_index_start & (kBitsPerWord - 1);
  if (left_bits != 0) {
    edge_word &= (1 << (kBitsPerWord - left_bits)) - 1;
  }

  // If word_start == word_end then handle this case at the same place we handle the right edge.
  if (edge_word != 0 && word_start < word_end) {
    uintptr_t ptr_base = IndexToOffset(word_start) + heap_begin_;
    finger_visitor(reinterpret_cast<void*>(ptr_base + word_span));
    do {
      const size_t shift = CLZ(edge_word);
      mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
      visitor(obj);
      edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift;
    } while (edge_word != 0);
  }
  word_start++;

  for (size_t i = word_start; i < word_end; i++) {
    size_t w = bitmap_begin_[i];
    if (w != 0) {
      uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;
      finger_visitor(reinterpret_cast<void*>(ptr_base + word_span));
      do {
        const size_t shift = CLZ(w);
        mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
        visitor(obj);
        w ^= static_cast<size_t>(kWordHighBitMask) >> shift;
      } while (w != 0);
    }
  }

  // Handle the right edge, and also the left edge if both edges are on the same word.
  size_t right_bits = bit_index_end & (kBitsPerWord - 1);

  // If word_start == word_end then we need to use the word which we removed the left bits.
  if (word_start <= word_end) {
    edge_word = bitmap_begin_[word_end];
  }

  // Bits that we trim off the right.
  edge_word &= ~((static_cast<size_t>(kWordHighBitMask) >> right_bits) - 1);
  uintptr_t ptr_base = IndexToOffset(word_end) + heap_begin_;
  finger_visitor(reinterpret_cast<void*>(ptr_base + word_span));
  while (edge_word != 0) {
    const size_t shift = CLZ(edge_word);
    mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment);
    visitor(obj);
    edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift;
  }
}

inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) {
  uintptr_t addr = reinterpret_cast<uintptr_t>(obj);
  DCHECK_GE(addr, heap_begin_);
  const uintptr_t offset = addr - heap_begin_;
  const size_t index = OffsetToIndex(offset);
  const word mask = OffsetToMask(offset);
  DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_;
  word* address = &bitmap_begin_[index];
  word old_word = *address;
  if (do_set) {
    *address = old_word | mask;
  } else {
    *address = old_word & ~mask;
  }
  return (old_word & mask) != 0;
}
}  // namespace art

#endif  // ART_SRC_GC_SPACE_BITMAP_INL_H_
