예제 #1
0
파일: event-hook.cpp 프로젝트: Eagle-X/hhvm
void EventHook::onFunctionExit(const ActRec* ar, const TypedValue* retval,
                               const Fault* fault, ssize_t flags) {
  // Xenon
  if (flags & XenonSignalFlag) {
    Xenon::getInstance().log(Xenon::ExitSample);
  }

  // Run IntervalTimer callbacks only if it's safe to do so, i.e., not when
  // there's a pending exception or we're unwinding from a C++ exception.
  if (flags & IntervalTimerFlag
      && ThreadInfo::s_threadInfo->m_pendingException == nullptr
      && (!fault || fault->m_faultType == Fault::Type::UserException)) {
    IntervalTimer::RunCallbacks(IntervalTimer::ExitSample);
  }

  // Inlined calls normally skip the function enter and exit events. If we
  // side exit in an inlined callee, we short-circuit here in order to skip
  // exit events that could unbalance the call stack.
  if (RuntimeOption::EvalJit &&
      ((jit::TCA) ar->m_savedRip == jit::mcg->tx().uniqueStubs.retInlHelper)) {
    return;
  }

  // User profiler
  if (flags & EventHookFlag) {
    auto profiler = ThreadInfo::s_threadInfo->m_profiler;
    if (profiler != nullptr &&
        !(profiler->shouldSkipBuiltins() && ar->func()->isBuiltin())) {
      // NB: we don't have a function type flag to match what we got in
      // onFunctionEnter. That's okay, though... we tolerate this in
      // TraceProfiler.
      end_profiler_frame(profiler,
                         retval,
                         GetFunctionNameForProfiler(ar->func(), NormalFunc));
    }

    if (shouldRunUserProfiler(ar->func())) {
      if (ThreadInfo::s_threadInfo->m_pendingException != nullptr) {
        // Avoid running PHP code when exception from destructor is pending.
        // TODO(#2329497) will not happen once CheckSurprise is used
      } else if (!fault) {
        runUserProfilerOnFunctionExit(ar, retval, nullptr);
      } else if (fault->m_faultType == Fault::Type::UserException) {
        runUserProfilerOnFunctionExit(ar, retval, fault->m_userException);
      } else {
        // Avoid running PHP code when unwinding C++ exception.
      }
    }
  }

  // Debugger hook
  if (flags & DebuggerHookFlag) {
    DEBUGGER_ATTACHED_ONLY(phpDebuggerFuncExitHook(ar));
  }
}
예제 #2
0
void EventHook::onFunctionExit(const ActRec* ar, TypedValue* retval) {
  auto const inlinedRip = JIT::tx->uniqueStubs.retInlHelper;
  if ((JIT::TCA)ar->m_savedRip == inlinedRip) {
    // Inlined calls normally skip the function enter and exit events. If we
    // side exit in an inlined callee, we want to make sure to skip the exit
    // event to avoid unbalancing the call stack.
    return;
  }

  Xenon::getInstance().log(false);

#ifdef HOTPROFILER
  Profiler* profiler = ThreadInfo::s_threadInfo->m_profiler;
  if (profiler != nullptr) {
    // NB: we don't have a function type flag to match what we got in
    // onFunctionEnter. That's okay, though... we tolerate this in
    // TraceProfiler.
    end_profiler_frame(profiler,
                       GetFunctionNameForProfiler(ar->func(), NormalFunc));
  }
#endif

  // If we have a pending exception, then we're in the process of unwinding
  // for that exception. We avoid running more PHP code (the user profiler) and
  // also avoid raising more exceptions for surprises (including the pending
  // exception).
  if (ThreadInfo::s_threadInfo->m_pendingException == nullptr) {
    if (shouldRunUserProfiler(ar->func())) {
      runUserProfilerOnFunctionExit(ar, retval);
    }
    // XXX Disabled until t2329497 is fixed:
    // CheckSurprise();
  }
}
예제 #3
0
void EventHook::onFunctionExit(const ActRec* ar, const TypedValue* retval,
                               const Fault* fault, ssize_t flags) {
  // Xenon
  if (flags & RequestInjectionData::XenonSignalFlag) {
    Xenon::getInstance().log(Xenon::ExitSample);
  }

  // Inlined calls normally skip the function enter and exit events. If we
  // side exit in an inlined callee, we short-circuit here in order to skip
  // exit events that could unbalance the call stack.
  if ((JIT::TCA) ar->m_savedRip == JIT::mcg->tx().uniqueStubs.retInlHelper) {
    return;
  }

  // User profiler
  if (flags & RequestInjectionData::EventHookFlag) {
    Profiler* profiler = ThreadInfo::s_threadInfo->m_profiler;
    if (profiler != nullptr) {
      // NB: we don't have a function type flag to match what we got in
      // onFunctionEnter. That's okay, though... we tolerate this in
      // TraceProfiler.
      end_profiler_frame(profiler,
                         retval,
                         GetFunctionNameForProfiler(ar->func(), NormalFunc));
    }

    if (shouldRunUserProfiler(ar->func())) {
      if (ThreadInfo::s_threadInfo->m_pendingException != nullptr) {
        // Avoid running PHP code when exception from destructor is pending.
        // TODO(#2329497) will not happen once CheckSurprise is used
      } else if (!fault) {
        runUserProfilerOnFunctionExit(ar, retval, nullptr);
      } else if (fault->m_faultType == Fault::Type::UserException) {
        runUserProfilerOnFunctionExit(ar, retval, fault->m_userException);
      } else {
        // Avoid running PHP code when unwinding C++ exception.
      }
    }
  }

  // Debugger hook
  if (flags & RequestInjectionData::DebuggerHookFlag) {
    DEBUGGER_ATTACHED_ONLY(phpDebuggerFuncExitHook(ar));
  }
}
예제 #4
0
void EventHook::onFunctionExit(const ActRec* ar, const TypedValue* retval,
                               const Fault* fault, ssize_t flags) {
  // Xenon
  if (flags & RequestInjectionData::XenonSignalFlag) {
    Xenon::getInstance().log(false);
  }

  // User profiler
  //
  // Inlined calls normally skip the function enter and exit events. If we
  // side exit in an inlined callee, we want to make sure to skip the exit
  // event to avoid unbalancing the call stack.
  if ((flags & RequestInjectionData::EventHookFlag) &&
      (JIT::TCA)ar->m_savedRip != JIT::tx->uniqueStubs.retInlHelper) {
#ifdef HOTPROFILER
    Profiler* profiler = ThreadInfo::s_threadInfo->m_profiler;
    if (profiler != nullptr) {
      // NB: we don't have a function type flag to match what we got in
      // onFunctionEnter. That's okay, though... we tolerate this in
      // TraceProfiler.
      end_profiler_frame(profiler,
                         GetFunctionNameForProfiler(ar->func(), NormalFunc));
    }
#endif

    if (shouldRunUserProfiler(ar->func())) {
      if (ThreadInfo::s_threadInfo->m_pendingException != nullptr) {
        // Avoid running PHP code when exception from destructor is pending.
        // TODO(#2329497) will not happen once CheckSurprise is used
      } else if (!fault) {
        runUserProfilerOnFunctionExit(ar, retval, nullptr);
      } else if (fault->m_faultType == Fault::Type::UserException) {
        runUserProfilerOnFunctionExit(ar, retval, fault->m_userException);
      } else {
        // Avoid running PHP code when unwinding C++ exception.
      }
    }
  }
}