コード例 #1
0
HOT_FUNC_VM
int64_t decodeCufIterHelper(Iter* it, TypedValue func) {
  DECLARE_FRAME_POINTER(framePtr);

  ObjectData* obj = nullptr;
  HPHP::Class* cls = nullptr;
  StringData* invName = nullptr;

  auto ar = (ActRec*)framePtr->m_savedRbp;
  if (LIKELY(ar->m_func->isBuiltin())) {
    ar = g_vmContext->getOuterVMFrame(ar);
  }
  const Func* f = vm_decode_function(tvAsVariant(&func),
                                     ar, false,
                                     obj, cls, invName,
                                     false);
  if (UNLIKELY(!f)) return false;
  CufIter &cit = it->cuf();
  cit.setFunc(f);
  if (obj) {
    cit.setCtx(obj);
    obj->incRefCount();
  } else {
    cit.setCtx(cls);
  }
  cit.setName(invName);
  return true;
}
コード例 #2
0
TCA fcallHelper(ActRec* ar) {
  try {
    TCA tca =
      Translator::Get()->funcPrologue((Func*)ar->m_func, ar->numArgs(), ar);
    if (tca) {
      return tca;
    }
    return callAndResume(ar);
  } catch (...) {
    /*
      The return address is set to __fcallHelperThunk,
      which has no unwind information. Its "logically"
      part of the tc, but the c++ unwinder wont know
      that. So point our return address at the called
      function's return address (which will be in the
      tc).
      Note that the registers really are clean - we
      just came from callAndResume which cleaned
      them for us - so we just have to tell the unwinder
      that.
    */
    DECLARE_FRAME_POINTER(framePtr);
    tl_regState = REGSTATE_CLEAN;
    framePtr->m_savedRip = ar->m_savedRip;
    throw;
  }
}
コード例 #3
0
ファイル: fixup.cpp プロジェクト: 191919/hhvm
void FixupMap::fixup(ExecutionContext* ec) const {
  if (RuntimeOption::EvalSimulateARM) {
    // Walking the C++ stack doesn't work in simulation mode. Fortunately, the
    // execution context has a stack of simulators, which we consult instead.
    fixupWorkSimulated(ec);
  } else {
    // Start looking for fixup entries at the current (C++) frame.  This
    // will walk the frames upward until we find a TC frame.
    DECLARE_FRAME_POINTER(framePtr);
    fixupWork(ec, framePtr);
  }
}
コード例 #4
0
ファイル: fixup.cpp プロジェクト: escherlat/hhvm
ActRec* callerFrameHelper() {
  DECLARE_FRAME_POINTER(frame);

  auto rbp = frame->m_sfp;
  while (true) {
    assertx(rbp && rbp != rbp->m_sfp && "Missing fixup for native call");
    if (isVMFrame(rbp)) {
      return rbp;
    }
    rbp = rbp->m_sfp;
  }
}
コード例 #5
0
void functionEnterHelper(const ActRec* ar) {
  DECLARE_FRAME_POINTER(framePtr);

  uint64_t savedRip = ar->m_savedRip;
  uint64_t savedRbp = ar->m_savedRbp;
  if (LIKELY(EventHook::onFunctionEnter(ar, EventHook::NormalFunc))) return;
  /* We need to skip the function.
     FunctionEnter already cleaned up ar, and pushed the return value,
     so all we need to do is return to where ar would have returned to,
     with rbp set to ar's outer frame.
  */
  framePtr->m_savedRip = savedRip;
  framePtr->m_savedRbp = savedRbp;
  sp = g_vmContext->m_stack.top();
}
コード例 #6
0
TCA fcallHelper(ActRec* ar, void* sp) {
  try {
    TCA tca =
      mcg->getFuncPrologue((Func*)ar->m_func, ar->numArgs(), ar);
    if (tca) {
      return tca;
    }
    if (!ar->m_func->isClonedClosure()) {
      /*
       * If the func is a cloned closure, then the original
       * closure has already run the prologue, and the prologues
       * array is just being used as entry points for the
       * dv funclets. Dont run the prologue again.
       */
      VMRegAnchor _(ar);
      uint64_t rip = ar->m_savedRip;
      if (g_context->doFCall(ar, g_context->m_pc)) {
        ar->m_savedRip = rip;
        return tx->uniqueStubs.resumeHelperRet;
      }
      // We've been asked to skip the function body
      // (fb_intercept). frame, stack and pc have
      // already been fixed - flag that with a negative
      // return address.
      return (TCA)-rip;
    }
    setupAfterPrologue(ar, sp);
    assert(ar == g_context->m_fp);
    return tx->uniqueStubs.resumeHelper;
  } catch (...) {
    /*
      The return address is set to __fcallHelperThunk,
      which has no unwind information. Its "logically"
      part of the tc, but the c++ unwinder wont know
      that. So point our return address at the called
      function's return address (which will be in the
      tc).
      Note that the registers really are clean - we
      cleaned them in the try above - so we just
      have to tell the unwinder that.
    */
    DECLARE_FRAME_POINTER(framePtr);
    tl_regState = VMRegState::CLEAN;
    framePtr->m_savedRip = ar->m_savedRip;
    throw;
  }
}
コード例 #7
0
ファイル: fixup.cpp プロジェクト: escherlat/hhvm
void syncVMRegsWork() {
  assertx(tl_regState != VMRegState::CLEAN);

  // Start looking for fixup entries at the current (C++) frame.  This
  // will walk the frames upward until we find a TC frame.

  // In order to avoid tail call elimination optimization issues, grab the
  // parent frame pointer in order make sure this pointer is valid. The
  // fixupWork() looks for a TC frame, and we never call fixup() directly
  // from the TC, so skipping this frame isn't a problem.
  DECLARE_FRAME_POINTER(framePtr);
  auto fp = tl_regState >= VMRegState::GUARDED_THRESHOLD ?
    (ActRec*)tl_regState : framePtr->m_sfp;

  FixupMap::fixupWork(g_context.getNoCheck(), fp);

  tl_regState = VMRegState::CLEAN;
  Stats::inc(Stats::TC_Sync);
}
コード例 #8
0
void TranslatorX64::fCallArrayHelper(const Offset pcOff, const Offset pcNext) {
  DECLARE_FRAME_POINTER(framePtr);
  ActRec* fp = (ActRec*)framePtr->m_savedRbp;

  VMExecutionContext *ec = g_vmContext;
  ec->m_fp = fp;
  ec->m_stack.top() = sp;
  ec->m_pc = curUnit()->at(pcOff);
  PC pc = curUnit()->at(pcNext);

  tl_regState = REGSTATE_CLEAN;
  bool runFunc = ec->doFCallArray(pc);
  sp = ec->m_stack.top();
  tl_regState = REGSTATE_DIRTY;
  if (!runFunc) return;

  ec->m_fp->m_savedRip = framePtr->m_savedRip;
  // smash our return and frame pointer chain
  framePtr->m_savedRip = (uint64_t)ec->m_fp->m_func->getFuncBody();
  framePtr->m_savedRbp = (uint64_t)ec->m_fp;
}