/*
 * Copyright (C) 2011 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 "profiler.h"

#include <sys/file.h>
#include <sys/stat.h>
#include <sys/uio.h>

#include <fstream>

#include "art_method-inl.h"
#include "base/stl_util.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "common_throws.h"
#include "dex_file-inl.h"
#include "instrumentation.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "os.h"
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
#include "thread.h"
#include "thread_list.h"
#include "utils.h"

#include "entrypoints/quick/quick_entrypoints.h"

namespace art {

BackgroundMethodSamplingProfiler* BackgroundMethodSamplingProfiler::profiler_ = nullptr;
pthread_t BackgroundMethodSamplingProfiler::profiler_pthread_ = 0U;
volatile bool BackgroundMethodSamplingProfiler::shutting_down_ = false;

// TODO: this profiler runs regardless of the state of the machine.  Maybe we should use the
// wakelock or something to modify the run characteristics.  This can be done when we
// have some performance data after it's been used for a while.

// Walk through the method within depth of max_depth_ on the Java stack
class BoundedStackVisitor : public StackVisitor {
 public:
  BoundedStackVisitor(std::vector<std::pair<ArtMethod*, uint32_t>>* stack,
      Thread* thread, uint32_t max_depth)
      SHARED_REQUIRES(Locks::mutator_lock_)
      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
        stack_(stack),
        max_depth_(max_depth),
        depth_(0) {}

  bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) {
    ArtMethod* m = GetMethod();
    if (m->IsRuntimeMethod()) {
      return true;
    }
    uint32_t dex_pc_ = GetDexPc();
    stack_->push_back(std::make_pair(m, dex_pc_));
    ++depth_;
    if (depth_ < max_depth_) {
      return true;
    } else {
      return false;
    }
  }

 private:
  std::vector<std::pair<ArtMethod*, uint32_t>>* stack_;
  const uint32_t max_depth_;
  uint32_t depth_;
};

// This is called from either a thread list traversal or from a checkpoint.  Regardless
// of which caller, the mutator lock must be held.
static void GetSample(Thread* thread, void* arg) SHARED_REQUIRES(Locks::mutator_lock_) {
  BackgroundMethodSamplingProfiler* profiler =
      reinterpret_cast<BackgroundMethodSamplingProfiler*>(arg);
  const ProfilerOptions profile_options = profiler->GetProfilerOptions();
  switch (profile_options.GetProfileType()) {
    case kProfilerMethod: {
      ArtMethod* method = thread->GetCurrentMethod(nullptr);
      if ((false) && method == nullptr) {
        LOG(INFO) << "No current method available";
        std::ostringstream os;
        thread->Dump(os);
        std::string data(os.str());
        LOG(INFO) << data;
      }
      profiler->RecordMethod(method);
      break;
    }
    case kProfilerBoundedStack: {
      std::vector<InstructionLocation> stack;
      uint32_t max_depth = profile_options.GetMaxStackDepth();
      BoundedStackVisitor bounded_stack_visitor(&stack, thread, max_depth);
      bounded_stack_visitor.WalkStack();
      profiler->RecordStack(stack);
      break;
    }
    default:
      LOG(INFO) << "This profile type is not implemented.";
  }
}

// A closure that is called by the thread checkpoint code.
class SampleCheckpoint FINAL : public Closure {
 public:
  explicit SampleCheckpoint(BackgroundMethodSamplingProfiler* const profiler) :
    profiler_(profiler) {}

  void Run(Thread* thread) OVERRIDE {
    Thread* self = Thread::Current();
    if (thread == nullptr) {
      LOG(ERROR) << "Checkpoint with nullptr thread";
      return;
    }

    // Grab the mutator lock (shared access).
    ScopedObjectAccess soa(self);

    // Grab a sample.
    GetSample(thread, this->profiler_);

    // And finally tell the barrier that we're done.
    this->profiler_->GetBarrier().Pass(self);
  }

 private:
  BackgroundMethodSamplingProfiler* const profiler_;
};

bool BackgroundMethodSamplingProfiler::ShuttingDown(Thread* self) {
  MutexLock mu(self, *Locks::profiler_lock_);
  return shutting_down_;
}

void* BackgroundMethodSamplingProfiler::RunProfilerThread(void* arg) {
  Runtime* runtime = Runtime::Current();
  BackgroundMethodSamplingProfiler* profiler =
      reinterpret_cast<BackgroundMethodSamplingProfiler*>(arg);

  // Add a random delay for the first time run so that we don't hammer the CPU
  // with all profiles running at the same time.
  const int kRandomDelayMaxSecs = 30;
  const double kMaxBackoffSecs = 24*60*60;   // Max backoff time.

  srand(MicroTime() * getpid());
  int startup_delay = rand() % kRandomDelayMaxSecs;   // random delay for startup.


  CHECK(runtime->AttachCurrentThread("Profiler", true, runtime->GetSystemThreadGroup(),
                                      !runtime->IsAotCompiler()));

  Thread* self = Thread::Current();

  double backoff = 1.0;
  while (true) {
    if (ShuttingDown(self)) {
      break;
    }

    {
      // wait until we need to run another profile
      uint64_t delay_secs = profiler->options_.GetPeriodS() * backoff;

      // Add a startup delay to prevent all the profiles running at once.
      delay_secs += startup_delay;

      // Immediate startup for benchmarking?
      if (profiler->options_.GetStartImmediately() && startup_delay > 0) {
        delay_secs = 0;
      }

      startup_delay = 0;

      VLOG(profiler) << "Delaying profile start for " << delay_secs << " secs";
      MutexLock mu(self, profiler->wait_lock_);
      profiler->period_condition_.TimedWait(self, delay_secs * 1000, 0);
      // We were either signaled by Stop or timedout, in either case ignore the timed out result.

      // Expand the backoff by its coefficient, but don't go beyond the max.
      backoff = std::min(backoff * profiler->options_.GetBackoffCoefficient(), kMaxBackoffSecs);
    }

    if (ShuttingDown(self)) {
      break;
    }


    uint64_t start_us = MicroTime();
    uint64_t end_us = start_us + profiler->options_.GetDurationS() * UINT64_C(1000000);
    uint64_t now_us = start_us;

    VLOG(profiler) << "Starting profiling run now for "
                   << PrettyDuration((end_us - start_us) * 1000);

    SampleCheckpoint check_point(profiler);

    size_t valid_samples = 0;
    while (now_us < end_us) {
      if (ShuttingDown(self)) {
        break;
      }

      usleep(profiler->options_.GetIntervalUs());    // Non-interruptible sleep.

      ThreadList* thread_list = runtime->GetThreadList();

      profiler->profiler_barrier_->Init(self, 0);
      size_t barrier_count = thread_list->RunCheckpointOnRunnableThreads(&check_point);

      // All threads are suspended, nothing to do.
      if (barrier_count == 0) {
        now_us = MicroTime();
        continue;
      }

      valid_samples += barrier_count;

      ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun);

      // Wait for the barrier to be crossed by all runnable threads.  This wait
      // is done with a timeout so that we can detect problems with the checkpoint
      // running code.  We should never see this.
      const uint32_t kWaitTimeoutMs = 10000;

      // Wait for all threads to pass the barrier.
      bool timed_out =  profiler->profiler_barrier_->Increment(self, barrier_count, kWaitTimeoutMs);

      // We should never get a timeout.  If we do, it suggests a problem with the checkpoint
      // code.  Crash the process in this case.
      CHECK(!timed_out);

      // Update the current time.
      now_us = MicroTime();
    }

    if (valid_samples > 0) {
      // After the profile has been taken, write it out.
      ScopedObjectAccess soa(self);   // Acquire the mutator lock.
      uint32_t size = profiler->WriteProfile();
      VLOG(profiler) << "Profile size: " << size;
    }
  }

  LOG(INFO) << "Profiler shutdown";
  runtime->DetachCurrentThread();
  return nullptr;
}

// Write out the profile file if we are generating a profile.
uint32_t BackgroundMethodSamplingProfiler::WriteProfile() {
  std::string full_name = output_filename_;
  VLOG(profiler) << "Saving profile to " << full_name;

  int fd = open(full_name.c_str(), O_RDWR);
  if (fd < 0) {
    // Open failed.
    LOG(ERROR) << "Failed to open profile file " << full_name;
    return 0;
  }

  // Lock the file for exclusive access.  This will block if another process is using
  // the file.
  int err = flock(fd, LOCK_EX);
  if (err < 0) {
    LOG(ERROR) << "Failed to lock profile file " << full_name;
    return 0;
  }

  // Read the previous profile.
  profile_table_.ReadPrevious(fd, options_.GetProfileType());

  // Move back to the start of the file.
  lseek(fd, 0, SEEK_SET);

  // Format the profile output and write to the file.
  std::ostringstream os;
  uint32_t num_methods = DumpProfile(os);
  std::string data(os.str());
  const char *p = data.c_str();
  size_t length = data.length();
  size_t full_length = length;
  do {
    int n = ::write(fd, p, length);
    p += n;
    length -= n;
  } while (length > 0);

  // Truncate the file to the new length.
  if (ftruncate(fd, full_length) == -1) {
    LOG(ERROR) << "Failed to truncate profile file " << full_name;
  }

  // Now unlock the file, allowing another process in.
  err = flock(fd, LOCK_UN);
  if (err < 0) {
    LOG(ERROR) << "Failed to unlock profile file " << full_name;
  }

  // Done, close the file.
  ::close(fd);

  // Clean the profile for the next time.
  CleanProfile();

  return num_methods;
}

bool BackgroundMethodSamplingProfiler::Start(
    const std::string& output_filename, const ProfilerOptions& options) {
  if (!options.IsEnabled()) {
    return false;
  }

  CHECK(!output_filename.empty());

  Thread* self = Thread::Current();
  {
    MutexLock mu(self, *Locks::profiler_lock_);
    // Don't start two profiler threads.
    if (profiler_ != nullptr) {
      return true;
    }
  }

  LOG(INFO) << "Starting profiler using output file: " << output_filename
            << " and options: " << options;
  {
    MutexLock mu(self, *Locks::profiler_lock_);
    profiler_ = new BackgroundMethodSamplingProfiler(output_filename, options);

    CHECK_PTHREAD_CALL(pthread_create, (&profiler_pthread_, nullptr, &RunProfilerThread,
        reinterpret_cast<void*>(profiler_)),
                       "Profiler thread");
  }
  return true;
}



void BackgroundMethodSamplingProfiler::Stop() {
  BackgroundMethodSamplingProfiler* profiler = nullptr;
  pthread_t profiler_pthread = 0U;
  {
    MutexLock trace_mu(Thread::Current(), *Locks::profiler_lock_);
    CHECK(!shutting_down_);
    profiler = profiler_;
    shutting_down_ = true;
    profiler_pthread = profiler_pthread_;
  }

  // Now wake up the sampler thread if it sleeping.
  {
    MutexLock profile_mu(Thread::Current(), profiler->wait_lock_);
    profiler->period_condition_.Signal(Thread::Current());
  }
  // Wait for the sample thread to stop.
  CHECK_PTHREAD_CALL(pthread_join, (profiler_pthread, nullptr), "profiler thread shutdown");

  {
    MutexLock mu(Thread::Current(), *Locks::profiler_lock_);
    profiler_ = nullptr;
  }
  delete profiler;
}


void BackgroundMethodSamplingProfiler::Shutdown() {
  Stop();
}

BackgroundMethodSamplingProfiler::BackgroundMethodSamplingProfiler(
  const std::string& output_filename, const ProfilerOptions& options)
    : output_filename_(output_filename),
      options_(options),
      wait_lock_("Profile wait lock"),
      period_condition_("Profile condition", wait_lock_),
      profile_table_(wait_lock_),
      profiler_barrier_(new Barrier(0)) {
  // Populate the filtered_methods set.
  // This is empty right now, but to add a method, do this:
  //
  // filtered_methods_.insert("void java.lang.Object.wait(long, int)");
}

// Filter out methods the profiler doesn't want to record.
// We require mutator lock since some statistics will be updated here.
bool BackgroundMethodSamplingProfiler::ProcessMethod(ArtMethod* method) {
  if (method == nullptr) {
    profile_table_.NullMethod();
    // Don't record a null method.
    return false;
  }

  mirror::Class* cls = method->GetDeclaringClass();
  if (cls != nullptr) {
    if (cls->GetClassLoader() == nullptr) {
      // Don't include things in the boot
      profile_table_.BootMethod();
      return false;
    }
  }

  bool is_filtered = false;

  if (strcmp(method->GetName(), "<clinit>") == 0) {
    // always filter out class init
    is_filtered = true;
  }

  // Filter out methods by name if there are any.
  if (!is_filtered && filtered_methods_.size() > 0) {
    std::string method_full_name = PrettyMethod(method);

    // Don't include specific filtered methods.
    is_filtered = filtered_methods_.count(method_full_name) != 0;
  }
  return !is_filtered;
}

// A method has been hit, record its invocation in the method map.
// The mutator_lock must be held (shared) when this is called.
void BackgroundMethodSamplingProfiler::RecordMethod(ArtMethod* method) {
  // Add to the profile table unless it is filtered out.
  if (ProcessMethod(method)) {
    profile_table_.Put(method);
  }
}

// Record the current bounded stack into sampling results.
void BackgroundMethodSamplingProfiler::RecordStack(const std::vector<InstructionLocation>& stack) {
  if (stack.size() == 0) {
    return;
  }
  // Get the method on top of the stack. We use this method to perform filtering.
  ArtMethod* method = stack.front().first;
  if (ProcessMethod(method)) {
      profile_table_.PutStack(stack);
  }
}

// Clean out any recordings for the method traces.
void BackgroundMethodSamplingProfiler::CleanProfile() {
  profile_table_.Clear();
}

uint32_t BackgroundMethodSamplingProfiler::DumpProfile(std::ostream& os) {
  return profile_table_.Write(os, options_.GetProfileType());
}

// Profile Table.
// This holds a mapping of ArtMethod* to a count of how many times a sample
// hit it at the top of the stack.
ProfileSampleResults::ProfileSampleResults(Mutex& lock)
    : lock_(lock),
      num_samples_(0U),
      num_null_methods_(0U),
      num_boot_methods_(0U),
      previous_num_samples_(0U),
      previous_num_null_methods_(0U),
      previous_num_boot_methods_(0U) {
  for (int i = 0; i < kHashSize; i++) {
    table[i] = nullptr;
  }
  method_context_table = nullptr;
  stack_trie_root_ = nullptr;
}

ProfileSampleResults::~ProfileSampleResults() {
  Clear();
}

// Add a method to the profile table.  If it's the first time the method
// has been seen, add it with count=1, otherwise increment the count.
void ProfileSampleResults::Put(ArtMethod* method) {
  MutexLock mu(Thread::Current(), lock_);
  uint32_t index = Hash(method);
  if (table[index] == nullptr) {
    table[index] = new Map();
  }
  Map::iterator i = table[index]->find(method);
  if (i == table[index]->end()) {
    (*table[index])[method] = 1;
  } else {
    i->second++;
  }
  num_samples_++;
}

// Add a bounded stack to the profile table. Only the count of the method on
// top of the frame will be increased.
void ProfileSampleResults::PutStack(const std::vector<InstructionLocation>& stack) {
  MutexLock mu(Thread::Current(), lock_);
  ScopedObjectAccess soa(Thread::Current());
  if (stack_trie_root_ == nullptr) {
    // The root of the stack trie is a dummy node so that we don't have to maintain
    // a collection of tries.
    stack_trie_root_ = new StackTrieNode();
  }

  StackTrieNode* current = stack_trie_root_;
  if (stack.size() == 0) {
    current->IncreaseCount();
    return;
  }

  for (std::vector<InstructionLocation>::const_reverse_iterator iter = stack.rbegin();
       iter != stack.rend(); ++iter) {
    InstructionLocation inst_loc = *iter;
    ArtMethod* method = inst_loc.first;
    if (method == nullptr) {
      // skip null method
      continue;
    }
    uint32_t dex_pc = inst_loc.second;
    uint32_t method_idx = method->GetDexMethodIndex();
    const DexFile* dex_file = method->GetDeclaringClass()->GetDexCache()->GetDexFile();
    MethodReference method_ref(dex_file, method_idx);
    StackTrieNode* child = current->FindChild(method_ref, dex_pc);
    if (child != nullptr) {
      current = child;
    } else {
      uint32_t method_size = 0;
      const DexFile::CodeItem* codeitem = method->GetCodeItem();
      if (codeitem != nullptr) {
        method_size = codeitem->insns_size_in_code_units_;
      }
      StackTrieNode* new_node = new StackTrieNode(method_ref, dex_pc, method_size, current);
      current->AppendChild(new_node);
      current = new_node;
    }
  }

  if (current != stack_trie_root_ && current->GetCount() == 0) {
    // Insert into method_context table;
    if (method_context_table == nullptr) {
      method_context_table = new MethodContextMap();
    }
    MethodReference method = current->GetMethod();
    MethodContextMap::iterator i = method_context_table->find(method);
    if (i == method_context_table->end()) {
      TrieNodeSet* node_set = new TrieNodeSet();
      node_set->insert(current);
      (*method_context_table)[method] = node_set;
    } else {
      TrieNodeSet* node_set = i->second;
      node_set->insert(current);
    }
  }
  current->IncreaseCount();
  num_samples_++;
}

// Write the profile table to the output stream.  Also merge with the previous profile.
uint32_t ProfileSampleResults::Write(std::ostream& os, ProfileDataType type) {
  ScopedObjectAccess soa(Thread::Current());
  num_samples_ += previous_num_samples_;
  num_null_methods_ += previous_num_null_methods_;
  num_boot_methods_ += previous_num_boot_methods_;

  VLOG(profiler) << "Profile: "
                 << num_samples_ << "/" << num_null_methods_ << "/" << num_boot_methods_;
  os << num_samples_ << "/" << num_null_methods_ << "/" << num_boot_methods_ << "\n";
  uint32_t num_methods = 0;
  if (type == kProfilerMethod) {
    for (int i = 0 ; i < kHashSize; i++) {
      Map *map = table[i];
      if (map != nullptr) {
        for (const auto &meth_iter : *map) {
          ArtMethod *method = meth_iter.first;
          std::string method_name = PrettyMethod(method);

          const DexFile::CodeItem* codeitem = method->GetCodeItem();
          uint32_t method_size = 0;
          if (codeitem != nullptr) {
            method_size = codeitem->insns_size_in_code_units_;
          }
          uint32_t count = meth_iter.second;

          // Merge this profile entry with one from a previous run (if present).  Also
          // remove the previous entry.
          PreviousProfile::iterator pi = previous_.find(method_name);
          if (pi != previous_.end()) {
            count += pi->second.count_;
            previous_.erase(pi);
          }
          os << StringPrintf("%s/%u/%u\n",  method_name.c_str(), count, method_size);
          ++num_methods;
        }
      }
    }
  } else if (type == kProfilerBoundedStack) {
    if (method_context_table != nullptr) {
      for (const auto &method_iter : *method_context_table) {
        MethodReference method = method_iter.first;
        TrieNodeSet* node_set = method_iter.second;
        std::string method_name = PrettyMethod(method.dex_method_index, *(method.dex_file));
        uint32_t method_size = 0;
        uint32_t total_count = 0;
        PreviousContextMap new_context_map;
        for (const auto &trie_node_i : *node_set) {
          StackTrieNode* node = trie_node_i;
          method_size = node->GetMethodSize();
          uint32_t count = node->GetCount();
          uint32_t dexpc = node->GetDexPC();
          total_count += count;

          StackTrieNode* current = node->GetParent();
          // We go backward on the trie to retrieve context and dex_pc until the dummy root.
          // The format of the context is "method_1@pc_1@method_2@pc_2@..."
          std::vector<std::string> context_vector;
          while (current != nullptr && current->GetParent() != nullptr) {
            context_vector.push_back(StringPrintf("%s@%u",
                PrettyMethod(current->GetMethod().dex_method_index, *(current->GetMethod().dex_file)).c_str(),
                current->GetDexPC()));
            current = current->GetParent();
          }
          std::string context_sig = Join(context_vector, '@');
          new_context_map[std::make_pair(dexpc, context_sig)] = count;
        }

        PreviousProfile::iterator pi = previous_.find(method_name);
        if (pi != previous_.end()) {
          total_count += pi->second.count_;
          PreviousContextMap* previous_context_map = pi->second.context_map_;
          if (previous_context_map != nullptr) {
            for (const auto &context_i : *previous_context_map) {
              uint32_t count = context_i.second;
              PreviousContextMap::iterator ci = new_context_map.find(context_i.first);
              if (ci == new_context_map.end()) {
                new_context_map[context_i.first] = count;
              } else {
                ci->second += count;
              }
            }
          }
          delete previous_context_map;
          previous_.erase(pi);
        }
        // We write out profile data with dex pc and context information in the following format:
        // "method/total_count/size/[pc_1:count_1:context_1#pc_2:count_2:context_2#...]".
        std::vector<std::string> context_count_vector;
        for (const auto &context_i : new_context_map) {
          context_count_vector.push_back(StringPrintf("%u:%u:%s", context_i.first.first,
              context_i.second, context_i.first.second.c_str()));
        }
        os << StringPrintf("%s/%u/%u/[%s]\n", method_name.c_str(), total_count,
            method_size, Join(context_count_vector, '#').c_str());
        ++num_methods;
      }
    }
  }

  // Now we write out the remaining previous methods.
  for (const auto &pi : previous_) {
    if (type == kProfilerMethod) {
      os << StringPrintf("%s/%u/%u\n",  pi.first.c_str(), pi.second.count_, pi.second.method_size_);
    } else if (type == kProfilerBoundedStack) {
      os << StringPrintf("%s/%u/%u/[",  pi.first.c_str(), pi.second.count_, pi.second.method_size_);
      PreviousContextMap* previous_context_map = pi.second.context_map_;
      if (previous_context_map != nullptr) {
        std::vector<std::string> context_count_vector;
        for (const auto &context_i : *previous_context_map) {
          context_count_vector.push_back(StringPrintf("%u:%u:%s", context_i.first.first,
              context_i.second, context_i.first.second.c_str()));
        }
        os << Join(context_count_vector, '#');
      }
      os << "]\n";
    }
    ++num_methods;
  }
  return num_methods;
}

void ProfileSampleResults::Clear() {
  num_samples_ = 0;
  num_null_methods_ = 0;
  num_boot_methods_ = 0;
  for (int i = 0; i < kHashSize; i++) {
    delete table[i];
    table[i] = nullptr;
  }
  if (stack_trie_root_ != nullptr) {
    stack_trie_root_->DeleteChildren();
    delete stack_trie_root_;
    stack_trie_root_ = nullptr;
    if (method_context_table != nullptr) {
      delete method_context_table;
      method_context_table = nullptr;
    }
  }
  for (auto &pi : previous_) {
    if (pi.second.context_map_ != nullptr) {
      delete pi.second.context_map_;
      pi.second.context_map_ = nullptr;
    }
  }
  previous_.clear();
}

uint32_t ProfileSampleResults::Hash(ArtMethod* method) {
  return (PointerToLowMemUInt32(method) >> 3) % kHashSize;
}

// Read a single line into the given string.  Returns true if everything OK, false
// on EOF or error.
static bool ReadProfileLine(int fd, std::string& line) {
  char buf[4];
  line.clear();
  while (true) {
    int n = read(fd, buf, 1);     // TODO: could speed this up but is it worth it?
    if (n != 1) {
      return false;
    }
    if (buf[0] == '\n') {
      break;
    }
    line += buf[0];
  }
  return true;
}

void ProfileSampleResults::ReadPrevious(int fd, ProfileDataType type) {
  // Reset counters.
  previous_num_samples_ = previous_num_null_methods_ = previous_num_boot_methods_ = 0;

  std::string line;

  // The first line contains summary information.
  if (!ReadProfileLine(fd, line)) {
    return;
  }
  std::vector<std::string> summary_info;
  Split(line, '/', &summary_info);
  if (summary_info.size() != 3) {
    // Bad summary info.  It should be count/nullcount/bootcount
    return;
  }
  previous_num_samples_ = strtoul(summary_info[0].c_str(), nullptr, 10);
  previous_num_null_methods_ = strtoul(summary_info[1].c_str(), nullptr, 10);
  previous_num_boot_methods_ = strtoul(summary_info[2].c_str(), nullptr, 10);

  // Now read each line until the end of file.  Each line consists of 3 or 4 fields separated by /
  while (true) {
    if (!ReadProfileLine(fd, line)) {
      break;
    }
    std::vector<std::string> info;
    Split(line, '/', &info);
    if (info.size() != 3 && info.size() != 4) {
      // Malformed.
      break;
    }
    std::string methodname = info[0];
    uint32_t total_count = strtoul(info[1].c_str(), nullptr, 10);
    uint32_t size = strtoul(info[2].c_str(), nullptr, 10);
    PreviousContextMap* context_map = nullptr;
    if (type == kProfilerBoundedStack && info.size() == 4) {
      context_map = new PreviousContextMap();
      std::string context_counts_str = info[3].substr(1, info[3].size() - 2);
      std::vector<std::string> context_count_pairs;
      Split(context_counts_str, '#', &context_count_pairs);
      for (uint32_t i = 0; i < context_count_pairs.size(); ++i) {
        std::vector<std::string> context_count;
        Split(context_count_pairs[i], ':', &context_count);
        if (context_count.size() == 2) {
          // Handles the situtation when the profile file doesn't contain context information.
          uint32_t dexpc = strtoul(context_count[0].c_str(), nullptr, 10);
          uint32_t count = strtoul(context_count[1].c_str(), nullptr, 10);
          (*context_map)[std::make_pair(dexpc, "")] = count;
        } else {
          // Handles the situtation when the profile file contains context information.
          uint32_t dexpc = strtoul(context_count[0].c_str(), nullptr, 10);
          uint32_t count = strtoul(context_count[1].c_str(), nullptr, 10);
          std::string context = context_count[2];
          (*context_map)[std::make_pair(dexpc, context)] = count;
        }
      }
    }
    previous_[methodname] = PreviousValue(total_count, size, context_map);
  }
}

bool ProfileFile::LoadFile(const std::string& fileName) {
  LOG(VERBOSE) << "reading profile file " << fileName;
  struct stat st;
  int err = stat(fileName.c_str(), &st);
  if (err == -1) {
    LOG(VERBOSE) << "not found";
    return false;
  }
  if (st.st_size == 0) {
    return false;  // Empty profiles are invalid.
  }
  std::ifstream in(fileName.c_str());
  if (!in) {
    LOG(VERBOSE) << "profile file " << fileName << " exists but can't be opened";
    LOG(VERBOSE) << "file owner: " << st.st_uid << ":" << st.st_gid;
    LOG(VERBOSE) << "me: " << getuid() << ":" << getgid();
    LOG(VERBOSE) << "file permissions: " << std::oct << st.st_mode;
    LOG(VERBOSE) << "errno: " << errno;
    return false;
  }
  // The first line contains summary information.
  std::string line;
  std::getline(in, line);
  if (in.eof()) {
    return false;
  }
  std::vector<std::string> summary_info;
  Split(line, '/', &summary_info);
  if (summary_info.size() != 3) {
    // Bad summary info.  It should be total/null/boot.
    return false;
  }
  // This is the number of hits in all profiled methods (without null or boot methods)
  uint32_t total_count = strtoul(summary_info[0].c_str(), nullptr, 10);

  // Now read each line until the end of file.  Each line consists of 3 fields separated by '/'.
  // Store the info in descending order given by the most used methods.
  typedef std::set<std::pair<int, std::vector<std::string>>> ProfileSet;
  ProfileSet countSet;
  while (!in.eof()) {
    std::getline(in, line);
    if (in.eof()) {
      break;
    }
    std::vector<std::string> info;
    Split(line, '/', &info);
    if (info.size() != 3 && info.size() != 4) {
      // Malformed.
      return false;
    }
    int count = atoi(info[1].c_str());
    countSet.insert(std::make_pair(-count, info));
  }

  uint32_t curTotalCount = 0;
  ProfileSet::iterator end = countSet.end();
  const ProfileData* prevData = nullptr;
  for (ProfileSet::iterator it = countSet.begin(); it != end ; it++) {
    const std::string& methodname = it->second[0];
    uint32_t count = -it->first;
    uint32_t size = strtoul(it->second[2].c_str(), nullptr, 10);
    double usedPercent = (count * 100.0) / total_count;

    curTotalCount += count;
    // Methods with the same count should be part of the same top K percentage bucket.
    double topKPercentage = (prevData != nullptr) && (prevData->GetCount() == count)
      ? prevData->GetTopKUsedPercentage()
      : 100 * static_cast<double>(curTotalCount) / static_cast<double>(total_count);

    // Add it to the profile map.
    ProfileData curData = ProfileData(methodname, count, size, usedPercent, topKPercentage);
    profile_map_[methodname] = curData;
    prevData = &curData;
  }
  return true;
}

bool ProfileFile::GetProfileData(ProfileFile::ProfileData* data, const std::string& method_name) {
  ProfileMap::iterator i = profile_map_.find(method_name);
  if (i == profile_map_.end()) {
    return false;
  }
  *data = i->second;
  return true;
}

bool ProfileFile::GetTopKSamples(std::set<std::string>& topKSamples, double topKPercentage) {
  ProfileMap::iterator end = profile_map_.end();
  for (ProfileMap::iterator it = profile_map_.begin(); it != end; it++) {
    if (it->second.GetTopKUsedPercentage() < topKPercentage) {
      topKSamples.insert(it->first);
    }
  }
  return true;
}

StackTrieNode* StackTrieNode::FindChild(MethodReference method, uint32_t dex_pc) {
  if (children_.size() == 0) {
    return nullptr;
  }
  // Create a dummy node for searching.
  StackTrieNode* node = new StackTrieNode(method, dex_pc, 0, nullptr);
  std::set<StackTrieNode*, StackTrieNodeComparator>::iterator i = children_.find(node);
  delete node;
  return (i == children_.end()) ? nullptr : *i;
}

void StackTrieNode::DeleteChildren() {
  for (auto &child : children_) {
    if (child != nullptr) {
      child->DeleteChildren();
      delete child;
    }
  }
}

}  // namespace art
