Exemplo n.º 1
0
NEVER_INLINE
APCHandle::Pair APCObject::ConstructSlow(ObjectData* objectData,
                                         ClassOrName name) {
  Array odProps;
  objectData->o_getArray(odProps);
  auto const propCount = odProps.size();

  auto size = sizeof(APCObject) + sizeof(Prop) * propCount;
  auto const apcObj = new (malloc_huge(size)) APCObject(name, propCount);
  if (!propCount) return {apcObj->getHandle(), size};

  auto prop = apcObj->props();
  for (ArrayIter it(odProps); !it.end(); it.next(), ++prop) {
    Variant key(it.first());
    assert(key.isString());
    auto const rval = it.secondRval();
    if (!isNullType(tvToCell(rval).type())) {
      auto val = APCHandle::Create(VarNR(rval.tv()), false,
                                   APCHandleLevel::Inner, true);
      prop->val = val.handle;
      size += val.size;
    } else {
      prop->val = nullptr;
    }

    const String& keySD = key.asCStrRef();

    if (!keySD.empty() && *keySD.data() == '\0') {
      int32_t subLen = keySD.find('\0', 1) + 1;
      String cls = keySD.substr(1, subLen - 2);
      if (cls.size() == 1 && cls[0] == '*') {
        // Protected.
        prop->ctx = nullptr;
      } else {
        // Private.
        auto* ctx = Unit::lookupClass(cls.get());
        if (ctx && ctx->attrs() & AttrUnique) {
          prop->ctx = ctx;
        } else {
          prop->ctx = makeStaticString(cls.get());
        }
      }
      prop->name = makeStaticString(keySD.substr(subLen));
    } else {
      prop->ctx = nullptr;
      prop->name = makeStaticString(keySD.get());
    }
  }
  assert(prop == apcObj->props() + propCount);

  return {apcObj->getHandle(), size};
}
Exemplo n.º 2
0
void *cgc_malloc(cgc_size_t size)
{
  if (size == 0)
    return NULL;

  if (size + HEADER_PADDING >= NEW_CHUNK_SIZE)
    return malloc_huge(size);

#ifdef PATCHED
  if (size >= 0x80000000)
    return NULL;
#endif

  if (size % ALIGNMENT != 0)
    size = (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);

  if (size >= 0x80000000)
    return NULL;
  size += HEADER_PADDING;

  struct blk_t *blk = NULL;
  int sc_i = find_fit(size, &blk);

  /* Allocate a new block if no fit */
  if (blk == NULL) {
    if (allocate_new_blk() != 0) {
      return NULL;
    } else {
      sc_i = NUM_FREE_LISTS - 1;
      blk = cgc_free_lists[sc_i];
    }
  }

  /* Remove the block we're going to use from the free list */
  cgc_remove_from_flist(blk);

  /* Split the block into two pieces if possible */
  cgc_size_t sdiff = blk->size - size;
  if (sdiff > 2 * HEADER_PADDING) {
    struct blk_t *nb = (struct blk_t *)((intptr_t)blk + size);

    nb->size = sdiff;
    nb->free = 1;
    nb->fsucc = NULL;
    nb->fpred = NULL;

    blk->size = size;

    /* Patch up blk list pointers */
    nb->prev = blk;
    nb->next = blk->next;
    if (blk->next)
      blk->next->prev = nb;
    blk->next = nb;

    /* Put the new block into the free list */
    cgc_insert_into_flist(nb);
  }

  return (void *)((intptr_t)blk + HEADER_PADDING);
}
Exemplo n.º 3
0
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};
}