bool MutableArrayIter::advance() {
    ArrayData *data = m_var ? getData() : m_data;
    if (!data) return false;
    // If the foreach loop's array changed since the previous iteration,
    // we recover by creating a new strong iterator for the new array,
    // starting with at the position indicated by the new array's internal
    // pointer.
    if (m_fp.container != data) {
        // Free the current strong iterator if its valid
        if (m_fp.container != NULL) {
            m_fp.container->freeFullPos(m_fp);
        }
        assert(m_fp.container == NULL);
        // If needed, escalate the array to an array type that can support
        // foreach by reference
        escalateCheck();
        // Trigger COW if needed, copying over strong iterators
        data = cowCheck();
        // Create a new strong iterator for the new array
        data->newFullPos(m_fp);
    } else {
        // Trigger COW if needed, copying over strong iterators
        data = cowCheck();
    }
    assert(m_fp.container == data);
    if (!data->setFullPos(m_fp)) return false;
    CVarRef curr = data->currentRef();
    m_valp->assignRef(curr);
    if (m_key) m_key->assignVal(data->key());
    data->next();
    data->getFullPos(m_fp);
    return true;
}
MutableArrayIter::MutableArrayIter(ArrayData *data, Variant *key,
                                   Variant &val)
    : m_var(NULL), m_data(data), m_key(key), m_valp(&val), m_fp() {
    if (data) {
        escalateCheck();
        data = cowCheck();
        data->reset();
        data->newFullPos(m_fp);
        assert(m_fp.container == data);
    }
}
Exemple #3
0
MutableArrayIter::MutableArrayIter(const Variant *var, Variant *key,
                                   Variant &val)
  : m_var(var), m_data(NULL), m_key(key), m_val(val), m_fp() {
  ASSERT(m_var);
  escalateCheck();
  ArrayData* data = cowCheck();
  if (data) {
    data->reset();
    data->newFullPos(m_fp);
    ASSERT(m_fp.container == data);
  }
}
Exemple #4
0
void HashCollection::grow(uint32_t newScale) {
  auto newCap = MixedArray::Capacity(newScale);
  assert(m_size <= posLimit() && posLimit() <= cap() && cap() <= newCap);
  assert(SmallSize <= newCap && newCap <= MaxSize);
  assert(m_size <= newCap);
  auto oldAd = arrayData();
  dropImmCopy();
  if (m_size > 0 && !oldAd->cowCheck()) {
    // MixedArray::Grow can only handle non-empty cases where the
    // buffer's refcount is 1.
    m_arr = MixedArray::Grow(oldAd, newScale);
    decRefArr(oldAd);
  } else {
    // For cases where m_size is zero or the buffer's refcount is
    // greater than 1, call resizeHelper().
    resizeHelper(newCap);
  }
  assert(canMutateBuffer());
  assert(m_immCopy.isNull());
}