// Copyright 2006-2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef V8_SPACES_INL_H_
#define V8_SPACES_INL_H_

#include "isolate.h"
#include "spaces.h"
#include "v8memory.h"

namespace v8 {
namespace internal {


// -----------------------------------------------------------------------------
// PageIterator

bool PageIterator::has_next() {
  return prev_page_ != stop_page_;
}


Page* PageIterator::next() {
  ASSERT(has_next());
  prev_page_ = (prev_page_ == NULL)
               ? space_->first_page_
               : prev_page_->next_page();
  return prev_page_;
}


// -----------------------------------------------------------------------------
// Page

Page* Page::next_page() {
  return heap_->isolate()->memory_allocator()->GetNextPage(this);
}


Address Page::AllocationTop() {
  PagedSpace* owner = heap_->isolate()->memory_allocator()->PageOwner(this);
  return owner->PageAllocationTop(this);
}


Address Page::AllocationWatermark() {
  PagedSpace* owner = heap_->isolate()->memory_allocator()->PageOwner(this);
  if (this == owner->AllocationTopPage()) {
    return owner->top();
  }
  return address() + AllocationWatermarkOffset();
}


uint32_t Page::AllocationWatermarkOffset() {
  return static_cast<uint32_t>((flags_ & kAllocationWatermarkOffsetMask) >>
                               kAllocationWatermarkOffsetShift);
}


void Page::SetAllocationWatermark(Address allocation_watermark) {
  if ((heap_->gc_state() == Heap::SCAVENGE) && IsWatermarkValid()) {
    // When iterating intergenerational references during scavenge
    // we might decide to promote an encountered young object.
    // We will allocate a space for such an object and put it
    // into the promotion queue to process it later.
    // If space for object was allocated somewhere beyond allocation
    // watermark this might cause garbage pointers to appear under allocation
    // watermark. To avoid visiting them during dirty regions iteration
    // which might be still in progress we store a valid allocation watermark
    // value and mark this page as having an invalid watermark.
    SetCachedAllocationWatermark(AllocationWatermark());
    InvalidateWatermark(true);
  }

  flags_ = (flags_ & kFlagsMask) |
           Offset(allocation_watermark) << kAllocationWatermarkOffsetShift;
  ASSERT(AllocationWatermarkOffset()
         == static_cast<uint32_t>(Offset(allocation_watermark)));
}


void Page::SetCachedAllocationWatermark(Address allocation_watermark) {
  mc_first_forwarded = allocation_watermark;
}


Address Page::CachedAllocationWatermark() {
  return mc_first_forwarded;
}


uint32_t Page::GetRegionMarks() {
  return dirty_regions_;
}


void Page::SetRegionMarks(uint32_t marks) {
  dirty_regions_ = marks;
}


int Page::GetRegionNumberForAddress(Address addr) {
  // Each page is divided into 256 byte regions. Each region has a corresponding
  // dirty mark bit in the page header. Region can contain intergenerational
  // references iff its dirty mark is set.
  // A normal 8K page contains exactly 32 regions so all region marks fit
  // into 32-bit integer field. To calculate a region number we just divide
  // offset inside page by region size.
  // A large page can contain more then 32 regions. But we want to avoid
  // additional write barrier code for distinguishing between large and normal
  // pages so we just ignore the fact that addr points into a large page and
  // calculate region number as if addr pointed into a normal 8K page. This way
  // we get a region number modulo 32 so for large pages several regions might
  // be mapped to a single dirty mark.
  ASSERT_PAGE_ALIGNED(this->address());
  STATIC_ASSERT((kPageAlignmentMask >> kRegionSizeLog2) < kBitsPerInt);

  // We are using masking with kPageAlignmentMask instead of Page::Offset()
  // to get an offset to the beginning of 8K page containing addr not to the
  // beginning of actual page which can be bigger then 8K.
  intptr_t offset_inside_normal_page = OffsetFrom(addr) & kPageAlignmentMask;
  return static_cast<int>(offset_inside_normal_page >> kRegionSizeLog2);
}


uint32_t Page::GetRegionMaskForAddress(Address addr) {
  return 1 << GetRegionNumberForAddress(addr);
}


uint32_t Page::GetRegionMaskForSpan(Address start, int length_in_bytes) {
  uint32_t result = 0;
  static const intptr_t kRegionMask = (1 << kRegionSizeLog2) - 1;
  if (length_in_bytes + (OffsetFrom(start) & kRegionMask) >= kPageSize) {
    result = kAllRegionsDirtyMarks;
  } else if (length_in_bytes > 0) {
    int start_region = GetRegionNumberForAddress(start);
    int end_region =
        GetRegionNumberForAddress(start + length_in_bytes - kPointerSize);
    uint32_t start_mask = (~0) << start_region;
    uint32_t end_mask = ~((~1) << end_region);
    result = start_mask & end_mask;
    // if end_region < start_region, the mask is ored.
    if (result == 0) result = start_mask | end_mask;
  }
#ifdef DEBUG
  if (FLAG_enable_slow_asserts) {
    uint32_t expected = 0;
    for (Address a = start; a < start + length_in_bytes; a += kPointerSize) {
      expected |= GetRegionMaskForAddress(a);
    }
    ASSERT(expected == result);
  }
#endif
  return result;
}


void Page::MarkRegionDirty(Address address) {
  SetRegionMarks(GetRegionMarks() | GetRegionMaskForAddress(address));
}


bool Page::IsRegionDirty(Address address) {
  return GetRegionMarks() & GetRegionMaskForAddress(address);
}


void Page::ClearRegionMarks(Address start, Address end, bool reaches_limit) {
  int rstart = GetRegionNumberForAddress(start);
  int rend = GetRegionNumberForAddress(end);

  if (reaches_limit) {
    end += 1;
  }

  if ((rend - rstart) == 0) {
    return;
  }

  uint32_t bitmask = 0;

  if ((OffsetFrom(start) & kRegionAlignmentMask) == 0
      || (start == ObjectAreaStart())) {
    // First region is fully covered
    bitmask = 1 << rstart;
  }

  while (++rstart < rend) {
    bitmask |= 1 << rstart;
  }

  if (bitmask) {
    SetRegionMarks(GetRegionMarks() & ~bitmask);
  }
}


void Page::FlipMeaningOfInvalidatedWatermarkFlag(Heap* heap) {
  heap->page_watermark_invalidated_mark_ ^= 1 << WATERMARK_INVALIDATED;
}


bool Page::IsWatermarkValid() {
  return (flags_ & (1 << WATERMARK_INVALIDATED)) !=
      heap_->page_watermark_invalidated_mark_;
}


void Page::InvalidateWatermark(bool value) {
  if (value) {
    flags_ = (flags_ & ~(1 << WATERMARK_INVALIDATED)) |
             heap_->page_watermark_invalidated_mark_;
  } else {
    flags_ =
        (flags_ & ~(1 << WATERMARK_INVALIDATED)) |
        (heap_->page_watermark_invalidated_mark_ ^
         (1 << WATERMARK_INVALIDATED));
  }

  ASSERT(IsWatermarkValid() == !value);
}


bool Page::GetPageFlag(PageFlag flag) {
  return (flags_ & static_cast<intptr_t>(1 << flag)) != 0;
}


void Page::SetPageFlag(PageFlag flag, bool value) {
  if (value) {
    flags_ |= static_cast<intptr_t>(1 << flag);
  } else {
    flags_ &= ~static_cast<intptr_t>(1 << flag);
  }
}


void Page::ClearPageFlags() {
  flags_ = 0;
}


void Page::ClearGCFields() {
  InvalidateWatermark(true);
  SetAllocationWatermark(ObjectAreaStart());
  if (heap_->gc_state() == Heap::SCAVENGE) {
    SetCachedAllocationWatermark(ObjectAreaStart());
  }
  SetRegionMarks(kAllRegionsCleanMarks);
}


bool Page::WasInUseBeforeMC() {
  return GetPageFlag(WAS_IN_USE_BEFORE_MC);
}


void Page::SetWasInUseBeforeMC(bool was_in_use) {
  SetPageFlag(WAS_IN_USE_BEFORE_MC, was_in_use);
}


bool Page::IsLargeObjectPage() {
  return !GetPageFlag(IS_NORMAL_PAGE);
}


void Page::SetIsLargeObjectPage(bool is_large_object_page) {
  SetPageFlag(IS_NORMAL_PAGE, !is_large_object_page);
}

Executability Page::PageExecutability() {
  return GetPageFlag(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE;
}


void Page::SetPageExecutability(Executability executable) {
  SetPageFlag(IS_EXECUTABLE, executable == EXECUTABLE);
}


// -----------------------------------------------------------------------------
// MemoryAllocator

void MemoryAllocator::ChunkInfo::init(Address a, size_t s, PagedSpace* o) {
  address_ = a;
  size_ = s;
  owner_ = o;
  executable_ = (o == NULL) ? NOT_EXECUTABLE : o->executable();
  owner_identity_ = (o == NULL) ? FIRST_SPACE : o->identity();
}


bool MemoryAllocator::IsValidChunk(int chunk_id) {
  if (!IsValidChunkId(chunk_id)) return false;

  ChunkInfo& c = chunks_[chunk_id];
  return (c.address() != NULL) && (c.size() != 0) && (c.owner() != NULL);
}


bool MemoryAllocator::IsValidChunkId(int chunk_id) {
  return (0 <= chunk_id) && (chunk_id < max_nof_chunks_);
}


bool MemoryAllocator::IsPageInSpace(Page* p, PagedSpace* space) {
  ASSERT(p->is_valid());

  int chunk_id = GetChunkId(p);
  if (!IsValidChunkId(chunk_id)) return false;

  ChunkInfo& c = chunks_[chunk_id];
  return (c.address() <= p->address()) &&
         (p->address() < c.address() + c.size()) &&
         (space == c.owner());
}


Page* MemoryAllocator::GetNextPage(Page* p) {
  ASSERT(p->is_valid());
  intptr_t raw_addr = p->opaque_header & ~Page::kPageAlignmentMask;
  return Page::FromAddress(AddressFrom<Address>(raw_addr));
}


int MemoryAllocator::GetChunkId(Page* p) {
  ASSERT(p->is_valid());
  return static_cast<int>(p->opaque_header & Page::kPageAlignmentMask);
}


void MemoryAllocator::SetNextPage(Page* prev, Page* next) {
  ASSERT(prev->is_valid());
  int chunk_id = GetChunkId(prev);
  ASSERT_PAGE_ALIGNED(next->address());
  prev->opaque_header = OffsetFrom(next->address()) | chunk_id;
}


PagedSpace* MemoryAllocator::PageOwner(Page* page) {
  int chunk_id = GetChunkId(page);
  ASSERT(IsValidChunk(chunk_id));
  return chunks_[chunk_id].owner();
}


bool MemoryAllocator::InInitialChunk(Address address) {
  if (initial_chunk_ == NULL) return false;

  Address start = static_cast<Address>(initial_chunk_->address());
  return (start <= address) && (address < start + initial_chunk_->size());
}


// --------------------------------------------------------------------------
// PagedSpace

bool PagedSpace::Contains(Address addr) {
  Page* p = Page::FromAddress(addr);
  if (!p->is_valid()) return false;
  return heap()->isolate()->memory_allocator()->IsPageInSpace(p, this);
}


// Try linear allocation in the page of alloc_info's allocation top.  Does
// not contain slow case logic (eg, move to the next page or try free list
// allocation) so it can be used by all the allocation functions and for all
// the paged spaces.
HeapObject* PagedSpace::AllocateLinearly(AllocationInfo* alloc_info,
                                         int size_in_bytes) {
  Address current_top = alloc_info->top;
  Address new_top = current_top + size_in_bytes;
  if (new_top > alloc_info->limit) return NULL;

  alloc_info->top = new_top;
  ASSERT(alloc_info->VerifyPagedAllocation());
  accounting_stats_.AllocateBytes(size_in_bytes);
  return HeapObject::FromAddress(current_top);
}


// Raw allocation.
MaybeObject* PagedSpace::AllocateRaw(int size_in_bytes) {
  ASSERT(HasBeenSetup());
  ASSERT_OBJECT_SIZE(size_in_bytes);
  HeapObject* object = AllocateLinearly(&allocation_info_, size_in_bytes);
  if (object != NULL) return object;

  object = SlowAllocateRaw(size_in_bytes);
  if (object != NULL) return object;

  return Failure::RetryAfterGC(identity());
}


// Reallocating (and promoting) objects during a compacting collection.
MaybeObject* PagedSpace::MCAllocateRaw(int size_in_bytes) {
  ASSERT(HasBeenSetup());
  ASSERT_OBJECT_SIZE(size_in_bytes);
  HeapObject* object = AllocateLinearly(&mc_forwarding_info_, size_in_bytes);
  if (object != NULL) return object;

  object = SlowMCAllocateRaw(size_in_bytes);
  if (object != NULL) return object;

  return Failure::RetryAfterGC(identity());
}


// -----------------------------------------------------------------------------
// NewSpace

MaybeObject* NewSpace::AllocateRawInternal(int size_in_bytes,
                                           AllocationInfo* alloc_info) {
  Address new_top = alloc_info->top + size_in_bytes;
  if (new_top > alloc_info->limit) return Failure::RetryAfterGC();

  Object* obj = HeapObject::FromAddress(alloc_info->top);
  alloc_info->top = new_top;
#ifdef DEBUG
  SemiSpace* space =
      (alloc_info == &allocation_info_) ? &to_space_ : &from_space_;
  ASSERT(space->low() <= alloc_info->top
         && alloc_info->top <= space->high()
         && alloc_info->limit == space->high());
#endif
  return obj;
}


intptr_t LargeObjectSpace::Available() {
  return LargeObjectChunk::ObjectSizeFor(
      heap()->isolate()->memory_allocator()->Available());
}


template <typename StringType>
void NewSpace::ShrinkStringAtAllocationBoundary(String* string, int length) {
  ASSERT(length <= string->length());
  ASSERT(string->IsSeqString());
  ASSERT(string->address() + StringType::SizeFor(string->length()) ==
         allocation_info_.top);
  allocation_info_.top =
      string->address() + StringType::SizeFor(length);
  string->set_length(length);
}


bool FreeListNode::IsFreeListNode(HeapObject* object) {
  return object->map() == HEAP->raw_unchecked_byte_array_map()
      || object->map() == HEAP->raw_unchecked_one_pointer_filler_map()
      || object->map() == HEAP->raw_unchecked_two_pointer_filler_map();
}

} }  // namespace v8::internal

#endif  // V8_SPACES_INL_H_
