// Copyright (c) 2012 The Chromium 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 "chrome/common/profiling.h"

#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/profiler.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/threading/thread.h"
#include "chrome/common/chrome_switches.h"
#include "v8/include/v8.h"

namespace {

base::debug::AddDynamicSymbol add_dynamic_symbol_func = NULL;
base::debug::MoveDynamicSymbol move_dynamic_symbol_func = NULL;

void JitCodeEventHandler(const v8::JitCodeEvent* event) {
  DCHECK_NE(static_cast<base::debug::AddDynamicSymbol>(NULL),
            add_dynamic_symbol_func);
  DCHECK_NE(static_cast<base::debug::MoveDynamicSymbol>(NULL),
            move_dynamic_symbol_func);

  switch (event->type) {
    case v8::JitCodeEvent::CODE_ADDED:
      add_dynamic_symbol_func(event->code_start, event->code_len,
                              event->name.str, event->name.len);
      break;

    case v8::JitCodeEvent::CODE_MOVED:
      move_dynamic_symbol_func(event->code_start, event->new_code_start);
      break;

    default:
      break;
  }
}

std::string GetProfileName() {
  static const char kDefaultProfileName[] = "chrome-profile-{type}-{pid}";
  CR_DEFINE_STATIC_LOCAL(std::string, profile_name, ());

  if (profile_name.empty()) {
    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    if (command_line.HasSwitch(switches::kProfilingFile))
      profile_name = command_line.GetSwitchValueASCII(switches::kProfilingFile);
    else
      profile_name = std::string(kDefaultProfileName);
    std::string process_type =
        command_line.GetSwitchValueASCII(switches::kProcessType);
    std::string type = process_type.empty() ?
        std::string("browser") : std::string(process_type);
    ReplaceSubstringsAfterOffset(&profile_name, 0, "{type}", type.c_str());
  }
  return profile_name;
}

void FlushProfilingData(base::Thread* thread) {
  static const int kProfilingFlushSeconds = 10;

  if (!Profiling::BeingProfiled())
    return;

  base::debug::FlushProfiling();
  static int flush_seconds;
  if (!flush_seconds) {
    const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    std::string profiling_flush =
        command_line.GetSwitchValueASCII(switches::kProfilingFlush);
    if (!profiling_flush.empty()) {
      flush_seconds = atoi(profiling_flush.c_str());
      DCHECK(flush_seconds > 0);
    } else {
      flush_seconds = kProfilingFlushSeconds;
    }
  }
  thread->message_loop()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&FlushProfilingData, thread),
      base::TimeDelta::FromSeconds(flush_seconds));
}

class ProfilingThreadControl {
 public:
  ProfilingThreadControl() : thread_(NULL) {}

  void Start() {
    base::AutoLock locked(lock_);

    if (thread_ && thread_->IsRunning())
      return;
    thread_ = new base::Thread("Profiling_Flush");
    thread_->Start();
    thread_->message_loop()->PostTask(
        FROM_HERE, base::Bind(&FlushProfilingData, thread_));
  }

  void Stop() {
    base::AutoLock locked(lock_);

    if (!thread_ || !thread_->IsRunning())
      return;
    thread_->Stop();
    delete thread_;
    thread_ = NULL;
  }

 private:
  base::Thread* thread_;
  base::Lock lock_;

  DISALLOW_COPY_AND_ASSIGN(ProfilingThreadControl);
};

base::LazyInstance<ProfilingThreadControl>::Leaky
    g_flush_thread_control = LAZY_INSTANCE_INITIALIZER;

} // namespace

// static
void Profiling::ProcessStarted() {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  std::string process_type =
      command_line.GetSwitchValueASCII(switches::kProcessType);

  // Establish the V8 profiling hooks if we're an instrumented binary.
  if (base::debug::IsBinaryInstrumented()) {
    base::debug::ReturnAddressLocationResolver resolve_func =
        base::debug::GetProfilerReturnAddrResolutionFunc();

    if (resolve_func != NULL) {
      v8::V8::SetReturnAddressLocationResolver(resolve_func);
    }

    // Set up the JIT code entry handler and the symbol callbacks if the
    // profiler supplies them.
    // TODO(siggi): Maybe add a switch or an environment variable to turn off
    //     V8 profiling?
    base::debug::DynamicFunctionEntryHook entry_hook_func =
        base::debug::GetProfilerDynamicFunctionEntryHookFunc();
    add_dynamic_symbol_func = base::debug::GetProfilerAddDynamicSymbolFunc();
    move_dynamic_symbol_func = base::debug::GetProfilerMoveDynamicSymbolFunc();

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    if (isolate != NULL &&
        entry_hook_func != NULL &&
        add_dynamic_symbol_func != NULL &&
        move_dynamic_symbol_func != NULL) {
      v8::V8::SetFunctionEntryHook(isolate, entry_hook_func);
      v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault,
                                     &JitCodeEventHandler);
    }
  }

  if (command_line.HasSwitch(switches::kProfilingAtStart)) {
    std::string process_type_to_start =
        command_line.GetSwitchValueASCII(switches::kProfilingAtStart);
    if (process_type == process_type_to_start)
      Start();
  }
}

// static
void Profiling::Start() {
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  bool flush = command_line.HasSwitch(switches::kProfilingFlush);
  base::debug::StartProfiling(GetProfileName());

  // Schedule profile data flushing for single process because it doesn't
  // get written out correctly on exit.
  if (flush)
    g_flush_thread_control.Get().Start();
}

// static
void Profiling::Stop() {
  g_flush_thread_control.Get().Stop();
  base::debug::StopProfiling();
}

// static
bool Profiling::BeingProfiled() {
  return base::debug::BeingProfiled();
}

// static
void Profiling::Toggle() {
  if (BeingProfiled())
    Stop();
  else
    Start();
}
