// Copyright 2020 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.

#include "src/heap/cppgc/heap-object-header.h"

#include <atomic>
#include <memory>

#include "include/cppgc/allocation.h"
#include "src/base/atomic-utils.h"
#include "src/base/macros.h"
#include "src/base/platform/platform.h"
#include "src/heap/cppgc/globals.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cppgc {
namespace internal {

TEST(HeapObjectHeaderTest, Constructor) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_EQ(kSize, header.GetSize());
  EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex());
  EXPECT_TRUE(header.IsInConstruction());
  EXPECT_FALSE(header.IsMarked());
}

TEST(HeapObjectHeaderTest, Payload) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_EQ(reinterpret_cast<ConstAddress>(&header) + sizeof(HeapObjectHeader),
            header.Payload());
}

TEST(HeapObjectHeaderTest, GetGCInfoIndex) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex());
  EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex<AccessMode::kAtomic>());
}

TEST(HeapObjectHeaderTest, GetSize) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity * 23;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_EQ(kSize, header.GetSize());
  EXPECT_EQ(kSize, header.GetSize<AccessMode::kAtomic>());
}

TEST(HeapObjectHeaderTest, IsLargeObject) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity * 23;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_EQ(false, header.IsLargeObject());
  EXPECT_EQ(false, header.IsLargeObject<AccessMode::kAtomic>());
  HeapObjectHeader large_header(0, kGCInfoIndex + 1);
  EXPECT_EQ(true, large_header.IsLargeObject());
  EXPECT_EQ(true, large_header.IsLargeObject<AccessMode::kAtomic>());
}

TEST(HeapObjectHeaderTest, MarkObjectAsFullyConstructed) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_TRUE(header.IsInConstruction());
  header.MarkAsFullyConstructed();
  EXPECT_FALSE(header.IsInConstruction());
  // Size shares the same bitfield and should be unaffected by
  // MarkObjectAsFullyConstructed.
  EXPECT_EQ(kSize, header.GetSize());
}

TEST(HeapObjectHeaderTest, TryMark) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity * 7;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_FALSE(header.IsMarked());
  EXPECT_TRUE(header.TryMarkAtomic());
  // GCInfoIndex shares the same bitfield and should be unaffected by
  // TryMarkAtomic.
  EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex());
  EXPECT_FALSE(header.TryMarkAtomic());
  // GCInfoIndex shares the same bitfield and should be unaffected by
  // TryMarkAtomic.
  EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex());
  EXPECT_TRUE(header.IsMarked());
}

TEST(HeapObjectHeaderTest, Unmark) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = kAllocationGranularity * 7;
  HeapObjectHeader header(kSize, kGCInfoIndex);
  EXPECT_FALSE(header.IsMarked());
  EXPECT_TRUE(header.TryMarkAtomic());
  EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex());
  EXPECT_TRUE(header.IsMarked());
  header.Unmark();
  // GCInfoIndex shares the same bitfield and should be unaffected by Unmark.
  EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex());
  EXPECT_FALSE(header.IsMarked());
  HeapObjectHeader header2(kSize, kGCInfoIndex);
  EXPECT_FALSE(header2.IsMarked());
  EXPECT_TRUE(header2.TryMarkAtomic());
  EXPECT_TRUE(header2.IsMarked());
  header2.Unmark<AccessMode::kAtomic>();
  // GCInfoIndex shares the same bitfield and should be unaffected by Unmark.
  EXPECT_EQ(kGCInfoIndex, header2.GetGCInfoIndex());
  EXPECT_FALSE(header2.IsMarked());
}

namespace {

struct Payload {
  volatile size_t value{5};
};

class ConcurrentGCThread final : public v8::base::Thread {
 public:
  explicit ConcurrentGCThread(HeapObjectHeader* header, Payload* payload)
      : v8::base::Thread(Options("Thread accessing object.")),
        header_(header),
        payload_(payload) {}

  void Run() final {
    while (header_->IsInConstruction<AccessMode::kAtomic>()) {
    }
    USE(v8::base::AsAtomicPtr(const_cast<size_t*>(&payload_->value))
            ->load(std::memory_order_relaxed));
  }

 private:
  HeapObjectHeader* header_;
  Payload* payload_;
};

}  // namespace

TEST(HeapObjectHeaderTest, ConstructionBitProtectsNonAtomicWrites) {
  // Object publishing: Test checks that non-atomic stores in the payload can be
  // guarded using MarkObjectAsFullyConstructed/IsInConstruction. The test
  // relies on TSAN to find data races.
  constexpr size_t kSize =
      (sizeof(HeapObjectHeader) + sizeof(Payload) + kAllocationMask) &
      ~kAllocationMask;
  typename std::aligned_storage<kSize, kAllocationGranularity>::type data;
  HeapObjectHeader* header = new (&data) HeapObjectHeader(kSize, 1);
  ConcurrentGCThread gc_thread(header,
                               reinterpret_cast<Payload*>(header->Payload()));
  CHECK(gc_thread.Start());
  new (header->Payload()) Payload();
  header->MarkAsFullyConstructed();
  gc_thread.Join();
}

#ifdef DEBUG

TEST(HeapObjectHeaderDeathTest, ConstructorTooLargeSize) {
  constexpr GCInfoIndex kGCInfoIndex = 17;
  constexpr size_t kSize = HeapObjectHeader::kMaxSize + 1;
  EXPECT_DEATH_IF_SUPPORTED(HeapObjectHeader header(kSize, kGCInfoIndex), "");
}

TEST(HeapObjectHeaderDeathTest, ConstructorTooLargeGCInfoIndex) {
  constexpr GCInfoIndex kGCInfoIndex = GCInfoTable::kMaxIndex + 1;
  constexpr size_t kSize = kAllocationGranularity;
  EXPECT_DEATH_IF_SUPPORTED(HeapObjectHeader header(kSize, kGCInfoIndex), "");
}

#endif  // DEBUG

}  // namespace internal
}  // namespace cppgc
