void ReportCommand::ProcessSampleRecord(const SampleRecord& r) {
  if (use_branch_address_ && (r.sample_type & PERF_SAMPLE_BRANCH_STACK)) {
    for (auto& item : r.branch_stack_data.stack) {
      if (item.from != 0 && item.to != 0) {
        sample_tree_->AddBranchSample(r.tid_data.pid, r.tid_data.tid, item.from, item.to,
                                      item.flags, r.time_data.time, r.period_data.period);
      }
    }
  } else {
    bool in_kernel = (r.header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_KERNEL;
    SampleEntry* sample = sample_tree_->AddSample(r.tid_data.pid, r.tid_data.tid, r.ip_data.ip,
                                                  r.time_data.time, r.period_data.period, in_kernel);
    CHECK(sample != nullptr);
    if (accumulate_callchain_ && (r.sample_type & PERF_SAMPLE_CALLCHAIN) != 0) {
      std::vector<SampleEntry*> callchain;
      callchain.push_back(sample);
      const std::vector<uint64_t>& ips = r.callchain_data.ips;
      bool first_ip = true;
      for (auto& ip : ips) {
        if (ip >= PERF_CONTEXT_MAX) {
          switch (ip) {
            case PERF_CONTEXT_KERNEL:
              in_kernel = true;
              break;
            case PERF_CONTEXT_USER:
              in_kernel = false;
              break;
            default:
              LOG(ERROR) << "Unexpected perf_context in callchain: " << ip;
          }
        } else {
          if (first_ip) {
            // Remove duplication with sampled ip.
            if (ip == r.ip_data.ip) {
              continue;
            }
            first_ip = false;
          }
          SampleEntry* sample =
              sample_tree_->AddCallChainSample(r.tid_data.pid, r.tid_data.tid, ip, r.time_data.time,
                                               r.period_data.period, in_kernel, callchain);
          callchain.push_back(sample);
        }
      }
      if (print_callgraph_) {
        std::set<SampleEntry*> added_set;
        while (callchain.size() >= 2) {
          SampleEntry* sample = callchain[0];
          callchain.erase(callchain.begin());
          // Add only once for recursive calls on callchain.
          if (added_set.find(sample) != added_set.end()) {
            continue;
          }
          added_set.insert(sample);
          sample_tree_->InsertCallChainForSample(sample, callchain, r.period_data.period);
        }
      }
    }
  }
}