Beispiel #1
0
static Variant reduce_func(CVarRef result, CVarRef operand, const void *data) {
  CallCtx* ctx = (CallCtx*)data;
  Variant ret;
  TypedValue args[2];
  tvDup(*result.asTypedValue(), args[0]);
  tvDup(*operand.asTypedValue(), args[1]);
  g_vmContext->invokeFuncFew(ret.asTypedValue(), *ctx, 2, args);
  return ret;
}
Beispiel #2
0
static void walk_func(VRefParam value, CVarRef key, CVarRef userdata,
                      const void *data) {
  CallCtx* ctx = (CallCtx*)data;
  Variant sink;
  TypedValue args[3];
  tvDup(*value->asTypedValue(), args[0]);
  tvDup(*key.asTypedValue(), args[1]);
  tvDup(*userdata.asTypedValue(), args[2]);
  g_vmContext->invokeFuncFew(sink.asTypedValue(), *ctx, 3, args);
}
Beispiel #3
0
int init_closure(ActRec* ar, TypedValue* sp) {
  c_Closure* closure = static_cast<c_Closure*>(ar->getThis());

  // Swap in the $this or late bound class or null if it is ony from a plain
  // function or pseudomain
  ar->setThisOrClassAllowNull(closure->getThisOrClass());

  if (ar->hasThis()) {
    ar->getThis()->incRefCount();
  }

  // Put in the correct context
  ar->m_func = closure->getInvokeFunc();

  // The closure is the first local.
  // Similar to tvWriteObject() but we don't incref because it used to be $this
  // and now it is a local, so they cancel out
  TypedValue* firstLocal = --sp;
  firstLocal->m_type = KindOfObject;
  firstLocal->m_data.pobj = closure;

  // Copy in all the use vars
  TypedValue* prop = closure->getUseVars();
  int n = closure->getNumUseVars();
  for (int i=0; i < n; i++) {
    tvDup(*prop++, *--sp);
  }

  return n + 1;
}
Beispiel #4
0
static bool filter_func(CVarRef value, const void *data) {
  CallCtx* ctx = (CallCtx*)data;
  Variant ret;
  TypedValue args[1];
  tvDup(*value.asTypedValue(), args[0]);
  g_vmContext->invokeFuncFew((TypedValue*)&ret, *ctx, 1, args);
  return ret.toBoolean();
}
Beispiel #5
0
bool EventHook::RunInterceptHandler(ActRec* ar) {
  const Func* func = ar->m_func;
  if (LIKELY(func->maybeIntercepted() == 0)) return true;

  Variant *h = get_intercept_handler(func->fullNameRef(),
                                     &func->maybeIntercepted());
  if (!h) return true;

  Transl::VMRegAnchor _;

  PC savePc = g_vmContext->m_pc;

  Variant doneFlag = true;
  Variant called_on;

  if (ar->hasThis()) {
    called_on = Variant(ar->getThis());
  } else if (ar->hasClass()) {
    // For static methods, give handler the name of called class
    called_on = Variant(const_cast<StringData*>(ar->getClass()->name()));
  }
  Array intArgs =
    CREATE_VECTOR5(ar->m_func->fullNameRef(),
                   called_on,
                   get_frame_args_with_ref(ar),
                   h->asCArrRef()[1],
                   ref(doneFlag));

  Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs);
  if (doneFlag.toBoolean()) {
    Offset pcOff;
    ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff);
    assert(outer);

    frame_free_locals_inl_no_hook<true>(ar, ar->m_func->numLocals());
    Stack& stack = g_vmContext->getStack();
    stack.top() = (Cell*)(ar + 1);
    tvDup(ret.asTypedValue(), stack.allocTV());

    g_vmContext->m_fp = outer;
    g_vmContext->m_pc = outer->m_func->unit()->at(pcOff);

    return false;
  }
  g_vmContext->m_fp = ar;
  g_vmContext->m_pc = savePc;

  return true;
}
Beispiel #6
0
bool EventHook::RunInterceptHandler(ActRec* ar) {
  const Func* func = ar->m_func;
  if (LIKELY(func->maybeIntercepted() == 0)) return true;

  Variant *h = get_intercept_handler(func->fullNameRef(),
                                     &func->maybeIntercepted());
  if (!h) return true;

  Transl::VMRegAnchor _;

  PC savePc = g_vmContext->m_pc;

  Offset pcOff;
  ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff);
  assert(outer);
  g_vmContext->m_fp = outer;
  g_vmContext->m_pc = outer->m_func->unit()->at(pcOff);

  try {
    Variant doneFlag = true;
    Variant obj = ar->hasThis() ?
      Variant(Object(ar->getThis())) : uninit_null();
    Array intArgs =
      CREATE_VECTOR5(ar->m_func->fullNameRef(),
                     obj,
                     get_frame_args_with_ref(ar),
                     h->asCArrRef()[1],
                     ref(doneFlag));

    Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs);
    if (doneFlag.toBoolean()) {
      frame_free_locals_inl_no_hook(ar, ar->m_func->numLocals());
      Stack& stack = g_vmContext->getStack();
      stack.top() = (Cell*)(ar + 1);
      tvDup(ret.asTypedValue(), stack.allocTV());
      return false;
    }
    g_vmContext->m_fp = ar;
    g_vmContext->m_pc = savePc;
  } catch (...) {
    g_vmContext->m_fp = ar;
    g_vmContext->m_pc = savePc;
    g_vmContext->m_stack.top() = Stack::frameStackBase(ar);
    throw;
  }

  return true;
}
Beispiel #7
0
ObjectData* c_Closure::clone() {
  auto const cls = getVMClass();
  auto ret = c_Closure::fromObject(closureInstanceCtorRepoAuth(cls));

  ret->hdr()->ctx = hdr()->ctx;
  if (auto t = getThis()) {
    t->incRefCount();
  }

  auto src  = getUseVars();
  auto dest = ret->getUseVars();
  auto const nProps = cls->numDeclProperties();
  auto const stop = src + nProps;
  for (; src != stop; ++src, ++dest) {
    tvDup(*src, *dest);
  }

  return ret;
}