Пример #1
0
void EventHook::onFunctionReturn(ActRec* ar, TypedValue retval) {
  // The locals are already gone. Null out everything.
  ar->setThisOrClassAllowNull(nullptr);
  ar->setLocalsDecRefd();
  ar->setVarEnv(nullptr);

  try {
    auto const flags = check_request_surprise();
    onFunctionExit(ar, &retval, false, nullptr, flags);

    // Async profiler
    if ((flags & AsyncEventHookFlag) &&
        ar->func()->isAsyncFunction() && ar->resumed()) {
      auto session = AsioSession::Get();
      // Return @ resumed execution => AsyncFunctionWaitHandle succeeded.
      if (session->hasOnResumableSuccess()) {
        auto afwh = frame_afwh(ar);
        session->onResumableSuccess(afwh, cellAsCVarRef(retval));
      }
    }
  } catch (...) {
    /*
     * We're responsible for freeing the return value if we exit with an
     * exception.  See irgen-ret.
     */
    tvRefcountedDecRef(retval);
    throw;
  }
}
Пример #2
0
void EventHook::CheckSurprise() {
  ThreadInfo* info = ThreadInfo::s_threadInfo.getNoCheck();
  check_request_surprise(info);
  if (info->m_pendingException) {
    throw_pending_exception(info);
  }
}
Пример #3
0
ssize_t check_request_surprise_unlikely() {
  auto info = ThreadInfo::s_threadInfo.getNoCheck();
  auto flags = info->m_reqInjectionData.getConditionFlags()->load();

  if (UNLIKELY(flags)) {
    check_request_surprise(info);
  }
  return flags;
}
Пример #4
0
// Child is the AFWH we're going to block on, nullptr iff this is a suspending
// generator.
void EventHook::onFunctionSuspendR(ActRec* suspending, ObjectData* child) {
  auto const flags = check_request_surprise();
  onFunctionExit(suspending, nullptr, false, nullptr, flags);

  if ((flags & AsyncEventHookFlag) &&
      suspending->func()->isAsyncFunction()) {
    assert(child != nullptr);  // This isn't a generator
    assert(child->instanceof(c_WaitableWaitHandle::classof()));
    assert(suspending->resumed());
    auto const afwh = frame_afwh(suspending);
    auto const session = AsioSession::Get();
    if (session->hasOnResumableAwait()) {
      session->onResumableAwait(
        afwh,
        static_cast<c_WaitableWaitHandle*>(child)
      );
    }
  }
}
Пример #5
0
void EventHook::onFunctionResumeYield(const ActRec* ar) {
  auto const flags = check_request_surprise();

  // Xenon
  if (flags & XenonSignalFlag) {
    Xenon::getInstance().log(Xenon::EnterSample);
  }

  // Memory Threhsold
  if (flags & MemThresholdFlag) {
    DoMemoryThresholdCallback();
  }

  if (flags & IntervalTimerFlag) {
    IntervalTimer::RunCallbacks(IntervalTimer::EnterSample);
  }

  onFunctionEnter(ar, EventHook::NormalFunc, flags);
}
Пример #6
0
void EventHook::onFunctionSuspendE(ActRec* suspending,
                                   const ActRec* resumableAR) {
  // When we're suspending an eagerly executing resumable, we've already
  // teleported the ActRec from suspending over to resumableAR, so we need to
  // make sure the unwinder knows not to touch the locals, $this, or
  // VarEnv/ExtraArgs.
  suspending->setThisOrClassAllowNull(nullptr);
  suspending->setLocalsDecRefd();
  suspending->setVarEnv(nullptr);

  try {
    auto const flags = check_request_surprise();
    onFunctionExit(resumableAR, nullptr, false, nullptr, flags);

    if ((flags & AsyncEventHookFlag) &&
        resumableAR->func()->isAsyncFunction()) {
      assert(resumableAR->resumed());
      auto const afwh = frame_afwh(resumableAR);
      auto const session = AsioSession::Get();
      if (session->hasOnResumableCreate()) {
        session->onResumableCreate(afwh, afwh->getChild());
      }
    }
  } catch (...) {
    auto const resumableObj = [&]() -> ObjectData* {
      if (resumableAR->func()->isAsyncFunction()) {
        return frame_afwh(resumableAR);
      }
      assert(resumableAR->func()->isGenerator());
      return !resumableAR->func()->isAsync()
        ? frame_generator(resumableAR)->toObject()
        : frame_async_generator(resumableAR)->toObject();
    }();
    decRefObj(resumableObj);
    throw;
  }
}
Пример #7
0
bool EventHook::onFunctionCall(const ActRec* ar, int funcType) {
  auto const flags = check_request_surprise();
  if (flags & InterceptFlag &&
      !RunInterceptHandler(const_cast<ActRec*>(ar))) {
    return false;
  }

  // Xenon
  if (flags & XenonSignalFlag) {
    Xenon::getInstance().log(Xenon::EnterSample);
  }

  // Memory Threhsold
  if (flags & MemThresholdFlag) {
    DoMemoryThresholdCallback();
  }

  if (flags & IntervalTimerFlag) {
    IntervalTimer::RunCallbacks(IntervalTimer::EnterSample);
  }

  onFunctionEnter(ar, funcType, flags);
  return true;
}
Пример #8
0
ssize_t EventHook::CheckSurprise() {
  ThreadInfo* info = ThreadInfo::s_threadInfo.getNoCheck();
  return check_request_surprise(info);
}
Пример #9
0
void check_request_surprise_unlikely() {
  if (UNLIKELY(checkSurpriseFlags())) check_request_surprise();
}
Пример #10
0
ssize_t EventHook::CheckSurprise() {
  return check_request_surprise();
}