// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_PROFILER_SAMPLING_HEAP_PROFILER_H_
#define V8_PROFILER_SAMPLING_HEAP_PROFILER_H_

#include <deque>
#include <map>
#include <memory>
#include <unordered_map>

#include "include/v8-profiler.h"
#include "src/heap/heap.h"
#include "src/profiler/strings-storage.h"

namespace v8 {

namespace base {
class RandomNumberGenerator;
}  // namespace base

namespace internal {

class AllocationProfile : public v8::AllocationProfile {
 public:
  AllocationProfile() = default;

  v8::AllocationProfile::Node* GetRootNode() override {
    return nodes_.size() == 0 ? nullptr : &nodes_.front();
  }

  const std::vector<v8::AllocationProfile::Sample>& GetSamples() override {
    return samples_;
  }

 private:
  std::deque<v8::AllocationProfile::Node> nodes_;
  std::vector<v8::AllocationProfile::Sample> samples_;

  friend class SamplingHeapProfiler;

  DISALLOW_COPY_AND_ASSIGN(AllocationProfile);
};

class SamplingHeapProfiler {
 public:
  class AllocationNode {
   public:
    using FunctionId = uint64_t;
    AllocationNode(AllocationNode* parent, const char* name, int script_id,
                   int start_position, uint32_t id)
        : parent_(parent),
          script_id_(script_id),
          script_position_(start_position),
          name_(name),
          id_(id) {}

    AllocationNode* FindChildNode(FunctionId id) {
      auto it = children_.find(id);
      return it != children_.end() ? it->second.get() : nullptr;
    }

    AllocationNode* AddChildNode(FunctionId id,
                                 std::unique_ptr<AllocationNode> node) {
      return children_.emplace(id, std::move(node)).first->second.get();
    }

    static FunctionId function_id(int script_id, int start_position,
                                  const char* name) {
      // script_id == kNoScriptId case:
      //   Use function name pointer as an id. Names derived from VM state
      //   must not collide with the builtin names. The least significant bit
      //   of the id is set to 1.
      if (script_id == v8::UnboundScript::kNoScriptId) {
        return reinterpret_cast<intptr_t>(name) | 1;
      }
      // script_id != kNoScriptId case:
      //   Use script_id, start_position pair to uniquelly identify the node.
      //   The least significant bit of the id is set to 0.
      DCHECK(static_cast<unsigned>(start_position) < (1u << 31));
      return (static_cast<uint64_t>(script_id) << 32) + (start_position << 1);
    }

   private:
    // TODO(alph): make use of unordered_map's here. Pay attention to
    // iterator invalidation during TranslateAllocationNode.
    std::map<size_t, unsigned int> allocations_;
    std::map<FunctionId, std::unique_ptr<AllocationNode>> children_;
    AllocationNode* const parent_;
    const int script_id_;
    const int script_position_;
    const char* const name_;
    uint32_t id_;
    bool pinned_ = false;

    friend class SamplingHeapProfiler;

    DISALLOW_COPY_AND_ASSIGN(AllocationNode);
  };

  struct Sample {
    Sample(size_t size_, AllocationNode* owner_, Local<Value> local_,
           SamplingHeapProfiler* profiler_, uint64_t sample_id)
        : size(size_),
          owner(owner_),
          global(reinterpret_cast<v8::Isolate*>(profiler_->isolate_), local_),
          profiler(profiler_),
          sample_id(sample_id) {}
    const size_t size;
    AllocationNode* const owner;
    Global<Value> global;
    SamplingHeapProfiler* const profiler;
    const uint64_t sample_id;

   private:
    DISALLOW_COPY_AND_ASSIGN(Sample);
  };

  SamplingHeapProfiler(Heap* heap, StringsStorage* names, uint64_t rate,
                       int stack_depth, v8::HeapProfiler::SamplingFlags flags);
  ~SamplingHeapProfiler();

  v8::AllocationProfile* GetAllocationProfile();
  StringsStorage* names() const { return names_; }

 private:
  class Observer : public AllocationObserver {
   public:
    Observer(Heap* heap, intptr_t step_size, uint64_t rate,
             SamplingHeapProfiler* profiler,
             base::RandomNumberGenerator* random)
        : AllocationObserver(step_size),
          profiler_(profiler),
          heap_(heap),
          random_(random),
          rate_(rate) {}

   protected:
    void Step(int bytes_allocated, Address soon_object, size_t size) override {
      USE(heap_);
      DCHECK(heap_->gc_state() == Heap::NOT_IN_GC);
      if (soon_object) {
        // TODO(ofrobots): it would be better to sample the next object rather
        // than skipping this sample epoch if soon_object happens to be null.
        profiler_->SampleObject(soon_object, size);
      }
    }

    intptr_t GetNextStepSize() override { return GetNextSampleInterval(rate_); }

   private:
    intptr_t GetNextSampleInterval(uint64_t rate);
    SamplingHeapProfiler* const profiler_;
    Heap* const heap_;
    base::RandomNumberGenerator* const random_;
    uint64_t const rate_;
  };

  void SampleObject(Address soon_object, size_t size);

  const std::vector<v8::AllocationProfile::Sample> BuildSamples() const;

  AllocationNode* FindOrAddChildNode(AllocationNode* parent, const char* name,
                                     int script_id, int start_position);
  static void OnWeakCallback(const WeakCallbackInfo<Sample>& data);

  uint32_t next_node_id() { return ++last_node_id_; }
  uint64_t next_sample_id() { return ++last_sample_id_; }

  // Methods that construct v8::AllocationProfile.

  // Translates the provided AllocationNode *node* returning an equivalent
  // AllocationProfile::Node. The newly created AllocationProfile::Node is added
  // to the provided AllocationProfile *profile*. Line numbers, column numbers,
  // and script names are resolved using *scripts* which maps all currently
  // loaded scripts keyed by their script id.
  v8::AllocationProfile::Node* TranslateAllocationNode(
      AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
      const std::map<int, Handle<Script>>& scripts);
  v8::AllocationProfile::Allocation ScaleSample(size_t size,
                                                unsigned int count) const;
  AllocationNode* AddStack();

  Isolate* const isolate_;
  Heap* const heap_;
  uint64_t last_sample_id_ = 0;
  uint32_t last_node_id_ = 0;
  Observer allocation_observer_;
  StringsStorage* const names_;
  AllocationNode profile_root_;
  std::unordered_map<Sample*, std::unique_ptr<Sample>> samples_;
  const int stack_depth_;
  const uint64_t rate_;
  v8::HeapProfiler::SamplingFlags flags_;

  DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_PROFILER_SAMPLING_HEAP_PROFILER_H_
