Beispiel #1
0
NativeDataInfo* getNativeDataInfo(const StringData* name) {
  auto it = s_nativedatainfo.find(name);
  if (it == s_nativedatainfo.end()) {
    return nullptr;
  }
  return &it->second;
}
Beispiel #2
0
void registerNativeDataInfo(const StringData* name,
                            size_t sz,
                            NativeDataInfo::InitFunc init,
                            NativeDataInfo::CopyFunc copy,
                            NativeDataInfo::DestroyFunc destroy,
                            NativeDataInfo::SweepFunc sweep,
                            NativeDataInfo::SleepFunc sleep,
                            NativeDataInfo::WakeupFunc wakeup,
                            NativeDataInfo::ScanFunc scan) {
  assert(s_nativedatainfo.find(name) == s_nativedatainfo.end());
  assert((sleep == nullptr && wakeup == nullptr) ||
         (sleep != nullptr && wakeup != nullptr));
  assert(scan);
  NativeDataInfo info;
  info.sz = sz;
  info.odattrs = ObjectData::Attribute::HasNativeData;
  info.init = init;
  info.copy = copy;
  info.destroy = destroy;
  info.sweep = sweep;
  info.sleep = sleep;
  info.wakeup = wakeup;
  info.scan = scan;
  s_nativedatainfo[name] = info;
}
Beispiel #3
0
void registerNativeDataInfo(const StringData* name,
                            size_t sz,
                            NativeDataInfo::InitFunc init,
                            NativeDataInfo::CopyFunc copy,
                            NativeDataInfo::DestroyFunc destroy,
                            NativeDataInfo::SweepFunc sweep) {
  assert(s_nativedatainfo.find(name) == s_nativedatainfo.end());
  NativeDataInfo info;
  info.sz = sz;
  info.odattrs = ObjectData::Attribute::HasNativeData;
  info.init = init;
  info.copy = copy;
  info.destroy = destroy;
  info.sweep = sweep;
  s_nativedatainfo[name] = info;
}
Beispiel #4
0
namespace HPHP { namespace Native {
//////////////////////////////////////////////////////////////////////////////

typedef std::unordered_map<const StringData*,NativeDataInfo> NativeDataInfoMap;
static NativeDataInfoMap s_nativedatainfo;

size_t ndsize(const ObjectData* obj, const NativeDataInfo* ndi) {
  auto cls = obj->getVMClass();
  if (cls == Generator::getClass()) {
    return Native::data<Generator>(obj)->resumable()->size() -
           sizeof(ObjectData);
  }
  if (cls == AsyncGenerator::getClass()) {
    return Native::data<AsyncGenerator>(obj)->resumable()->size() -
           sizeof(ObjectData);
  }
  return ndsize(ndi->sz);
}

void registerNativeDataInfo(const StringData* name,
                            size_t sz,
                            NativeDataInfo::InitFunc init,
                            NativeDataInfo::CopyFunc copy,
                            NativeDataInfo::DestroyFunc destroy,
                            NativeDataInfo::SweepFunc sweep,
                            NativeDataInfo::SleepFunc sleep,
                            NativeDataInfo::WakeupFunc wakeup,
                            NativeDataInfo::ScanFunc scan) {
  assert(s_nativedatainfo.find(name) == s_nativedatainfo.end());
  assert((sleep == nullptr && wakeup == nullptr) ||
         (sleep != nullptr && wakeup != nullptr));
  assert(scan);
  NativeDataInfo info;
  info.sz = sz;
  info.odattrs = ObjectData::Attribute::HasNativeData;
  info.init = init;
  info.copy = copy;
  info.destroy = destroy;
  info.sweep = sweep;
  info.sleep = sleep;
  info.wakeup = wakeup;
  info.scan = scan;
  s_nativedatainfo[name] = info;
}

NativeDataInfo* getNativeDataInfo(const StringData* name) {
  auto it = s_nativedatainfo.find(name);
  if (it == s_nativedatainfo.end()) {
    return nullptr;
  }
  return &it->second;
}

/* Classes with NativeData structs allocate extra memory prior
 * to the ObjectData.
 *
 * [NativeNode][padding][NativeData][ObjectData](prop0)...(propN)
 *                                 /\
 *                             ObjectData* points here
 *
 * padding is added by alignTypedValue(sizeof(NativeData)) to ensure
 * that ObjectData* falls on a 16-aligned boundary. NativeData is
 * sizeof(NativeData) (NativeDataInfo.sz) bytes for the custom struct.
 * NativeNode is a link in the NativeData sweep list for this ND block
 */
ObjectData* nativeDataInstanceCtor(Class* cls) {
  HPHP::Attr attrs = cls->attrs();
  if (UNLIKELY(attrs &
               (AttrAbstract | AttrInterface | AttrTrait | AttrEnum))) {
    ObjectData::raiseAbstractClassError(cls);
  }
  auto ndi = cls->getNativeDataInfo();
  size_t nativeDataSize = ndsize(ndi->sz);
  size_t nProps = cls->numDeclProperties();
  size_t size = ObjectData::sizeForNProps(nProps) + nativeDataSize;

  auto node = reinterpret_cast<NativeNode*>(
    MM().objMalloc(size)
  );
  node->obj_offset = nativeDataSize;
  node->hdr.kind = HeaderKind::NativeData;
  auto obj = new (reinterpret_cast<char*>(node) + nativeDataSize)
             ObjectData(cls);
  assert(obj->hasExactlyOneRef());
  obj->setAttribute(static_cast<ObjectData::Attribute>(ndi->odattrs));
  if (ndi->init) {
    ndi->init(obj);
  }
  if (ndi->sweep) {
    MM().addNativeObject(node);
  }
  if (UNLIKELY(cls->needsInitThrowable())) {
    obj->callCustomInstanceInit();
  }
  return obj;
}

void nativeDataInstanceCopy(ObjectData* dest, ObjectData *src) {
  auto ndi = dest->getVMClass()->getNativeDataInfo();
  if (!ndi) return;
  assert(ndi == src->getVMClass()->getNativeDataInfo());
  if (!ndi->copy) {
    throw_not_implemented("NativeDataInfoCopy");
  }
  ndi->copy(dest, src);
  // Already in the sweep list from init call, no need to add again
}

void nativeDataInstanceDtor(ObjectData* obj, const Class* cls) {
  assert(!cls->preClass()->builtinObjSize());
  assert(!cls->preClass()->builtinODOffset());
  obj->~ObjectData();

  auto const nProps = size_t{cls->numDeclProperties()};
  auto prop = reinterpret_cast<TypedValue*>(obj + 1);
  auto const stop = prop + nProps;
  for (; prop != stop; ++prop) {
    tvRefcountedDecRef(prop);
  }

  auto ndi = cls->getNativeDataInfo();
  if (ndi->destroy) {
    ndi->destroy(obj);
  }
  auto node = getNativeNode(obj, ndi);
  if (ndi->sweep) {
    MM().removeNativeObject(node);
  }

  size_t size = ObjectData::sizeForNProps(nProps) + ndsize(obj, ndi);
  if (LIKELY(size <= kMaxSmallSize)) {
    return MM().freeSmallSize(node, size);
  }
  MM().freeBigSize(node, size);
}

Variant nativeDataSleep(const ObjectData* obj) {
  auto ndi = obj->getVMClass()->getNativeDataInfo();
  assert(ndi);
  assert(ndi->sleep);
  return ndi->sleep(obj);
}

void nativeDataWakeup(ObjectData* obj, const Variant& data) {
  auto ndi = obj->getVMClass()->getNativeDataInfo();
  assert(ndi);
  assert(ndi->wakeup);
  ndi->wakeup(obj, data);
}

//////////////////////////////////////////////////////////////////////////////
}} // namespace HPHP::Native
Beispiel #5
0
namespace HPHP { namespace Native {
//////////////////////////////////////////////////////////////////////////////

typedef std::unordered_map<const StringData*,NativeDataInfo> NativeDataInfoMap;
static NativeDataInfoMap s_nativedatainfo;

void registerNativeDataInfo(const StringData* name,
                            size_t sz,
                            NativeDataInfo::InitFunc init,
                            NativeDataInfo::CopyFunc copy,
                            NativeDataInfo::DestroyFunc destroy,
                            NativeDataInfo::SweepFunc sweep,
                            NativeDataInfo::SleepFunc sleep,
                            NativeDataInfo::WakeupFunc wakeup) {
  assert(s_nativedatainfo.find(name) == s_nativedatainfo.end());
  assert((sleep == nullptr && wakeup == nullptr) ||
         (sleep != nullptr && wakeup != nullptr));
  NativeDataInfo info;
  info.sz = sz;
  info.odattrs = ObjectData::Attribute::HasNativeData;
  info.init = init;
  info.copy = copy;
  info.destroy = destroy;
  info.sweep = sweep;
  info.sleep = sleep;
  info.wakeup = wakeup;
  s_nativedatainfo[name] = info;
}

NativeDataInfo* getNativeDataInfo(const StringData* name) {
  auto it = s_nativedatainfo.find(name);
  if (it == s_nativedatainfo.end()) {
    return nullptr;
  }
  return &it->second;
}

// return the full native header size, which is also the distance from
// the allocated pointer to the ObjectData*.
inline size_t ndsize(const NativeDataInfo* ndi) {
  return alignTypedValue(ndi->sz + sizeof(NativeNode));
}

inline NativeNode* getSweepNode(ObjectData *obj, const NativeDataInfo* ndi) {
  return reinterpret_cast<NativeNode*>(
    reinterpret_cast<char*>(obj) - ndsize(ndi)
  );
}

DEBUG_ONLY
static bool invalidateNativeData(ObjectData* obj, const NativeDataInfo* ndi) {
  memset(getSweepNode(obj, ndi), kSmartFreeFill, ndsize(ndi));
  return true;
}

void sweepNativeData(std::vector<NativeNode*>& natives) {
  while (!natives.empty()) {
    assert(natives.back()->sweep_index == natives.size() - 1);
    auto node = natives.back();
    natives.pop_back();
    auto obj = Native::obj(node);
    auto ndi = obj->getVMClass()->getNativeDataInfo();
    assert(ndi->sweep);
    assert(node->obj_offset == ndsize(ndi));
    ndi->sweep(obj);
    assert(invalidateNativeData(obj, ndi));
  }
}

/* Classes with NativeData structs allocate extra memory prior
 * to the ObjectData.
 *
 * [NativeNode][padding][NativeData][ObjectData](prop0)...(propN)
 *                                 /\
 *                             ObjectData* points here
 *
 * padding is added by alignTypedValue(sizeof(NativeData)) to ensure
 * that ObjectData* falls on a 16-aligned boundary. NativeData is
 * sizeof(NativeData) (NativeDataInfo.sz) bytes for the custom struct.
 * NativeNode is a link in the NativeData sweep list for this ND block
 */
ObjectData* nativeDataInstanceCtor(Class* cls) {
  Attr attrs = cls->attrs();
  if (UNLIKELY(attrs &
               (AttrAbstract | AttrInterface | AttrTrait | AttrEnum))) {
    ObjectData::raiseAbstractClassError(cls);
  }
  auto ndi = cls->getNativeDataInfo();
  size_t nativeDataSize = ndsize(ndi);
  size_t nProps = cls->numDeclProperties();
  size_t size = ObjectData::sizeForNProps(nProps) + nativeDataSize;

  auto node = reinterpret_cast<NativeNode*>(
    MM().objMallocLogged(size)
  );
  node->obj_offset = nativeDataSize;
  node->kind = HeaderKind::Native;
  auto obj = new (reinterpret_cast<char*>(node) + nativeDataSize)
             ObjectData(cls);
  obj->setAttribute(static_cast<ObjectData::Attribute>(ndi->odattrs));
  if (ndi->init) {
    ndi->init(obj);
  }
  if (ndi->sweep) {
    MM().addNativeObject(node);
  }
  if (UNLIKELY(cls->callsCustomInstanceInit())) {
    obj->callCustomInstanceInit();
  }
  return obj;
}

void nativeDataInstanceCopy(ObjectData* dest, ObjectData *src) {
  auto ndi = dest->getVMClass()->getNativeDataInfo();
  if (!ndi) return;
  assert(ndi == src->getVMClass()->getNativeDataInfo());
  if (!ndi->copy) {
    throw_not_implemented("NativeDataInfoCopy");
  }
  ndi->copy(dest, src);
  // Already in the sweep list from init call, no need to add again
}

void nativeDataInstanceDtor(ObjectData* obj, const Class* cls) {
  assert(!cls->preClass()->builtinObjSize());
  assert(!cls->preClass()->builtinODOffset());
  obj->~ObjectData();

  auto const nProps = size_t{cls->numDeclProperties()};
  auto prop = reinterpret_cast<TypedValue*>(obj + 1);
  auto const stop = prop + nProps;
  for (; prop != stop; ++prop) {
    tvRefcountedDecRef(prop);
  }

  auto ndi = cls->getNativeDataInfo();
  if (ndi->destroy) {
    ndi->destroy(obj);
  }
  auto node = getSweepNode(obj, ndi);
  if (ndi->sweep) {
    MM().removeNativeObject(node);
  }

  size_t size = ObjectData::sizeForNProps(nProps) + ndsize(ndi);
  if (LIKELY(size <= kMaxSmartSize)) {
    return MM().smartFreeSizeLogged(node, size);
  }
  MM().smartFreeSizeBigLogged(node, size);
}

Variant nativeDataSleep(const ObjectData* obj) {
  auto ndi = obj->getVMClass()->getNativeDataInfo();
  assert(ndi);
  assert(ndi->sleep);
  return ndi->sleep(obj);
}

void nativeDataWakeup(ObjectData* obj, const Variant& data) {
  auto ndi = obj->getVMClass()->getNativeDataInfo();
  assert(ndi);
  assert(ndi->wakeup);
  ndi->wakeup(obj, data);
}

//////////////////////////////////////////////////////////////////////////////
}} // namespace HPHP::Native
Beispiel #6
0
namespace HPHP { namespace Native {
//////////////////////////////////////////////////////////////////////////////

typedef std::unordered_map<const StringData*,NativeDataInfo> NativeDataInfoMap;
static NativeDataInfoMap s_nativedatainfo;

void registerNativeDataInfo(const StringData* name,
                            size_t sz,
                            NativeDataInfo::InitFunc init,
                            NativeDataInfo::CopyFunc copy,
                            NativeDataInfo::DestroyFunc destroy,
                            NativeDataInfo::SweepFunc sweep) {
  assert(s_nativedatainfo.find(name) == s_nativedatainfo.end());
  NativeDataInfo info;
  info.sz = sz;
  info.odattrs = ObjectData::Attribute::HasNativeData;
  info.init = init;
  info.copy = copy;
  info.destroy = destroy;
  info.sweep = sweep;
  s_nativedatainfo[name] = info;
}

NativeDataInfo* getNativeDataInfo(const StringData* name) {
  auto it = s_nativedatainfo.find(name);
  if (it == s_nativedatainfo.end()) {
    return nullptr;
  }
  return &it->second;
}

static __thread SweepNode* s_sweep = nullptr;

DEBUG_ONLY
static bool nodeInSweepList(SweepNode *check) {
  for (auto node = s_sweep; node; node = node->next) {
    if (node == check) return true;
  }
  return false;
}

static void prependSweepNode(SweepNode *node) {
  assert(!nodeInSweepList(node));
  if (s_sweep) {
    s_sweep->prev = node;
  }
  node->next = s_sweep;
  node->prev = nullptr;
  s_sweep = node;
}

static void removeSweepNode(SweepNode *node) {
  if (node->prev) {
    node->prev->next = node->next;
  }
  if (node->next) {
    node->next->prev = node->prev;
  }
  if (s_sweep == node) {
    s_sweep = node->next;
  }
}

inline SweepNode* getSweepNode(ObjectData *obj) {
  return reinterpret_cast<SweepNode*>(obj) - 1;
}

DEBUG_ONLY
static bool invalidateNativeData(ObjectData* obj, const NativeDataInfo* ndi) {
  const size_t size = ndi->sz + sizeof(SweepNode);
  void *ptr = reinterpret_cast<char*>(obj) - size;
  memset(ptr, kSmartFreeFill, size);
  return true;
}

void sweepNativeData() {
  for (auto node = s_sweep; node;) {
    auto obj = reinterpret_cast<ObjectData*>(node + 1);
    auto ndi = obj->getVMClass()->getNativeDataInfo();
    assert(ndi->sweep);
    ndi->sweep(obj);
    node = node->next;
    assert(invalidateNativeData(obj, ndi));
  }
  s_sweep = nullptr;
}


/* Classes with NativeData structs allocate extra memory prior
 * to the ObjectData.
 *
 * [padding][NativeData][SweepNode][ObjectData](prop0)...(propN)
 *                                /\
 *                             ObjectData* points here
 *
 * padding is added by alignTypedValue() to ensure that ObjectData*
 *   falls on a memory alignment boundary
 * NativeData is info.sz bytes for the custom class Native Data
 * SweepNode is a link in the NativeData sweep list for this ND block
 */
ObjectData* nativeDataInstanceCtor(Class* cls) {
  Attr attrs = cls->attrs();
  if (UNLIKELY(attrs &
               (AttrAbstract | AttrInterface | AttrTrait | AttrEnum))) {
    ObjectData::raiseAbstractClassError(cls);
  }
  auto ndi = cls->getNativeDataInfo();
  size_t nativeDataSize = alignTypedValue(ndi->sz + sizeof(SweepNode));
  size_t nProps = cls->numDeclProperties();
  size_t size = ObjectData::sizeForNProps(nProps) + nativeDataSize;

  void *ptr = MM().objMallocLogged(size);
  auto obj = new (static_cast<char*>(ptr) + nativeDataSize) ObjectData(cls);
  obj->setAttribute(static_cast<ObjectData::Attribute>(ndi->odattrs));
  if (ndi->init) {
    ndi->init(obj);
  }
  if (ndi->sweep) {
    prependSweepNode(getSweepNode(obj));
  }
  if (UNLIKELY(cls->callsCustomInstanceInit())) {
    obj->callCustomInstanceInit();
  }
  return obj;
}

void nativeDataInstanceCopy(ObjectData* dest, ObjectData *src) {
  auto ndi = dest->getVMClass()->getNativeDataInfo();
  if (!ndi) return;
  assert(ndi == src->getVMClass()->getNativeDataInfo());
  if (!ndi->copy) {
    throw_not_implemented("NativeDataInfoCopy");
  }
  ndi->copy(dest, src);

  // Already in the sweep list from init call, no need to add again
}

void nativeDataInstanceDtor(ObjectData* obj, const Class* cls) {
  assert(!cls->preClass()->builtinObjSize());
  assert(!cls->preClass()->builtinODOffset());
  obj->~ObjectData();

  auto const nProps = size_t{cls->numDeclProperties()};
  auto prop = reinterpret_cast<TypedValue*>(obj + 1);
  auto const stop = prop + nProps;
  for (; prop != stop; ++prop) {
    tvRefcountedDecRef(prop);
  }

  auto ndi = cls->getNativeDataInfo();
  assert(ndi);
  if (ndi->destroy) {
    ndi->destroy(obj);
  }
  if (ndi->sweep) {
    removeSweepNode(getSweepNode(obj));
  }

  size_t nativeDataSize = alignTypedValue(ndi->sz + sizeof(SweepNode));
  size_t size = ObjectData::sizeForNProps(nProps) + nativeDataSize;
  void *ptr = obj;
  ptr = static_cast<char*>(ptr) - nativeDataSize;

  if (LIKELY(size <= kMaxSmartSize)) {
    return MM().smartFreeSizeLogged(ptr, size);
  }
  MM().smartFreeSizeBigLogged(ptr, size);
}

//////////////////////////////////////////////////////////////////////////////
}} // namespace HPHP::Native