Exemple #1
0
void EventHook::onFunctionReturn(ActRec* ar, const TypedValue& retval) {
  // Null out $this for the exiting function, it has been decref'd so it's
  // garbage.
  ar->setThisOrClassAllowNull(nullptr);

  // The locals are already gone. Mark them as decref'd so that if this hook
  // fails and unwinder kicks in, it won't try to decref them again.
  ar->setLocalsDecRefd();

  // TODO(#5758054): does this need setVarEnv(nullptr) ?

  ssize_t flags = CheckSurprise();
  onFunctionExit(ar, &retval, nullptr, flags);

  // Async profiler
  if ((flags & RequestInjectionData::AsyncEventHookFlag) &&
      ar->func()->isAsyncFunction() && ar->resumed()) {
    auto session = AsioSession::Get();
    // Return @ resumed execution => AsyncFunctionWaitHandle succeeded.
    if (session->hasOnResumableSuccessCallback()) {
      auto afwh = frame_afwh(ar);
      session->onResumableSuccess(afwh, cellAsCVarRef(retval));
    }
  }
}
Exemple #2
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 {
    ssize_t flags = CheckSurprise();
    onFunctionExit(resumableAR, nullptr, nullptr, flags);

    if ((flags & RequestInjectionData::AsyncEventHookFlag) &&
        resumableAR->func()->isAsyncFunction()) {
      assert(resumableAR->resumed());
      auto const afwh = frame_afwh(resumableAR);
      auto const session = AsioSession::Get();
      if (session->hasOnResumableCreateCallback()) {
        session->onResumableCreate(afwh, afwh->getChild());
      }
    }
  } catch (...) {
    auto const resumableObj = [&]() -> ObjectData* {
      if (resumableAR->func()->isAsyncFunction()) {
        return frame_afwh(resumableAR);
      }
      assert(resumableAR->func()->isGenerator());
      return frame_base_generator(resumableAR);
    }();
    decRefObj(resumableObj);
    throw;
  }
}
Exemple #3
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 {
    ssize_t flags = CheckSurprise();
    onFunctionExit(ar, &retval, nullptr, flags);

    // Async profiler
    if ((flags & AsyncEventHookFlag) &&
        ar->func()->isAsyncFunction() && ar->resumed()) {
      auto session = AsioSession::Get();
      // Return @ resumed execution => AsyncFunctionWaitHandle succeeded.
      if (session->hasOnResumableSuccessCallback()) {
        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;
  }
}
Exemple #4
0
void EventHook::onFunctionUnwind(ActRec* ar, const Fault& fault) {
  // The locals are already gone. Null out everything.
  ar->setThisOrClassAllowNull(nullptr);
  ar->setLocalsDecRefd();
  ar->setVarEnv(nullptr);

  // TODO(#2329497) can't CheckSurprise() yet, unwinder unable to replace fault
  auto const flags = GetSurpriseFlags();
  onFunctionExit(ar, nullptr, &fault, flags);
}
Exemple #5
0
void EventHook::onFunctionUnwind(ActRec* ar, ObjectData* phpException) {
  // The locals are already gone. Null out everything.
  ar->setThisOrClassAllowNull(nullptr);
  ar->setLocalsDecRefd();
  ar->setVarEnv(nullptr);

  // TODO(#2329497) can't check_request_surprise() yet, unwinder unable to
  // replace fault
  auto const flags = stackLimitAndSurprise().load() & kSurpriseFlagMask;
  onFunctionExit(ar, nullptr, true, phpException, flags);
}
Exemple #6
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) {
  ssize_t flags = CheckSurprise();
  onFunctionExit(suspending, nullptr, nullptr, flags);

  if ((flags & RequestInjectionData::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->hasOnResumableAwaitCallback()) {
      session->onResumableAwait(
        afwh,
        static_cast<c_WaitableWaitHandle*>(child)
      );
    }
  }
}
Exemple #7
0
void EventHook::onFunctionSuspend(const ActRec* ar, bool suspendingResumed) {
  ssize_t flags = CheckSurprise();
  onFunctionExit(ar, nullptr, nullptr, flags);

  // Async profiler
  if ((flags & RequestInjectionData::AsyncEventHookFlag) &&
      ar->func()->isAsyncFunction()) {
    assert(ar->resumed());
    auto afwh = frame_afwh(ar);
    auto session = AsioSession::Get();
    // Blocking await @ eager execution => AsyncFunctionWaitHandle created.
    if (!suspendingResumed && session->hasOnAsyncFunctionCreateCallback()) {
      session->onAsyncFunctionCreate(afwh, afwh->getChild());
    }
    // Blocking await @ resumed execution => AsyncFunctionWaitHandle awaiting.
    if (suspendingResumed && session->hasOnAsyncFunctionAwaitCallback()) {
      session->onAsyncFunctionAwait(afwh, afwh->getChild());
    }
  }
}
Exemple #8
0
void EventHook::onFunctionUnwind(const ActRec* ar, const Fault& fault) {
  // TODO(#2329497) can't CheckSurprise() yet, unwinder unable to replace fault
  ssize_t flags = GetConditionFlags();
  onFunctionExit(ar, nullptr, &fault, flags);
}