// Copyright 2018 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-inl.h"
#include "src/api/api.h"
#include "src/execution/isolate.h"
#include "src/heap/heap-inl.h"
#include "src/heap/spaces.h"
#include "src/objects/objects-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/heap/heap-tester.h"
#include "test/cctest/heap/heap-utils.h"

#define TEST_STR "tests are great!"

namespace v8 {
namespace internal {
namespace heap {

// Adapted from cctest/test-api.cc
class TestOneByteResource : public v8::String::ExternalOneByteStringResource {
 public:
  explicit TestOneByteResource(const char* data, int* counter = nullptr,
                               size_t offset = 0)
      : orig_data_(data),
        data_(data + offset),
        length_(strlen(data) - offset),
        counter_(counter) {}

  ~TestOneByteResource() override {
    i::DeleteArray(orig_data_);
    if (counter_ != nullptr) ++*counter_;
  }

  const char* data() const override { return data_; }

  size_t length() const override { return length_; }

 private:
  const char* orig_data_;
  const char* data_;
  size_t length_;
  int* counter_;
};

TEST(ExternalString_ExternalBackingStoreSizeIncreases) {
  CcTest::InitializeVM();
  LocalContext env;
  v8::Isolate* isolate = env->GetIsolate();
  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
  ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;

  const size_t backing_store_before =
      heap->old_space()->ExternalBackingStoreBytes(type);

  {
    v8::HandleScope handle_scope(isolate);
    v8::Local<v8::String> es = v8::String::NewExternalOneByte(
        isolate, new TestOneByteResource(i::StrDup(TEST_STR))).ToLocalChecked();
    USE(es);

    const size_t backing_store_after =
        heap->old_space()->ExternalBackingStoreBytes(type);

    CHECK_EQ(es->Length(), backing_store_after - backing_store_before);
  }
}

TEST(ExternalString_ExternalBackingStoreSizeDecreases) {
  ManualGCScope manual_gc_scope;
  CcTest::InitializeVM();
  LocalContext env;
  v8::Isolate* isolate = env->GetIsolate();
  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
  ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;

  const size_t backing_store_before =
      heap->old_space()->ExternalBackingStoreBytes(type);

  {
    v8::HandleScope handle_scope(isolate);
    v8::Local<v8::String> es = v8::String::NewExternalOneByte(
        isolate, new TestOneByteResource(i::StrDup(TEST_STR))).ToLocalChecked();
    USE(es);
  }

  heap::GcAndSweep(heap, OLD_SPACE);

  const size_t backing_store_after =
      heap->old_space()->ExternalBackingStoreBytes(type);

  CHECK_EQ(0, backing_store_after - backing_store_before);
}

TEST(ExternalString_ExternalBackingStoreSizeIncreasesMarkCompact) {
  if (FLAG_never_compact) return;
  ManualGCScope manual_gc_scope;
  FLAG_manual_evacuation_candidates_selection = true;
  CcTest::InitializeVM();
  LocalContext env;
  v8::Isolate* isolate = env->GetIsolate();
  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
  heap::AbandonCurrentlyFreeMemory(heap->old_space());
  ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;

  const size_t backing_store_before =
      heap->old_space()->ExternalBackingStoreBytes(type);

  {
    v8::HandleScope handle_scope(isolate);
    v8::Local<v8::String> es = v8::String::NewExternalOneByte(
        isolate, new TestOneByteResource(i::StrDup(TEST_STR))).ToLocalChecked();
    v8::internal::Handle<v8::internal::String> esh = v8::Utils::OpenHandle(*es);

    Page* page_before_gc = Page::FromHeapObject(*esh);
    heap::ForceEvacuationCandidate(page_before_gc);

    CcTest::CollectAllGarbage();

    const size_t backing_store_after =
        heap->old_space()->ExternalBackingStoreBytes(type);
    CHECK_EQ(es->Length(), backing_store_after - backing_store_before);
  }

  heap::GcAndSweep(heap, OLD_SPACE);
  const size_t backing_store_after =
      heap->old_space()->ExternalBackingStoreBytes(type);
  CHECK_EQ(0, backing_store_after - backing_store_before);
}

TEST(ExternalString_ExternalBackingStoreSizeIncreasesAfterExternalization) {
  ManualGCScope manual_gc_scope;
  CcTest::InitializeVM();
  LocalContext env;
  v8::Isolate* isolate = env->GetIsolate();
  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
  ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
  size_t old_backing_store_before = 0, new_backing_store_before = 0;

  {
    v8::HandleScope handle_scope(isolate);

    new_backing_store_before =
        heap->new_space()->ExternalBackingStoreBytes(type);
    old_backing_store_before =
        heap->old_space()->ExternalBackingStoreBytes(type);

    // Allocate normal string in the new gen.
    v8::Local<v8::String> str =
        v8::String::NewFromUtf8Literal(isolate, TEST_STR);

    CHECK_EQ(0, heap->new_space()->ExternalBackingStoreBytes(type) -
                    new_backing_store_before);

    // Trigger GCs so that the newly allocated string moves to old gen.
    heap::GcAndSweep(heap, NEW_SPACE);  // in survivor space now
    heap::GcAndSweep(heap, NEW_SPACE);  // in old gen now

    bool success =
        str->MakeExternal(new TestOneByteResource(i::StrDup(TEST_STR)));
    CHECK(success);

    CHECK_EQ(str->Length(), heap->old_space()->ExternalBackingStoreBytes(type) -
                                old_backing_store_before);
  }

  heap::GcAndSweep(heap, OLD_SPACE);

  CHECK_EQ(0, heap->old_space()->ExternalBackingStoreBytes(type) -
                  old_backing_store_before);
}

TEST(ExternalString_PromotedThinString) {
  if (FLAG_single_generation) return;
  ManualGCScope manual_gc_scope;
  CcTest::InitializeVM();
  LocalContext env;
  v8::Isolate* isolate = env->GetIsolate();
  i::Isolate* i_isolate = CcTest::i_isolate();
  i::Factory* factory = i_isolate->factory();
  Heap* heap = i_isolate->heap();

  {
    v8::HandleScope handle_scope(isolate);

    // New external string in the old space.
    v8::internal::Handle<v8::internal::String> string1 =
        factory
            ->NewExternalStringFromOneByte(
                new TestOneByteResource(i::StrDup(TEST_STR)))
            .ToHandleChecked();

    // Internalize external string.
    i::Handle<i::String> isymbol1 = factory->InternalizeString(string1);
    CHECK(isymbol1->IsInternalizedString());
    CHECK(string1->IsExternalString());
    CHECK(!heap->InYoungGeneration(*isymbol1));

    // New external string in the young space. This string has the same content
    // as the previous one (that was already internalized).
    v8::Local<v8::String> string2 =
        v8::String::NewFromUtf8Literal(isolate, TEST_STR);
    bool success =
        string2->MakeExternal(new TestOneByteResource(i::StrDup(TEST_STR)));
    CHECK(success);

    // Internalize (it will create a thin string in the new space).
    i::Handle<i::String> istring = v8::Utils::OpenHandle(*string2);
    i::Handle<i::String> isymbol2 = factory->InternalizeString(istring);
    CHECK(isymbol2->IsInternalizedString());
    CHECK(istring->IsThinString());
    CHECK(heap->InYoungGeneration(*istring));

    // Collect thin string. References to the thin string will be updated to
    // point to the actual external string in the old space.
    heap::GcAndSweep(heap, NEW_SPACE);

    USE(isymbol1);
    USE(isymbol2);
  }
}
}  // namespace heap
}  // namespace internal
}  // namespace v8

#undef TEST_STR
