// Copyright 2016 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 "test/fuzzer/fuzzer-support.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "include/libplatform/libplatform.h"

#include "src/flags.h"

namespace v8_fuzzer {

namespace {

FuzzerSupport* g_fuzzer_support = nullptr;

void DeleteFuzzerSupport() {
  if (g_fuzzer_support) {
    delete g_fuzzer_support;
    g_fuzzer_support = nullptr;
  }
}

}  // namespace

class FuzzerSupport::ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
 public:
  virtual void* Allocate(size_t length) {
    void* data = AllocateUninitialized(length);
    return data == NULL ? data : memset(data, 0, length);
  }
  virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
  virtual void Free(void* data, size_t) { free(data); }
};

FuzzerSupport::FuzzerSupport(int* argc, char*** argv) {
  v8::internal::FLAG_expose_gc = true;
  v8::V8::SetFlagsFromCommandLine(argc, *argv, true);
  v8::V8::InitializeICUDefaultLocation((*argv)[0]);
  v8::V8::InitializeExternalStartupData((*argv)[0]);
  platform_ = v8::platform::CreateDefaultPlatform();
  v8::V8::InitializePlatform(platform_);
  v8::V8::Initialize();

  allocator_ = new ArrayBufferAllocator;
  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = allocator_;
  isolate_ = v8::Isolate::New(create_params);

  {
    v8::Isolate::Scope isolate_scope(isolate_);
    v8::HandleScope handle_scope(isolate_);
    context_.Reset(isolate_, v8::Context::New(isolate_));
  }
}

FuzzerSupport::~FuzzerSupport() {
  {
    v8::Isolate::Scope isolate_scope(isolate_);
    while (v8::platform::PumpMessageLoop(platform_, isolate_)) /* empty */
      ;

    v8::HandleScope handle_scope(isolate_);
    context_.Reset();
  }

  isolate_->LowMemoryNotification();
  isolate_->Dispose();
  isolate_ = nullptr;

  delete allocator_;
  allocator_ = nullptr;

  v8::V8::Dispose();
  v8::V8::ShutdownPlatform();

  delete platform_;
  platform_ = nullptr;
}

// static
FuzzerSupport* FuzzerSupport::Get() { return g_fuzzer_support; }

v8::Isolate* FuzzerSupport::GetIsolate() { return isolate_; }

v8::Local<v8::Context> FuzzerSupport::GetContext() {
  v8::Isolate::Scope isolate_scope(isolate_);
  v8::EscapableHandleScope handle_scope(isolate_);
  v8::Local<v8::Context> context =
      v8::Local<v8::Context>::New(isolate_, context_);
  return handle_scope.Escape(context);
}

}  // namespace v8_fuzzer

extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
  v8_fuzzer::g_fuzzer_support = new v8_fuzzer::FuzzerSupport(argc, argv);
  atexit(&v8_fuzzer::DeleteFuzzerSupport);
  return 0;
}
