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

#include "src/profiler/sampling-heap-profiler.h"

#include <stdint.h>
#include <memory>

#include "src/api/api-inl.h"
#include "src/base/ieee754.h"
#include "src/base/utils/random-number-generator.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate.h"
#include "src/heap/heap.h"
#include "src/profiler/strings-storage.h"

namespace v8 {
namespace internal {

// We sample with a Poisson process, with constant average sampling interval.
// This follows the exponential probability distribution with parameter
// λ = 1/rate where rate is the average number of bytes between samples.
//
// Let u be a uniformly distributed random number between 0 and 1, then
// next_sample = (- ln u) / λ
intptr_t SamplingHeapProfiler::Observer::GetNextSampleInterval(uint64_t rate) {
  if (FLAG_sampling_heap_profiler_suppress_randomness)
    return static_cast<intptr_t>(rate);
  double u = random_->NextDouble();
  double next = (-base::ieee754::log(u)) * rate;
  return next < kTaggedSize
             ? kTaggedSize
             : (next > INT_MAX ? INT_MAX : static_cast<intptr_t>(next));
}

// Samples were collected according to a poisson process. Since we have not
// recorded all allocations, we must approximate the shape of the underlying
// space of allocations based on the samples we have collected. Given that
// we sample at rate R, the probability that an allocation of size S will be
// sampled is 1-exp(-S/R). This function uses the above probability to
// approximate the true number of allocations with size *size* given that
// *count* samples were observed.
v8::AllocationProfile::Allocation SamplingHeapProfiler::ScaleSample(
    size_t size, unsigned int count) const {
  double scale = 1.0 / (1.0 - std::exp(-static_cast<double>(size) / rate_));
  // Round count instead of truncating.
  return {size, static_cast<unsigned int>(count * scale + 0.5)};
}

SamplingHeapProfiler::SamplingHeapProfiler(
    Heap* heap, StringsStorage* names, uint64_t rate, int stack_depth,
    v8::HeapProfiler::SamplingFlags flags)
    : isolate_(Isolate::FromHeap(heap)),
      heap_(heap),
      allocation_observer_(heap_, static_cast<intptr_t>(rate), rate, this,
                           isolate_->random_number_generator()),
      names_(names),
      profile_root_(nullptr, "(root)", v8::UnboundScript::kNoScriptId, 0,
                    next_node_id()),
      stack_depth_(stack_depth),
      rate_(rate),
      flags_(flags) {
  CHECK_GT(rate_, 0u);
  heap_->AddAllocationObserversToAllSpaces(&allocation_observer_,
                                           &allocation_observer_);
}

SamplingHeapProfiler::~SamplingHeapProfiler() {
  heap_->RemoveAllocationObserversFromAllSpaces(&allocation_observer_,
                                                &allocation_observer_);
}

void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) {
  DisallowHeapAllocation no_allocation;

  // Check if the area is iterable by confirming that it starts with a map.
  DCHECK((*ObjectSlot(soon_object)).IsMap());

  HandleScope scope(isolate_);
  HeapObject heap_object = HeapObject::FromAddress(soon_object);
  Handle<Object> obj(heap_object, isolate_);

  Local<v8::Value> loc = v8::Utils::ToLocal(obj);

  AllocationNode* node = AddStack();
  node->allocations_[size]++;
  auto sample =
      std::make_unique<Sample>(size, node, loc, this, next_sample_id());
  sample->global.SetWeak(sample.get(), OnWeakCallback,
                         WeakCallbackType::kParameter);
  samples_.emplace(sample.get(), std::move(sample));
}

void SamplingHeapProfiler::OnWeakCallback(
    const WeakCallbackInfo<Sample>& data) {
  Sample* sample = data.GetParameter();
  AllocationNode* node = sample->owner;
  DCHECK_GT(node->allocations_[sample->size], 0);
  node->allocations_[sample->size]--;
  if (node->allocations_[sample->size] == 0) {
    node->allocations_.erase(sample->size);
    while (node->allocations_.empty() && node->children_.empty() &&
           node->parent_ && !node->parent_->pinned_) {
      AllocationNode* parent = node->parent_;
      AllocationNode::FunctionId id = AllocationNode::function_id(
          node->script_id_, node->script_position_, node->name_);
      parent->children_.erase(id);
      node = parent;
    }
  }
  sample->profiler->samples_.erase(sample);
  // sample is deleted because its unique ptr was erased from samples_.
}

SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::FindOrAddChildNode(
    AllocationNode* parent, const char* name, int script_id,
    int start_position) {
  AllocationNode::FunctionId id =
      AllocationNode::function_id(script_id, start_position, name);
  AllocationNode* child = parent->FindChildNode(id);
  if (child) {
    DCHECK_EQ(strcmp(child->name_, name), 0);
    return child;
  }
  auto new_child = std::make_unique<AllocationNode>(
      parent, name, script_id, start_position, next_node_id());
  return parent->AddChildNode(id, std::move(new_child));
}

SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() {
  AllocationNode* node = &profile_root_;

  std::vector<SharedFunctionInfo> stack;
  JavaScriptFrameIterator it(isolate_);
  int frames_captured = 0;
  bool found_arguments_marker_frames = false;
  while (!it.done() && frames_captured < stack_depth_) {
    JavaScriptFrame* frame = it.frame();
    // If we are materializing objects during deoptimization, inlined
    // closures may not yet be materialized, and this includes the
    // closure on the stack. Skip over any such frames (they'll be
    // in the top frames of the stack). The allocations made in this
    // sensitive moment belong to the formerly optimized frame anyway.
    if (frame->unchecked_function().IsJSFunction()) {
      SharedFunctionInfo shared = frame->function().shared();
      stack.push_back(shared);
      frames_captured++;
    } else {
      found_arguments_marker_frames = true;
    }
    it.Advance();
  }

  if (frames_captured == 0) {
    const char* name = nullptr;
    switch (isolate_->current_vm_state()) {
      case GC:
        name = "(GC)";
        break;
      case PARSER:
        name = "(PARSER)";
        break;
      case COMPILER:
        name = "(COMPILER)";
        break;
      case BYTECODE_COMPILER:
        name = "(BYTECODE_COMPILER)";
        break;
      case OTHER:
        name = "(V8 API)";
        break;
      case EXTERNAL:
        name = "(EXTERNAL)";
        break;
      case IDLE:
        name = "(IDLE)";
        break;
      // Treat atomics wait as a normal JS event; we don't care about the
      // difference for allocations.
      case ATOMICS_WAIT:
      case JS:
        name = "(JS)";
        break;
    }
    return FindOrAddChildNode(node, name, v8::UnboundScript::kNoScriptId, 0);
  }

  // We need to process the stack in reverse order as the top of the stack is
  // the first element in the list.
  for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
    SharedFunctionInfo shared = *it;
    const char* name = this->names()->GetName(shared.DebugName());
    int script_id = v8::UnboundScript::kNoScriptId;
    if (shared.script().IsScript()) {
      Script script = Script::cast(shared.script());
      script_id = script.id();
    }
    node = FindOrAddChildNode(node, name, script_id, shared.StartPosition());
  }

  if (found_arguments_marker_frames) {
    node =
        FindOrAddChildNode(node, "(deopt)", v8::UnboundScript::kNoScriptId, 0);
  }

  return node;
}

v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode(
    AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
    const std::map<int, Handle<Script>>& scripts) {
  // By pinning the node we make sure its children won't get disposed if
  // a GC kicks in during the tree retrieval.
  node->pinned_ = true;
  Local<v8::String> script_name =
      ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String(""));
  int line = v8::AllocationProfile::kNoLineNumberInfo;
  int column = v8::AllocationProfile::kNoColumnNumberInfo;
  std::vector<v8::AllocationProfile::Allocation> allocations;
  allocations.reserve(node->allocations_.size());
  if (node->script_id_ != v8::UnboundScript::kNoScriptId &&
      scripts.find(node->script_id_) != scripts.end()) {
    // Cannot use std::map<T>::at because it is not available on android.
    auto non_const_scripts =
        const_cast<std::map<int, Handle<Script>>&>(scripts);
    Handle<Script> script = non_const_scripts[node->script_id_];
    if (!script.is_null()) {
      if (script->name().IsName()) {
        Name name = Name::cast(script->name());
        script_name = ToApiHandle<v8::String>(
            isolate_->factory()->InternalizeUtf8String(names_->GetName(name)));
      }
      line = 1 + Script::GetLineNumber(script, node->script_position_);
      column = 1 + Script::GetColumnNumber(script, node->script_position_);
    }
  }
  for (auto alloc : node->allocations_) {
    allocations.push_back(ScaleSample(alloc.first, alloc.second));
  }

  profile->nodes_.push_back(v8::AllocationProfile::Node{
      ToApiHandle<v8::String>(
          isolate_->factory()->InternalizeUtf8String(node->name_)),
      script_name, node->script_id_, node->script_position_, line, column,
      node->id_, std::vector<v8::AllocationProfile::Node*>(), allocations});
  v8::AllocationProfile::Node* current = &profile->nodes_.back();
  // The |children_| map may have nodes inserted into it during translation
  // because the translation may allocate strings on the JS heap that have
  // the potential to be sampled. That's ok since map iterators are not
  // invalidated upon std::map insertion.
  for (const auto& it : node->children_) {
    current->children.push_back(
        TranslateAllocationNode(profile, it.second.get(), scripts));
  }
  node->pinned_ = false;
  return current;
}

v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() {
  if (flags_ & v8::HeapProfiler::kSamplingForceGC) {
    isolate_->heap()->CollectAllGarbage(
        Heap::kNoGCFlags, GarbageCollectionReason::kSamplingProfiler);
  }
  // To resolve positions to line/column numbers, we will need to look up
  // scripts. Build a map to allow fast mapping from script id to script.
  std::map<int, Handle<Script>> scripts;
  {
    Script::Iterator iterator(isolate_);
    for (Script script = iterator.Next(); !script.is_null();
         script = iterator.Next()) {
      scripts[script.id()] = handle(script, isolate_);
    }
  }
  auto profile = new v8::internal::AllocationProfile();
  TranslateAllocationNode(profile, &profile_root_, scripts);
  profile->samples_ = BuildSamples();

  return profile;
}

const std::vector<v8::AllocationProfile::Sample>
SamplingHeapProfiler::BuildSamples() const {
  std::vector<v8::AllocationProfile::Sample> samples;
  samples.reserve(samples_.size());
  for (const auto& it : samples_) {
    const Sample* sample = it.second.get();
    samples.emplace_back(v8::AllocationProfile::Sample{
        sample->owner->id_, sample->size, ScaleSample(sample->size, 1).count,
        sample->sample_id});
  }
  return samples;
}

}  // namespace internal
}  // namespace v8
