コード例 #1
0
ファイル: apc-object.cpp プロジェクト: smcshaner/hhvm
ALWAYS_INLINE
APCObject::~APCObject() {
  auto const numProps = m_propCount;

  if (m_persistent) {
    auto props = persistentProps();
    for (unsigned i = 0; i < numProps; ++i) {
      if (props[i]) props[i]->unreferenceRoot();
    }
    return;
  }

  for (auto i = uint32_t{0}; i < numProps; ++i) {
    if (props()[i].val) props()[i].val->unreferenceRoot();
    assert(props()[i].name->isStatic());
  }
}
コード例 #2
0
ファイル: apc-object.cpp プロジェクト: smcshaner/hhvm
Object APCObject::createObject() const {
  auto cls = m_cls.left();
  assert(cls != nullptr);

  auto obj = Object::attach(
    m_fast_init ? ObjectData::newInstanceNoPropInit(const_cast<Class*>(cls))
                : ObjectData::newInstance(const_cast<Class*>(cls))
  );

  auto const numProps = cls->numDeclProperties();
  auto const objProp = obj->propVec();
  auto const apcProp = persistentProps();

  if (m_fast_init) {
    // re-entry is possible while we're executing toLocal() on each
    // property, so heap inspectors may see partially initid objects
    // not yet exposed to PHP.
    unsigned i = 0;
    try {
      for (; i < numProps; ++i) {
        new (objProp + i) Variant(apcProp[i]->toLocal());
      }
    } catch (...) {
      for (; i < numProps; ++i) {
        new (objProp + i) Variant();
      }
      throw;
    }
  } else {
    for (unsigned i = 0; i < numProps; ++i) {
      tvAsVariant(&objProp[i]) = apcProp[i]->toLocal();
    }
  }

  if (UNLIKELY(numProps < m_propCount)) {
    auto dynProps = apcProp[numProps];
    assert(dynProps->kind() == APCKind::StaticArray ||
           dynProps->kind() == APCKind::UncountedArray ||
           dynProps->kind() == APCKind::SharedArray);
    obj->setDynPropArray(dynProps->toLocal().asCArrRef());
  }

  if (!m_no_wakeup) obj->invokeWakeup();
  return obj;
}
コード例 #3
0
ファイル: apc-object.cpp プロジェクト: AeroEng43/hhvm
Object APCObject::createObject() const {
  auto cls = m_cls.left();
  assert(cls != nullptr);

  auto obj = Object::attach(
    m_fast_init ? ObjectData::newInstanceNoPropInit(const_cast<Class*>(cls))
                : ObjectData::newInstance(const_cast<Class*>(cls))
  );

  auto const numProps = cls->numDeclProperties();
  auto const objProp = obj->propVec();
  auto const apcProp = persistentProps();

  if (m_fast_init) {
    unsigned i = 0;
    try {
      while (i < numProps) {
        new (objProp + i) Variant(apcProp[i]->toLocal());
        ++i;
      }
    } catch (...) {
      while (i < numProps) {
        new (objProp + i) Variant();
        ++i;
      }
      throw;
    }
  } else {
    for (unsigned i = 0; i < numProps; ++i) {
      tvAsVariant(&objProp[i]) = apcProp[i]->toLocal();
    }
  }

  if (UNLIKELY(numProps < m_propCount)) {
    auto dynProps = apcProp[numProps];
    assert(dynProps->kind() == APCKind::StaticArray ||
           dynProps->kind() == APCKind::UncountedArray ||
           dynProps->kind() == APCKind::SharedArray);
    obj->setDynPropArray(dynProps->toLocal().asCArrRef());
  }

  if (!m_no_wakeup) obj->invokeWakeup();
  return obj;
}
コード例 #4
0
ファイル: apc-object.cpp プロジェクト: smcshaner/hhvm
APCHandle::Pair APCObject::Construct(ObjectData* objectData) {
  // This function assumes the object and object/array down the tree have no
  // internal references and do not implement the serializable interface.
  assert(!objectData->instanceof(SystemLib::s_SerializableClass));

  auto cls = objectData->getVMClass();
  auto clsOrName = make_class(cls);
  if (clsOrName.right()) return ConstructSlow(objectData, clsOrName);

  // We have a persistent Class. Build an array of APCHandle* to mirror the
  // declared properties in the object.
  auto const propInfo = cls->declProperties();
  auto const hasDynProps = objectData->hasDynProps();
  auto const numRealProps = propInfo.size();
  auto const numApcProps = numRealProps + hasDynProps;
  auto size = sizeof(APCObject) + sizeof(APCHandle*) * numApcProps;
  auto const apcObj = new (malloc_huge(size)) APCObject(clsOrName, numApcProps);
  apcObj->m_persistent = 1;

  // Set a few more flags for faster fetching: whether or not the object has a
  // wakeup method, and whether or not we can use a fast path that avoids
  // default-initializing properties before setting them to their APC values.
  if (!cls->lookupMethod(s___wakeup.get())) apcObj->m_no_wakeup = 1;
  if (!cls->instanceCtor()) {
    apcObj->m_fast_init = 1;
  }

  auto const apcPropVec = apcObj->persistentProps();
  auto const objPropVec = objectData->propVec();
  const TypedValueAux* propInit = nullptr;

  for (unsigned i = 0; i < numRealProps; ++i) {
    auto const attrs = propInfo[i].attrs;
    assert((attrs & AttrStatic) == 0);

    const TypedValue* objProp;
    if (attrs & AttrBuiltin) {
      // Special properties like the Memoize cache should be set to their
      // default value, not the current value.
      if (propInit == nullptr) {
        propInit = cls->pinitVec().empty() ? &cls->declPropInit()[0]
                                           : &(*cls->getPropData())[0];
      }

      objProp = propInit + i;
    } else {
      objProp = objPropVec + i;
    }

    auto val = APCHandle::Create(tvAsCVarRef(objProp), false,
                                 APCHandleLevel::Inner, true);
    size += val.size;
    apcPropVec[i] = val.handle;
  }

  if (UNLIKELY(hasDynProps)) {
    auto val = APCHandle::Create(objectData->dynPropArray(), false,
                                 APCHandleLevel::Inner, true);
    size += val.size;
    apcPropVec[numRealProps] = val.handle;
  }

  return {apcObj->getHandle(), size};
}