// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler/aot/precompiler_tracer.h"

#include "vm/compiler/aot/precompiler.h"
#include "vm/zone_text_buffer.h"

namespace dart {

#if defined(DART_PRECOMPILER)

DEFINE_FLAG(charp,
            trace_precompiler_to,
            nullptr,
            "Output machine readable precompilation trace into the given file");

PrecompilerTracer* PrecompilerTracer::StartTracingIfRequested(
    Precompiler* precompiler) {
  const char* filename = FLAG_trace_precompiler_to;
  if (filename == nullptr) {
    return nullptr;
  }
  if ((Dart::file_write_callback() == nullptr) ||
      (Dart::file_open_callback() == nullptr) ||
      (Dart::file_close_callback() == nullptr)) {
    OS::PrintErr("warning: Could not access file callbacks.");
    return nullptr;
  }
  void* file = Dart::file_open_callback()(filename, /*write=*/true);
  if (file == NULL) {
    OS::PrintErr("warning: Failed to write precompiler trace: %s\n", filename);
    return nullptr;
  }
  return new PrecompilerTracer(precompiler, file);
}

PrecompilerTracer::PrecompilerTracer(Precompiler* precompiler, void* stream)
    : zone_(Thread::Current()->zone()),
      precompiler_(precompiler),
      buffer_(1024),
      stream_(stream),
      strings_(HashTables::New<StringTable>(1024)),
      entities_(HashTables::New<EntityTable>(1024)),
      object_(Object::Handle()),
      cls_(Class::Handle()) {
  Write("{\"trace\":[\"R\",");
}

void PrecompilerTracer::Finalize() {
  Write("\"E\"],");
  WriteEntityTable();
  Write(",");
  WriteStringTable();
  Write("}\n");

  const intptr_t output_length = buffer_.length();
  char* output = buffer_.Steal();
  Dart::file_write_callback()(output, output_length, stream_);
  free(output);
  Dart::file_close_callback()(stream_);

  strings_.Release();
  entities_.Release();
}

void PrecompilerTracer::WriteEntityTable() {
  Write("\"entities\":[");
  const auto& entities_by_id =
      Array::Handle(zone_, Array::New(entities_.NumOccupied()));

  EntityTable::Iterator it(&entities_);
  while (it.MoveNext()) {
    object_ = entities_.GetPayload(it.Current(), 0);
    const intptr_t index = Smi::Cast(object_).Value();
    object_ = entities_.GetKey(it.Current());
    entities_by_id.SetAt(index, object_);
  }

  auto& obj = Object::Handle(zone_);
  auto& lib = Library::Handle(zone_);
  auto& str = String::Handle(zone_);
  for (intptr_t i = 0; i < entities_by_id.Length(); i++) {
    if (i > 0) {
      Write(",");
    }
    obj = entities_by_id.At(i);
    if (obj.IsFunction()) {
      const auto& fun = Function::Cast(obj);
      cls_ = fun.Owner();
      const intptr_t selector_id =
          precompiler_->selector_map()->SelectorId(fun);
      Write("\"%c\",%" Pd ",%" Pd ",%" Pd "",
            fun.IsDynamicFunction() ? 'F' : 'S', InternEntity(cls_),
            InternString(NameForTrace(fun)), selector_id);
    } else if (obj.IsField()) {
      const auto& field = Field::Cast(obj);
      cls_ = field.Owner();
      str = field.name();
      Write("\"V\",%" Pd ",%" Pd ",0", InternEntity(cls_), InternString(str));
    } else if (obj.IsClass()) {
      const auto& cls = Class::Cast(obj);
      lib = cls.library();
      str = lib.url();
      const auto url_id = InternString(str);
      str = cls.ScrubbedName();
      const auto name_id = InternString(str);
      Write("\"C\",%" Pd ",%" Pd ",0", url_id, name_id);
    } else {
      UNREACHABLE();
    }
  }
  Write("]");
}

void PrecompilerTracer::WriteStringTable() {
  Write("\"strings\":[");
  GrowableArray<const char*> strings_by_id(strings_.NumOccupied());
  strings_by_id.EnsureLength(strings_.NumOccupied(), nullptr);
  StringTable::Iterator it(&strings_);
  while (it.MoveNext()) {
    object_ = strings_.GetPayload(it.Current(), 0);
    const auto index = Smi::Cast(object_).Value();
    object_ = strings_.GetKey(it.Current());
    strings_by_id[index] = String::Cast(object_).ToCString();
  }
  auto comma = false;
  for (auto str : strings_by_id) {
    Write("%s\"%s\"", comma ? "," : "", str);
    comma = true;
  }
  Write("]");
}

intptr_t PrecompilerTracer::InternString(const CString& cstr) {
  object_ = Smi::New(strings_.NumOccupied());
  object_ = strings_.InsertNewOrGetValue(cstr, object_);
  return Smi::Cast(object_).Value();
}

intptr_t PrecompilerTracer::InternString(const String& str) {
  object_ = Smi::New(strings_.NumOccupied());
  object_ = strings_.InsertOrGetValue(str, object_);
  return Smi::Cast(object_).Value();
}

intptr_t PrecompilerTracer::InternEntity(const Object& obj) {
  ASSERT(obj.IsFunction() || obj.IsClass() || obj.IsField());
  const auto num_occupied = entities_.NumOccupied();
  object_ = Smi::New(num_occupied);
  object_ = entities_.InsertOrGetValue(obj, object_);
  const auto id = Smi::Cast(object_).Value();
  if (id == num_occupied) {
    cls_ = Class::null();
    if (obj.IsFunction()) {
      cls_ = Function::Cast(obj).Owner();
    } else if (obj.IsField()) {
      cls_ = Field::Cast(obj).Owner();
    }
    if (cls_.ptr() != Class::null()) {
      InternEntity(cls_);
    }
  }
  return id;
}

PrecompilerTracer::CString PrecompilerTracer::NameForTrace(const Function& f) {
  ZoneTextBuffer buffer(zone_);
  f.PrintName(NameFormattingParams::DisambiguatedWithoutClassName(
                  Object::NameVisibility::kInternalName),
              &buffer);
  return {buffer.buffer(), buffer.length(),
          String::Hash(buffer.buffer(), buffer.length())};
}

#endif  // defined(DART_PRECOMPILER)

}  // namespace dart
