/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/profiling/common/interning_output.h"

#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"

namespace {
// Flags used to distinguish distinct types of interned strings.
constexpr int kDumpedBuildID = 1 << 0;
constexpr int kDumpedMappingPath = 1 << 1;
constexpr int kDumpedFunctionName = 1 << 2;
}  // namespace

namespace perfetto {
namespace profiling {

// static
void InterningOutputTracker::WriteFixedInterningsPacket(
    TraceWriter* trace_writer,
    uint32_t sequence_flags) {
  constexpr const uint8_t kEmptyString[] = "";
  // Explicitly reserve intern ID 0 for the empty string, so unset string
  // fields get mapped to this.
  auto packet = trace_writer->NewTracePacket();
  auto* interned_data = packet->set_interned_data();
  auto* interned_string = interned_data->add_build_ids();
  interned_string->set_iid(0);
  interned_string->set_str(kEmptyString, 0);

  interned_string = interned_data->add_mapping_paths();
  interned_string->set_iid(0);
  interned_string->set_str(kEmptyString, 0);

  interned_string = interned_data->add_function_names();
  interned_string->set_iid(0);
  interned_string->set_str(kEmptyString, 0);

  if (sequence_flags) {
    packet->set_sequence_flags(sequence_flags);
  }
}

void InterningOutputTracker::WriteMap(const Interned<Mapping> map,
                                      protos::pbzero::InternedData* out) {
  auto map_it_and_inserted = dumped_mappings_.emplace(map.id());
  if (map_it_and_inserted.second) {
    for (const Interned<std::string>& str : map->path_components)
      WriteMappingPathString(str, out);

    WriteBuildIDString(map->build_id, out);

    protos::pbzero::Mapping* mapping = out->add_mappings();
    mapping->set_iid(map.id());
    mapping->set_exact_offset(map->exact_offset);
    mapping->set_start_offset(map->start_offset);
    mapping->set_start(map->start);
    mapping->set_end(map->end);
    mapping->set_load_bias(map->load_bias);
    mapping->set_build_id(map->build_id.id());
    for (const Interned<std::string>& str : map->path_components)
      mapping->add_path_string_ids(str.id());
  }
}

void InterningOutputTracker::WriteFrame(Interned<Frame> frame,
                                        protos::pbzero::InternedData* out) {
  // Trace processor depends on the map being written before the
  // frame. See StackProfileTracker::AddFrame.
  WriteMap(frame->mapping, out);
  WriteFunctionNameString(frame->function_name, out);
  bool inserted;
  std::tie(std::ignore, inserted) = dumped_frames_.emplace(frame.id());
  if (inserted) {
    protos::pbzero::Frame* frame_proto = out->add_frames();
    frame_proto->set_iid(frame.id());
    frame_proto->set_function_name_id(frame->function_name.id());
    frame_proto->set_mapping_id(frame->mapping.id());
    frame_proto->set_rel_pc(frame->rel_pc);
  }
}

void InterningOutputTracker::WriteBuildIDString(
    const Interned<std::string>& str,
    protos::pbzero::InternedData* out) {
  auto it_and_inserted = dumped_strings_.emplace(str.id(), 0);
  auto it = it_and_inserted.first;
  // This is for the rare case that the same string is used as two different
  // types (e.g. a function name that matches a path segment). In that case
  // we need to emit the string as all of its types.
  if ((it->second & kDumpedBuildID) == 0) {
    protos::pbzero::InternedString* interned_string = out->add_build_ids();
    interned_string->set_iid(str.id());
    interned_string->set_str(str.data());
    it->second |= kDumpedBuildID;
  }
}

void InterningOutputTracker::WriteMappingPathString(
    const Interned<std::string>& str,
    protos::pbzero::InternedData* out) {
  auto it_and_inserted = dumped_strings_.emplace(str.id(), 0);
  auto it = it_and_inserted.first;
  // This is for the rare case that the same string is used as two different
  // types (e.g. a function name that matches a path segment). In that case
  // we need to emit the string as all of its types.
  if ((it->second & kDumpedMappingPath) == 0) {
    protos::pbzero::InternedString* interned_string = out->add_mapping_paths();
    interned_string->set_iid(str.id());
    interned_string->set_str(str.data());
    it->second |= kDumpedMappingPath;
  }
}

void InterningOutputTracker::WriteFunctionNameString(
    const Interned<std::string>& str,
    protos::pbzero::InternedData* out) {
  auto it_and_inserted = dumped_strings_.emplace(str.id(), 0);
  auto it = it_and_inserted.first;
  // This is for the rare case that the same string is used as two different
  // types (e.g. a function name that matches a path segment). In that case
  // we need to emit the string as all of its types.
  if ((it->second & kDumpedFunctionName) == 0) {
    protos::pbzero::InternedString* interned_string = out->add_function_names();
    interned_string->set_iid(str.id());
    interned_string->set_str(str.data());
    it->second |= kDumpedFunctionName;
  }
}

void InterningOutputTracker::WriteCallstack(GlobalCallstackTrie::Node* node,
                                            GlobalCallstackTrie* trie,
                                            protos::pbzero::InternedData* out) {
  bool inserted;
  std::tie(std::ignore, inserted) = dumped_callstacks_.emplace(node->id());
  if (inserted) {
    // There need to be two separate loops over built_callstack because
    // protozero cannot interleave different messages.
    auto built_callstack = trie->BuildInverseCallstack(node);
    for (const Interned<Frame>& frame : built_callstack)
      WriteFrame(frame, out);

    protos::pbzero::Callstack* callstack = out->add_callstacks();
    callstack->set_iid(node->id());
    for (auto frame_it = built_callstack.crbegin();
         frame_it != built_callstack.crend(); ++frame_it) {
      const Interned<Frame>& frame = *frame_it;
      callstack->add_frame_ids(frame.id());
    }
  }
}

void InterningOutputTracker::ClearHistory() {
  dumped_strings_.clear();
  dumped_frames_.clear();
  dumped_mappings_.clear();
  dumped_callstacks_.clear();
}

}  // namespace profiling
}  // namespace perfetto
