// 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/api/api.h"
#include "src/base/platform/semaphore.h"
#include "src/handles/handles-inl.h"
#include "src/handles/local-handles-inl.h"
#include "src/handles/persistent-handles.h"
#include "src/heap/heap.h"
#include "src/heap/local-heap-inl.h"
#include "src/heap/local-heap.h"
#include "test/cctest/cctest.h"
#include "test/cctest/heap/heap-utils.h"

namespace v8 {
namespace internal {

static constexpr int kNumHandles = kHandleBlockSize * 2 + kHandleBlockSize / 2;

namespace {

class ConcurrentSearchThread final : public v8::base::Thread {
 public:
  ConcurrentSearchThread(Heap* heap, std::vector<Handle<JSObject>> handles,
                         std::unique_ptr<PersistentHandles> ph,
                         base::Semaphore* sema_started)
      : v8::base::Thread(base::Thread::Options("ThreadWithLocalHeap")),
        heap_(heap),
        handles_(std::move(handles)),
        ph_(std::move(ph)),
        sema_started_(sema_started) {}

  void Run() override {
    LocalHeap local_heap(heap_, ThreadKind::kBackground, std::move(ph_));
    UnparkedScope unparked_scope(&local_heap);
    LocalHandleScope scope(&local_heap);

    for (int i = 0; i < kNumHandles; i++) {
      handles_.push_back(local_heap.NewPersistentHandle(handles_[0]));
    }

    sema_started_->Signal();

    for (Handle<JSObject> js_obj : handles_) {
      // Walk up the prototype chain all the way to the top.
      Handle<Map> map(js_obj->synchronized_map(), &local_heap);
      while (!map->prototype().IsNull()) {
        Handle<Map> map_prototype_map(map->prototype().synchronized_map(),
                                      &local_heap);
        if (!map_prototype_map->IsJSObjectMap()) {
          break;
        }
        map = map_prototype_map;
      }
    }

    CHECK_EQ(handles_.size(), kNumHandles * 2);
  }

 private:
  Heap* heap_;
  std::vector<Handle<JSObject>> handles_;
  std::unique_ptr<PersistentHandles> ph_;
  base::Semaphore* sema_started_;
};

// Test to search on a background thread, while the main thread is idle.
TEST(ProtoWalkBackground) {
  heap::EnsureFlagLocalHeapsEnabled();
  CcTest::InitializeVM();
  Isolate* isolate = CcTest::i_isolate();

  std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
  std::vector<Handle<JSObject>> handles;

  auto factory = isolate->factory();
  HandleScope handle_scope(isolate);

  Handle<JSFunction> function =
      factory->NewFunctionForTest(factory->empty_string());
  Handle<JSObject> js_object = factory->NewJSObject(function);
  Handle<String> name = CcTest::MakeString("property");
  Handle<Object> value = CcTest::MakeString("dummy_value");
  // For the default constructor function no in-object properties are reserved
  // hence adding a single property will initialize the property-array.
  JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, name, value,
                                                    NONE)
      .Check();

  for (int i = 0; i < kNumHandles; i++) {
    handles.push_back(ph->NewHandle(js_object));
  }

  base::Semaphore sema_started(0);

  // Pass persistent handles to background thread.
  std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
      isolate->heap(), std::move(handles), std::move(ph), &sema_started));
  CHECK(thread->Start());

  sema_started.Wait();

  thread->Join();
}

// Test to search on a background thread, while the main thread modifies the
// descriptor array.
TEST(ProtoWalkBackground_DescriptorArrayWrite) {
  heap::EnsureFlagLocalHeapsEnabled();
  CcTest::InitializeVM();
  Isolate* isolate = CcTest::i_isolate();

  std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
  std::vector<Handle<JSObject>> handles;

  auto factory = isolate->factory();
  HandleScope handle_scope(isolate);

  Handle<JSFunction> function =
      factory->NewFunctionForTest(factory->empty_string());
  Handle<JSObject> js_object = factory->NewJSObject(function);
  Handle<String> name = CcTest::MakeString("property");
  Handle<Object> value = CcTest::MakeString("dummy_value");
  // For the default constructor function no in-object properties are reserved
  // hence adding a single property will initialize the property-array.
  JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, name, value,
                                                    NONE)
      .Check();

  for (int i = 0; i < kNumHandles; i++) {
    handles.push_back(ph->NewHandle(js_object));
  }

  base::Semaphore sema_started(0);

  // Pass persistent handles to background thread.
  std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
      isolate->heap(), std::move(handles), std::move(ph), &sema_started));
  CHECK(thread->Start());

  sema_started.Wait();

  // Exercise descriptor array.
  for (int i = 0; i < 20; ++i) {
    Handle<String> filler_name = CcTest::MakeName("filler_property_", i);
    Handle<Object> filler_value = CcTest::MakeString("dummy_value");
    JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, filler_name,
                                                      filler_value, NONE)
        .Check();
  }

  thread->Join();
}

TEST(ProtoWalkBackground_PrototypeChainWrite) {
  heap::EnsureFlagLocalHeapsEnabled();
  CcTest::InitializeVM();
  Isolate* isolate = CcTest::i_isolate();

  std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
  std::vector<Handle<JSObject>> handles;

  auto factory = isolate->factory();
  HandleScope handle_scope(isolate);

  Handle<JSFunction> function =
      factory->NewFunctionForTest(factory->empty_string());
  Handle<JSObject> js_object = factory->NewJSObject(function);

  for (int i = 0; i < kNumHandles; i++) {
    handles.push_back(ph->NewHandle(js_object));
  }

  base::Semaphore sema_started(0);

  // Pass persistent handles to background thread.
  std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
      isolate->heap(), std::move(handles), std::move(ph), &sema_started));
  CHECK(thread->Start());

  // The prototype chain looks like this JSObject -> Object -> null. Change the
  // prototype of the js_object to be JSObject -> null, and then back a bunch of
  // times.
  Handle<Map> map(js_object->map(), isolate);
  Handle<HeapObject> old_proto(map->prototype(), isolate);
  DCHECK(!old_proto->IsNull());
  Handle<HeapObject> new_proto(old_proto->map().prototype(), isolate);

  sema_started.Wait();

  for (int i = 0; i < 20; ++i) {
    CHECK(JSReceiver::SetPrototype(
              js_object, i % 2 == 0 ? new_proto : old_proto, false, kDontThrow)
              .FromJust());
  }

  thread->Join();
}

}  // anonymous namespace

}  // namespace internal
}  // namespace v8
