// 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.

#ifndef RUNTIME_VM_PROFILER_SERVICE_H_
#define RUNTIME_VM_PROFILER_SERVICE_H_

#include "vm/allocation.h"
#include "vm/code_observers.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/object.h"
#include "vm/profiler.h"
#include "vm/tags.h"
#include "vm/thread_interrupter.h"
#include "vm/token_position.h"

// CPU Profile model and service protocol bits.
// NOTE: For sampling and stack walking related code, see profiler.h.

namespace dart {

// Forward declarations.
class Code;
class Function;
class JSONArray;
class JSONStream;
class ProfileFunctionTable;
class ProfileCodeTable;
class RawCode;
class RawFunction;
class SampleFilter;
class ProcessedSample;
class ProcessedSampleBuffer;

class ProfileFunctionSourcePosition {
 public:
  explicit ProfileFunctionSourcePosition(TokenPosition token_pos);

  void Tick(bool exclusive);

  TokenPosition token_pos() const { return token_pos_; }
  intptr_t exclusive_ticks() const { return exclusive_ticks_; }
  intptr_t inclusive_ticks() const { return inclusive_ticks_; }

 private:
  TokenPosition token_pos_;
  intptr_t exclusive_ticks_;
  intptr_t inclusive_ticks_;

  DISALLOW_ALLOCATION();
};

// Profile data related to a |Function|.
class ProfileFunction : public ZoneAllocated {
 public:
  enum Kind {
    kDartFunction,     // Dart function.
    kNativeFunction,   // Synthetic function for Native (C/C++).
    kTagFunction,      // Synthetic function for a VM or User tag.
    kStubFunction,     // Synthetic function for stub code.
    kUnknownFunction,  // A singleton function for unknown objects.
  };

  ProfileFunction(Kind kind,
                  const char* name,
                  const Function& function,
                  const intptr_t table_index);

  const char* name() const {
    ASSERT(name_ != NULL);
    return name_;
  }

  const char* Name() const;

  const Function* function() const { return &function_; }

  bool is_visible() const;

  intptr_t table_index() const { return table_index_; }

  Kind kind() const { return kind_; }

  intptr_t exclusive_ticks() const { return exclusive_ticks_; }
  intptr_t inclusive_ticks() const { return inclusive_ticks_; }

  void IncInclusiveTicks() { inclusive_ticks_++; }

  void Tick(bool exclusive,
            intptr_t inclusive_serial,
            TokenPosition token_position);

  static const char* KindToCString(Kind kind);

  void PrintToJSONArray(JSONArray* functions);

  // Returns true if the call was successful and |pfsp| is set.
  bool GetSinglePosition(ProfileFunctionSourcePosition* pfsp);

  void TickSourcePosition(TokenPosition token_position, bool exclusive);

  intptr_t NumSourcePositions() const {
    return source_position_ticks_.length();
  }

  const ProfileFunctionSourcePosition& GetSourcePosition(intptr_t i) const {
    return source_position_ticks_.At(i);
  }

 private:
  const Kind kind_;
  const char* name_;
  const Function& function_;
  const intptr_t table_index_;
  ZoneGrowableArray<intptr_t> profile_codes_;
  ZoneGrowableArray<ProfileFunctionSourcePosition> source_position_ticks_;

  intptr_t exclusive_ticks_;
  intptr_t inclusive_ticks_;
  intptr_t inclusive_serial_;

  void PrintToJSONObject(JSONObject* func);
  // A |ProfileCode| that contains this function.
  void AddProfileCode(intptr_t code_table_index);

  friend class ProfileCode;
  friend class ProfileBuilder;
};

class ProfileCodeAddress {
 public:
  explicit ProfileCodeAddress(uword pc);

  void Tick(bool exclusive);

  uword pc() const { return pc_; }
  intptr_t exclusive_ticks() const { return exclusive_ticks_; }
  intptr_t inclusive_ticks() const { return inclusive_ticks_; }

 private:
  uword pc_;
  intptr_t exclusive_ticks_;
  intptr_t inclusive_ticks_;
};

// Profile data related to a |Code|.
class ProfileCode : public ZoneAllocated {
 public:
  enum Kind {
    kDartCode,       // Live Dart code.
    kCollectedCode,  // Dead Dart code.
    kNativeCode,     // Native code.
    kReusedCode,     // Dead Dart code that has been reused by new kDartCode.
    kTagCode,        // A special kind of code representing a tag.
  };

  ProfileCode(Kind kind,
              uword start,
              uword end,
              int64_t timestamp,
              const AbstractCode code);

  Kind kind() const { return kind_; }

  uword start() const { return start_; }
  void set_start(uword start) { start_ = start; }

  uword end() const { return end_; }
  void set_end(uword end) { end_ = end; }

  void ExpandLower(uword start);
  void ExpandUpper(uword end);
  void TruncateLower(uword start);
  void TruncateUpper(uword end);

  bool Contains(uword pc) const { return (pc >= start_) && (pc < end_); }

  bool Overlaps(const ProfileCode* other) const;

  int64_t compile_timestamp() const { return compile_timestamp_; }
  void set_compile_timestamp(int64_t timestamp) {
    compile_timestamp_ = timestamp;
  }

  intptr_t exclusive_ticks() const { return exclusive_ticks_; }
  void set_exclusive_ticks(intptr_t exclusive_ticks) {
    exclusive_ticks_ = exclusive_ticks;
  }
  void IncExclusiveTicks() { exclusive_ticks_++; }

  intptr_t inclusive_ticks() const { return inclusive_ticks_; }
  void set_inclusive_ticks(intptr_t inclusive_ticks) {
    inclusive_ticks_ = inclusive_ticks;
  }
  void IncInclusiveTicks() { inclusive_ticks_++; }

  bool IsOptimizedDart() const;
  const AbstractCode code() const { return code_; }

  const char* name() const { return name_; }
  void SetName(const char* name);
  void GenerateAndSetSymbolName(const char* prefix);

  static const char* KindToCString(Kind kind);

  void PrintToJSONArray(JSONArray* codes);

 private:
  void Tick(uword pc, bool exclusive, intptr_t serial);
  void TickAddress(uword pc, bool exclusive);

  ProfileFunction* SetFunctionAndName(ProfileFunctionTable* table);

  ProfileFunction* function() const { return function_; }

  void PrintNativeCode(JSONObject* profile_code_obj);
  void PrintCollectedCode(JSONObject* profile_code_obj);
  void PrintOverwrittenCode(JSONObject* profile_code_obj);
  void PrintTagCode(JSONObject* profile_code_obj);

  void set_code_table_index(intptr_t index) { code_table_index_ = index; }
  intptr_t code_table_index() const { return code_table_index_; }

  const Kind kind_;
  uword start_;
  uword end_;
  intptr_t exclusive_ticks_;
  intptr_t inclusive_ticks_;
  intptr_t inclusive_serial_;

  const AbstractCode code_;
  char* name_;
  int64_t compile_timestamp_;
  ProfileFunction* function_;
  intptr_t code_table_index_;
  ZoneGrowableArray<ProfileCodeAddress> address_ticks_;

  friend class ProfileBuilder;
};

class ProfileCodeTable : public ZoneAllocated {
 public:
  ProfileCodeTable() : table_(8) {}

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

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

  // Find the table index to the ProfileCode containing pc.
  // Returns < 0 if not found.
  intptr_t FindCodeIndexForPC(uword pc) const;

  ProfileCode* FindCodeForPC(uword pc) const {
    intptr_t index = FindCodeIndexForPC(pc);
    if (index < 0) {
      return NULL;
    }
    return At(index);
  }

  // Insert |new_code| into the table. Returns the table index where |new_code|
  // was inserted. Will merge with an overlapping ProfileCode if one is present.
  intptr_t InsertCode(ProfileCode* new_code);

 private:
  void FindNeighbors(uword pc,
                     intptr_t* lo,
                     intptr_t* hi,
                     ProfileCode** lo_code,
                     ProfileCode** hi_code) const;

  void VerifyOrder();
  void VerifyOverlap();

  ZoneGrowableArray<ProfileCode*> table_;
};

// Stack traces are organized in a trie. This holds information about one node
// in the trie. A node in a tree represents a stack frame and a path in the tree
// represents a stack trace. Each unique stack trace appears in the tree once
// and each node has a count indicating how many times this has been observed.
// The index can be used to look up a |ProfileFunction| or |ProfileCode|.
// A node can have zero or more children. Depending on the kind of trie the
// children are callers or callees of the current node.
class ProfileTrieNode : public ZoneAllocated {
 public:
  explicit ProfileTrieNode(intptr_t index);
  virtual ~ProfileTrieNode();

  virtual void PrintToJSONArray(JSONArray* array) const = 0;

  // Index into function or code tables.
  intptr_t table_index() const { return table_index_; }

  intptr_t count() const { return count_; }

  void Tick(ProcessedSample* sample, bool exclusive = false);

  void IncrementAllocation(intptr_t allocation, bool exclusive) {
    ASSERT(allocation >= 0);
    if (exclusive) {
      exclusive_allocations_ += allocation;
    }
    inclusive_allocations_ += allocation;
  }

  intptr_t inclusive_allocations() const { return inclusive_allocations_; }
  intptr_t exclusive_allocations() const { return exclusive_allocations_; }

  intptr_t NumChildren() const { return children_.length(); }

  ProfileTrieNode* At(intptr_t i) { return children_.At(i); }

  intptr_t IndexOf(ProfileTrieNode* node);

  intptr_t frame_id() const { return frame_id_; }
  void set_frame_id(intptr_t id) {
    ASSERT(frame_id_ == -1);
    frame_id_ = id;
  }

 protected:
  void SortChildren();

  static int ProfileTrieNodeCompare(ProfileTrieNode* const* a,
                                    ProfileTrieNode* const* b) {
    ASSERT(a != NULL);
    ASSERT(b != NULL);
    return (*b)->count() - (*a)->count();
  }

  intptr_t table_index_;
  intptr_t count_;
  intptr_t exclusive_allocations_;
  intptr_t inclusive_allocations_;
  ZoneGrowableArray<ProfileTrieNode*> children_;
  intptr_t frame_id_;

  friend class ProfileBuilder;
};

// The model for a profile. Most of the model is zone allocated, therefore
// a zone must be created that lives longer than this object.
class Profile : public ValueObject {
 public:
  enum TagOrder { kNoTags, kUser, kUserVM, kVM, kVMUser };

  enum TrieKind {
    kExclusiveCode,
    kExclusiveFunction,
    kInclusiveCode,
    kInclusiveFunction,
    kNumTrieKinds,
  };

  static bool IsCodeTrie(TrieKind kind) {
    return (kind == kExclusiveCode) || (kind == kInclusiveCode);
  }

  static bool IsFunctionTrie(TrieKind kind) { return !IsCodeTrie(kind); }

  explicit Profile(Isolate* isolate);

  // Build a filtered model using |filter| with the specified |tag_order|.
  void Build(Thread* thread,
             SampleFilter* filter,
             SampleBuffer* sample_buffer,
             TagOrder tag_order,
             intptr_t extra_tags = 0);

  // After building:
  int64_t min_time() const { return min_time_; }
  int64_t max_time() const { return max_time_; }
  int64_t GetTimeSpan() const { return max_time() - min_time(); }
  intptr_t sample_count() const { return sample_count_; }

  intptr_t NumFunctions() const;

  ProfileFunction* GetFunction(intptr_t index);
  ProfileCode* GetCode(intptr_t index);
  ProfileTrieNode* GetTrieRoot(TrieKind trie_kind);

  void PrintProfileJSON(JSONStream* stream);
  void PrintTimelineJSON(JSONStream* stream);

  ProfileFunction* FindFunction(const Function& function);

 private:
  void PrintHeaderJSON(JSONObject* obj);
  void PrintTimelineFrameJSON(JSONObject* frames,
                              ProfileTrieNode* current,
                              ProfileTrieNode* parent,
                              intptr_t* next_id);

  Isolate* isolate_;
  Zone* zone_;
  ProcessedSampleBuffer* samples_;
  ProfileCodeTable* live_code_;
  ProfileCodeTable* dead_code_;
  ProfileCodeTable* tag_code_;
  ProfileFunctionTable* functions_;
  intptr_t dead_code_index_offset_;
  intptr_t tag_code_index_offset_;

  ProfileTrieNode* roots_[kNumTrieKinds];

  int64_t min_time_;
  int64_t max_time_;

  intptr_t sample_count_;

  friend class ProfileBuilder;
};

class ProfileTrieWalker : public ValueObject {
 public:
  explicit ProfileTrieWalker(Profile* profile)
      : profile_(profile), parent_(NULL), current_(NULL), code_trie_(false) {
    ASSERT(profile_ != NULL);
  }

  void Reset(Profile::TrieKind trie_kind);

  const char* CurrentName();
  // Return the current node's peer's inclusive tick count.
  intptr_t CurrentInclusiveTicks();
  // Return the current node's peer's exclusive tick count.
  intptr_t CurrentExclusiveTicks();
  // Return the current node's inclusive allocation count.
  intptr_t CurrentInclusiveAllocations();
  // Return the current node's exclusive allocation count.
  intptr_t CurrentExclusiveAllocations();
  // Return the current node's tick count.
  intptr_t CurrentNodeTickCount();
  // Return the number siblings (including yourself).
  intptr_t SiblingCount();

  // If the following conditions are met returns the current token:
  // 1) This is a function trie.
  // 2) There is only one token position for a given function.
  // Will return NULL otherwise.
  const char* CurrentToken();

  bool Down();
  bool NextSibling();

 private:
  Profile* profile_;
  ProfileTrieNode* parent_;
  ProfileTrieNode* current_;
  bool code_trie_;
};

class ProfilerService : public AllStatic {
 public:
  enum {
    kNoExtraTags = 0,
    kCodeTransitionTagsBit = (1 << 0),
  };

  static void PrintJSON(JSONStream* stream,
                        Profile::TagOrder tag_order,
                        intptr_t extra_tags,
                        int64_t time_origin_micros,
                        int64_t time_extent_micros);

  static void PrintAllocationJSON(JSONStream* stream,
                                  Profile::TagOrder tag_order,
                                  const Class& cls,
                                  int64_t time_origin_micros,
                                  int64_t time_extent_micros);

  static void PrintNativeAllocationJSON(JSONStream* stream,
                                        Profile::TagOrder tag_order,
                                        int64_t time_origin_micros,
                                        int64_t time_extent_micros);

  static void PrintTimelineJSON(JSONStream* stream,
                                Profile::TagOrder tag_order,
                                int64_t time_origin_micros,
                                int64_t time_extent_micros);

  static void ClearSamples();

 private:
  static void PrintJSONImpl(Thread* thread,
                            JSONStream* stream,
                            Profile::TagOrder tag_order,
                            intptr_t extra_tags,
                            SampleFilter* filter,
                            SampleBuffer* sample_buffer,
                            bool as_timline);
};

}  // namespace dart

#endif  // RUNTIME_VM_PROFILER_SERVICE_H_
