// Copyright 2012 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 <stdio.h>

#include "include/libplatform/libplatform.h"
#include "include/v8.h"

#include "src/frames.h"
#include "src/heap/heap.h"
#include "src/heap/spaces.h"
#include "src/isolate.h"
#include "src/objects-inl.h"

namespace v8 {

static const char* kHeader =
    "# Copyright 2017 the V8 project authors. All rights reserved.\n"
    "# Use of this source code is governed by a BSD-style license that can\n"
    "# be found in the LICENSE file.\n"
    "\n"
    "# This file is automatically generated by mkgrokdump and should not\n"
    "# be modified manually.\n"
    "\n"
    "# List of known V8 instance types.\n";

// Non-snapshot builds allocate objects to different places.
// Debug builds emit debug code, affecting code object sizes.
#if defined(V8_USE_SNAPSHOT) && !defined(DEBUG)
static const char* kBuild = "shipping";
#else
static const char* kBuild = "non-shipping";
#endif

class MockArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
 public:
  void* Allocate(size_t length) override { return nullptr; }
  void* AllocateUninitialized(size_t length) override { return nullptr; }
  void* Reserve(size_t length) override { return nullptr; }
  void Free(void* data, size_t length, AllocationMode mode) override {}
  void Free(void* p, size_t) override {}
  void SetProtection(void* data, size_t length,
                     Protection protection) override {}
};

static int DumpHeapConstants(const char* argv0) {
  // Start up V8.
  std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
  v8::V8::InitializePlatform(platform.get());
  v8::V8::Initialize();
  v8::V8::InitializeExternalStartupData(argv0);
  Isolate::CreateParams create_params;
  MockArrayBufferAllocator mock_arraybuffer_allocator;
  create_params.array_buffer_allocator = &mock_arraybuffer_allocator;
  Isolate* isolate = Isolate::New(create_params);
  {
    Isolate::Scope scope(isolate);
    i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
    i::PrintF("%s", kHeader);
#define DUMP_TYPE(T) i::PrintF("  %d: \"%s\",\n", i::T, #T);
    i::PrintF("INSTANCE_TYPES = {\n");
    INSTANCE_TYPE_LIST(DUMP_TYPE)
    i::PrintF("}\n");
#undef DUMP_TYPE

    // Dump the KNOWN_MAP table to the console.
    i::PrintF("\n# List of known V8 maps.\n");
#define ROOT_LIST_CASE(type, name, camel_name) \
  if (n == NULL && o == heap->name()) n = #camel_name;
#define STRUCT_LIST_CASE(upper_name, camel_name, name) \
  if (n == NULL && o == heap->name##_map()) n = #camel_name "Map";
    i::HeapObjectIterator it(heap->map_space());
    i::PrintF("KNOWN_MAPS = {\n");
    for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
      i::Map* m = i::Map::cast(o);
      const char* n = NULL;
      intptr_t p = reinterpret_cast<intptr_t>(m) & 0x7FFFF;
      int t = m->instance_type();
      ROOT_LIST(ROOT_LIST_CASE)
      STRUCT_LIST(STRUCT_LIST_CASE)
      if (n == NULL) continue;
      i::PrintF("  0x%05" V8PRIxPTR ": (%d, \"%s\"),\n", p, t, n);
    }
    i::PrintF("}\n");
#undef STRUCT_LIST_CASE
#undef ROOT_LIST_CASE

    // Dump the KNOWN_OBJECTS table to the console.
    i::PrintF("\n# List of known V8 objects.\n");
#define ROOT_LIST_CASE(type, name, camel_name) \
  if (n == NULL && o == heap->name()) {        \
    n = #camel_name;                           \
    i = i::Heap::k##camel_name##RootIndex;     \
  }
    i::PagedSpaces spit(heap);
    i::PrintF("KNOWN_OBJECTS = {\n");
    for (i::PagedSpace* s = spit.next(); s != NULL; s = spit.next()) {
      i::HeapObjectIterator it(s);
      // Code objects are generally platform-dependent.
      if (s->identity() == i::CODE_SPACE || s->identity() == i::MAP_SPACE)
        continue;
      const char* sname = AllocationSpaceName(s->identity());
      for (i::Object* o = it.Next(); o != NULL; o = it.Next()) {
        const char* n = NULL;
        i::Heap::RootListIndex i = i::Heap::kStrongRootListLength;
        intptr_t p = reinterpret_cast<intptr_t>(o) & 0x7FFFF;
        ROOT_LIST(ROOT_LIST_CASE)
        if (n == NULL) continue;
        if (!i::Heap::RootIsImmortalImmovable(i)) continue;
        i::PrintF("  (\"%s\", 0x%05" V8PRIxPTR "): \"%s\",\n", sname, p, n);
      }
    }
    i::PrintF("}\n");
#undef ROOT_LIST_CASE

    // Dump frame markers
    i::PrintF("\n# List of known V8 Frame Markers.\n");
#define DUMP_MARKER(T, class) i::PrintF("  \"%s\",\n", #T);
    i::PrintF("FRAME_MARKERS = (\n");
    STACK_FRAME_TYPE_LIST(DUMP_MARKER)
    i::PrintF(")\n");
#undef DUMP_TYPE
  }

  i::PrintF("\n# This set of constants is generated from a %s build.\n",
            kBuild);

  // Teardown.
  isolate->Dispose();
  v8::V8::ShutdownPlatform();
  return 0;
}

}  // namespace v8

int main(int argc, char* argv[]) { return v8::DumpHeapConstants(argv[0]); }
