// Copyright 2016 The Chromium 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 "bindings/core/v8/ScriptWrappableVisitor.h"

#include "bindings/core/v8/ToV8.h"
#include "bindings/core/v8/TraceWrapperV8Reference.h"
#include "bindings/core/v8/V8BindingForTesting.h"
#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "core/testing/DeathAwareScriptWrappable.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace blink {

static void preciselyCollectGarbage() {
  ThreadState::current()->collectAllGarbage();
}

static void runV8Scavenger(v8::Isolate* isolate) {
  V8GCController::collectGarbage(isolate, true);
}

static void runV8FullGc(v8::Isolate* isolate) {
  V8GCController::collectGarbage(isolate, false);
}

static bool DequeContains(const WTF::Deque<WrapperMarkingData>& deque,
                          DeathAwareScriptWrappable* needle) {
  for (auto item : deque) {
    if (item.rawObjectPointer() == needle)
      return true;
  }
  return false;
}

TEST(ScriptWrappableVisitorTest, ScriptWrappableVisitorTracesWrappers) {
  V8TestingScope scope;
  ScriptWrappableVisitor* visitor =
      V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor();
  visitor->TracePrologue();

  DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::create();
  DeathAwareScriptWrappable* dependency = DeathAwareScriptWrappable::create();
  target->setRawDependency(dependency);

  HeapObjectHeader* targetHeader = HeapObjectHeader::fromPayload(target);
  HeapObjectHeader* dependencyHeader =
      HeapObjectHeader::fromPayload(dependency);

  EXPECT_TRUE(visitor->getMarkingDeque()->isEmpty());
  EXPECT_FALSE(targetHeader->isWrapperHeaderMarked());
  EXPECT_FALSE(dependencyHeader->isWrapperHeaderMarked());

  std::pair<void*, void*> pair = std::make_pair(
      const_cast<WrapperTypeInfo*>(target->wrapperTypeInfo()), target);
  visitor->RegisterV8Reference(pair);
  EXPECT_EQ(visitor->getMarkingDeque()->size(), 1ul);

  visitor->AdvanceTracing(
      0, v8::EmbedderHeapTracer::AdvanceTracingActions(
             v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
  v8::MicrotasksScope::PerformCheckpoint(scope.isolate());
  EXPECT_EQ(visitor->getMarkingDeque()->size(), 0ul);
  EXPECT_TRUE(targetHeader->isWrapperHeaderMarked());
  EXPECT_TRUE(dependencyHeader->isWrapperHeaderMarked());

  visitor->AbortTracing();
}

TEST(ScriptWrappableVisitorTest, OilpanCollectObjectsNotReachableFromV8) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.isolate();

  {
    v8::HandleScope handleScope(isolate);
    DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create();
    DeathAwareScriptWrappable::observeDeathsOf(object);

    // Creates new V8 wrapper and associates it with global scope
    ToV8(object, scope.context()->Global(), isolate);
  }

  runV8Scavenger(isolate);
  runV8FullGc(isolate);
  preciselyCollectGarbage();

  EXPECT_TRUE(DeathAwareScriptWrappable::hasDied());
}

TEST(ScriptWrappableVisitorTest, OilpanDoesntCollectObjectsReachableFromV8) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.isolate();
  v8::HandleScope handleScope(isolate);
  DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create();
  DeathAwareScriptWrappable::observeDeathsOf(object);

  // Creates new V8 wrapper and associates it with global scope
  ToV8(object, scope.context()->Global(), isolate);

  runV8Scavenger(isolate);
  runV8FullGc(isolate);
  preciselyCollectGarbage();

  EXPECT_FALSE(DeathAwareScriptWrappable::hasDied());
}

TEST(ScriptWrappableVisitorTest, V8ReportsLiveObjectsDuringScavenger) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.isolate();
  v8::HandleScope handleScope(isolate);
  DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create();
  DeathAwareScriptWrappable::observeDeathsOf(object);

  v8::Local<v8::Value> wrapper =
      ToV8(object, scope.context()->Global(), isolate);
  EXPECT_TRUE(wrapper->IsObject());
  v8::Local<v8::Object> wrapperObject = wrapper->ToObject();
  // V8 collects wrappers with unmodified maps (as they can be recreated
  // without loosing any data if needed). We need to create some property on
  // wrapper so V8 will not see it as unmodified.
  EXPECT_TRUE(
      wrapperObject->CreateDataProperty(scope.context(), 1, wrapper).IsJust());

  runV8Scavenger(isolate);
  preciselyCollectGarbage();

  EXPECT_FALSE(DeathAwareScriptWrappable::hasDied());
}

TEST(ScriptWrappableVisitorTest, V8ReportsLiveObjectsDuringFullGc) {
  V8TestingScope scope;
  v8::Isolate* isolate = scope.isolate();
  v8::HandleScope handleScope(isolate);
  DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create();
  DeathAwareScriptWrappable::observeDeathsOf(object);

  ToV8(object, scope.context()->Global(), isolate);

  runV8Scavenger(isolate);
  runV8FullGc(isolate);
  preciselyCollectGarbage();

  EXPECT_FALSE(DeathAwareScriptWrappable::hasDied());
}

TEST(ScriptWrappableVisitorTest, OilpanClearsHeadersWhenObjectDied) {
  V8TestingScope scope;

  DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create();
  ScriptWrappableVisitor* visitor =
      V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor();
  visitor->TracePrologue();
  auto header = HeapObjectHeader::fromPayload(object);
  visitor->getHeadersToUnmark()->push_back(header);

  preciselyCollectGarbage();

  EXPECT_FALSE(visitor->getHeadersToUnmark()->contains(header));
  visitor->AbortTracing();
}

TEST(ScriptWrappableVisitorTest, OilpanClearsMarkingDequeWhenObjectDied) {
  V8TestingScope scope;

  DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::create();
  ScriptWrappableVisitor* visitor =
      V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor();
  visitor->TracePrologue();

  visitor->markAndPushToMarkingDeque(object);

  EXPECT_EQ(visitor->getMarkingDeque()->first().rawObjectPointer(), object);

  preciselyCollectGarbage();

  EXPECT_EQ(visitor->getMarkingDeque()->first().rawObjectPointer(), nullptr);

  visitor->AbortTracing();
}

TEST(ScriptWrappableVisitorTest, NonMarkedObjectDoesNothingOnWriteBarrierHit) {
  V8TestingScope scope;

  ScriptWrappableVisitor* visitor =
      V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor();
  visitor->TracePrologue();

  DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::create();
  DeathAwareScriptWrappable* dependency = DeathAwareScriptWrappable::create();

  EXPECT_TRUE(visitor->getMarkingDeque()->isEmpty());

  target->setRawDependency(dependency);

  EXPECT_TRUE(visitor->getMarkingDeque()->isEmpty());
  visitor->AbortTracing();
}

TEST(ScriptWrappableVisitorTest,
     MarkedObjectDoesNothingOnWriteBarrierHitWhenDependencyIsMarkedToo) {
  V8TestingScope scope;

  ScriptWrappableVisitor* visitor =
      V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor();
  visitor->TracePrologue();

  DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::create();
  DeathAwareScriptWrappable* dependencies[] = {
      DeathAwareScriptWrappable::create(), DeathAwareScriptWrappable::create(),
      DeathAwareScriptWrappable::create(), DeathAwareScriptWrappable::create(),
      DeathAwareScriptWrappable::create()};

  HeapObjectHeader::fromPayload(target)->markWrapperHeader();
  for (int i = 0; i < 5; i++) {
    HeapObjectHeader::fromPayload(dependencies[i])->markWrapperHeader();
  }

  EXPECT_TRUE(visitor->getMarkingDeque()->isEmpty());

  target->setRawDependency(dependencies[0]);
  target->setWrappedDependency(dependencies[1]);
  target->addWrappedVectorDependency(dependencies[2]);
  target->addWrappedHashMapDependency(dependencies[3], dependencies[4]);

  EXPECT_TRUE(visitor->getMarkingDeque()->isEmpty());
  visitor->AbortTracing();
}

TEST(ScriptWrappableVisitorTest,
     MarkedObjectMarksDependencyOnWriteBarrierHitWhenNotMarked) {
  V8TestingScope scope;

  ScriptWrappableVisitor* visitor =
      V8PerIsolateData::from(scope.isolate())->scriptWrappableVisitor();
  visitor->TracePrologue();

  DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::create();
  DeathAwareScriptWrappable* dependencies[] = {
      DeathAwareScriptWrappable::create(), DeathAwareScriptWrappable::create(),
      DeathAwareScriptWrappable::create(), DeathAwareScriptWrappable::create(),
      DeathAwareScriptWrappable::create()};

  HeapObjectHeader::fromPayload(target)->markWrapperHeader();

  EXPECT_TRUE(visitor->getMarkingDeque()->isEmpty());

  target->setRawDependency(dependencies[0]);
  target->setWrappedDependency(dependencies[1]);
  target->addWrappedVectorDependency(dependencies[2]);
  target->addWrappedHashMapDependency(dependencies[3], dependencies[4]);

  for (int i = 0; i < 5; i++) {
    EXPECT_TRUE(DequeContains(*visitor->getMarkingDeque(), dependencies[i]));
  }

  visitor->AbortTracing();
}

namespace {

class HandleContainer
    : public blink::GarbageCollectedFinalized<HandleContainer>,
      blink::TraceWrapperBase {
 public:
  static HandleContainer* create() { return new HandleContainer(); }
  virtual ~HandleContainer() {}

  DEFINE_INLINE_TRACE() {}
  DEFINE_INLINE_TRACE_WRAPPERS() {
    visitor->traceWrappers(m_handle.cast<v8::Value>());
  }

  void setValue(v8::Isolate* isolate, v8::Local<v8::String> string) {
    m_handle.set(isolate, string);
  }

 private:
  HandleContainer() : m_handle(this) {}

  TraceWrapperV8Reference<v8::String> m_handle;
};

class InterceptingScriptWrappableVisitor
    : public blink::ScriptWrappableVisitor {
 public:
  InterceptingScriptWrappableVisitor(v8::Isolate* isolate)
      : ScriptWrappableVisitor(isolate), m_markedWrappers(new size_t(0)) {}
  ~InterceptingScriptWrappableVisitor() { delete m_markedWrappers; }

  virtual void markWrapper(const v8::PersistentBase<v8::Value>* handle) const {
    *m_markedWrappers += 1;
    // Do not actually mark this visitor, as this would call into v8, which
    // would require executing an actual GC.
  }

  size_t numberOfMarkedWrappers() const { return *m_markedWrappers; }

 private:
  size_t* m_markedWrappers;  // Indirection required because of const override.
};

void swapInNewVisitor(v8::Isolate* isolate,
                      blink::ScriptWrappableVisitor* newVisitor) {
  isolate->SetEmbedderHeapTracer(newVisitor);
  std::unique_ptr<blink::ScriptWrappableVisitor> visitor(newVisitor);
  V8PerIsolateData::from(isolate)->setScriptWrappableVisitor(
      std::move(visitor));
}

}  // namespace

TEST(ScriptWrappableVisitorTest, NoWriteBarrierOnUnmarkedContainer) {
  V8TestingScope scope;
  auto rawVisitor = new InterceptingScriptWrappableVisitor(scope.isolate());
  swapInNewVisitor(scope.isolate(), rawVisitor);
  rawVisitor->TracePrologue();
  v8::Local<v8::String> str =
      v8::String::NewFromUtf8(scope.isolate(), "teststring",
                              v8::NewStringType::kNormal, sizeof("teststring"))
          .ToLocalChecked();
  HandleContainer* container = HandleContainer::create();
  CHECK_EQ(0u, rawVisitor->numberOfMarkedWrappers());
  container->setValue(scope.isolate(), str);
  CHECK_EQ(0u, rawVisitor->numberOfMarkedWrappers());
  // Gracefully terminate tracing.
  rawVisitor->AdvanceTracing(
      0, v8::EmbedderHeapTracer::AdvanceTracingActions(
             v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
  rawVisitor->AbortTracing();
}

TEST(ScriptWrappableVisitorTest, WriteBarrierTriggersOnMarkedContainer) {
  V8TestingScope scope;
  auto rawVisitor = new InterceptingScriptWrappableVisitor(scope.isolate());
  swapInNewVisitor(scope.isolate(), rawVisitor);
  rawVisitor->TracePrologue();
  v8::Local<v8::String> str =
      v8::String::NewFromUtf8(scope.isolate(), "teststring",
                              v8::NewStringType::kNormal, sizeof("teststring"))
          .ToLocalChecked();
  HandleContainer* container = HandleContainer::create();
  HeapObjectHeader::fromPayload(container)->markWrapperHeader();
  CHECK_EQ(0u, rawVisitor->numberOfMarkedWrappers());
  container->setValue(scope.isolate(), str);
  CHECK_EQ(1u, rawVisitor->numberOfMarkedWrappers());
  // Gracefully terminate tracing.
  rawVisitor->AdvanceTracing(
      0, v8::EmbedderHeapTracer::AdvanceTracingActions(
             v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
  rawVisitor->AbortTracing();
}

TEST(ScriptWrappableVisitorTest, VtableAtObjectStart) {
  // This test makes sure that the subobject v8::EmbedderHeapTracer is placed
  // at the start of a ScriptWrappableVisitor object. We do this to mitigate
  // potential problems that could be caused by LTO when passing
  // v8::EmbedderHeapTracer across the API boundary.
  V8TestingScope scope;
  std::unique_ptr<blink::ScriptWrappableVisitor> visitor(
      new ScriptWrappableVisitor(scope.isolate()));
  CHECK_EQ(
      static_cast<void*>(visitor.get()),
      static_cast<void*>(dynamic_cast<v8::EmbedderHeapTracer*>(visitor.get())));
}

}  // namespace blink
