// Copyright 2006-2008 the V8 project authors. All rights reserved.

#include <stdlib.h>

#include "v8.h"

#include "execution.h"
#include "factory.h"
#include "macro-assembler.h"
#include "global-handles.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();
}


static void CheckMap(Map* map, int type, int instance_size) {
  CHECK(map->IsHeapObject());
#ifdef DEBUG
  CHECK(Heap::Contains(map));
#endif
  CHECK_EQ(Heap::meta_map(), map->map());
  CHECK_EQ(type, map->instance_type());
  CHECK_EQ(instance_size, map->instance_size());
}


TEST(HeapMaps) {
  InitializeVM();
  CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize);
  CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
  CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, FixedArray::kHeaderSize);
  CheckMap(Heap::string_map(), STRING_TYPE, SeqTwoByteString::kAlignedSize);
}


static void CheckOddball(Object* obj, const char* string) {
  CHECK(obj->IsOddball());
  bool exc;
  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
}


static void CheckSmi(int value, const char* string) {
  bool exc;
  Object* print_string =
      *Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
}


static void CheckNumber(double value, const char* string) {
  Object* obj = Heap::NumberFromDouble(value);
  CHECK(obj->IsNumber());
  bool exc;
  Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
  CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
}


static void CheckFindCodeObject() {
  // Test FindCodeObject
#define __ assm.

  Assembler assm(NULL, 0);

  __ nop();  // supported on all architectures

  CodeDesc desc;
  assm.GetCode(&desc);
  Object* code = Heap::CreateCode(desc,
                                  NULL,
                                  Code::ComputeFlags(Code::STUB),
                                  Handle<Object>(Heap::undefined_value()));
  CHECK(code->IsCode());

  HeapObject* obj = HeapObject::cast(code);
  Address obj_addr = obj->address();

  for (int i = 0; i < obj->Size(); i += kPointerSize) {
    Object* found = Heap::FindCodeObject(obj_addr + i);
    CHECK_EQ(code, found);
  }

  Object* copy = Heap::CreateCode(desc,
                                  NULL,
                                  Code::ComputeFlags(Code::STUB),
                                  Handle<Object>(Heap::undefined_value()));
  CHECK(copy->IsCode());
  HeapObject* obj_copy = HeapObject::cast(copy);
  Object* not_right = Heap::FindCodeObject(obj_copy->address() +
                                           obj_copy->Size() / 2);
  CHECK(not_right != code);
}


TEST(HeapObjects) {
  InitializeVM();

  v8::HandleScope sc;
  Object* value = Heap::NumberFromDouble(1.000123);
  CHECK(value->IsHeapNumber());
  CHECK(value->IsNumber());
  CHECK_EQ(1.000123, value->Number());

  value = Heap::NumberFromDouble(1.0);
  CHECK(value->IsSmi());
  CHECK(value->IsNumber());
  CHECK_EQ(1.0, value->Number());

  value = Heap::NumberFromInt32(1024);
  CHECK(value->IsSmi());
  CHECK(value->IsNumber());
  CHECK_EQ(1024.0, value->Number());

  value = Heap::NumberFromInt32(Smi::kMinValue);
  CHECK(value->IsSmi());
  CHECK(value->IsNumber());
  CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());

  value = Heap::NumberFromInt32(Smi::kMaxValue);
  CHECK(value->IsSmi());
  CHECK(value->IsNumber());
  CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());

#ifndef V8_TARGET_ARCH_X64
  // TODO(lrn): We need a NumberFromIntptr function in order to test this.
  value = Heap::NumberFromInt32(Smi::kMinValue - 1);
  CHECK(value->IsHeapNumber());
  CHECK(value->IsNumber());
  CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
#endif

  value = Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
  CHECK(value->IsHeapNumber());
  CHECK(value->IsNumber());
  CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
           value->Number());

  // nan oddball checks
  CHECK(Heap::nan_value()->IsNumber());
  CHECK(isnan(Heap::nan_value()->Number()));

  Object* str = Heap::AllocateStringFromAscii(CStrVector("fisk hest "));
  if (!str->IsFailure()) {
    String* s =  String::cast(str);
    CHECK(s->IsString());
    CHECK_EQ(10, s->length());
  } else {
    CHECK(false);
  }

  String* object_symbol = String::cast(Heap::Object_symbol());
  CHECK(Top::context()->global()->HasLocalProperty(object_symbol));

  // Check ToString for oddballs
  CheckOddball(Heap::true_value(), "true");
  CheckOddball(Heap::false_value(), "false");
  CheckOddball(Heap::null_value(), "null");
  CheckOddball(Heap::undefined_value(), "undefined");

  // Check ToString for Smis
  CheckSmi(0, "0");
  CheckSmi(42, "42");
  CheckSmi(-42, "-42");

  // Check ToString for Numbers
  CheckNumber(1.1, "1.1");

  CheckFindCodeObject();
}


TEST(Tagging) {
  InitializeVM();
  int request = 24;
  CHECK_EQ(request, static_cast<int>(OBJECT_SIZE_ALIGN(request)));
  CHECK(Smi::FromInt(42)->IsSmi());
  CHECK(Failure::RetryAfterGC(request, NEW_SPACE)->IsFailure());
  CHECK_EQ(request, Failure::RetryAfterGC(request, NEW_SPACE)->requested());
  CHECK_EQ(NEW_SPACE,
           Failure::RetryAfterGC(request, NEW_SPACE)->allocation_space());
  CHECK_EQ(OLD_POINTER_SPACE,
           Failure::RetryAfterGC(request,
                                 OLD_POINTER_SPACE)->allocation_space());
  CHECK(Failure::Exception()->IsFailure());
  CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
  CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
}


TEST(GarbageCollection) {
  InitializeVM();

  v8::HandleScope sc;
  // check GC when heap is empty
  int free_bytes = Heap::MaxObjectSizeInPagedSpace();
  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));

  // allocate a function and keep it in global object's property
  String* func_name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
  SharedFunctionInfo* function_share =
    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name));
  JSFunction* function =
      JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
                                              function_share,
                                              Heap::undefined_value()));
  Map* initial_map =
      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
  function->set_initial_map(initial_map);
  Top::context()->global()->SetProperty(func_name, function, NONE);

  // allocate an object, but it is unrooted
  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
  String* prop_namex = String::cast(Heap::LookupAsciiSymbol("theSlotx"));
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
  obj->SetProperty(prop_namex, Smi::FromInt(24), NONE);

  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
  CHECK_EQ(Smi::FromInt(24), obj->GetProperty(prop_namex));

  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));

  // function should be alive, func_name might be invalid after GC
  func_name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
  CHECK(Top::context()->global()->HasLocalProperty(func_name));
  // check function is retained
  Object* func_value = Top::context()->global()->GetProperty(func_name);
  CHECK(func_value->IsJSFunction());
  // old function pointer may not be valid
  function = JSFunction::cast(func_value);

  // allocate another object, make it reachable from global
  obj = JSObject::cast(Heap::AllocateJSObject(function));
  String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
  Top::context()->global()->SetProperty(obj_name, obj, NONE);
  // set property
  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);

  // after gc, it should survive
  CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));

  obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
  CHECK(Top::context()->global()->HasLocalProperty(obj_name));
  CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject());
  obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name));
  prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
}


static void VerifyStringAllocation(const char* string) {
  String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string)));
  CHECK_EQ(StrLength(string), s->length());
  for (int index = 0; index < s->length(); index++) {
    CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index));  }
}


TEST(String) {
  InitializeVM();

  VerifyStringAllocation("a");
  VerifyStringAllocation("ab");
  VerifyStringAllocation("abc");
  VerifyStringAllocation("abcd");
  VerifyStringAllocation("fiskerdrengen er paa havet");
}


TEST(LocalHandles) {
  InitializeVM();

  v8::HandleScope scope;
  const char* name = "Kasper the spunky";
  Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
  CHECK_EQ(StrLength(name), string->length());
}


TEST(GlobalHandles) {
  InitializeVM();

  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
  Object* u = Heap::AllocateHeapNumber(1.12344);

  Handle<Object> h1 = GlobalHandles::Create(i);
  Handle<Object> h2 = GlobalHandles::Create(u);
  Handle<Object> h3 = GlobalHandles::Create(i);
  Handle<Object> h4 = GlobalHandles::Create(u);

  // after gc, it should survive
  CHECK(Heap::CollectGarbage(0, NEW_SPACE));

  CHECK((*h1)->IsString());
  CHECK((*h2)->IsHeapNumber());
  CHECK((*h3)->IsString());
  CHECK((*h4)->IsHeapNumber());

  CHECK_EQ(*h3, *h1);
  GlobalHandles::Destroy(h1.location());
  GlobalHandles::Destroy(h3.location());

  CHECK_EQ(*h4, *h2);
  GlobalHandles::Destroy(h2.location());
  GlobalHandles::Destroy(h4.location());
}


static bool WeakPointerCleared = false;

static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle,
                                         void* id) {
  USE(handle);
  if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
}


TEST(WeakGlobalHandlesScavenge) {
  InitializeVM();

  WeakPointerCleared = false;

  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
  Object* u = Heap::AllocateHeapNumber(1.12344);

  Handle<Object> h1 = GlobalHandles::Create(i);
  Handle<Object> h2 = GlobalHandles::Create(u);

  GlobalHandles::MakeWeak(h2.location(),
                          reinterpret_cast<void*>(1234),
                          &TestWeakGlobalHandleCallback);

  // Scavenge treats weak pointers as normal roots.
  Heap::PerformScavenge();

  CHECK((*h1)->IsString());
  CHECK((*h2)->IsHeapNumber());

  CHECK(!WeakPointerCleared);
  CHECK(!GlobalHandles::IsNearDeath(h2.location()));
  CHECK(!GlobalHandles::IsNearDeath(h1.location()));

  GlobalHandles::Destroy(h1.location());
  GlobalHandles::Destroy(h2.location());
}


TEST(WeakGlobalHandlesMark) {
  InitializeVM();

  WeakPointerCleared = false;

  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
  Object* u = Heap::AllocateHeapNumber(1.12344);

  Handle<Object> h1 = GlobalHandles::Create(i);
  Handle<Object> h2 = GlobalHandles::Create(u);

  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));
  CHECK(Heap::CollectGarbage(0, NEW_SPACE));
  // Make sure the object is promoted.

  GlobalHandles::MakeWeak(h2.location(),
                          reinterpret_cast<void*>(1234),
                          &TestWeakGlobalHandleCallback);
  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
  CHECK(!GlobalHandles::IsNearDeath(h2.location()));

  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));

  CHECK((*h1)->IsString());

  CHECK(WeakPointerCleared);
  CHECK(!GlobalHandles::IsNearDeath(h1.location()));
  CHECK(GlobalHandles::IsNearDeath(h2.location()));

  GlobalHandles::Destroy(h1.location());
  GlobalHandles::Destroy(h2.location());
}

static void TestDeleteWeakGlobalHandleCallback(
    v8::Persistent<v8::Value> handle,
    void* id) {
  if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true;
  handle.Dispose();
}

TEST(DeleteWeakGlobalHandle) {
  InitializeVM();

  WeakPointerCleared = false;

  Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
  Handle<Object> h = GlobalHandles::Create(i);

  GlobalHandles::MakeWeak(h.location(),
                          reinterpret_cast<void*>(1234),
                          &TestDeleteWeakGlobalHandleCallback);

  // Scanvenge does not recognize weak reference.
  Heap::PerformScavenge();

  CHECK(!WeakPointerCleared);

  // Mark-compact treats weak reference properly.
  CHECK(Heap::CollectGarbage(0, OLD_POINTER_SPACE));

  CHECK(WeakPointerCleared);
}

static const char* not_so_random_string_table[] = {
  "abstract",
  "boolean",
  "break",
  "byte",
  "case",
  "catch",
  "char",
  "class",
  "const",
  "continue",
  "debugger",
  "default",
  "delete",
  "do",
  "double",
  "else",
  "enum",
  "export",
  "extends",
  "false",
  "final",
  "finally",
  "float",
  "for",
  "function",
  "goto",
  "if",
  "implements",
  "import",
  "in",
  "instanceof",
  "int",
  "interface",
  "long",
  "native",
  "new",
  "null",
  "package",
  "private",
  "protected",
  "public",
  "return",
  "short",
  "static",
  "super",
  "switch",
  "synchronized",
  "this",
  "throw",
  "throws",
  "transient",
  "true",
  "try",
  "typeof",
  "var",
  "void",
  "volatile",
  "while",
  "with",
  0
};


static void CheckSymbols(const char** strings) {
  for (const char* string = *strings; *strings != 0; string = *strings++) {
    Object* a = Heap::LookupAsciiSymbol(string);
    // LookupAsciiSymbol may return a failure if a GC is needed.
    if (a->IsFailure()) continue;
    CHECK(a->IsSymbol());
    Object* b = Heap::LookupAsciiSymbol(string);
    if (b->IsFailure()) continue;
    CHECK_EQ(b, a);
    CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
  }
}


TEST(SymbolTable) {
  InitializeVM();

  CheckSymbols(not_so_random_string_table);
  CheckSymbols(not_so_random_string_table);
}


TEST(FunctionAllocation) {
  InitializeVM();

  v8::HandleScope sc;
  String* name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
  SharedFunctionInfo* function_share =
    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
  JSFunction* function =
    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
                                            function_share,
                                            Heap::undefined_value()));
  Map* initial_map =
      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
  function->set_initial_map(initial_map);

  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
  // Check that we can add properties to function objects.
  function->SetProperty(prop_name, Smi::FromInt(24), NONE);
  CHECK_EQ(Smi::FromInt(24), function->GetProperty(prop_name));
}


TEST(ObjectProperties) {
  InitializeVM();

  v8::HandleScope sc;
  JSFunction* constructor =
      JSFunction::cast(
          Top::context()->global()->GetProperty(String::cast(
                                                    Heap::Object_symbol())));
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
  String* first = String::cast(Heap::LookupAsciiSymbol("first"));
  String* second = String::cast(Heap::LookupAsciiSymbol("second"));

  // check for empty
  CHECK(!obj->HasLocalProperty(first));

  // add first
  obj->SetProperty(first, Smi::FromInt(1), NONE);
  CHECK(obj->HasLocalProperty(first));

  // delete first
  CHECK(obj->DeleteProperty(first, JSObject::NORMAL_DELETION));
  CHECK(!obj->HasLocalProperty(first));

  // add first and then second
  obj->SetProperty(first, Smi::FromInt(1), NONE);
  obj->SetProperty(second, Smi::FromInt(2), NONE);
  CHECK(obj->HasLocalProperty(first));
  CHECK(obj->HasLocalProperty(second));

  // delete first and then second
  CHECK(obj->DeleteProperty(first, JSObject::NORMAL_DELETION));
  CHECK(obj->HasLocalProperty(second));
  CHECK(obj->DeleteProperty(second, JSObject::NORMAL_DELETION));
  CHECK(!obj->HasLocalProperty(first));
  CHECK(!obj->HasLocalProperty(second));

  // add first and then second
  obj->SetProperty(first, Smi::FromInt(1), NONE);
  obj->SetProperty(second, Smi::FromInt(2), NONE);
  CHECK(obj->HasLocalProperty(first));
  CHECK(obj->HasLocalProperty(second));

  // delete second and then first
  CHECK(obj->DeleteProperty(second, JSObject::NORMAL_DELETION));
  CHECK(obj->HasLocalProperty(first));
  CHECK(obj->DeleteProperty(first, JSObject::NORMAL_DELETION));
  CHECK(!obj->HasLocalProperty(first));
  CHECK(!obj->HasLocalProperty(second));

  // check string and symbol match
  static const char* string1 = "fisk";
  String* s1 =
      String::cast(Heap::AllocateStringFromAscii(CStrVector(string1)));
  obj->SetProperty(s1, Smi::FromInt(1), NONE);
  CHECK(obj->HasLocalProperty(String::cast(Heap::LookupAsciiSymbol(string1))));

  // check symbol and string match
  static const char* string2 = "fugl";
  String* s2 = String::cast(Heap::LookupAsciiSymbol(string2));
  obj->SetProperty(s2, Smi::FromInt(1), NONE);
  CHECK(obj->HasLocalProperty(
            String::cast(Heap::AllocateStringFromAscii(CStrVector(string2)))));
}


TEST(JSObjectMaps) {
  InitializeVM();

  v8::HandleScope sc;
  String* name  = String::cast(Heap::LookupAsciiSymbol("theFunction"));
  SharedFunctionInfo* function_share =
    SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
  JSFunction* function =
    JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
                                            function_share,
                                            Heap::undefined_value()));
  Map* initial_map =
      Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
  function->set_initial_map(initial_map);
  String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));

  // Set a propery
  obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
  CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));

  // Check the map has changed
  CHECK(initial_map != obj->map());
}


TEST(JSArray) {
  InitializeVM();

  v8::HandleScope sc;
  String* name = String::cast(Heap::LookupAsciiSymbol("Array"));
  JSFunction* function =
      JSFunction::cast(Top::context()->global()->GetProperty(name));

  // Allocate the object.
  JSArray* array = JSArray::cast(Heap::AllocateJSObject(function));
  array->Initialize(0);

  // Set array length to 0.
  array->SetElementsLength(Smi::FromInt(0));
  CHECK_EQ(Smi::FromInt(0), array->length());
  CHECK(array->HasFastElements());  // Must be in fast mode.

  // array[length] = name.
  array->SetElement(0, name);
  CHECK_EQ(Smi::FromInt(1), array->length());
  CHECK_EQ(array->GetElement(0), name);

// Set array length with larger than smi value.
  Object* length =
      Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
  array->SetElementsLength(length);

  uint32_t int_length = 0;
  CHECK(Array::IndexFromObject(length, &int_length));
  CHECK_EQ(length, array->length());
  CHECK(array->HasDictionaryElements());  // Must be in slow mode.

  // array[length] = name.
  array->SetElement(int_length, name);
  uint32_t new_int_length = 0;
  CHECK(Array::IndexFromObject(array->length(), &new_int_length));
  CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
  CHECK_EQ(array->GetElement(int_length), name);
  CHECK_EQ(array->GetElement(0), name);
}


TEST(JSObjectCopy) {
  InitializeVM();

  v8::HandleScope sc;
  String* name = String::cast(Heap::Object_symbol());
  JSFunction* constructor =
      JSFunction::cast(Top::context()->global()->GetProperty(name));
  JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
  String* first = String::cast(Heap::LookupAsciiSymbol("first"));
  String* second = String::cast(Heap::LookupAsciiSymbol("second"));

  obj->SetProperty(first, Smi::FromInt(1), NONE);
  obj->SetProperty(second, Smi::FromInt(2), NONE);

  obj->SetElement(0, first);
  obj->SetElement(1, second);

  // Make the clone.
  JSObject* clone = JSObject::cast(Heap::CopyJSObject(obj));
  CHECK(clone != obj);

  CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
  CHECK_EQ(obj->GetElement(1), clone->GetElement(1));

  CHECK_EQ(obj->GetProperty(first), clone->GetProperty(first));
  CHECK_EQ(obj->GetProperty(second), clone->GetProperty(second));

  // Flip the values.
  clone->SetProperty(first, Smi::FromInt(2), NONE);
  clone->SetProperty(second, Smi::FromInt(1), NONE);

  clone->SetElement(0, second);
  clone->SetElement(1, first);

  CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
  CHECK_EQ(obj->GetElement(0), clone->GetElement(1));

  CHECK_EQ(obj->GetProperty(second), clone->GetProperty(first));
  CHECK_EQ(obj->GetProperty(first), clone->GetProperty(second));
}


TEST(StringAllocation) {
  InitializeVM();


  const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
  for (int length = 0; length < 100; length++) {
    v8::HandleScope scope;
    char* non_ascii = NewArray<char>(3 * length + 1);
    char* ascii = NewArray<char>(length + 1);
    non_ascii[3 * length] = 0;
    ascii[length] = 0;
    for (int i = 0; i < length; i++) {
      ascii[i] = 'a';
      non_ascii[3 * i] = chars[0];
      non_ascii[3 * i + 1] = chars[1];
      non_ascii[3 * i + 2] = chars[2];
    }
    Handle<String> non_ascii_sym =
        Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length));
    CHECK_EQ(length, non_ascii_sym->length());
    Handle<String> ascii_sym =
        Factory::LookupSymbol(Vector<const char>(ascii, length));
    CHECK_EQ(length, ascii_sym->length());
    Handle<String> non_ascii_str =
        Factory::NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
    non_ascii_str->Hash();
    CHECK_EQ(length, non_ascii_str->length());
    Handle<String> ascii_str =
        Factory::NewStringFromUtf8(Vector<const char>(ascii, length));
    ascii_str->Hash();
    CHECK_EQ(length, ascii_str->length());
    DeleteArray(non_ascii);
    DeleteArray(ascii);
  }
}


static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
  // Count the number of objects found in the heap.
  int found_count = 0;
  HeapIterator iterator;
  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
    for (int i = 0; i < size; i++) {
      if (*objs[i] == obj) {
        found_count++;
      }
    }
  }
  return found_count;
}


TEST(Iteration) {
  InitializeVM();
  v8::HandleScope scope;

  // Array of objects to scan haep for.
  const int objs_count = 6;
  Handle<Object> objs[objs_count];
  int next_objs_index = 0;

  // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE
  objs[next_objs_index++] = Factory::NewJSArray(10);
  objs[next_objs_index++] = Factory::NewJSArray(10, TENURED);

  // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
  objs[next_objs_index++] =
      Factory::NewStringFromAscii(CStrVector("abcdefghij"));
  objs[next_objs_index++] =
      Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);

  // Allocate a large string (for large object space).
  int large_size = Heap::MaxObjectSizeInPagedSpace() + 1;
  char* str = new char[large_size];
  for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
  str[large_size - 1] = '\0';
  objs[next_objs_index++] =
      Factory::NewStringFromAscii(CStrVector(str), TENURED);
  delete[] str;

  // Add a Map object to look for.
  objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());

  CHECK_EQ(objs_count, next_objs_index);
  CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
}
