#!/usr/bin/env python
# Copyright 2019 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.

"""This program writes a C++ file that can be used to look up whether a given
address matches known object locations. The first argument is the directory
containing the file v8heapconst.py; the second argument is the output .cc file.
"""

import sys
sys.path.insert(0, sys.argv[1])
import v8heapconst

out = """
#include <cstdint>
#include <string>

#include "src/common/ptr-compr-inl.h"
#include "tools/debug_helper/debug-helper-internal.h"

namespace v8 {
namespace internal {
namespace debug_helper_internal {
"""

def iterate_objects(target_space, camel_space_name):
  global out
  result = []
  for (space, offset), (instance_type, name) in v8heapconst.KNOWN_MAPS.items():
    if space == target_space:
      result.append((offset, name))
  for (space, offset), name in v8heapconst.KNOWN_OBJECTS.items():
    if space == target_space:
      result.append((offset, name))
  out = out + '\nstd::string FindKnownObjectIn' + camel_space_name \
      + '(uintptr_t offset) {\n  switch (offset) {\n'
  for offset, name in result:
    out = out + '    case ' + str(offset) + ': return "' + name + '";\n'
  out = out + '    default: return "";\n  }\n}\n'

iterate_objects('map_space', 'MapSpace')
iterate_objects('read_only_space', 'ReadOnlySpace')
iterate_objects('old_space', 'OldSpace')

def iterate_maps(target_space, camel_space_name):
  global out
  out = out + '\nint FindKnownMapInstanceTypeIn' + camel_space_name \
      + '(uintptr_t offset) {\n  switch (offset) {\n'
  for (space, offset), (instance_type, name) in v8heapconst.KNOWN_MAPS.items():
    if space == target_space:
      out = out + '    case ' + str(offset) + ': return ' + str(instance_type) \
          + ';\n'
  out = out + '    default: return -1;\n  }\n}\n'

iterate_maps('map_space', 'MapSpace')
iterate_maps('read_only_space', 'ReadOnlySpace')

out = out + '\nvoid FillInUnknownHeapAddresses(' + \
    'd::HeapAddresses* heap_addresses, uintptr_t any_uncompressed_ptr) {\n'
if (hasattr(v8heapconst, 'HEAP_FIRST_PAGES')):  # Only exists in ptr-compr builds.
  out = out + '  if (heap_addresses->any_heap_pointer == 0) {\n'
  out = out + '    heap_addresses->any_heap_pointer = any_uncompressed_ptr;\n'
  out = out + '  }\n'
  expected_spaces = set(['map_space', 'read_only_space', 'old_space'])
  for offset, space_name in v8heapconst.HEAP_FIRST_PAGES.items():
    if (space_name in expected_spaces):
      out = out + '  if (heap_addresses->' + space_name + '_first_page == 0) {\n'
      out = out + '    heap_addresses->' + space_name + \
          '_first_page = i::DecompressTaggedPointer(any_uncompressed_ptr, ' + \
          str(offset) + ');\n'
      out = out + '  }\n'
out = out + '}\n'

out = out + '\n}\n}\n}\n'

try:
  with open(sys.argv[2], "r") as out_file:
    if out == out_file.read():
      sys.exit(0)  # No modification needed.
except:
  pass  # File probably doesn't exist; write it.
with open(sys.argv[2], "w") as out_file:
  out_file.write(out)
