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

#include "src/global-handles.h"

#include "test/cctest/cctest.h"

using namespace v8::internal;
using v8::UniqueId;


static List<Object*> skippable_objects;
static List<Object*> can_skip_called_objects;


static bool CanSkipCallback(Heap* heap, Object** pointer) {
  can_skip_called_objects.Add(*pointer);
  return skippable_objects.Contains(*pointer);
}


static void ResetCanSkipData() {
  skippable_objects.Clear();
  can_skip_called_objects.Clear();
}


class TestRetainedObjectInfo : public v8::RetainedObjectInfo {
 public:
  TestRetainedObjectInfo() : has_been_disposed_(false) {}

  bool has_been_disposed() { return has_been_disposed_; }

  virtual void Dispose() {
    DCHECK(!has_been_disposed_);
    has_been_disposed_ = true;
  }

  virtual bool IsEquivalent(v8::RetainedObjectInfo* other) {
    return other == this;
  }

  virtual intptr_t GetHash() { return 0; }

  virtual const char* GetLabel() { return "whatever"; }

 private:
  bool has_been_disposed_;
};


class TestObjectVisitor : public ObjectVisitor {
 public:
  virtual void VisitPointers(Object** start, Object** end) {
    for (Object** o = start; o != end; ++o)
      visited.Add(*o);
  }

  List<Object*> visited;
};


TEST(IterateObjectGroupsOldApi) {
  CcTest::InitializeVM();
  Isolate* isolate = CcTest::i_isolate();
  GlobalHandles* global_handles = isolate->global_handles();
  v8::HandleScope handle_scope(CcTest::isolate());

  Handle<Object> g1s1 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g1s2 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));

  Handle<Object> g2s1 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g2s2 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));

  TestRetainedObjectInfo info1;
  TestRetainedObjectInfo info2;
  {
    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
    Object** g2_objects[] = { g2s1.location(), g2s2.location() };

    global_handles->AddObjectGroup(g1_objects, 2, &info1);
    global_handles->AddObjectGroup(g2_objects, 2, &info2);
  }

  // Iterate the object groups. First skip all.
  {
    ResetCanSkipData();
    skippable_objects.Add(*g1s1.location());
    skippable_objects.Add(*g1s2.location());
    skippable_objects.Add(*g2s1.location());
    skippable_objects.Add(*g2s2.location());
    TestObjectVisitor visitor;
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);

    // CanSkipCallback was called for all objects.
    DCHECK(can_skip_called_objects.length() == 4);
    DCHECK(can_skip_called_objects.Contains(*g1s1.location()));
    DCHECK(can_skip_called_objects.Contains(*g1s2.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s1.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s2.location()));

    // Nothing was visited.
    DCHECK(visitor.visited.length() == 0);
    DCHECK(!info1.has_been_disposed());
    DCHECK(!info2.has_been_disposed());
  }

  // Iterate again, now only skip the second object group.
  {
    ResetCanSkipData();
    // The first grough should still be visited, since only one object is
    // skipped.
    skippable_objects.Add(*g1s1.location());
    skippable_objects.Add(*g2s1.location());
    skippable_objects.Add(*g2s2.location());
    TestObjectVisitor visitor;
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);

    // CanSkipCallback was called for all objects.
    DCHECK(can_skip_called_objects.length() == 3 ||
           can_skip_called_objects.length() == 4);
    DCHECK(can_skip_called_objects.Contains(*g1s2.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s1.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s2.location()));

    // The first group was visited.
    DCHECK(visitor.visited.length() == 2);
    DCHECK(visitor.visited.Contains(*g1s1.location()));
    DCHECK(visitor.visited.Contains(*g1s2.location()));
    DCHECK(info1.has_been_disposed());
    DCHECK(!info2.has_been_disposed());
  }

  // Iterate again, don't skip anything.
  {
    ResetCanSkipData();
    TestObjectVisitor visitor;
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);

    // CanSkipCallback was called for all objects.
    DCHECK(can_skip_called_objects.length() == 1);
    DCHECK(can_skip_called_objects.Contains(*g2s1.location()) ||
           can_skip_called_objects.Contains(*g2s2.location()));

    // The second group was visited.
    DCHECK(visitor.visited.length() == 2);
    DCHECK(visitor.visited.Contains(*g2s1.location()));
    DCHECK(visitor.visited.Contains(*g2s2.location()));
    DCHECK(info2.has_been_disposed());
  }
}


TEST(IterateObjectGroups) {
  CcTest::InitializeVM();
  Isolate* isolate = CcTest::i_isolate();
  GlobalHandles* global_handles = isolate->global_handles();

  v8::HandleScope handle_scope(CcTest::isolate());

  Handle<Object> g1s1 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g1s2 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));

  Handle<Object> g2s1 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g2s2 =
    global_handles->Create(*isolate->factory()->NewFixedArray(1));

  TestRetainedObjectInfo info1;
  TestRetainedObjectInfo info2;
  global_handles->SetObjectGroupId(g2s1.location(), UniqueId(2));
  global_handles->SetObjectGroupId(g2s2.location(), UniqueId(2));
  global_handles->SetRetainedObjectInfo(UniqueId(2), &info2);
  global_handles->SetObjectGroupId(g1s1.location(), UniqueId(1));
  global_handles->SetObjectGroupId(g1s2.location(), UniqueId(1));
  global_handles->SetRetainedObjectInfo(UniqueId(1), &info1);

  // Iterate the object groups. First skip all.
  {
    ResetCanSkipData();
    skippable_objects.Add(*g1s1.location());
    skippable_objects.Add(*g1s2.location());
    skippable_objects.Add(*g2s1.location());
    skippable_objects.Add(*g2s2.location());
    TestObjectVisitor visitor;
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);

    // CanSkipCallback was called for all objects.
    DCHECK(can_skip_called_objects.length() == 4);
    DCHECK(can_skip_called_objects.Contains(*g1s1.location()));
    DCHECK(can_skip_called_objects.Contains(*g1s2.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s1.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s2.location()));

    // Nothing was visited.
    DCHECK(visitor.visited.length() == 0);
    DCHECK(!info1.has_been_disposed());
    DCHECK(!info2.has_been_disposed());
  }

  // Iterate again, now only skip the second object group.
  {
    ResetCanSkipData();
    // The first grough should still be visited, since only one object is
    // skipped.
    skippable_objects.Add(*g1s1.location());
    skippable_objects.Add(*g2s1.location());
    skippable_objects.Add(*g2s2.location());
    TestObjectVisitor visitor;
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);

    // CanSkipCallback was called for all objects.
    DCHECK(can_skip_called_objects.length() == 3 ||
           can_skip_called_objects.length() == 4);
    DCHECK(can_skip_called_objects.Contains(*g1s2.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s1.location()));
    DCHECK(can_skip_called_objects.Contains(*g2s2.location()));

    // The first group was visited.
    DCHECK(visitor.visited.length() == 2);
    DCHECK(visitor.visited.Contains(*g1s1.location()));
    DCHECK(visitor.visited.Contains(*g1s2.location()));
    DCHECK(info1.has_been_disposed());
    DCHECK(!info2.has_been_disposed());
  }

  // Iterate again, don't skip anything.
  {
    ResetCanSkipData();
    TestObjectVisitor visitor;
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);

    // CanSkipCallback was called for all objects.
    DCHECK(can_skip_called_objects.length() == 1);
    DCHECK(can_skip_called_objects.Contains(*g2s1.location()) ||
           can_skip_called_objects.Contains(*g2s2.location()));

    // The second group was visited.
    DCHECK(visitor.visited.length() == 2);
    DCHECK(visitor.visited.Contains(*g2s1.location()));
    DCHECK(visitor.visited.Contains(*g2s2.location()));
    DCHECK(info2.has_been_disposed());
  }
}


TEST(ImplicitReferences) {
  CcTest::InitializeVM();
  Isolate* isolate = CcTest::i_isolate();
  GlobalHandles* global_handles = isolate->global_handles();

  v8::HandleScope handle_scope(CcTest::isolate());

  Handle<Object> g1s1 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g1c1 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g1c2 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));


  Handle<Object> g2s1 =
      global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g2s2 =
    global_handles->Create(*isolate->factory()->NewFixedArray(1));
  Handle<Object> g2c1 =
    global_handles->Create(*isolate->factory()->NewFixedArray(1));

  global_handles->SetObjectGroupId(g1s1.location(), UniqueId(1));
  global_handles->SetObjectGroupId(g2s1.location(), UniqueId(2));
  global_handles->SetObjectGroupId(g2s2.location(), UniqueId(2));
  global_handles->SetReferenceFromGroup(UniqueId(1), g1c1.location());
  global_handles->SetReferenceFromGroup(UniqueId(1), g1c2.location());
  global_handles->SetReferenceFromGroup(UniqueId(2), g2c1.location());

  List<ImplicitRefGroup*>* implicit_refs =
      global_handles->implicit_ref_groups();
  USE(implicit_refs);
  DCHECK(implicit_refs->length() == 2);
  DCHECK(implicit_refs->at(0)->parent ==
         reinterpret_cast<HeapObject**>(g1s1.location()));
  DCHECK(implicit_refs->at(0)->length == 2);
  DCHECK(implicit_refs->at(0)->children[0] == g1c1.location());
  DCHECK(implicit_refs->at(0)->children[1] == g1c2.location());
  DCHECK(implicit_refs->at(1)->parent ==
         reinterpret_cast<HeapObject**>(g2s1.location()));
  DCHECK(implicit_refs->at(1)->length == 1);
  DCHECK(implicit_refs->at(1)->children[0] == g2c1.location());
  global_handles->RemoveObjectGroups();
  global_handles->RemoveImplicitRefGroups();
}


TEST(EternalHandles) {
  CcTest::InitializeVM();
  Isolate* isolate = CcTest::i_isolate();
  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
  EternalHandles* eternal_handles = isolate->eternal_handles();

  // Create a number of handles that will not be on a block boundary
  const int kArrayLength = 2048-1;
  int indices[kArrayLength];
  v8::Eternal<v8::Value> eternals[kArrayLength];

  CHECK_EQ(0, eternal_handles->NumberOfHandles());
  for (int i = 0; i < kArrayLength; i++) {
    indices[i] = -1;
    HandleScope scope(isolate);
    v8::Local<v8::Object> object = v8::Object::New(v8_isolate);
    object->Set(i, v8::Integer::New(v8_isolate, i));
    // Create with internal api
    eternal_handles->Create(
        isolate, *v8::Utils::OpenHandle(*object), &indices[i]);
    // Create with external api
    CHECK(eternals[i].IsEmpty());
    eternals[i].Set(v8_isolate, object);
    CHECK(!eternals[i].IsEmpty());
  }

  isolate->heap()->CollectAllAvailableGarbage();

  for (int i = 0; i < kArrayLength; i++) {
    for (int j = 0; j < 2; j++) {
      HandleScope scope(isolate);
      v8::Local<v8::Value> local;
      if (j == 0) {
        // Test internal api
        local = v8::Utils::ToLocal(eternal_handles->Get(indices[i]));
      } else {
        // Test external api
        local = eternals[i].Get(v8_isolate);
      }
      v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(local);
      v8::Local<v8::Value> value = object->Get(i);
      CHECK(value->IsInt32());
      CHECK_EQ(i, value->Int32Value());
    }
  }

  CHECK_EQ(2*kArrayLength, eternal_handles->NumberOfHandles());

  // Create an eternal via the constructor
  {
    HandleScope scope(isolate);
    v8::Local<v8::Object> object = v8::Object::New(v8_isolate);
    v8::Eternal<v8::Object> eternal(v8_isolate, object);
    CHECK(!eternal.IsEmpty());
    CHECK(object == eternal.Get(v8_isolate));
  }

  CHECK_EQ(2*kArrayLength + 1, eternal_handles->NumberOfHandles());
}
