// Copyright (c) 2015, 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/profiler_service.h"

#include <memory>

#include "platform/text_buffer.h"
#include "vm/growable_array.h"
#include "vm/hash_map.h"
#include "vm/heap/safepoint.h"
#if !defined(PRODUCT)
#include "vm/json_stream.h"
#endif
#include "vm/log.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/profiler.h"
#include "vm/reusable_handles.h"
#include "vm/scope_timer.h"
#include "vm/service.h"
#include "vm/service_event.h"
#include "vm/timeline.h"

#if defined(SUPPORT_PERFETTO)
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "third_party/perfetto/protos/perfetto/common/builtin_clock.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/profiling/profile_packet.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
#include "vm/perfetto_utils.h"
#endif  // defined(SUPPORT_PERFETTO)

namespace dart {

DECLARE_FLAG(int, max_profile_depth);
DECLARE_FLAG(int, profile_period);
DECLARE_FLAG(bool, profile_vm);

#if defined(DART_INCLUDE_PROFILER)

ProfileFunctionSourcePosition::ProfileFunctionSourcePosition(
    TokenPosition token_pos)
    : token_pos_(token_pos), exclusive_ticks_(0), inclusive_ticks_(0) {}

void ProfileFunctionSourcePosition::Tick(bool exclusive) {
  if (exclusive) {
    exclusive_ticks_++;
  } else {
    inclusive_ticks_++;
  }
}

ProfileFunction::ProfileFunction(Kind kind,
                                 const char* name,
                                 const Function& function,
                                 const intptr_t table_index)
    : kind_(kind),
      name_(name),
      function_(Function::ZoneHandle(function.ptr())),
      table_index_(table_index),
      profile_codes_(0),
      source_position_ticks_(0),
      exclusive_ticks_(0),
      inclusive_ticks_(0),
      inclusive_serial_(-1) {
  ASSERT((kind_ != kDartFunction) || !function_.IsNull());
  ASSERT((kind_ != kDartFunction) || (table_index_ >= 0));
  ASSERT(profile_codes_.length() == 0);
}

const char* ProfileFunction::Name() const {
  if (name_ != nullptr) {
    return name_;
  }
  ASSERT(!function_.IsNull());
  const String& func_name =
      String::Handle(function_.QualifiedUserVisibleName());
  return func_name.ToCString();
}

const char* ProfileFunction::ResolvedScriptUrl() const {
  if (function_.IsNull()) {
    return nullptr;
  }
  const Script& script = Script::Handle(function_.script());
  if (script.IsNull()) {
    return nullptr;
  }
  const String& uri = String::Handle(script.resolved_url());
  if (uri.IsNull()) {
    return nullptr;
  }
  return uri.ToCString();
}

bool ProfileFunction::is_visible() const {
  if (function_.IsNull()) {
    // Some synthetic function.
    return true;
  }
  return FLAG_show_invisible_frames || function_.is_visible();
}

void ProfileFunction::Tick(bool exclusive,
                           intptr_t inclusive_serial,
                           TokenPosition token_position) {
  if (exclusive) {
    exclusive_ticks_++;
    TickSourcePosition(token_position, exclusive);
  }
  // Fall through and tick inclusive count too.
  if (inclusive_serial_ == inclusive_serial) {
    // Already ticked.
    return;
  }
  inclusive_serial_ = inclusive_serial;
  inclusive_ticks_++;
  TickSourcePosition(token_position, false);
}

void ProfileFunction::TickSourcePosition(TokenPosition token_position,
                                         bool exclusive) {
  intptr_t i = 0;
  for (; i < source_position_ticks_.length(); i++) {
    ProfileFunctionSourcePosition& position = source_position_ticks_[i];
    const intptr_t cmp =
        TokenPosition::CompareForSorting(position.token_pos(), token_position);
    if (cmp > 0) {
      // Found insertion point.
      break;
    } else if (cmp == 0) {
      if (FLAG_trace_profiler_verbose) {
        OS::PrintErr("Ticking source position %s %s\n",
                     exclusive ? "exclusive" : "inclusive",
                     token_position.ToCString());
      }
      // Found existing position, tick it.
      position.Tick(exclusive);
      return;
    }
  }

  // Add new one, sorted by token position value.
  ProfileFunctionSourcePosition pfsp(token_position);
  if (FLAG_trace_profiler_verbose) {
    OS::PrintErr("Ticking source position %s %s\n",
                 exclusive ? "exclusive" : "inclusive",
                 token_position.ToCString());
  }
  pfsp.Tick(exclusive);

  if (i < source_position_ticks_.length()) {
    source_position_ticks_.InsertAt(i, pfsp);
  } else {
    source_position_ticks_.Add(pfsp);
  }
}

const char* ProfileFunction::KindToCString(Kind kind) {
  switch (kind) {
    case kDartFunction:
      return "Dart";
    case kNativeFunction:
      return "Native";
    case kTagFunction:
      return "Tag";
    case kStubFunction:
      return "Stub";
    case kUnknownFunction:
      return "Collected";
    default:
      UNIMPLEMENTED();
      return "";
  }
}

#if !defined(PRODUCT)
void ProfileFunction::PrintToJSONObject(JSONObject* func) {
  func->AddProperty("type", "NativeFunction");
  func->AddProperty("name", name());
  func->AddProperty("_kind", KindToCString(kind()));
}

void ProfileFunction::PrintToJSONArray(JSONArray* functions,
                                       bool print_only_ids) {
  if (print_only_ids) {
    JSONObject obj(functions);
    if (kind() == kDartFunction) {
      ASSERT(!function_.IsNull());
      obj.AddProperty("type", "@Object");
      function_.AddFunctionServiceId(obj);
    } else {
      PrintToJSONObject(&obj);
    }
    return;
  }
  JSONObject obj(functions);
  obj.AddProperty("type", "ProfileFunction");
  obj.AddProperty("kind", KindToCString(kind()));
  obj.AddProperty("inclusiveTicks", inclusive_ticks());
  obj.AddProperty("exclusiveTicks", exclusive_ticks());
  obj.AddProperty("resolvedUrl", ResolvedScriptUrl());
  if (kind() == kDartFunction) {
    ASSERT(!function_.IsNull());
    obj.AddProperty("function", function_);
  } else {
    JSONObject func(&obj, "function");
    PrintToJSONObject(&func);
  }
  {
    JSONArray codes(&obj, "_codes");
    for (intptr_t i = 0; i < profile_codes_.length(); i++) {
      intptr_t code_index = profile_codes_[i];
      codes.AddValue(code_index);
    }
  }
}
#endif  // !defined(PRODUCT)

void ProfileFunction::AddProfileCode(intptr_t code_table_index) {
  for (intptr_t i = 0; i < profile_codes_.length(); i++) {
    if (profile_codes_[i] == code_table_index) {
      return;
    }
  }
  profile_codes_.Add(code_table_index);
}

bool ProfileFunction::GetSinglePosition(ProfileFunctionSourcePosition* pfsp) {
  if (pfsp == nullptr) {
    return false;
  }
  if (source_position_ticks_.length() != 1) {
    return false;
  }
  *pfsp = source_position_ticks_[0];
  return true;
}

ProfileCodeAddress::ProfileCodeAddress(uword pc)
    : pc_(pc), exclusive_ticks_(0), inclusive_ticks_(0) {}

void ProfileCodeAddress::Tick(bool exclusive) {
  if (exclusive) {
    exclusive_ticks_++;
  } else {
    inclusive_ticks_++;
  }
}

ProfileCode::ProfileCode(Kind kind,
                         uword start,
                         uword end,
                         int64_t timestamp,
                         const AbstractCode code)
    : kind_(kind),
      start_(start),
      end_(end),
      exclusive_ticks_(0),
      inclusive_ticks_(0),
      inclusive_serial_(-1),
      code_(code),
      name_(nullptr),
      compile_timestamp_(0),
      function_(nullptr),
      code_table_index_(-1),
      address_ticks_(0) {
  ASSERT(start_ < end_);
}

void ProfileCode::TruncateLower(uword start) {
  if (start > start_) {
    start_ = start;
  }
  ASSERT(start_ < end_);
}

void ProfileCode::TruncateUpper(uword end) {
  if (end < end_) {
    end_ = end;
  }
  ASSERT(start_ < end_);
}

void ProfileCode::ExpandLower(uword start) {
  if (start < start_) {
    start_ = start;
  }
  ASSERT(start_ < end_);
}

void ProfileCode::ExpandUpper(uword end) {
  if (end > end_) {
    end_ = end;
  }
  ASSERT(start_ < end_);
}

bool ProfileCode::Overlaps(const ProfileCode* other) const {
  ASSERT(other != nullptr);
  return other->Contains(start_) || other->Contains(end_ - 1) ||
         Contains(other->start()) || Contains(other->end() - 1);
}

bool ProfileCode::IsOptimizedDart() const {
  return !code_.IsNull() && code_.is_optimized();
}

void ProfileCode::SetName(const char* name) {
  if (name == nullptr) {
    name_ = nullptr;
  }
  intptr_t len = strlen(name) + 1;
  name_ = Thread::Current()->zone()->Alloc<char>(len);
  strncpy(name_, name, len);
}

void ProfileCode::GenerateAndSetSymbolName(const char* prefix) {
  const intptr_t kBuffSize = 512;
  char buff[kBuffSize];
  Utils::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix,
                 start(), end());
  SetName(buff);
}

void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) {
  // If exclusive is set, tick it.
  if (exclusive) {
    exclusive_ticks_++;
    TickAddress(pc, true);
  }
  // Fall through and tick inclusive count too.
  if (inclusive_serial_ == serial) {
    // Already gave inclusive tick for this sample.
    return;
  }
  inclusive_serial_ = serial;
  inclusive_ticks_++;
  TickAddress(pc, false);
}

void ProfileCode::TickAddress(uword pc, bool exclusive) {
  const intptr_t length = address_ticks_.length();

  intptr_t i = 0;
  for (; i < length; i++) {
    ProfileCodeAddress& entry = address_ticks_[i];
    if (entry.pc() == pc) {
      // Tick the address entry.
      entry.Tick(exclusive);
      return;
    }
    if (entry.pc() > pc) {
      break;
    }
  }

  // New address, add entry.
  ProfileCodeAddress entry(pc);

  entry.Tick(exclusive);

  if (i < length) {
    // Insert at i.
    address_ticks_.InsertAt(i, entry);
  } else {
    // Add to end.
    address_ticks_.Add(entry);
  }
}

#if !defined(PRODUCT)
void ProfileCode::PrintNativeCode(JSONObject* profile_code_obj) {
  ASSERT(kind() == kNativeCode);
  JSONObject obj(profile_code_obj, "code");
  obj.AddProperty("type", "@Code");
  obj.AddProperty("kind", "Native");
  obj.AddProperty("name", name());
  obj.AddProperty("_optimized", false);
  obj.AddPropertyF("start", "%" Px "", start());
  obj.AddPropertyF("end", "%" Px "", end());
  {
    // Generate a fake function entry.
    JSONObject func(&obj, "function");
    ASSERT(function_ != nullptr);
    function_->PrintToJSONObject(&func);
  }
}

void ProfileCode::PrintCollectedCode(JSONObject* profile_code_obj) {
  ASSERT(kind() == kCollectedCode);
  JSONObject obj(profile_code_obj, "code");
  obj.AddProperty("type", "@Code");
  obj.AddProperty("kind", "Collected");
  obj.AddProperty("name", name());
  obj.AddProperty("_optimized", false);
  obj.AddPropertyF("start", "%" Px "", start());
  obj.AddPropertyF("end", "%" Px "", end());
  {
    // Generate a fake function entry.
    JSONObject func(&obj, "function");
    ASSERT(function_ != nullptr);
    function_->PrintToJSONObject(&func);
  }
}

void ProfileCode::PrintOverwrittenCode(JSONObject* profile_code_obj) {
  ASSERT(kind() == kReusedCode);
  JSONObject obj(profile_code_obj, "code");
  obj.AddProperty("type", "@Code");
  obj.AddProperty("kind", "Collected");
  obj.AddProperty("name", name());
  obj.AddProperty("_optimized", false);
  obj.AddPropertyF("start", "%" Px "", start());
  obj.AddPropertyF("end", "%" Px "", end());
  {
    // Generate a fake function entry.
    JSONObject func(&obj, "function");
    ASSERT(function_ != nullptr);
    function_->PrintToJSONObject(&func);
  }
}

void ProfileCode::PrintTagCode(JSONObject* profile_code_obj) {
  ASSERT(kind() == kTagCode);
  JSONObject obj(profile_code_obj, "code");
  obj.AddProperty("type", "@Code");
  obj.AddProperty("kind", "Tag");
  obj.AddProperty("name", name());
  obj.AddPropertyF("start", "%" Px "", start());
  obj.AddPropertyF("end", "%" Px "", end());
  obj.AddProperty("_optimized", false);
  {
    // Generate a fake function entry.
    JSONObject func(&obj, "function");
    ASSERT(function_ != nullptr);
    function_->PrintToJSONObject(&func);
  }
}

const char* ProfileCode::KindToCString(Kind kind) {
  switch (kind) {
    case kDartCode:
      return "Dart";
    case kCollectedCode:
      return "Collected";
    case kNativeCode:
      return "Native";
    case kReusedCode:
      return "Overwritten";
    case kTagCode:
      return "Tag";
  }
  UNREACHABLE();
  return nullptr;
}

void ProfileCode::PrintToJSONArray(JSONArray* codes) {
  JSONObject obj(codes);
  obj.AddProperty("kind", ProfileCode::KindToCString(kind()));
  obj.AddProperty("inclusiveTicks", inclusive_ticks());
  obj.AddProperty("exclusiveTicks", exclusive_ticks());
  if (kind() == kDartCode) {
    ASSERT(!code_.IsNull());
    obj.AddProperty("code", *code_.handle());
  } else if (kind() == kCollectedCode) {
    PrintCollectedCode(&obj);
  } else if (kind() == kReusedCode) {
    PrintOverwrittenCode(&obj);
  } else if (kind() == kTagCode) {
    PrintTagCode(&obj);
  } else {
    ASSERT(kind() == kNativeCode);
    PrintNativeCode(&obj);
  }
  {
    JSONArray ticks(&obj, "ticks");
    for (intptr_t i = 0; i < address_ticks_.length(); i++) {
      const ProfileCodeAddress& entry = address_ticks_[i];
      ticks.AddValueF("%" Px "", entry.pc());
      ticks.AddValue(entry.exclusive_ticks());
      ticks.AddValue(entry.inclusive_ticks());
    }
  }
}
#endif  // !defined(PRODUCT)

class ProfileFunctionTable : public ZoneObject {
 public:
  ProfileFunctionTable()
      : null_function_(Function::ZoneHandle()),
        unknown_function_(nullptr),
        table_(8) {
    unknown_function_ =
        Add(ProfileFunction::kUnknownFunction, "<unknown Dart function>");
  }

  ProfileFunction* LookupOrAdd(const Function& function) {
    ASSERT(!function.IsNull());
    ProfileFunction* profile_function = Lookup(function);
    if (profile_function != nullptr) {
      return profile_function;
    }
    return Add(function);
  }

  ProfileFunction* Lookup(const Function& function) {
    ASSERT(!function.IsNull());
    return function_hash_.LookupValue(&function);
  }

  ProfileFunction* GetUnknown() {
    ASSERT(unknown_function_ != nullptr);
    return unknown_function_;
  }

  // No protection against being called more than once for the same tag_id.
  ProfileFunction* AddTag(uword tag_id, const char* name) {
    // TODO(johnmccutchan): Canonicalize ProfileFunctions for tags.
    return Add(ProfileFunction::kTagFunction, name);
  }

  // No protection against being called more than once for the same native
  // address.
  ProfileFunction* AddNative(uword start_address, const char* name) {
    // TODO(johnmccutchan): Canonicalize ProfileFunctions for natives.
    return Add(ProfileFunction::kNativeFunction, name);
  }

  // No protection against being called more tha once for the same stub.
  ProfileFunction* AddStub(uword start_address, const char* name) {
    return Add(ProfileFunction::kStubFunction, name);
  }

  intptr_t length() const { return table_.length(); }

  ProfileFunction* At(intptr_t i) const {
    ASSERT(i >= 0);
    ASSERT(i < length());
    return table_[i];
  }

 private:
  ProfileFunction* Add(ProfileFunction::Kind kind, const char* name) {
    ASSERT(kind != ProfileFunction::kDartFunction);
    ASSERT(name != nullptr);
    ProfileFunction* profile_function =
        new ProfileFunction(kind, name, null_function_, table_.length());
    table_.Add(profile_function);
    return profile_function;
  }

  ProfileFunction* Add(const Function& function) {
    ASSERT(Lookup(function) == nullptr);
    ProfileFunction* profile_function = new ProfileFunction(
        ProfileFunction::kDartFunction, nullptr, function, table_.length());
    table_.Add(profile_function);
    function_hash_.Insert(profile_function);
    return profile_function;
  }

  // Needed for DirectChainedHashMap.
  struct ProfileFunctionTableTrait {
    typedef ProfileFunction* Value;
    typedef const Function* Key;
    typedef ProfileFunction* Pair;

    static Key KeyOf(Pair kv) { return kv->function(); }

    static Value ValueOf(Pair kv) { return kv; }

    static inline uword Hash(Key key) { return key->Hash(); }

    static inline bool IsKeyEqual(Pair kv, Key key) {
      return kv->function()->ptr() == key->ptr();
    }
  };

  const Function& null_function_;
  ProfileFunction* unknown_function_;
  ZoneGrowableArray<ProfileFunction*> table_;
  DirectChainedHashMap<ProfileFunctionTableTrait> function_hash_;
};

intptr_t ProfileCodeTable::FindCodeIndexForPC(uword pc) const {
  intptr_t length = table_.length();
  if (length == 0) {
    return -1;  // Not found.
  }
  intptr_t lo = 0;
  intptr_t hi = length - 1;
  while (lo <= hi) {
    intptr_t mid = (hi - lo + 1) / 2 + lo;
    ASSERT(mid >= lo);
    ASSERT(mid <= hi);
    ProfileCode* code = At(mid);
    if (code->Contains(pc)) {
      return mid;
    } else if (pc < code->start()) {
      hi = mid - 1;
    } else {
      lo = mid + 1;
    }
  }
  return -1;
}

intptr_t ProfileCodeTable::InsertCode(ProfileCode* new_code) {
  const intptr_t length = table_.length();
  if (length == 0) {
    table_.Add(new_code);
    return length;
  }

  // Determine the correct place to insert or merge |new_code| into table.
  intptr_t lo = -1;
  intptr_t hi = -1;
  ProfileCode* lo_code = nullptr;
  ProfileCode* hi_code = nullptr;
  const uword pc = new_code->end() - 1;
  FindNeighbors(pc, &lo, &hi, &lo_code, &hi_code);
  ASSERT((lo_code != nullptr) || (hi_code != nullptr));

  if (lo != -1) {
    // Has left neighbor.
    new_code->TruncateLower(lo_code->end());
    ASSERT(!new_code->Overlaps(lo_code));
  }
  if (hi != -1) {
    // Has right neighbor.
    new_code->TruncateUpper(hi_code->start());
    ASSERT(!new_code->Overlaps(hi_code));
  }

  if ((lo != -1) && (lo_code->kind() == ProfileCode::kNativeCode) &&
      (new_code->kind() == ProfileCode::kNativeCode) &&
      (lo_code->end() == new_code->start())) {
    // Adjacent left neighbor of the same kind: merge.
    // (dladdr doesn't give us symbol size so processing more samples may see
    // more PCs we didn't previously know belonged to it.)
    lo_code->ExpandUpper(new_code->end());
    return lo;
  }

  if ((hi != -1) && (hi_code->kind() == ProfileCode::kNativeCode) &&
      (new_code->kind() == ProfileCode::kNativeCode) &&
      (new_code->end() == hi_code->start())) {
    // Adjacent right neighbor of the same kind: merge.
    // (dladdr doesn't give us symbol size so processing more samples may see
    // more PCs we didn't previously know belonged to it.)
    hi_code->ExpandLower(new_code->start());
    return hi;
  }

  intptr_t insert;
  if (lo == -1) {
    insert = 0;
  } else if (hi == -1) {
    insert = length;
  } else {
    insert = lo + 1;
  }
  table_.InsertAt(insert, new_code);
  return insert;
}

void ProfileCodeTable::FindNeighbors(uword pc,
                                     intptr_t* lo,
                                     intptr_t* hi,
                                     ProfileCode** lo_code,
                                     ProfileCode** hi_code) const {
  ASSERT(table_.length() >= 1);

  intptr_t length = table_.length();

  if (pc < At(0)->start()) {
    // Lower than any existing code.
    *lo = -1;
    *lo_code = nullptr;
    *hi = 0;
    *hi_code = At(*hi);
    return;
  }

  if (pc >= At(length - 1)->end()) {
    // Higher than any existing code.
    *lo = length - 1;
    *lo_code = At(*lo);
    *hi = -1;
    *hi_code = nullptr;
    return;
  }

  *lo = 0;
  *lo_code = At(*lo);
  *hi = length - 1;
  *hi_code = At(*hi);

  while ((*hi - *lo) > 1) {
    intptr_t mid = (*hi - *lo + 1) / 2 + *lo;
    ASSERT(*lo <= mid);
    ASSERT(*hi >= mid);
    ProfileCode* code = At(mid);
    if (code->end() <= pc) {
      *lo = mid;
      *lo_code = code;
    }
    if (pc < code->end()) {
      *hi = mid;
      *hi_code = code;
    }
  }
}

void ProfileCodeTable::VerifyOrder() {
  const intptr_t length = table_.length();
  if (length == 0) {
    return;
  }
  uword last = table_[0]->end();
  for (intptr_t i = 1; i < length; i++) {
    ProfileCode* a = table_[i];
    ASSERT(last <= a->start());
    last = a->end();
  }
}

void ProfileCodeTable::VerifyOverlap() {
  const intptr_t length = table_.length();
  for (intptr_t i = 0; i < length; i++) {
    ProfileCode* a = table_[i];
    for (intptr_t j = i + 1; j < length; j++) {
      ProfileCode* b = table_[j];
      ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) &&
             !b->Contains(a->start()) && !b->Contains(a->end() - 1));
    }
  }
}

void ProfileCodeInlinedFunctionsCache::Get(
    uword pc,
    const Code& code,
    ProcessedSample* sample,
    intptr_t frame_index,
    // Outputs:
    GrowableArray<const Function*>** inlined_functions,
    GrowableArray<TokenPosition>** inlined_token_positions,
    TokenPosition* token_position) {
  const intptr_t offset = OffsetForPC(pc, code, sample, frame_index);
  if (FindInCache(pc, offset, inlined_functions, inlined_token_positions,
                  token_position)) {
    // Found in cache.
    return;
  }
  Add(pc, code, sample, frame_index, inlined_functions, inlined_token_positions,
      token_position);
}

bool ProfileCodeInlinedFunctionsCache::FindInCache(
    uword pc,
    intptr_t offset,
    GrowableArray<const Function*>** inlined_functions,
    GrowableArray<TokenPosition>** inlined_token_positions,
    TokenPosition* token_position) {
  // Simple linear scan.
  for (intptr_t i = 0; i < kCacheSize; i++) {
    intptr_t index = (last_hit_ + i) % kCacheSize;
    if ((cache_[index].pc == pc) && (cache_[index].offset == offset)) {
      // Hit.
      if (cache_[index].inlined_functions.length() == 0) {
        *inlined_functions = nullptr;
        *inlined_token_positions = nullptr;
      } else {
        *inlined_functions = &cache_[index].inlined_functions;
        *inlined_token_positions = &cache_[index].inlined_token_positions;
      }
      *token_position = cache_[index].token_position;
      cache_hit_++;
      last_hit_ = index;
      return true;
    }
  }
  cache_miss_++;
  return false;
}

// Add to cache and fill in outputs.
void ProfileCodeInlinedFunctionsCache::Add(
    uword pc,
    const Code& code,
    ProcessedSample* sample,
    intptr_t frame_index,
    // Outputs:
    GrowableArray<const Function*>** inlined_functions,
    GrowableArray<TokenPosition>** inlined_token_positions,
    TokenPosition* token_position) {
  const intptr_t offset = OffsetForPC(pc, code, sample, frame_index);
  CacheEntry* cache_entry = &cache_[NextFreeIndex()];
  cache_entry->Reset();
  cache_entry->pc = pc;
  cache_entry->offset = offset;
  code.GetInlinedFunctionsAtInstruction(
      offset, &(cache_entry->inlined_functions),
      &(cache_entry->inlined_token_positions));
  if (cache_entry->inlined_functions.length() == 0) {
    *inlined_functions = nullptr;
    *inlined_token_positions = nullptr;
    *token_position = cache_entry->token_position = TokenPosition::kNoSource;
    return;
  }

  // Write outputs.
  *inlined_functions = &(cache_entry->inlined_functions);
  *inlined_token_positions = &(cache_entry->inlined_token_positions);
  *token_position = cache_entry->token_position =
      cache_entry->inlined_token_positions[0];
}

intptr_t ProfileCodeInlinedFunctionsCache::OffsetForPC(uword pc,
                                                       const Code& code,
                                                       ProcessedSample* sample,
                                                       intptr_t frame_index) {
  intptr_t offset = pc - code.PayloadStart();
  if (frame_index != 0) {
    // The PC of frames below the top frame is a call's return address,
    // which can belong to a different inlining interval than the call.
    offset--;
  } else if (sample->IsAllocationSample()) {
    // Allocation samples skip the top frame, so the top frame's pc is
    // also a call's return address.
    offset--;
  } else if (!sample->first_frame_executing()) {
    // If the first frame wasn't executing code (i.e. we started to collect
    // the stack trace at an exit frame), the top frame's pc is also a
    // call's return address.
    offset--;
  }
  return offset;
}

class ProfileBuilder : public ValueObject {
 public:
  enum ProfileInfoKind {
    kNone,
    kOptimized,
    kUnoptimized,
    kNative,
    kInlineStart,
    kInlineFinish,
    kNumProfileInfoKind,
  };

  ProfileBuilder(Thread* thread,
                 Isolate* isolate,
                 SampleFilter* filter,
                 SampleBlockBuffer* sample_buffer,
                 Profile* profile)
      : thread_(thread),
        isolate_(isolate),
        vm_isolate_(Dart::vm_isolate()),
        filter_(filter),
        sample_buffer_(sample_buffer),
        profile_(profile),
        null_code_(Code::null()),
        null_function_(Function::ZoneHandle()),
        inclusive_tree_(false),
        inlined_functions_cache_(new ProfileCodeInlinedFunctionsCache()),
        samples_(nullptr),
        info_kind_(kNone) {
    ASSERT(profile_ != nullptr);
  }

  void Build() {
    ScopeTimer sw("ProfileBuilder::Build", FLAG_trace_profiler);
    if (!FilterSamples()) {
      return;
    }
    Setup();
    BuildCodeTable();
    FinalizeCodeIndexes();
    BuildFunctionTable();
    PopulateFunctionTicks();
    SanitizeMinMaxTimes();
  }

  Thread* thread() const { return thread_; }
  Isolate* isolate() const { return isolate_; }
  ProfileFunctionTable* function_table() const { return profile_->functions_; }

 private:
  // Returns true if |frame_index| in |sample| is using CPU.
  static bool IsExecutingFrame(ProcessedSample* sample, intptr_t frame_index) {
    return (frame_index == 0) &&
           (sample->first_frame_executing() || sample->IsAllocationSample());
  }

  void Setup() {
    profile_->live_code_ = new ProfileCodeTable();
    profile_->dead_code_ = new ProfileCodeTable();
    profile_->tag_code_ = new ProfileCodeTable();
    profile_->functions_ = new ProfileFunctionTable();
    // Register some synthetic tags.
    RegisterProfileCodeTag(VMTag::kRootTagId);
    RegisterProfileCodeTag(VMTag::kTruncatedTagId);
    RegisterProfileCodeTag(VMTag::kNoneCodeTagId);
    RegisterProfileCodeTag(VMTag::kOptimizedCodeTagId);
    RegisterProfileCodeTag(VMTag::kUnoptimizedCodeTagId);
    RegisterProfileCodeTag(VMTag::kNativeCodeTagId);
    RegisterProfileCodeTag(VMTag::kInlineStartCodeTagId);
    RegisterProfileCodeTag(VMTag::kInlineEndCodeTagId);
  }

  bool FilterSamples() {
    ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler);
    if (sample_buffer_ == nullptr) {
      return false;
    }
    samples_ = sample_buffer_->BuildProcessedSampleBuffer(isolate_, filter_);
    profile_->samples_ = samples_;
    profile_->sample_count_ = samples_->length();
    return true;
  }

  void UpdateMinMaxTimes(int64_t timestamp) {
    profile_->min_time_ =
        timestamp < profile_->min_time_ ? timestamp : profile_->min_time_;
    profile_->max_time_ =
        timestamp > profile_->max_time_ ? timestamp : profile_->max_time_;
  }

  void SanitizeMinMaxTimes() {
    if ((profile_->min_time_ == kMaxInt64) && (profile_->max_time_ == 0)) {
      profile_->min_time_ = 0;
      profile_->max_time_ = 0;
    }
  }

  void BuildCodeTable() {
    ScopeTimer sw("ProfileBuilder::BuildCodeTable", FLAG_trace_profiler);

    // Build the live code table eagerly by populating it with code objects
    // from the processed sample buffer.
    const CodeLookupTable& code_lookup_table = samples_->code_lookup_table();
    for (intptr_t i = 0; i < code_lookup_table.length(); i++) {
      const CodeDescriptor* descriptor = code_lookup_table.At(i);
      ASSERT(descriptor != nullptr);
      const AbstractCode code = descriptor->code();
      RegisterLiveProfileCode(new ProfileCode(
          ProfileCode::kDartCode, code.PayloadStart(),
          code.PayloadStart() + code.Size(), code.compile_timestamp(), code));
      thread_->CheckForSafepoint();
    }

    // Iterate over samples.
    for (intptr_t sample_index = 0; sample_index < samples_->length();
         sample_index++) {
      ProcessedSample* sample = samples_->At(sample_index);
      const int64_t timestamp = sample->timestamp();

      // This is our first pass over the sample buffer, use this as an
      // opportunity to determine the min and max time ranges of this profile.
      UpdateMinMaxTimes(timestamp);

      // Make sure VM tag exists.
      if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
        RegisterProfileCodeTag(VMTag::kNativeTagId);
      } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
        RegisterProfileCodeTag(VMTag::kRuntimeTagId);
      }
      RegisterProfileCodeTag(sample->vm_tag());
      // Make sure user tag exists.
      RegisterProfileCodeTag(sample->user_tag());

      // Make sure that a ProfileCode objects exist for all pcs in the sample
      // and tick each one.
      for (intptr_t frame_index = 0; frame_index < sample->length();
           frame_index++) {
        const uword pc = sample->At(frame_index);
        ASSERT(pc != 0);
        ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp);
        ASSERT(code != nullptr);
        code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index);
      }

      TickExitFrame(sample->vm_tag(), sample_index, sample);
      thread_->CheckForSafepoint();
    }
  }

  void FinalizeCodeIndexes() {
    ScopeTimer sw("ProfileBuilder::FinalizeCodeIndexes", FLAG_trace_profiler);
    ProfileCodeTable* live_table = profile_->live_code_;
    ProfileCodeTable* dead_table = profile_->dead_code_;
    ProfileCodeTable* tag_table = profile_->tag_code_;
    const intptr_t dead_code_index_offset = live_table->length();
    const intptr_t tag_code_index_offset =
        dead_table->length() + dead_code_index_offset;

    profile_->dead_code_index_offset_ = dead_code_index_offset;
    profile_->tag_code_index_offset_ = tag_code_index_offset;

    for (intptr_t i = 0; i < live_table->length(); i++) {
      const intptr_t index = i;
      ProfileCode* code = live_table->At(i);
      ASSERT(code != nullptr);
      code->set_code_table_index(index);
    }

    for (intptr_t i = 0; i < dead_table->length(); i++) {
      const intptr_t index = dead_code_index_offset + i;
      ProfileCode* code = dead_table->At(i);
      ASSERT(code != nullptr);
      code->set_code_table_index(index);
    }

    for (intptr_t i = 0; i < tag_table->length(); i++) {
      const intptr_t index = tag_code_index_offset + i;
      ProfileCode* code = tag_table->At(i);
      ASSERT(code != nullptr);
      code->set_code_table_index(index);
    }
  }

  void BuildFunctionTable() {
    ScopeTimer sw("ProfileBuilder::BuildFunctionTable", FLAG_trace_profiler);
    ProfileCodeTable* live_table = profile_->live_code_;
    ProfileCodeTable* dead_table = profile_->dead_code_;
    ProfileCodeTable* tag_table = profile_->tag_code_;
    for (intptr_t i = 0; i < live_table->length(); i++) {
      ProfileCode* code = live_table->At(i);
      ASSERT(code != nullptr);
      code->SetFunctionAndName(this);
      thread_->CheckForSafepoint();
    }

    for (intptr_t i = 0; i < dead_table->length(); i++) {
      ProfileCode* code = dead_table->At(i);
      ASSERT(code != nullptr);
      code->SetFunctionAndName(this);
      thread_->CheckForSafepoint();
    }

    for (intptr_t i = 0; i < tag_table->length(); i++) {
      ProfileCode* code = tag_table->At(i);
      ASSERT(code != nullptr);
      code->SetFunctionAndName(this);
      thread_->CheckForSafepoint();
    }
  }

  void PopulateFunctionTicks() {
    ScopeTimer sw("ProfileBuilder::PopulateFunctionTicks", FLAG_trace_profiler);
    for (intptr_t sample_index = 0; sample_index < samples_->length();
         sample_index++) {
      ProcessedSample* sample = samples_->At(sample_index);

      // Walk the sampled PCs.
      for (intptr_t frame_index = 0; frame_index < sample->length();
           frame_index++) {
        ASSERT(sample->At(frame_index) != 0);
        ProcessFrame(sample_index, sample, frame_index);
      }
      if (sample->truncated()) {
        InclusiveTickTruncatedTag(sample);
      }
    }
  }

  void ProcessFrame(intptr_t sample_index,
                    ProcessedSample* sample,
                    intptr_t frame_index) {
    const uword pc = sample->At(frame_index);
    ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp());
    ProfileFunction* function = profile_code->function();
    ASSERT(function != nullptr);
    const intptr_t code_index = profile_code->code_table_index();
    ASSERT(profile_code != nullptr);

    GrowableArray<const Function*>* inlined_functions = nullptr;
    GrowableArray<TokenPosition>* inlined_token_positions = nullptr;
    TokenPosition token_position = TokenPosition::kNoSource;
    Code& code = Code::ZoneHandle();
    if (profile_code->code().IsCode()) {
      code ^= profile_code->code().ptr();
      inlined_functions_cache_->Get(pc, code, sample, frame_index,
                                    &inlined_functions,
                                    &inlined_token_positions, &token_position);
      if (FLAG_trace_profiler_verbose && (inlined_functions != nullptr)) {
        for (intptr_t i = 0; i < inlined_functions->length(); i++) {
          const String& name =
              String::Handle((*inlined_functions)[i]->QualifiedScrubbedName());
          THR_Print("InlinedFunction[%" Pd "] = {%s, %s}\n", i,
                    name.ToCString(),
                    (*inlined_token_positions)[i].ToCString());
        }
      }
    }

    if (code.IsNull() || (inlined_functions == nullptr) ||
        (inlined_functions->length() <= 1)) {
      ProcessFunction(sample_index, sample, frame_index, function,
                      token_position, code_index);
      return;
    }

    if (!code.is_optimized()) {
      OS::PrintErr("Code that should be optimized is not. Please file a bug\n");
      OS::PrintErr("Code object: %s\n", code.ToCString());
      OS::PrintErr("Inlined functions length: %" Pd "\n",
                   inlined_functions->length());
      for (intptr_t i = 0; i < inlined_functions->length(); i++) {
        OS::PrintErr("IF[%" Pd "] = %s\n", i,
                     (*inlined_functions)[i]->ToFullyQualifiedCString());
      }
    }

    ASSERT(code.is_optimized());

    // Append the inlined children.
    for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) {
      const Function* inlined_function = (*inlined_functions)[i];
      ASSERT(inlined_function != nullptr);
      ASSERT(!inlined_function->IsNull());
      TokenPosition inlined_token_position = (*inlined_token_positions)[i];
      ProcessInlinedFunction(sample_index, sample, frame_index + i,
                             inlined_function, inlined_token_position,
                             code_index);
    }
  }

  void ProcessInlinedFunction(intptr_t sample_index,
                              ProcessedSample* sample,
                              intptr_t frame_index,
                              const Function* inlined_function,
                              TokenPosition inlined_token_position,
                              intptr_t code_index) {
    ProfileFunctionTable* function_table = profile_->functions_;
    ProfileFunction* function = function_table->LookupOrAdd(*inlined_function);
    ASSERT(function != nullptr);
    ProcessFunction(sample_index, sample, frame_index, function,
                    inlined_token_position, code_index);
  }

  bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) {
    if (frame_index != 0) {
      return true;
    }
    // Only tick the first frame's node, if we are executing
    return IsExecutingFrame(sample, frame_index) || !FLAG_profile_vm;
  }

  void ProcessFunction(intptr_t sample_index,
                       ProcessedSample* sample,
                       intptr_t frame_index,
                       ProfileFunction* function,
                       TokenPosition token_position,
                       intptr_t code_index) {
    if (!function->is_visible()) {
      return;
    }
    if (FLAG_trace_profiler_verbose) {
      THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", sample_index,
                frame_index, function->Name(), token_position.ToCString(),
                sample->At(frame_index));
    }
    function->Tick(IsExecutingFrame(sample, frame_index), sample_index,
                   token_position);
    function->AddProfileCode(code_index);
  }

  // Tick the truncated tag's inclusive tick count.
  void InclusiveTickTruncatedTag(ProcessedSample* sample) {
    ProfileCodeTable* tag_table = profile_->tag_code_;
    intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId);
    ASSERT(index >= 0);
    ProfileCode* code = tag_table->At(index);
    code->IncInclusiveTicks();
    ASSERT(code != nullptr);
    ProfileFunction* function = code->function();
    function->IncInclusiveTicks();
  }

  uword ProfileInfoKindToVMTag(ProfileInfoKind kind) {
    switch (kind) {
      case kNone:
        return VMTag::kNoneCodeTagId;
      case kOptimized:
        return VMTag::kOptimizedCodeTagId;
      case kUnoptimized:
        return VMTag::kUnoptimizedCodeTagId;
      case kNative:
        return VMTag::kNativeCodeTagId;
      case kInlineStart:
        return VMTag::kInlineStartCodeTagId;
      case kInlineFinish:
        return VMTag::kInlineEndCodeTagId;
      default:
        UNIMPLEMENTED();
        return VMTag::kInvalidTagId;
    }
  }

  void TickExitFrame(uword vm_tag, intptr_t serial, ProcessedSample* sample) {
    if (FLAG_profile_vm) {
      return;
    }
    if (!VMTag::IsExitFrameTag(vm_tag)) {
      return;
    }
    ProfileCodeTable* tag_table = profile_->tag_code_;
    ProfileCode* code = tag_table->FindCodeForPC(vm_tag);
    ASSERT(code != nullptr);
    code->Tick(vm_tag, true, serial);
  }

  void TickExitFrameFunction(uword vm_tag, intptr_t serial) {
    if (FLAG_profile_vm) {
      return;
    }
    if (!VMTag::IsExitFrameTag(vm_tag)) {
      return;
    }
    ProfileCodeTable* tag_table = profile_->tag_code_;
    ProfileCode* code = tag_table->FindCodeForPC(vm_tag);
    ASSERT(code != nullptr);
    ProfileFunction* function = code->function();
    ASSERT(function != nullptr);
    function->Tick(true, serial, TokenPosition::kNoSource);
  }

  intptr_t GetProfileCodeTagIndex(uword tag) {
    ProfileCodeTable* tag_table = profile_->tag_code_;
    intptr_t index = tag_table->FindCodeIndexForPC(tag);
    ASSERT(index >= 0);
    ProfileCode* code = tag_table->At(index);
    ASSERT(code != nullptr);
    return code->code_table_index();
  }

  intptr_t GetProfileFunctionTagIndex(uword tag) {
    ProfileCodeTable* tag_table = profile_->tag_code_;
    intptr_t index = tag_table->FindCodeIndexForPC(tag);
    ASSERT(index >= 0);
    ProfileCode* code = tag_table->At(index);
    ASSERT(code != nullptr);
    ProfileFunction* function = code->function();
    ASSERT(function != nullptr);
    return function->table_index();
  }

  intptr_t GetProfileCodeIndex(uword pc, int64_t timestamp) {
    return GetProfileCode(pc, timestamp)->code_table_index();
  }

  ProfileCode* GetProfileCode(uword pc, int64_t timestamp) {
    return profile_->GetCodeFromPC(pc, timestamp);
  }

  void RegisterProfileCodeTag(uword tag) {
    if (tag == 0) {
      // No tag.
      return;
    }
    ProfileCodeTable* tag_table = profile_->tag_code_;
    intptr_t index = tag_table->FindCodeIndexForPC(tag);
    if (index >= 0) {
      // Already created.
      return;
    }
    ProfileCode* code =
        new ProfileCode(ProfileCode::kTagCode, tag, tag + 1, 0, null_code_);
    index = tag_table->InsertCode(code);
    ASSERT(index >= 0);
  }

  ProfileCode* CreateProfileCodeReused(uword pc) {
    ProfileCode* code =
        new ProfileCode(ProfileCode::kReusedCode, pc, pc + 1, 0, null_code_);
    return code;
  }

  bool IsPCInDartHeap(uword pc) {
    return vm_isolate_->group()->heap()->CodeContains(pc) ||
           thread_->isolate_group()->heap()->CodeContains(pc);
  }

  ProfileCode* FindOrRegisterNativeProfileCode(uword pc) {
    // Check if |pc| is already known in the live code table.
    ProfileCodeTable* live_table = profile_->live_code_;
    ProfileCode* profile_code = live_table->FindCodeForPC(pc);
    if (profile_code != nullptr) {
      return profile_code;
    }

    // We haven't seen this pc yet.

    // Check NativeSymbolResolver for pc.
    uword native_start = 0;
    const char* native_name =
        NativeSymbolResolver::LookupSymbolName(pc, &native_start);
    if (native_name == nullptr) {
      // Failed to find a native symbol for pc.
      native_start = pc;
    }

#if defined(HOST_ARCH_ARM)
    // The symbol for a Thumb function will be xxx1, but we may have samples
    // at function entry which will have pc xxx0.
    native_start &= ~1;
#endif

    if (native_start > pc) {
      // Bogus lookup result.
      if (native_name != nullptr) {
        NativeSymbolResolver::FreeSymbolName(native_name);
        native_name = nullptr;
      }
      native_start = pc;
    }
    if ((pc - native_start) > (32 * KB)) {
      // Suspect lookup result. More likely dladdr going off the rails than a
      // jumbo function.
      if (native_name != nullptr) {
        NativeSymbolResolver::FreeSymbolName(native_name);
        native_name = nullptr;
      }
      native_start = pc;
    }

    ASSERT(pc >= native_start);
    ASSERT(pc < (pc + 1));  // Should not overflow.
    profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start,
                                   pc + 1, 0, null_code_);
    if (native_name != nullptr) {
      profile_code->SetName(native_name);
      NativeSymbolResolver::FreeSymbolName(native_name);
    }

    RegisterLiveProfileCode(profile_code);
    return profile_code;
  }

  void RegisterLiveProfileCode(ProfileCode* code) {
    ProfileCodeTable* live_table = profile_->live_code_;
    intptr_t index = live_table->InsertCode(code);
    ASSERT(index >= 0);
  }

  ProfileCode* FindOrRegisterDeadProfileCode(uword pc) {
    ProfileCodeTable* dead_table = profile_->dead_code_;

    ProfileCode* code = dead_table->FindCodeForPC(pc);
    if (code != nullptr) {
      return code;
    }

    // Create a new dead code entry.
    intptr_t index = dead_table->InsertCode(CreateProfileCodeReused(pc));
    ASSERT(index >= 0);
    return dead_table->At(index);
  }

  ProfileCode* FindOrRegisterProfileCode(uword pc, int64_t timestamp) {
    ProfileCodeTable* live_table = profile_->live_code_;
    ProfileCode* code = live_table->FindCodeForPC(pc);
    if ((code != nullptr) && (code->compile_timestamp() <= timestamp)) {
      // Code was compiled before sample was taken.
      return code;
    }
    if ((code == nullptr) && !IsPCInDartHeap(pc)) {
      // Not a PC from Dart code. Check with native code.
      return FindOrRegisterNativeProfileCode(pc);
    }
    // We either didn't find the code or it was compiled after the sample.
    return FindOrRegisterDeadProfileCode(pc);
  }

  Thread* thread_;
  Isolate* isolate_;
  Isolate* vm_isolate_;
  SampleFilter* filter_;
  SampleBlockBuffer* sample_buffer_;
  Profile* profile_;
  const AbstractCode null_code_;
  const Function& null_function_;
  bool inclusive_tree_;
  ProfileCodeInlinedFunctionsCache* inlined_functions_cache_;
  ProcessedSampleBuffer* samples_;
  ProfileInfoKind info_kind_;
};  // ProfileBuilder.

ProfileFunction* ProfileCode::SetFunctionAndName(ProfileBuilder* builder) {
  ASSERT(function_ == nullptr);

  auto table = builder->function_table();
  ProfileFunction* function = nullptr;
  if ((kind() == kReusedCode) || (kind() == kCollectedCode)) {
    if (name() == nullptr) {
      // Lazily set generated name.
      GenerateAndSetSymbolName("[Collected]");
    }
    // Map these to a canonical unknown function.
    function = table->GetUnknown();
  } else if (kind() == kDartCode) {
    ASSERT(!code_.IsNull());
    const char* name = code_.QualifiedName();
    const Object& obj = Object::Handle(code_.owner());
    if (obj.IsFunction()) {
      function = table->LookupOrAdd(Function::Cast(obj));
    } else {
      // A stub.
      function = table->AddStub(start(), name);
    }
    SetName(name);
  } else if (kind() == kNativeCode) {
    if (name() == nullptr) {
      // Lazily set generated name.
      const intptr_t kBuffSize = 512;
      char buff[kBuffSize];
      uword dso_base;
      const char* dso_name;
      if (NativeSymbolResolver::LookupSharedObject(start(), &dso_base,
                                                   &dso_name)) {
        uword dso_offset = start() - dso_base;
        Utils::SNPrint(&buff[0], kBuffSize - 1, "[Native] %s+0x%" Px, dso_name,
                       dso_offset);
        NativeSymbolResolver::FreeSymbolName(dso_name);
      } else {
        Utils::SNPrint(&buff[0], kBuffSize - 1, "[Native] %" Px, start());
      }
      SetName(buff);
    }
    function = table->AddNative(start(), name());
  } else if (kind() == kTagCode) {
    if (name() == nullptr) {
      if (UserTags::IsUserTag(start())) {
        const char* tag_name = UserTags::TagName(
            builder->thread(), builder->isolate()->group(), start());
        ASSERT(tag_name != nullptr);
        SetName(tag_name);
      } else if (VMTag::IsVMTag(start()) || VMTag::IsRuntimeEntryTag(start()) ||
                 VMTag::IsNativeEntryTag(start())) {
        const char* tag_name = VMTag::TagName(start());
        ASSERT(tag_name != nullptr);
        SetName(tag_name);
      } else {
        switch (start()) {
          case VMTag::kRootTagId:
            SetName("Root");
            break;
          case VMTag::kTruncatedTagId:
            SetName("[Truncated]");
            break;
          case VMTag::kNoneCodeTagId:
            SetName("[No Code]");
            break;
          case VMTag::kOptimizedCodeTagId:
            SetName("[Optimized Code]");
            break;
          case VMTag::kUnoptimizedCodeTagId:
            SetName("[Unoptimized Code]");
            break;
          case VMTag::kNativeCodeTagId:
            SetName("[Native Code]");
            break;
          case VMTag::kInlineStartCodeTagId:
            SetName("[Inline Start]");
            break;
          case VMTag::kInlineEndCodeTagId:
            SetName("[Inline End]");
            break;
          default:
            UNIMPLEMENTED();
            break;
        }
      }
    }
    function = table->AddTag(start(), name());
  } else {
    UNREACHABLE();
  }
  ASSERT(function != nullptr);

  function->AddProfileCode(code_table_index());

  function_ = function;
  return function_;
}

Profile::Profile()
    : zone_(Thread::Current()->zone()),
      samples_(nullptr),
      live_code_(nullptr),
      dead_code_(nullptr),
      tag_code_(nullptr),
      functions_(nullptr),
      dead_code_index_offset_(-1),
      tag_code_index_offset_(-1),
      min_time_(kMaxInt64),
      max_time_(0),
      sample_count_(0) {}

void Profile::Build(Thread* thread,
                    Isolate* isolate,
                    SampleFilter* filter,
                    SampleBlockBuffer* sample_buffer) {
  thread_ = thread;
  isolate_ = isolate;
  ASSERT(isolate != nullptr);

  // Disable thread interrupts while processing the buffer.
  DisableThreadInterruptsScope dtis(thread);
  ProfileBuilder builder(thread, isolate, filter, sample_buffer, this);
  builder.Build();
}

ProcessedSample* Profile::SampleAt(intptr_t index) {
  ASSERT(index >= 0);
  ASSERT(index < sample_count_);
  return samples_->At(index);
}

intptr_t Profile::NumFunctions() const {
  return functions_->length();
}

ProfileFunction* Profile::GetFunction(intptr_t index) {
  ASSERT(functions_ != nullptr);
  return functions_->At(index);
}

ProfileCode* Profile::GetCode(intptr_t index) {
  ASSERT(live_code_ != nullptr);
  ASSERT(dead_code_ != nullptr);
  ASSERT(tag_code_ != nullptr);
  ASSERT(dead_code_index_offset_ >= 0);
  ASSERT(tag_code_index_offset_ >= 0);

  // Code indexes span three arrays.
  //           0 ... |live_code|
  // |live_code| ... |dead_code|
  // |dead_code| ... |tag_code|

  if (index < dead_code_index_offset_) {
    return live_code_->At(index);
  }

  if (index < tag_code_index_offset_) {
    index -= dead_code_index_offset_;
    return dead_code_->At(index);
  }

  index -= tag_code_index_offset_;
  return tag_code_->At(index);
}

ProfileCode* Profile::GetCodeFromPC(uword pc, int64_t timestamp) {
  intptr_t index = live_code_->FindCodeIndexForPC(pc);
  ProfileCode* code = nullptr;
  if (index < 0) {
    index = dead_code_->FindCodeIndexForPC(pc);
    ASSERT(index >= 0);
    code = dead_code_->At(index);
  } else {
    code = live_code_->At(index);
    ASSERT(code != nullptr);
    if (code->compile_timestamp() > timestamp) {
      // Code is newer than sample. Fall back to dead code table.
      index = dead_code_->FindCodeIndexForPC(pc);
      ASSERT(index >= 0);
      code = dead_code_->At(index);
    }
  }

  ASSERT(code != nullptr);
  ASSERT(code->Contains(pc));
  ASSERT(code->compile_timestamp() <= timestamp);
  return code;
}

#if !defined(PRODUCT)
void Profile::PrintHeaderJSON(JSONObject* obj) {
  intptr_t pid = OS::ProcessId();

  obj->AddProperty("samplePeriod", Profiler::CurrentConfig().period_us);
  obj->AddProperty("maxStackDepth", Profiler::CurrentConfig().max_depth.load());
  obj->AddProperty("sampleCount", sample_count());
  obj->AddPropertyTimeMicros("timeOriginMicros", min_time());
  obj->AddPropertyTimeMicros("timeExtentMicros", GetTimeSpan());
  obj->AddProperty64("pid", pid);
  ProfilerCounters counters = Profiler::counters();
  {
    JSONObject counts(obj, "_counters");
    counts.AddProperty64("bail_out_unknown_task",
                         counters.bail_out_unknown_task);
    counts.AddProperty64("bail_out_jump_to_exception_handler",
                         counters.bail_out_jump_to_exception_handler);
    counts.AddProperty64("bail_out_check_isolate",
                         counters.bail_out_check_isolate);
    counts.AddProperty64("bail_out_deoptimizing",
                         counters.bail_out_deoptimizing);
    counts.AddProperty64(
        "single_frame_sample_get_and_validate_stack_bounds",
        counters.single_frame_sample_get_and_validate_stack_bounds);
    counts.AddProperty64("stack_walker_native", counters.stack_walker_native);
    counts.AddProperty64("stack_walker_dart_exit",
                         counters.stack_walker_dart_exit);
    counts.AddProperty64("stack_walker_dart", counters.stack_walker_dart);
    counts.AddProperty64("stack_walker_none", counters.stack_walker_none);
  }
}

void Profile::ProcessSampleFrameJSON(JSONArray* stack,
                                     ProfileCodeInlinedFunctionsCache* cache,
                                     ProcessedSample* sample,
                                     intptr_t frame_index) {
  const uword pc = sample->At(frame_index);
  ProfileCode* profile_code = GetCodeFromPC(pc, sample->timestamp());
  ASSERT(profile_code != nullptr);
  ProfileFunction* function = profile_code->function();
  ASSERT(function != nullptr);

  // Don't show stubs in stack traces.
  if (!function->is_visible() ||
      (function->kind() == ProfileFunction::kStubFunction)) {
    return;
  }

  GrowableArray<const Function*>* inlined_functions = nullptr;
  GrowableArray<TokenPosition>* inlined_token_positions = nullptr;
  TokenPosition token_position = TokenPosition::kNoSource;
  Code& code = Code::ZoneHandle();

  if (profile_code->code().IsCode()) {
    code ^= profile_code->code().ptr();
    cache->Get(pc, code, sample, frame_index, &inlined_functions,
               &inlined_token_positions, &token_position);
    if (FLAG_trace_profiler_verbose && (inlined_functions != nullptr)) {
      for (intptr_t i = 0; i < inlined_functions->length(); i++) {
        const String& name =
            String::Handle((*inlined_functions)[i]->QualifiedScrubbedName());
        THR_Print("InlinedFunction[%" Pd "] = {%s, %s}\n", i, name.ToCString(),
                  (*inlined_token_positions)[i].ToCString());
      }
    }
  }

  if (code.IsNull() || (inlined_functions == nullptr) ||
      (inlined_functions->length() <= 1)) {
    PrintFunctionFrameIndexJSON(stack, function);
    return;
  }

  if (!code.is_optimized()) {
    OS::PrintErr("Code that should be optimized is not. Please file a bug\n");
    OS::PrintErr("Code object: %s\n", code.ToCString());
    OS::PrintErr("Inlined functions length: %" Pd "\n",
                 inlined_functions->length());
    for (intptr_t i = 0; i < inlined_functions->length(); i++) {
      OS::PrintErr("IF[%" Pd "] = %s\n", i,
                   (*inlined_functions)[i]->ToFullyQualifiedCString());
    }
  }

  ASSERT(code.is_optimized());

  for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) {
    const Function* inlined_function = (*inlined_functions)[i];
    ASSERT(inlined_function != nullptr);
    ASSERT(!inlined_function->IsNull());
    ProcessInlinedFunctionFrameJSON(stack, inlined_function);
  }
}

void Profile::ProcessInlinedFunctionFrameJSON(
    JSONArray* stack,
    const Function* inlined_function) {
  ProfileFunction* function = functions_->LookupOrAdd(*inlined_function);
  ASSERT(function != nullptr);
  PrintFunctionFrameIndexJSON(stack, function);
}

void Profile::PrintFunctionFrameIndexJSON(JSONArray* stack,
                                          ProfileFunction* function) {
  stack->AddValue64(function->table_index());
}

void Profile::PrintCodeFrameIndexJSON(JSONArray* stack,
                                      ProcessedSample* sample,
                                      intptr_t frame_index) {
  ProfileCode* code =
      GetCodeFromPC(sample->At(frame_index), sample->timestamp());
  const AbstractCode codeObj = code->code();

  // Ignore stub code objects.
  if (codeObj.IsStubCode() || codeObj.IsAllocationStubCode() ||
      codeObj.IsTypeTestStubCode()) {
    return;
  }
  stack->AddValue64(code->code_table_index());
}

void Profile::PrintSamplesJSON(JSONObject* obj, bool code_samples) {
  JSONArray samples(obj, "samples");
  // Note that |cache| is zone-allocated, so it does not need to be deallocated
  // manually.
  auto* cache = new ProfileCodeInlinedFunctionsCache();
  for (intptr_t sample_index = 0; sample_index < samples_->length();
       sample_index++) {
    JSONObject sample_obj(&samples);
    ProcessedSample* sample = samples_->At(sample_index);
    sample_obj.AddProperty64("tid", OSThread::ThreadIdToIntPtr(sample->tid()));
    sample_obj.AddPropertyTimeMicros("timestamp", sample->timestamp());
    sample_obj.AddProperty("vmTag", VMTag::TagName(sample->vm_tag()));
    if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
      sample_obj.AddProperty("nativeEntryTag", true);
    }
    if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
      sample_obj.AddProperty("runtimeEntryTag", true);
    }
    if (UserTags::IsUserTag(sample->user_tag())) {
      sample_obj.AddProperty(
          "userTag",
          UserTags::TagName(thread(), isolate()->group(), sample->user_tag()));
    }
    if (sample->truncated()) {
      sample_obj.AddProperty("truncated", true);
    }
    {
      JSONArray stack(&sample_obj, "stack");
      // Walk the sampled PCs.
      for (intptr_t frame_index = 0; frame_index < sample->length();
           frame_index++) {
        ASSERT(sample->At(frame_index) != 0);
        ProcessSampleFrameJSON(&stack, cache, sample, frame_index);
      }
    }
    if (code_samples) {
      JSONArray stack(&sample_obj, "_codeStack");
      for (intptr_t frame_index = 0; frame_index < sample->length();
           frame_index++) {
        ASSERT(sample->At(frame_index) != 0);
        PrintCodeFrameIndexJSON(&stack, sample, frame_index);
      }
    }
    if (sample->IsAllocationSample()) {
      sample_obj.AddProperty64("classId", sample->allocation_cid());
      sample_obj.AddProperty64("identityHashCode",
                               sample->allocation_identity_hash());
    }
  }
}

void Profile::PrintProfileJSON(JSONStream* stream, bool include_code_samples) {
  JSONObject obj(stream);
  PrintProfileJSON(&obj, include_code_samples);
}

void Profile::PrintProfileJSON(JSONObject* obj,
                               bool include_code_samples,
                               bool is_event) {
  ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler);
  Thread* thread = Thread::Current();
  if (is_event) {
    obj->AddProperty("type", "CpuSamplesEvent");
  } else {
    obj->AddProperty("type", "CpuSamples");
  }
  PrintHeaderJSON(obj);
  if (include_code_samples) {
    JSONArray codes(obj, "_codes");
    for (intptr_t i = 0; i < live_code_->length(); i++) {
      ProfileCode* code = live_code_->At(i);
      ASSERT(code != nullptr);
      code->PrintToJSONArray(&codes);
      thread->CheckForSafepoint();
    }
    for (intptr_t i = 0; i < dead_code_->length(); i++) {
      ProfileCode* code = dead_code_->At(i);
      ASSERT(code != nullptr);
      code->PrintToJSONArray(&codes);
      thread->CheckForSafepoint();
    }
    for (intptr_t i = 0; i < tag_code_->length(); i++) {
      ProfileCode* code = tag_code_->At(i);
      ASSERT(code != nullptr);
      code->PrintToJSONArray(&codes);
      thread->CheckForSafepoint();
    }
  }

  {
    JSONArray functions(obj, "functions");
    for (intptr_t i = 0; i < functions_->length(); i++) {
      ProfileFunction* function = functions_->At(i);
      ASSERT(function != nullptr);
      function->PrintToJSONArray(&functions, is_event);
      thread->CheckForSafepoint();
    }
  }
  PrintSamplesJSON(obj, include_code_samples);
  thread->CheckForSafepoint();
}
#endif  // !defined(PRODUCT)

#if defined(SUPPORT_PERFETTO)
namespace {
void ProcessSampleFramePerfetto(Profile* profile,
                                GrowableArray<uint64_t>& callstack,
                                ProfileCodeInlinedFunctionsCache* cache,
                                ProcessedSample* sample,
                                intptr_t frame_index,
                                const GrowableArray<uint64_t>& function_iids) {
  const uword pc = sample->At(frame_index);
  ProfileCode* profile_code = profile->GetCodeFromPC(pc, sample->timestamp());
  ASSERT(profile_code != nullptr);
  ProfileFunction* function = profile_code->function();
  ASSERT(function != nullptr);

  // Don't show stubs in stack traces.
  if (!function->is_visible() ||
      (function->kind() == ProfileFunction::kStubFunction)) {
    return;
  }

  GrowableArray<const Function*>* inlined_functions = nullptr;
  GrowableArray<TokenPosition>* inlined_token_positions = nullptr;
  TokenPosition token_position = TokenPosition::kNoSource;
  Code& code = Code::ZoneHandle();

  if (profile_code->code().IsCode()) {
    code ^= profile_code->code().ptr();
    cache->Get(pc, code, sample, frame_index, &inlined_functions,
               &inlined_token_positions, &token_position);
  }

  if (code.IsNull() || (inlined_functions == nullptr) ||
      (inlined_functions->length() <= 1)) {
    // This is the ID of a |Frame| that was added to the interned data table in
    // |ProfilerService::PrintProfilePerfetto|. See the comments in that method
    // for more details.
    callstack.Add(function_iids[function->table_index()]);
    return;
  }

  for (intptr_t i = 0; i < inlined_functions->length(); ++i) {
    const Function* inlined_function = (*inlined_functions)[i];
    ASSERT(inlined_function != NULL);
    ASSERT(!inlined_function->IsNull());
    ProfileFunction* profile_function =
        profile->FindFunction(*inlined_function);
    ASSERT(profile_function != NULL);
    callstack.Add(function_iids[profile_function->table_index()]);
  }
}
}  // namespace

template <typename WriteBytesFunction>
void Profile::PrintSamplesPerfetto(
    protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>* packet_ptr,
    WriteBytesFunction&& write_bytes,
    perfetto_utils::InternedDataBuilder& interned_data_builder,
    const GrowableArray<uint64_t>& function_iids) {
  ASSERT(packet_ptr != nullptr);
  auto& packet = *packet_ptr;

  GrowableArray<uint64_t> callstack(128);

  // Note that |cache| is zone-allocated, so it does not need to be deallocated
  // manually.
  auto* cache = new ProfileCodeInlinedFunctionsCache();
  for (intptr_t sample_index = 0; sample_index < samples_->length();
       ++sample_index) {
    ProcessedSample* sample = samples_->At(sample_index);

    // Walk the sampled PCs and intern the stack.
    callstack.Clear();
    for (intptr_t frame_index = sample->length() - 1; frame_index >= 0;
         --frame_index) {
      ASSERT(sample->At(frame_index) != 0);
      ProcessSampleFramePerfetto(this, callstack, cache, sample, frame_index,
                                 function_iids);
    }

    // Empty sample (everything is invisible).
    if (callstack.is_empty()) {
      continue;
    }

    const auto callstack_iid = interned_data_builder.callstacks().Intern(
        {&callstack[0], callstack.length()});

    perfetto_utils::SetTrustedPacketSequenceId(packet.get());
    perfetto_utils::SetTimestampAndMonotonicClockId(packet.get(),
                                                    sample->timestamp());

    // Populate |packet| with a |PerfSample| that is linked to the |Callstack|
    // that we populated above.
    auto& perf_sample = *packet->set_perf_sample();
    perf_sample.set_pid(OS::ProcessId());
    perf_sample.set_tid(OSThread::ThreadIdToIntPtr(sample->tid()));
    perf_sample.set_callstack_iid(callstack_iid);

    interned_data_builder.AttachInternedDataTo(packet.get());

    perfetto_utils::WritePacketBytes(&packet, write_bytes);
    packet.Reset();
  }
}
#endif  // defined(SUPPORT_PERFETTO)

ProfileFunction* Profile::FindFunction(const Function& function) {
  return (functions_ != nullptr) ? functions_->Lookup(function) : nullptr;
}

#if defined(SUPPORT_PERFETTO)
template <typename WriteBytesFunction>
void Profile::PrintProfilePerfettoImpl(
    WriteBytesFunction&& write_bytes,
    perfetto_utils::InternedDataBuilder& interned_data_builder) {
  Thread* thread = Thread::Current();

  // We allocate one heap-buffered packet and continuously follow a cycle of
  // resetting the buffer and writing its contents.
  protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket> packet;

  perfetto_utils::PopulateClockSnapshotPacket(packet.get());
  perfetto_utils::WritePacketBytes(&packet, write_bytes);
  packet.Reset();

  perfetto_utils::SetTrustedPacketSequenceId(packet.get());

  GrowableArray<uint64_t> function_iids(functions_->length());
  for (intptr_t i = 0; i < functions_->length(); ++i) {
    ProfileFunction* function = functions_->At(i);
    ASSERT(function != NULL);

    const uint64_t function_name_iid =
        interned_data_builder.function_names().Intern(function->Name());

    uint64_t mapping_iid = 0;
    const char* resolved_script_url = function->ResolvedScriptUrl();
    if (resolved_script_url != nullptr) {
      const Script& script_handle =
          Script::Handle(function->function()->script());
      TokenPosition token_pos = function->function()->token_pos();

      uint64_t mapping_path_iid;
      if (!script_handle.IsNull() && token_pos.IsReal()) {
        intptr_t line = -1;
        intptr_t column = -1;
        script_handle.GetTokenLocation(token_pos, &line, &column);
        intptr_t path_with_location_buffer_size =
            Utils::SNPrint(nullptr, 0, "%s:%" Pd ":%" Pd, resolved_script_url,
                           line, column) +
            1;
        std::unique_ptr<char[]> path_with_location =
            std::make_unique<char[]>(path_with_location_buffer_size);
        Utils::SNPrint(path_with_location.get(), path_with_location_buffer_size,
                       "%s:%" Pd ":%" Pd, resolved_script_url, line, column);

        mapping_path_iid = interned_data_builder.mapping_paths().Intern(
            path_with_location.get());
      } else {
        mapping_path_iid =
            interned_data_builder.mapping_paths().Intern(resolved_script_url);
      }

      mapping_iid = interned_data_builder.mappings().Intern(
          {.path_string = mapping_path_iid});
    }

    if (mapping_iid == 0) {
      interned_data_builder.MarkNeedUnknownMapping();
    }

    // Add a |Frame| to the interned data table that is linked to |function|'s
    // name and source location (through the interned data table). A Perfetto
    // |Callstack| consists of a stack of |Frame|s, so the |Callstack|s
    // populated by |PrintSamplesPerfetto| will refer to these |Frame|s.
    function_iids.Add(interned_data_builder.frames().Intern(
        {.mapping_iid = static_cast<uint32_t>(mapping_iid),
         .function_name_iid = static_cast<uint32_t>(function_name_iid)}));

    thread->CheckForSafepoint();
  }
  interned_data_builder.AttachInternedDataTo(packet.get());
  perfetto_utils::WritePacketBytes(&packet, write_bytes);
  packet.Reset();

  PrintSamplesPerfetto(&packet, write_bytes, interned_data_builder,
                       function_iids);
  thread->CheckForSafepoint();
}

#if !defined(PRODUCT)
void Profile::PrintProfilePerfetto(JSONStream* js) {
  ScopeTimer sw("Profile::PrintProfilePerfetto", FLAG_trace_profiler);

  JSONObject jsobj_topLevel(js);
  jsobj_topLevel.AddProperty("type", "PerfettoCpuSamples");
  PrintHeaderJSON(&jsobj_topLevel);

  js->AppendSerializedObject("\"samples\":");
  JSONBase64String jsonBase64String(js);

  perfetto_utils::InternedDataBuilder interned_data_builder;

  PrintProfilePerfettoImpl(
      [&](auto bytes, auto bytes_length) {
        jsonBase64String.AppendBytes(bytes, bytes_length);
      },
      interned_data_builder);
}
#endif

void Profile::PrintProfilePerfetto(
    perfetto_utils::InternedDataBuilder& interned_data_builder,
    void* file,
    Dart_FileWriteCallback write_bytes) {
  ScopeTimer sw("Profile::PrintProfilePerfetto", FLAG_trace_profiler);
  PrintProfilePerfettoImpl(
      [&](auto bytes, auto bytes_length) {
        write_bytes(bytes, bytes_length, file);
      },
      interned_data_builder);
}
#endif  // defined(SUPPORT_PERFETTO)

#if !defined(PRODUCT)
void ProfilerService::PrintCommonImpl(PrintFormat format,
                                      Thread* thread,
                                      JSONStream* js,
                                      SampleFilter* filter,
                                      SampleBlockBuffer* buffer,
                                      bool include_code_samples) {
  // We should bail out in service.cc if the profiler is disabled.
  ASSERT(buffer != nullptr);

  StackZone zone(thread);
  Profile profile;
  profile.Build(thread, thread->isolate(), filter, buffer);

  if (format == PrintFormat::JSON) {
    profile.PrintProfileJSON(js, include_code_samples);
  } else if (format == PrintFormat::Perfetto) {
#if defined(SUPPORT_PERFETTO)
    // This branch will never be reached when SUPPORT_PERFETTO is not defined or
    // when PRODUCT is defined, because |PrintPerfetto| is not defined when
    // SUPPORT_PERFETTO is not defined or when PRODUCT is defined.
    profile.PrintProfilePerfetto(js);
#else
    UNREACHABLE();

#endif  // defined(SUPPORT_PERFETTO)
  }
}

void ProfilerService::PrintCommon(PrintFormat format,
                                  JSONStream* js,
                                  int64_t time_origin_micros,
                                  int64_t time_extent_micros,
                                  bool include_code_samples) {
  Thread* thread = Thread::Current();
  const Isolate* isolate = thread->isolate();
  NoAllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask,
                                  time_origin_micros, time_extent_micros);

  PrintCommonImpl(format, thread, js, &filter, Profiler::sample_block_buffer(),
                  include_code_samples);
}

void ProfilerService::PrintJSON(JSONStream* js,
                                int64_t time_origin_micros,
                                int64_t time_extent_micros,
                                bool include_code_samples) {
  PrintCommon(PrintFormat::JSON, js, time_origin_micros, time_extent_micros,
              include_code_samples);
}

#if defined(SUPPORT_PERFETTO)
void ProfilerService::PrintPerfetto(JSONStream* js,
                                    int64_t time_origin_micros,
                                    int64_t time_extent_micros) {
  PrintCommon(PrintFormat::Perfetto, js, time_origin_micros,
              time_extent_micros);
}
#endif  // defined(SUPPORT_PERFETTO)

class AllocationSampleFilter : public SampleFilter {
 public:
  AllocationSampleFilter(Dart_Port port,
                         intptr_t thread_task_mask,
                         int64_t time_origin_micros,
                         int64_t time_extent_micros)
      : SampleFilter(port,
                     thread_task_mask,
                     time_origin_micros,
                     time_extent_micros) {}

  bool FilterSample(Sample* sample) { return sample->is_allocation_sample(); }
};

void ProfilerService::PrintAllocationJSON(JSONStream* stream,
                                          int64_t time_origin_micros,
                                          int64_t time_extent_micros) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  AllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask,
                                time_origin_micros, time_extent_micros);
  PrintCommonImpl(PrintFormat::JSON, thread, stream, &filter,
                  Profiler::sample_block_buffer(), true);
}

class ClassAllocationSampleFilter : public SampleFilter {
 public:
  ClassAllocationSampleFilter(Dart_Port port,
                              const Class& cls,
                              intptr_t thread_task_mask,
                              int64_t time_origin_micros,
                              int64_t time_extent_micros)
      : SampleFilter(port,
                     thread_task_mask,
                     time_origin_micros,
                     time_extent_micros),
        cls_(Class::Handle(cls.ptr())) {
    ASSERT(!cls_.IsNull());
  }

  bool FilterSample(Sample* sample) {
    return sample->is_allocation_sample() &&
           (sample->allocation_cid() == cls_.id());
  }

 private:
  const Class& cls_;
};

void ProfilerService::PrintAllocationJSON(JSONStream* stream,
                                          const Class& cls,
                                          int64_t time_origin_micros,
                                          int64_t time_extent_micros) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ClassAllocationSampleFilter filter(isolate->main_port(), cls,
                                     Thread::kMutatorTask, time_origin_micros,
                                     time_extent_micros);
  PrintCommonImpl(PrintFormat::JSON, thread, stream, &filter,
                  Profiler::sample_block_buffer(), true);
}

void ProfilerService::ClearSamples() {
  SampleBlockBuffer* sample_block_buffer = Profiler::sample_block_buffer();
  if (sample_block_buffer == nullptr) {
    return;
  }

  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();

  // Disable thread interrupts while processing the buffer.
  DisableThreadInterruptsScope dtis(thread);

  ClearProfileVisitor clear_profile(isolate);
  sample_block_buffer->VisitSamples(&clear_profile);
}
#endif  // !defined(PRODUCT)

#endif  // defined(DART_INCLUDE_PROFILER)

}  // namespace dart
