Esempio n. 1
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;
  }
}
Esempio n. 2
0
void EventHook::onFunctionEnter(const ActRec* ar, int funcType) {
  CheckSurprise();
  RunUserProfiler(ar, ProfileEnter);
#ifdef HOTPROFILER
  Profiler* profiler = ThreadInfo::s_threadInfo->m_profiler;
  if (profiler != nullptr) {
    const char* name;
    switch (funcType) {
      case NormalFunc:
        name = ar->m_func->fullName()->data();
        if (name[0] == '\0') {
          // We're evaling some code for internal purposes, most
          // likely getting the default value for a function parameter
          name = "{internal}";
        }
        break;
      case PseudoMain:
        name = StringData::GetStaticString(
          std::string("run_init::") + ar->m_func->unit()->filepath()->data())
          ->data();
        break;
      case Eval:
        name = "_";
        break;
      default:
        not_reached();
    }
    begin_profiler_frame(profiler, name);
  }
#endif
}
Esempio n. 3
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));
    }
  }
}
Esempio n. 4
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;
  }
}
Esempio n. 5
0
bool EventHook::onFunctionCall(const ActRec* ar, int funcType) {
  ssize_t flags = CheckSurprise();
  if (flags & RequestInjectionData::InterceptFlag &&
      !RunInterceptHandler(const_cast<ActRec*>(ar))) {
    return false;
  }
  onFunctionEnter(ar, funcType, flags);
  return true;
}
Esempio n. 6
0
void EventHook::onFunctionResumeYield(const ActRec* ar) {
  ssize_t flags = CheckSurprise();

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

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

  onFunctionEnter(ar, EventHook::NormalFunc, flags);
}
Esempio n. 7
0
bool EventHook::onFunctionEnter(const ActRec* ar, int funcType) {
  ssize_t flags = CheckSurprise();
  if (flags & RequestInjectionData::InterceptFlag &&
      !RunInterceptHandler(const_cast<ActRec*>(ar))) {
    return false;
  }
  if (flags & RequestInjectionData::EventHookFlag) {
    RunUserProfiler(ar, ProfileEnter);
#ifdef HOTPROFILER
    Profiler* profiler = ThreadInfo::s_threadInfo->m_profiler;
    if (profiler != nullptr) {
      begin_profiler_frame(profiler, GetFunctionNameForProfiler(ar, funcType));
    }
#endif
  }
  return true;
}
Esempio n. 8
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)
      );
    }
  }
}
Esempio n. 9
0
bool EventHook::onFunctionCall(const ActRec* ar, int funcType) {
  ssize_t flags = CheckSurprise();
  if (flags & InterceptFlag &&
      !RunInterceptHandler(const_cast<ActRec*>(ar))) {
    return false;
  }

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

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

  onFunctionEnter(ar, funcType, flags);
  return true;
}
Esempio n. 10
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());
    }
  }
}
Esempio n. 11
0
bool EventHook::onFunctionEnter(const ActRec* ar, int funcType) {
  ssize_t flags = CheckSurprise();
  if (flags & RequestInjectionData::InterceptFlag &&
      !RunInterceptHandler(const_cast<ActRec*>(ar))) {
    return false;
  }
  if (flags & RequestInjectionData::EventHookFlag) {
    RunUserProfiler(ar, ProfileEnter);
#ifdef HOTPROFILER
    Profiler* profiler = ThreadInfo::s_threadInfo->m_profiler;
    if (profiler != nullptr) {
      const char* name;
      switch (funcType) {
        case NormalFunc:
          name = ar->m_func->fullName()->data();
          if (name[0] == '\0') {
            // We're evaling some code for internal purposes, most
            // likely getting the default value for a function parameter
            name = "{internal}";
          }
          break;
        case PseudoMain:
          name = StringData::GetStaticString(
            std::string("run_init::") + ar->m_func->unit()->filepath()->data())
            ->data();
          break;
        case Eval:
          name = "_";
          break;
        default:
          not_reached();
      }
      begin_profiler_frame(profiler, name);
    }
#endif
  }
  return true;
}
Esempio n. 12
0
void EventHook::onFunctionResume(const ActRec* ar) {
  ssize_t flags = CheckSurprise();
  onFunctionEnter(ar, EventHook::NormalFunc, flags);
}