// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
#define V8_HEAP_HEAP_WRITE_BARRIER_INL_H_

// Clients of this interface shouldn't depend on lots of heap internals.
// Do not include anything from src/heap here!

#include "src/heap/heap-write-barrier.h"

#include "src/globals.h"
#include "src/objects-inl.h"
#include "src/objects/heap-object.h"
#include "src/objects/maybe-object-inl.h"
#include "src/objects/slots.h"

namespace v8 {
namespace internal {

// Do not use these internal details anywhere outside of this file. These
// internals are only intended to shortcut write barrier checks.
namespace heap_internals {

struct MemoryChunk {
  static constexpr uintptr_t kFlagsOffset = sizeof(size_t);
  static constexpr uintptr_t kMarkingBit = uintptr_t{1} << 18;
  static constexpr uintptr_t kFromSpaceBit = uintptr_t{1} << 3;
  static constexpr uintptr_t kToSpaceBit = uintptr_t{1} << 4;

  V8_INLINE static heap_internals::MemoryChunk* FromHeapObject(
      HeapObject* object) {
    return reinterpret_cast<MemoryChunk*>(reinterpret_cast<Address>(object) &
                                          ~kPageAlignmentMask);
  }

  V8_INLINE bool IsMarking() const { return GetFlags() & kMarkingBit; }

  V8_INLINE bool InNewSpace() const {
    constexpr uintptr_t kNewSpaceMask = kFromSpaceBit | kToSpaceBit;
    return GetFlags() & kNewSpaceMask;
  }

  V8_INLINE uintptr_t GetFlags() const {
    return *reinterpret_cast<const uintptr_t*>(
        reinterpret_cast<const uint8_t*>(this) + kFlagsOffset);
  }
};

inline void GenerationalBarrierInternal(HeapObject* object, Address slot,
                                        HeapObject* value) {
  DCHECK(Heap::PageFlagsAreConsistent(object));
  heap_internals::MemoryChunk* value_chunk =
      heap_internals::MemoryChunk::FromHeapObject(value);
  heap_internals::MemoryChunk* object_chunk =
      heap_internals::MemoryChunk::FromHeapObject(object);

  if (!value_chunk->InNewSpace() || object_chunk->InNewSpace()) return;

  Heap::GenerationalBarrierSlow(object, slot, value);
}

inline void MarkingBarrierInternal(HeapObject* object, Address slot,
                                   HeapObject* value) {
  DCHECK(Heap::PageFlagsAreConsistent(object));
  heap_internals::MemoryChunk* value_chunk =
      heap_internals::MemoryChunk::FromHeapObject(value);

  if (!value_chunk->IsMarking()) return;

  Heap::MarkingBarrierSlow(object, slot, value);
}

}  // namespace heap_internals

inline void WriteBarrierForCode(Code* host, RelocInfo* rinfo, Object* value) {
  DCHECK(!HasWeakHeapObjectTag(value));
  if (!value->IsHeapObject()) return;
  HeapObject* object = HeapObject::cast(value);
  GenerationalBarrierForCode(host, rinfo, object);
  MarkingBarrierForCode(host, rinfo, object);
}

inline void WriteBarrierForCode(Code* host) {
  Heap::WriteBarrierForCodeSlow(host);
}

inline void GenerationalBarrier(HeapObject* object, ObjectSlot slot,
                                Object* value) {
  DCHECK(!HasWeakHeapObjectTag(*slot));
  DCHECK(!HasWeakHeapObjectTag(value));
  if (!value->IsHeapObject()) return;
  heap_internals::GenerationalBarrierInternal(object, slot.address(),
                                              HeapObject::cast(value));
}

inline void GenerationalBarrier(HeapObject* object, MaybeObjectSlot slot,
                                MaybeObject* value) {
  HeapObject* value_heap_object;
  if (!value->GetHeapObject(&value_heap_object)) return;
  heap_internals::GenerationalBarrierInternal(object, slot.address(),
                                              value_heap_object);
}

inline void GenerationalBarrier(HeapObjectPtr* object, ObjectSlot slot,
                                Object* value) {
  DCHECK(!HasWeakHeapObjectTag(*slot));
  DCHECK(!HasWeakHeapObjectTag(value));
  if (!value->IsHeapObject()) return;
  heap_internals::GenerationalBarrierInternal(
      reinterpret_cast<HeapObject*>(object->ptr()), slot.address(),
      HeapObject::cast(value));
}

inline void GenerationalBarrierForElements(Heap* heap, FixedArray* array,
                                           int offset, int length) {
  heap_internals::MemoryChunk* array_chunk =
      heap_internals::MemoryChunk::FromHeapObject(array);
  if (array_chunk->InNewSpace()) return;

  Heap::GenerationalBarrierForElementsSlow(heap, array, offset, length);
}

inline void GenerationalBarrierForCode(Code* host, RelocInfo* rinfo,
                                       HeapObject* object) {
  heap_internals::MemoryChunk* object_chunk =
      heap_internals::MemoryChunk::FromHeapObject(object);
  if (!object_chunk->InNewSpace()) return;
  Heap::GenerationalBarrierForCodeSlow(host, rinfo, object);
}

inline void MarkingBarrier(HeapObject* object, ObjectSlot slot, Object* value) {
  DCHECK_IMPLIES(slot.address() != kNullAddress, !HasWeakHeapObjectTag(*slot));
  DCHECK(!HasWeakHeapObjectTag(value));
  if (!value->IsHeapObject()) return;
  heap_internals::MarkingBarrierInternal(object, slot.address(),
                                         HeapObject::cast(value));
}

inline void MarkingBarrier(HeapObject* object, MaybeObjectSlot slot,
                           MaybeObject* value) {
  HeapObject* value_heap_object;
  if (!value->GetHeapObject(&value_heap_object)) return;
  heap_internals::MarkingBarrierInternal(object, slot.address(),
                                         value_heap_object);
}

inline void MarkingBarrier(HeapObjectPtr* object, ObjectSlot slot,
                           Object* value) {
  DCHECK_IMPLIES(slot.address() != kNullAddress, !HasWeakHeapObjectTag(*slot));
  DCHECK(!HasWeakHeapObjectTag(value));
  if (!value->IsHeapObject()) return;
  heap_internals::MarkingBarrierInternal(
      reinterpret_cast<HeapObject*>(object->ptr()), slot.address(),
      HeapObject::cast(value));
}

inline void MarkingBarrierForElements(Heap* heap, HeapObject* object) {
  heap_internals::MemoryChunk* object_chunk =
      heap_internals::MemoryChunk::FromHeapObject(object);
  if (!object_chunk->IsMarking()) return;

  Heap::MarkingBarrierForElementsSlow(heap, object);
}

inline void MarkingBarrierForCode(Code* host, RelocInfo* rinfo,
                                  HeapObject* object) {
  DCHECK(!HasWeakHeapObjectTag(object));
  heap_internals::MemoryChunk* object_chunk =
      heap_internals::MemoryChunk::FromHeapObject(object);
  if (!object_chunk->IsMarking()) return;
  Heap::MarkingBarrierForCodeSlow(host, rinfo, object);
}

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
