예제 #1
0
/* 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;
}
예제 #2
0
/* 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;
}
예제 #3
0
ObjectData* new_ZendObjectData_Instance(Class* cls) {
  TSRMLS_FETCH();
  size_t nProps = cls->numDeclProperties();
  size_t builtinObjSize = sizeof(c_ZendObjectData) - sizeof(ObjectData);
  size_t size = ObjectData::sizeForNProps(nProps) + builtinObjSize;
  auto obj = new (MM().objMallocLogged(size)) c_ZendObjectData(cls);

  zend_class_entry* ce = zend_hphp_class_to_class_entry(cls);
  auto create_func = ce->create_object;
  Class * current_class = cls;
  while (!create_func) {
    Class* parent = current_class->parent();
    if (!parent) {
      break;
    }
    zend_class_entry* parent_ce = zend_hphp_class_to_class_entry(parent);
    create_func = parent_ce->create_object;
    current_class = parent;
  }

  zend_object_value ov;
  if (create_func) {
    ov = create_func(ce TSRMLS_CC);
  } else {
    zend_object *object;
    ov = zend_objects_new(&object, ce TSRMLS_CC);
  }
  obj->setHandle(ov.handle);

  if (UNLIKELY(cls->callsCustomInstanceInit())) {
    /*
      This must happen after the constructor finishes,
      because it can leak references to obj AND it can
      throw exceptions. If we have this in the ObjectData
      constructor, and it throws, obj will be partially
      destroyed (ie ~ObjectData will be called, resetting
      the vtable pointer) leaving dangling references
      to the object (eg in backtraces).
    */
    obj->callCustomInstanceInit();
  }

  return obj;
}