Пример #1
0
ArrayData* StructArray::CopyWithStrongIterators(const ArrayData* ad) {
  auto const cpy = Copy(ad);
  if (LIKELY(strong_iterators_exist())) {
    // This returns its first argument just so we can tail call it.
    return move_strong_iterators(cpy, const_cast<ArrayData*>(ad));
  }
  return cpy;
}
Пример #2
0
NEVER_INLINE
ArrayData* PackedArray::Grow(ArrayData* old) {
  assert(checkInvariants(old));
  assert(old->m_size == old->m_packedCap);

  DEBUG_ONLY auto const oldPos  = old->m_pos;

  auto const oldCap  = old->m_packedCap;
  auto const cap     = oldCap * 2;
  if (UNLIKELY(cap >= kMaxPackedCap)) return nullptr;

  auto const ad = static_cast<ArrayData*>(
    MM().objMallocLogged(sizeof(ArrayData) + cap * sizeof(TypedValue))
  );

  auto const oldSize        = old->m_size;
  auto const oldPosUnsigned = uint64_t{static_cast<uint32_t>(old->m_pos)};

  ad->m_kindAndSize = uint64_t{oldSize} << 32 | cap;
  ad->m_posAndCount = oldPosUnsigned;
  if (UNLIKELY(strong_iterators_exist())) {
    move_strong_iterators(ad, old);
  }

  // Steal the old array payload.  At the time of this writing, it was
  // better not to reuse the memcpy return value here because gcc had
  // `ad' in a callee saved register anyway.  The reg-to-reg move was
  // smaller than subtracting sizeof(ArrayData) from rax to return.
  old->m_size = 0;
  std::memcpy(packedData(ad), packedData(old), oldSize * sizeof(TypedValue));

  // TODO(#2926276): it would be good to refactor callers to expect
  // our refcount to start at 1.

  assert(ad->m_kind == ArrayData::kPackedKind);
  assert(ad->m_pos == oldPos);
  assert(ad->m_count == 0);
  assert(ad->m_packedCap == cap);
  assert(ad->m_size == oldSize);
  assert(checkInvariants(ad));
  return ad;
}
Пример #3
0
StructArray* StructArray::Grow(StructArray* old, Shape* newShape) {
  assert(old->shape()->transitionRequiresGrowth());

  auto result = StructArray::create(newShape, old->data(),
    old->shape()->size());
  result->m_size = newShape->size();

  if (UNLIKELY(strong_iterators_exist())) {
    move_strong_iterators(result, old);
  }

  old->m_size = 0;
  if (debug) {
    // For debug builds, set m_pos to 0 as well to make the
    // asserts in checkInvariants() happy.
    old->m_pos = 0;
  }

  assert(result->hasExactlyOneRef());
  return result;
}