Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / src / sampler.cc
index 684ef48..394efeb 100644 (file)
@@ -1,31 +1,8 @@
 // Copyright 2013 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "sampler.h"
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/sampler.h"
 
 #if V8_OS_POSIX && !V8_OS_CYGWIN
 
 #include <pthread.h>
 #include <signal.h>
 #include <sys/time.h>
-#include <sys/syscall.h>
+
+#if !V8_OS_QNX && !V8_OS_NACL
+#include <sys/syscall.h>  // NOLINT
+#endif
 
 #if V8_OS_MACOSX
 #include <mach/mach.h>
 // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
 // and is a typedef for struct sigcontext. There is no uc_mcontext.
-#elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) \
-    && !V8_OS_OPENBSD
+#elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && \
+    !V8_OS_OPENBSD && !V8_OS_NACL
 #include <ucontext.h>
 #endif
+
 #include <unistd.h>
 
 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
 // Old versions of the C library <signal.h> didn't define the type.
 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
-    defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
-#include <asm/sigcontext.h>
+    (defined(__arm__) || defined(__aarch64__)) && \
+    !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
+#include <asm/sigcontext.h>  // NOLINT
 #endif
 
 #elif V8_OS_WIN || V8_OS_CYGWIN
 
-#include "win32-headers.h"
+#include "src/base/win32-headers.h"
 
 #endif
 
-#include "v8.h"
+#include "src/v8.h"
 
-#include "cpu-profiler-inl.h"
-#include "flags.h"
-#include "frames-inl.h"
-#include "log.h"
-#include "platform.h"
-#include "simulator.h"
-#include "v8threads.h"
-#include "vm-state-inl.h"
+#include "src/base/platform/platform.h"
+#include "src/cpu-profiler-inl.h"
+#include "src/flags.h"
+#include "src/frames-inl.h"
+#include "src/log.h"
+#include "src/simulator.h"
+#include "src/v8threads.h"
+#include "src/vm-state-inl.h"
 
 
 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
@@ -93,6 +75,18 @@ typedef struct ucontext {
   // Other fields are not used by V8, don't define them here.
 } ucontext_t;
 
+#elif defined(__aarch64__)
+
+typedef struct sigcontext mcontext_t;
+
+typedef struct ucontext {
+  uint64_t uc_flags;
+  struct ucontext *uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  // Other fields are not used by V8, don't define them here.
+} ucontext_t;
+
 #elif defined(__mips__)
 // MIPS version of sigcontext, for Android bionic.
 typedef struct {
@@ -142,6 +136,23 @@ typedef struct ucontext {
   // Other fields are not used by V8, don't define them here.
 } ucontext_t;
 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
+
+#elif defined(__x86_64__)
+// x64 version for Android.
+typedef struct {
+  uint64_t gregs[23];
+  void* fpregs;
+  uint64_t __reserved1[8];
+} mcontext_t;
+
+typedef struct ucontext {
+  uint64_t uc_flags;
+  struct ucontext *uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  // Other fields are not used by V8, don't define them here.
+} ucontext_t;
+enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
 #endif
 
 #endif  // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
@@ -222,13 +233,33 @@ class SimulatorHelper {
   }
 
   inline void FillRegisters(RegisterState* state) {
+#if V8_TARGET_ARCH_ARM
     state->pc = reinterpret_cast<Address>(simulator_->get_pc());
     state->sp = reinterpret_cast<Address>(simulator_->get_register(
         Simulator::sp));
-#if V8_TARGET_ARCH_ARM
     state->fp = reinterpret_cast<Address>(simulator_->get_register(
         Simulator::r11));
+#elif V8_TARGET_ARCH_ARM64
+    if (simulator_->sp() == 0 || simulator_->fp() == 0) {
+      // It possible that the simulator is interrupted while it is updating
+      // the sp or fp register. ARM64 simulator does this in two steps:
+      // first setting it to zero and then setting it to the new value.
+      // Bailout if sp/fp doesn't contain the new value.
+      return;
+    }
+    state->pc = reinterpret_cast<Address>(simulator_->pc());
+    state->sp = reinterpret_cast<Address>(simulator_->sp());
+    state->fp = reinterpret_cast<Address>(simulator_->fp());
 #elif V8_TARGET_ARCH_MIPS
+    state->pc = reinterpret_cast<Address>(simulator_->get_pc());
+    state->sp = reinterpret_cast<Address>(simulator_->get_register(
+        Simulator::sp));
+    state->fp = reinterpret_cast<Address>(simulator_->get_register(
+        Simulator::fp));
+#elif V8_TARGET_ARCH_MIPS64
+    state->pc = reinterpret_cast<Address>(simulator_->get_pc());
+    state->sp = reinterpret_cast<Address>(simulator_->get_register(
+        Simulator::sp));
     state->fp = reinterpret_cast<Address>(simulator_->get_register(
         Simulator::fp));
 #endif
@@ -244,16 +275,16 @@ class SimulatorHelper {
 
 class SignalHandler : public AllStatic {
  public:
-  static void SetUp() { if (!mutex_) mutex_ = new Mutex(); }
-  static void TearDown() { delete mutex_; }
+  static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
+  static void TearDown() { delete mutex_; mutex_ = NULL; }
 
   static void IncreaseSamplerCount() {
-    LockGuard<Mutex> lock_guard(mutex_);
+    base::LockGuard<base::Mutex> lock_guard(mutex_);
     if (++client_count_ == 1) Install();
   }
 
   static void DecreaseSamplerCount() {
-    LockGuard<Mutex> lock_guard(mutex_);
+    base::LockGuard<base::Mutex> lock_guard(mutex_);
     if (--client_count_ == 0) Restore();
   }
 
@@ -263,46 +294,53 @@ class SignalHandler : public AllStatic {
 
  private:
   static void Install() {
+#if !V8_OS_NACL
     struct sigaction sa;
     sa.sa_sigaction = &HandleProfilerSignal;
     sigemptyset(&sa.sa_mask);
+#if V8_OS_QNX
+    sa.sa_flags = SA_SIGINFO;
+#else
     sa.sa_flags = SA_RESTART | SA_SIGINFO;
+#endif
     signal_handler_installed_ =
         (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
+#endif
   }
 
   static void Restore() {
+#if !V8_OS_NACL
     if (signal_handler_installed_) {
       sigaction(SIGPROF, &old_signal_handler_, 0);
       signal_handler_installed_ = false;
     }
+#endif
   }
 
+#if !V8_OS_NACL
   static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
+#endif
   // Protects the process wide state below.
-  static Mutex* mutex_;
+  static base::Mutex* mutex_;
   static int client_count_;
   static bool signal_handler_installed_;
   static struct sigaction old_signal_handler_;
 };
 
 
-Mutex* SignalHandler::mutex_ = NULL;
+base::Mutex* SignalHandler::mutex_ = NULL;
 int SignalHandler::client_count_ = 0;
 struct sigaction SignalHandler::old_signal_handler_;
 bool SignalHandler::signal_handler_installed_ = false;
 
 
+// As Native Client does not support signal handling, profiling is disabled.
+#if !V8_OS_NACL
 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
                                          void* context) {
-#if V8_OS_NACL
-  // As Native Client does not support signal handling, profiling
-  // is disabled.
-  return;
-#else
   USE(info);
   if (signal != SIGPROF) return;
-  Isolate* isolate = Isolate::UncheckedCurrent();
+  Isolate* isolate = Isolate::UnsafeCurrent();
   if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
     // We require a fully initialized and entered isolate.
     return;
@@ -321,6 +359,11 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
   SimulatorHelper helper;
   if (!helper.Init(sampler, isolate)) return;
   helper.FillRegisters(&state);
+  // It possible that the simulator is interrupted while it is updating
+  // the sp or fp register. ARM64 simulator does this in two steps:
+  // first setting it to zero and then setting it to the new value.
+  // Bailout if sp/fp doesn't contain the new value.
+  if (state.sp == 0 || state.fp == 0) return;
 #else
   // Extracting the sample from the context is extremely machine dependent.
   ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
@@ -350,10 +393,19 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
   state.fp = reinterpret_cast<Address>(mcontext.arm_fp);
 #endif  // defined(__GLIBC__) && !defined(__UCLIBC__) &&
         // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
+#elif V8_HOST_ARCH_ARM64
+  state.pc = reinterpret_cast<Address>(mcontext.pc);
+  state.sp = reinterpret_cast<Address>(mcontext.sp);
+  // FP is an alias for x29.
+  state.fp = reinterpret_cast<Address>(mcontext.regs[29]);
 #elif V8_HOST_ARCH_MIPS
   state.pc = reinterpret_cast<Address>(mcontext.pc);
   state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
   state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
+#elif V8_HOST_ARCH_MIPS64
+  state.pc = reinterpret_cast<Address>(mcontext.pc);
+  state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
+  state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
 #endif  // V8_HOST_ARCH_*
 #elif V8_OS_MACOSX
 #if V8_HOST_ARCH_X64
@@ -415,29 +467,39 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
   state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
   state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
   state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
-#endif  // V8_OS_SOLARIS
+#elif V8_OS_QNX
+#if V8_HOST_ARCH_IA32
+  state.pc = reinterpret_cast<Address>(mcontext.cpu.eip);
+  state.sp = reinterpret_cast<Address>(mcontext.cpu.esp);
+  state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp);
+#elif V8_HOST_ARCH_ARM
+  state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]);
+  state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]);
+  state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]);
+#endif  // V8_HOST_ARCH_*
+#endif  // V8_OS_QNX
 #endif  // USE_SIMULATOR
   sampler->SampleStack(state);
-#endif  // V8_OS_NACL
 }
+#endif  // V8_OS_NACL
 
 #endif
 
 
-class SamplerThread : public Thread {
+class SamplerThread : public base::Thread {
  public:
   static const int kSamplerThreadStackSize = 64 * KB;
 
   explicit SamplerThread(int interval)
-      : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
+      : Thread(base::Thread::Options("SamplerThread", kSamplerThreadStackSize)),
         interval_(interval) {}
 
-  static void SetUp() { if (!mutex_) mutex_ = new Mutex(); }
+  static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
   static void TearDown() { delete mutex_; mutex_ = NULL; }
 
   static void AddActiveSampler(Sampler* sampler) {
     bool need_to_start = false;
-    LockGuard<Mutex> lock_guard(mutex_);
+    base::LockGuard<base::Mutex> lock_guard(mutex_);
     if (instance_ == NULL) {
       // Start a thread that will send SIGPROF signal to VM threads,
       // when CPU profiling will be enabled.
@@ -445,9 +507,9 @@ class SamplerThread : public Thread {
       need_to_start = true;
     }
 
-    ASSERT(sampler->IsActive());
-    ASSERT(!instance_->active_samplers_.Contains(sampler));
-    ASSERT(instance_->interval_ == sampler->interval());
+    DCHECK(sampler->IsActive());
+    DCHECK(!instance_->active_samplers_.Contains(sampler));
+    DCHECK(instance_->interval_ == sampler->interval());
     instance_->active_samplers_.Add(sampler);
 
     if (need_to_start) instance_->StartSynchronously();
@@ -456,11 +518,11 @@ class SamplerThread : public Thread {
   static void RemoveActiveSampler(Sampler* sampler) {
     SamplerThread* instance_to_remove = NULL;
     {
-      LockGuard<Mutex> lock_guard(mutex_);
+      base::LockGuard<base::Mutex> lock_guard(mutex_);
 
-      ASSERT(sampler->IsActive());
+      DCHECK(sampler->IsActive());
       bool removed = instance_->active_samplers_.RemoveElement(sampler);
-      ASSERT(removed);
+      DCHECK(removed);
       USE(removed);
 
       // We cannot delete the instance immediately as we need to Join() the
@@ -480,7 +542,7 @@ class SamplerThread : public Thread {
   virtual void Run() {
     while (true) {
       {
-        LockGuard<Mutex> lock_guard(mutex_);
+        base::LockGuard<base::Mutex> lock_guard(mutex_);
         if (active_samplers_.is_empty()) break;
         // When CPU profiling is enabled both JavaScript and C++ code is
         // profiled. We must not suspend.
@@ -491,13 +553,13 @@ class SamplerThread : public Thread {
           sampler->DoSample();
         }
       }
-      OS::Sleep(interval_);
+      base::OS::Sleep(interval_);
     }
   }
 
  private:
   // Protects the process wide state below.
-  static Mutex* mutex_;
+  static base::Mutex* mutex_;
   static SamplerThread* instance_;
 
   const int interval_;
@@ -507,7 +569,7 @@ class SamplerThread : public Thread {
 };
 
 
-Mutex* SamplerThread::mutex_ = NULL;
+base::Mutex* SamplerThread::mutex_ = NULL;
 SamplerThread* SamplerThread::instance_ = NULL;
 
 
@@ -516,7 +578,8 @@ SamplerThread* SamplerThread::instance_ = NULL;
 //
 DISABLE_ASAN void TickSample::Init(Isolate* isolate,
                                    const RegisterState& regs) {
-  ASSERT(isolate->IsInitialized());
+  DCHECK(isolate->IsInitialized());
+  timestamp = base::TimeTicks::HighResolutionNow();
   pc = regs.pc;
   state = isolate->current_vm_state();
 
@@ -546,7 +609,7 @@ DISABLE_ASAN void TickSample::Init(Isolate* isolate,
 
   SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp);
   top_frame_type = it.top_frame_type();
-  int i = 0;
+  unsigned i = 0;
   while (!it.done() && i < TickSample::kMaxFramesCount) {
     stack[i++] = it.frame()->pc();
     it.Advance();
@@ -584,27 +647,27 @@ Sampler::Sampler(Isolate* isolate, int interval)
 
 
 Sampler::~Sampler() {
-  ASSERT(!IsActive());
+  DCHECK(!IsActive());
   delete data_;
 }
 
 
 void Sampler::Start() {
-  ASSERT(!IsActive());
+  DCHECK(!IsActive());
   SetActive(true);
   SamplerThread::AddActiveSampler(this);
 }
 
 
 void Sampler::Stop() {
-  ASSERT(IsActive());
+  DCHECK(IsActive());
   SamplerThread::RemoveActiveSampler(this);
   SetActive(false);
 }
 
 
 void Sampler::IncreaseProfilingDepth() {
-  NoBarrier_AtomicIncrement(&profiling_, 1);
+  base::NoBarrier_AtomicIncrement(&profiling_, 1);
 #if defined(USE_SIGNALS)
   SignalHandler::IncreaseSamplerCount();
 #endif
@@ -615,7 +678,7 @@ void Sampler::DecreaseProfilingDepth() {
 #if defined(USE_SIGNALS)
   SignalHandler::DecreaseSamplerCount();
 #endif
-  NoBarrier_AtomicIncrement(&profiling_, -1);
+  base::NoBarrier_AtomicIncrement(&profiling_, -1);
 }