Пример #1
0
ArrayData* PackedArray::Dequeue(ArrayData* adIn, Variant& value) {
  assert(checkInvariants(adIn));

  auto const ad = adIn->hasMultipleRefs() ? Copy(adIn) : adIn;
  // To conform to PHP behavior, we invalidate all strong iterators when an
  // element is removed from the beginning of the array.
  if (UNLIKELY(strong_iterators_exist())) {
    free_strong_iterators(ad);
  }

  if (UNLIKELY(ad->m_size == 0)) {
    value = uninit_null();
    ad->m_pos = ArrayData::invalid_index;
    return ad;
  }

  // This is O(N), but so is Dequeue on a mixed array, because it
  // needs to renumber keys.  So it makes sense to stay packed.
  auto n = ad->m_size - 1;
  auto const data = packedData(ad);
  value = std::move(tvAsVariant(data)); // no incref+decref
  std::memmove(data, data + 1, n * sizeof *data);
  ad->m_size = n;
  ad->m_pos = n > 0 ? 0 : ArrayData::invalid_index;
  return ad;
}
Пример #2
0
void PackedArray::Sort(ArrayData* ad, int sort_flags, bool ascending) {
  assert(ad->isPacked());
  if (ad->m_size <= 1) {
    return;
  }
  assert(!ad->hasMultipleRefs());
  auto a = ad;
  if (UNLIKELY(strong_iterators_exist())) {
    free_strong_iterators(a);
  }
  SortFlavor flav = preSort(ad);
  a->m_pos = 0;
  auto data_begin = packedData(ad);
  auto data_end = data_begin + a->m_size;
  CALL_SORT(TVAccessor);
}
Пример #3
0
void StructArray::Release(ArrayData* ad) {
  assert(ad->isRefCounted());
  assert(ad->hasExactlyOneRef());
  auto array = asStructArray(ad);

  auto const size = array->size();
  auto const data = array->data();
  auto const stop = data + size;
  for (auto ptr = data; ptr != stop; ++ptr) {
    tvRefcountedDecRef(ptr);
  }
  if (UNLIKELY(strong_iterators_exist())) {
    free_strong_iterators(ad);
  }

  auto const cap = array->capacity();
  MM().objFree(array, sizeof(StructArray) + sizeof(TypedValue) * cap);
}
Пример #4
0
NEVER_INLINE
void PackedArray::Release(ArrayData* ad) {
  assert(checkInvariants(ad));
  assert(ad->isRefCounted());

  auto const size = ad->m_size;
  auto const data = packedData(ad);
  auto const stop = data + size;
  for (auto ptr = data; ptr != stop; ++ptr) {
    tvRefcountedDecRef(*ptr);
  }
  if (UNLIKELY(strong_iterators_exist())) {
    free_strong_iterators(ad);
  }

  auto const cap = ad->m_packedCap;
  MM().objFreeLogged(ad, sizeof(ArrayData) + sizeof(TypedValue) * cap);
}
Пример #5
0
bool PackedArray::Usort(ArrayData* ad, const Variant& cmp_function) {
  assert(ad->isPacked());
  if (ad->m_size <= 1) {
    return true;
  }
  assert(!ad->hasMultipleRefs());
  if (UNLIKELY(strong_iterators_exist())) {
    free_strong_iterators(ad);
  }
  ElmUCompare<TVAccessor> comp;
  CallCtx ctx;
  CallerFrame cf;
  vm_decode_function(cmp_function, cf(), false, ctx);
  if (!ctx.func) {
    return false;
  }
  comp.ctx = &ctx;
  auto const data = packedData(ad);
  Sort::sort(data, data + ad->m_size, comp);
  return true;
}
Пример #6
0
ArrayData* PackedArray::Prepend(ArrayData* adIn,
                                const Variant& v,
                                bool copy) {
  assert(checkInvariants(adIn));

  auto const ad = adIn->hasMultipleRefs() ? CopyAndResizeIfNeeded(adIn)
                                          : ResizeIfNeeded(adIn);
  // To conform to PHP behavior, we invalidate all strong iterators when an
  // element is added to the beginning of the array.
  if (UNLIKELY(strong_iterators_exist())) {
    free_strong_iterators(ad);
  }

  auto const size = ad->m_size;
  auto const data = packedData(ad);
  std::memmove(data + 1, data, sizeof *data * size);
  // TODO(#3888164): constructValHelper is making KindOfUninit checks.
  tvAsUninitializedVariant(&data[0]).constructValHelper(v);
  ad->m_size = size + 1;
  ad->m_pos = 0;
  return ad;
}