// Copyright 2006-2008 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 <stdlib.h>

#include "v8.h"

#include "global-handles.h"
#include "snapshot.h"
#include "cctest.h"

using namespace v8::internal;

static v8::Persistent<v8::Context> env;

static void InitializeVM() {
  if (env.IsEmpty()) env = v8::Context::New();
  v8::HandleScope scope;
  env->Enter();
}


TEST(MarkingStack) {
  int mem_size = 20 * kPointerSize;
  byte* mem = NewArray<byte>(20*kPointerSize);
  Address low = reinterpret_cast<Address>(mem);
  Address high = low + mem_size;
  MarkingStack s;
  s.Initialize(low, high);

  Address address = NULL;
  while (!s.is_full()) {
    s.Push(HeapObject::FromAddress(address));
    address += kPointerSize;
  }

  while (!s.is_empty()) {
    Address value = s.Pop()->address();
    address -= kPointerSize;
    CHECK_EQ(address, value);
  }

  CHECK_EQ(NULL, address);
  DeleteArray(mem);
}


TEST(Promotion) {
  // This test requires compaction. If compaction is turned off, we
  // skip the entire test.
  if (FLAG_never_compact) return;

  // Ensure that we get a compacting collection so that objects are promoted
  // from new space.
  FLAG_gc_global = true;
  FLAG_always_compact = true;
  HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB);

  InitializeVM();

  v8::HandleScope sc;

  // Allocate a fixed array in the new space.
  int array_size =
      (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
      (kPointerSize * 4);
  Object* obj = HEAP->AllocateFixedArray(array_size)->ToObjectChecked();

  Handle<FixedArray> array(FixedArray::cast(obj));

  // Array should be in the new space.
  CHECK(HEAP->InSpace(*array, NEW_SPACE));

  // Call the m-c collector, so array becomes an old object.
  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  // Array now sits in the old space
  CHECK(HEAP->InSpace(*array, OLD_POINTER_SPACE));
}


TEST(NoPromotion) {
  HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB);

  // Test the situation that some objects in new space are promoted to
  // the old space
  InitializeVM();

  v8::HandleScope sc;

  // Do a mark compact GC to shrink the heap.
  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  // Allocate a big Fixed array in the new space.
  int size = (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
      kPointerSize;
  Object* obj = HEAP->AllocateFixedArray(size)->ToObjectChecked();

  Handle<FixedArray> array(FixedArray::cast(obj));

  // Array still stays in the new space.
  CHECK(HEAP->InSpace(*array, NEW_SPACE));

  // Allocate objects in the old space until out of memory.
  FixedArray* host = *array;
  while (true) {
    Object* obj;
    { MaybeObject* maybe_obj = HEAP->AllocateFixedArray(100, TENURED);
      if (!maybe_obj->ToObject(&obj)) break;
    }

    host->set(0, obj);
    host = FixedArray::cast(obj);
  }

  // Call mark compact GC, and it should pass.
  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  // array should not be promoted because the old space is full.
  CHECK(HEAP->InSpace(*array, NEW_SPACE));
}


TEST(MarkCompactCollector) {
  InitializeVM();

  v8::HandleScope sc;
  // call mark-compact when heap is empty
  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  // keep allocating garbage in new space until it fails
  const int ARRAY_SIZE = 100;
  Object* array;
  MaybeObject* maybe_array;
  do {
    maybe_array = HEAP->AllocateFixedArray(ARRAY_SIZE);
  } while (maybe_array->ToObject(&array));
  HEAP->CollectGarbage(NEW_SPACE);

  array = HEAP->AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked();

  // keep allocating maps until it fails
  Object* mapp;
  MaybeObject* maybe_mapp;
  do {
    maybe_mapp = HEAP->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
  } while (maybe_mapp->ToObject(&mapp));
  HEAP->CollectGarbage(MAP_SPACE);
  mapp = HEAP->AllocateMap(JS_OBJECT_TYPE,
                           JSObject::kHeaderSize)->ToObjectChecked();

  // allocate a garbage
  String* func_name =
      String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked());
  SharedFunctionInfo* function_share = SharedFunctionInfo::cast(
      HEAP->AllocateSharedFunctionInfo(func_name)->ToObjectChecked());
  JSFunction* function = JSFunction::cast(
      HEAP->AllocateFunction(*Isolate::Current()->function_map(),
                             function_share,
                             HEAP->undefined_value())->ToObjectChecked());
  Map* initial_map =
      Map::cast(HEAP->AllocateMap(JS_OBJECT_TYPE,
                                  JSObject::kHeaderSize)->ToObjectChecked());
  function->set_initial_map(initial_map);
  Isolate::Current()->context()->global()->SetProperty(
      func_name, function, NONE, kNonStrictMode)->ToObjectChecked();

  JSObject* obj = JSObject::cast(
      HEAP->AllocateJSObject(function)->ToObjectChecked());
  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  func_name =
      String::cast(HEAP->LookupAsciiSymbol("theFunction")->ToObjectChecked());
  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(func_name));
  Object* func_value = Isolate::Current()->context()->global()->
      GetProperty(func_name)->ToObjectChecked();
  CHECK(func_value->IsJSFunction());
  function = JSFunction::cast(func_value);

  obj = JSObject::cast(HEAP->AllocateJSObject(function)->ToObjectChecked());
  String* obj_name =
      String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked());
  Isolate::Current()->context()->global()->SetProperty(
      obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked();
  String* prop_name =
      String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked());
  obj->SetProperty(prop_name,
                   Smi::FromInt(23),
                   NONE,
                   kNonStrictMode)->ToObjectChecked();

  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  obj_name =
      String::cast(HEAP->LookupAsciiSymbol("theObject")->ToObjectChecked());
  CHECK(Isolate::Current()->context()->global()->HasLocalProperty(obj_name));
  CHECK(Isolate::Current()->context()->global()->
        GetProperty(obj_name)->ToObjectChecked()->IsJSObject());
  obj = JSObject::cast(Isolate::Current()->context()->global()->
                       GetProperty(obj_name)->ToObjectChecked());
  prop_name =
      String::cast(HEAP->LookupAsciiSymbol("theSlot")->ToObjectChecked());
  CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
}


static Handle<Map> CreateMap() {
  return FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
}


TEST(MapCompact) {
  FLAG_max_map_space_pages = 16;
  InitializeVM();

  {
    v8::HandleScope sc;
    // keep allocating maps while pointers are still encodable and thus
    // mark compact is permitted.
    Handle<JSObject> root = FACTORY->NewJSObjectFromMap(CreateMap());
    do {
      Handle<Map> map = CreateMap();
      map->set_prototype(*root);
      root = FACTORY->NewJSObjectFromMap(map);
    } while (HEAP->map_space()->MapPointersEncodable());
  }
  // Now, as we don't have any handles to just allocated maps, we should
  // be able to trigger map compaction.
  // To give an additional chance to fail, try to force compaction which
  // should be impossible right now.
  HEAP->CollectAllGarbage(true);
  // And now map pointers should be encodable again.
  CHECK(HEAP->map_space()->MapPointersEncodable());
}


static int gc_starts = 0;
static int gc_ends = 0;

static void GCPrologueCallbackFunc() {
  CHECK(gc_starts == gc_ends);
  gc_starts++;
}


static void GCEpilogueCallbackFunc() {
  CHECK(gc_starts == gc_ends + 1);
  gc_ends++;
}


TEST(GCCallback) {
  InitializeVM();

  HEAP->SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
  HEAP->SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);

  // Scavenge does not call GC callback functions.
  HEAP->PerformScavenge();

  CHECK_EQ(0, gc_starts);
  CHECK_EQ(gc_ends, gc_starts);

  HEAP->CollectGarbage(OLD_POINTER_SPACE);
  CHECK_EQ(1, gc_starts);
  CHECK_EQ(gc_ends, gc_starts);
}


static int NumberOfWeakCalls = 0;
static void WeakPointerCallback(v8::Persistent<v8::Value> handle, void* id) {
  ASSERT(id == reinterpret_cast<void*>(1234));
  NumberOfWeakCalls++;
  handle.Dispose();
}

TEST(ObjectGroups) {
  InitializeVM();
  GlobalHandles* global_handles = Isolate::Current()->global_handles();

  NumberOfWeakCalls = 0;
  v8::HandleScope handle_scope;

  Handle<Object> g1s1 =
      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
  Handle<Object> g1s2 =
      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
  Handle<Object> g1c1 =
      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
  global_handles->MakeWeak(g1s1.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);
  global_handles->MakeWeak(g1s2.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);
  global_handles->MakeWeak(g1c1.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);

  Handle<Object> g2s1 =
      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
  Handle<Object> g2s2 =
    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
  Handle<Object> g2c1 =
    global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());
  global_handles->MakeWeak(g2s1.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);
  global_handles->MakeWeak(g2s2.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);
  global_handles->MakeWeak(g2c1.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);

  Handle<Object> root = global_handles->Create(*g1s1);  // make a root.

  // Connect group 1 and 2, make a cycle.
  Handle<FixedArray>::cast(g1s2)->set(0, *g2s2);
  Handle<FixedArray>::cast(g2s1)->set(0, *g1s1);

  {
    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
    Object** g1_children[] = { g1c1.location() };
    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
    Object** g2_children[] = { g2c1.location() };
    global_handles->AddObjectGroup(g1_objects, 2, NULL);
    global_handles->AddImplicitReferences(
        Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
    global_handles->AddObjectGroup(g2_objects, 2, NULL);
    global_handles->AddImplicitReferences(
        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
  }
  // Do a full GC
  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  // All object should be alive.
  CHECK_EQ(0, NumberOfWeakCalls);

  // Weaken the root.
  global_handles->MakeWeak(root.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);
  // But make children strong roots---all the objects (except for children)
  // should be collectable now.
  global_handles->ClearWeakness(g1c1.location());
  global_handles->ClearWeakness(g2c1.location());

  // Groups are deleted, rebuild groups.
  {
    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
    Object** g1_children[] = { g1c1.location() };
    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
    Object** g2_children[] = { g2c1.location() };
    global_handles->AddObjectGroup(g1_objects, 2, NULL);
    global_handles->AddImplicitReferences(
        Handle<HeapObject>::cast(g1s1).location(), g1_children, 1);
    global_handles->AddObjectGroup(g2_objects, 2, NULL);
    global_handles->AddImplicitReferences(
        Handle<HeapObject>::cast(g2s2).location(), g2_children, 1);
  }

  HEAP->CollectGarbage(OLD_POINTER_SPACE);

  // All objects should be gone. 5 global handles in total.
  CHECK_EQ(5, NumberOfWeakCalls);

  // And now make children weak again and collect them.
  global_handles->MakeWeak(g1c1.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);
  global_handles->MakeWeak(g2c1.location(),
                           reinterpret_cast<void*>(1234),
                           &WeakPointerCallback);

  HEAP->CollectGarbage(OLD_POINTER_SPACE);
  CHECK_EQ(7, NumberOfWeakCalls);
}


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

  bool has_been_disposed() { return has_been_disposed_; }

  virtual void Dispose() {
    ASSERT(!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_;
};


TEST(EmptyObjectGroups) {
  InitializeVM();
  GlobalHandles* global_handles = Isolate::Current()->global_handles();

  v8::HandleScope handle_scope;

  Handle<Object> object =
      global_handles->Create(HEAP->AllocateFixedArray(1)->ToObjectChecked());

  TestRetainedObjectInfo info;
  global_handles->AddObjectGroup(NULL, 0, &info);
  ASSERT(info.has_been_disposed());

  global_handles->AddImplicitReferences(
        Handle<HeapObject>::cast(object).location(), NULL, 0);
}
