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;
}
Exemple #2
0
/*
 * Helper method from converting between a PHP function and a CufIter.
 */
static bool vm_decode_function_cufiter(const Variant& function,
                                       SmartCufIterPtr& cufIter) {
  ObjectData* obj = nullptr;
  HPHP::Class* cls = nullptr;
  HPHP::JIT::CallerFrame cf;
  StringData* invName = nullptr;
  // Don't warn here, let the caller decide what to do if the func is nullptr.
  const HPHP::Func* func = vm_decode_function(function, cf(), false,
                                              obj, cls, invName, false);
  if (func == nullptr) {
    return false;
  }

  cufIter = smart::make_unique<CufIter>();
  cufIter->setFunc(func);
  cufIter->setName(invName);
  if (obj) {
    cufIter->setCtx(obj);
    obj->incRefCount();
  } else {
    cufIter->setCtx(cls);
  }

  return true;
}
Exemple #3
0
Variant::Variant(const Object& v) {
  m_type = KindOfObject;
  ObjectData *o = v.get();
  if (o) {
    m_data.pobj = o;
    o->incRefCount();
  } else {
    m_type = KindOfNull;
  }
}
 Variant do_callback(CVarRef cb, CArrRef args) {
   ASSERT(!m_exception);
   try {
     return f_call_user_func_array(cb, args);
   } catch (Object &e) {
     ObjectData *od = e.get();
     od->incRefCount();
     m_exception = od;
     m_phpException = true;
   } catch (Exception &e) {
     m_exception = e.clone();
     m_phpException = false;
   }
   return null;
 }
    static ObjectData *
    create_object(const StaticString * className, Array params) {
        TypedValue ret;
        Class * cls = Unit::loadClass(className -> get());
        ObjectData * obj = ObjectData::newInstance(cls);
        obj->incRefCount();

        g_context->invokeFunc(
                &ret,
                cls->getCtor(),
                params,
                obj
                );
        return obj;
    }
Exemple #6
0
 Variant do_callback(CVarRef cb, CArrRef args) {
   assert(!m_exception);
   try {
     return vm_call_user_func(cb, args);
   } catch (Object &e) {
     ObjectData *od = e.get();
     od->incRefCount();
     m_exception = od;
     m_phpException = true;
   } catch (Exception &e) {
     m_exception = e.clone();
     m_phpException = false;
   }
   return uninit_null();
 }
Exemple #7
0
int hphp_ffi_exportVariant(CVarRef v, void** result) {
  switch (v.getType()) {
  case KindOfNull:    return 0;
  case KindOfBoolean: *result = (void*)v.toBoolean(); return 1;
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64: {
    *result = (void*)v.toInt64();
    return 2;
  }
  case KindOfDouble: {
    union {
      double d;
      void* p;
    } u;
    u.d = v.toDouble();
    *result = u.p;
    return 3;
  }
  case LiteralString: *result = (void*)v.getLiteralString(); return 4;
  case KindOfString: {
    StringData *sd = v.getStringData();
    sd->incRefCount();
    *result = (void*)sd;
    return 5;
  }
  case KindOfArray: {
    ArrayData *ad = v.getArrayData();
    ad->incRefCount();
    *result = (void*)ad;
    return 6;
  }
  case KindOfObject: {
    ObjectData *od = v.getObjectData();
    od->incRefCount();
    *result = (void*)od;
    return 7;
  }
  default:
    ASSERT(false);
    return 0;
  }
}
void loadArrayFunctionContext(ArrayData* arr, ActRec* preLiveAR, ActRec* fp) {
  ObjectData* inst = nullptr;
  HPHP::Class* cls = nullptr;
  StringData* invName = nullptr;

  try {

    // if size != 2, throws exception
    // if the first element of the array is a string classname, will autoload it
    const Func* func = vm_decode_function(
      Variant(arr),
      fp,
      /* forwarding */ false,
      inst,
      cls,
      invName,
      /* warn */ false
    );
    if (UNLIKELY(func == nullptr)) {
      raise_error("Invalid callable (array)");
    }
    assert(cls != nullptr); // array should resolve only to a method

    preLiveAR->m_func = func;
    if (inst) {
      inst->incRefCount();
      preLiveAR->setThis(inst);
    } else {
      preLiveAR->setClass(cls);
    }
    if (UNLIKELY(invName != nullptr)) {
      preLiveAR->setInvName(invName);
    }
  } catch (...) {
    // This is extreme shadiness. See the comments of
    // arPreliveOverwriteCells() for more info on how this code gets the
    // unwinder to restore the pre-FPush state.
    auto firstActRecCell = arPreliveOverwriteCells(preLiveAR);
    firstActRecCell->m_type = KindOfArray;
    firstActRecCell->m_data.parr = arr;
    throw;
  }
}
Exemple #9
0
ObjectData* newPairHelper() {
  ObjectData *obj = NEWOBJ(c_Pair)();
  obj->incRefCount();
  TRACE(2, "newPairHelper: capacity 2\n");
  return obj;
}
Exemple #10
0
Object c_Closure::t_bindto(const Variant& newthis, const Variant& scope) {
  if (RuntimeOption::RepoAuthoritative &&
      RuntimeOption::EvalAllowScopeBinding) {
    raise_warning("Closure binding is not supported in RepoAuthoritative mode");
    return Object{};
  }

  auto const cls = getVMClass();
  auto const invoke = cls->getCachedInvoke();

  ObjectData* od = nullptr;
  if (newthis.isObject()) {
    if (invoke->isStatic()) {
      raise_warning("Cannot bind an instance to a static closure");
    } else {
      od = newthis.getObjectData();
    }
  } else if (!newthis.isNull()) {
    raise_warning("Closure::bindto() expects parameter 1 to be object");
    return Object{};
  }

  auto const curscope = invoke->cls();
  auto newscope = curscope;

  if (scope.isObject()) {
    newscope = scope.getObjectData()->getVMClass();
  } else if (scope.isString()) {
    auto const className = scope.getStringData();

    if (!className->equal(s_static.get())) {
      newscope = Unit::loadClass(className);
      if (!newscope) {
        raise_warning("Class '%s' not found", className->data());
        return Object{};
      }
    }
  } else if (scope.isNull()) {
    newscope = nullptr;
  } else {
    raise_warning("Closure::bindto() expects parameter 2 "
                  "to be string or object");
    return Object{};
  }

  if (od && !newscope) {
    // Bound closures should be scoped.  If no scope is specified, scope it to
    // the Closure class.
    newscope = static_cast<Class*>(c_Closure::classof());
  }

  bool thisNotOfCtx = od && !od->getVMClass()->classof(newscope);

  if (!RuntimeOption::EvalAllowScopeBinding) {
    if (newscope != curscope) {
      raise_warning("Re-binding closure scopes is disabled");
      return Object{};
    }

    if (thisNotOfCtx) {
      raise_warning("Binding to objects not subclassed from closure "
                    "context is disabled");
      return Object{};
    }
  }

  c_Closure* clone = Clone(this);
  clone->setClass(nullptr);

  Attr curattrs = invoke->attrs();
  Attr newattrs = static_cast<Attr>(curattrs & ~AttrHasForeignThis);

  if (od) {
    od->incRefCount();
    clone->setThis(od);

    if (thisNotOfCtx) {
      // If the bound $this is not a subclass of the context class, then we
      // have to pessimize translation.
      newattrs |= AttrHasForeignThis;
    }
  } else if (newscope) {
    // If we attach a scope to a function with no bound $this we need to make
    // the function static.
    newattrs |= AttrStatic;
    clone->setClass(newscope);
  }

  // If we are changing either the scope or the attributes of the closure, we
  // need to re-scope its Closure subclass.
  if (newscope != curscope || newattrs != curattrs) {
    assert(newattrs != AttrNone);

    auto newcls = cls->rescope(newscope, newattrs);
    clone->setVMClass(newcls);
  }

  return Object(clone);
}
ObjectData* newColHelper(uint32_t type, uint32_t size) {
  ObjectData* obj = newCollectionHelper(type, size);
  obj->incRefCount();
  return obj;
}