Exemple #1
0
ArrayData* StructArray::SetStr(
  ArrayData* ad,
  StringData* k,
  Cell v,
  bool copy
) {
  auto structArray = asStructArray(ad);
  auto shape = structArray->shape();
  auto result = structArray;

  auto offset = shape->offsetFor(k);
  bool isNewProperty = offset == PropertyTable::kInvalidOffset;

  auto convertToMixedAndAdd = [&]() {
    auto mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
    return mixed->addValNoAsserts(k, v);
  };

  if (isNewProperty) {
    StringData* staticKey;
    // We don't support adding non-static strings yet.
    if (k->isStatic()) {
      staticKey = k;
    } else {
      staticKey = lookupStaticString(k);
      if (!staticKey) return convertToMixedAndAdd();
    }

    auto newShape = shape->transition(staticKey);
    if (!newShape) return convertToMixedAndAdd();
    result = copy ? CopyAndResizeIfNeeded(structArray, newShape)
                  : ResizeIfNeeded(structArray, newShape);
    offset = result->shape()->offsetFor(staticKey);
    assert(offset != PropertyTable::kInvalidOffset);
    TypedValue* dst = &result->data()[offset];
    // TODO(#3888164): we should restructure things so we don't have to
    // check KindOfUninit here.
    if (UNLIKELY(v.m_type == KindOfUninit)) v = make_tv<KindOfNull>();
    cellDup(v, *dst);
    return result;
  }

  if (copy) {
    result = asStructArray(Copy(structArray));
  }

  assert(offset != PropertyTable::kInvalidOffset);
  TypedValue* dst = &result->data()[offset];
  if (UNLIKELY(v.m_type == KindOfUninit)) v = make_tv<KindOfNull>();
  cellSet(v, *tvToCell(dst));
  return result;
}
Exemple #2
0
ArrayData* PackedArray::LvalNew(ArrayData* adIn, Variant*& ret, bool copy) {
  assert(checkInvariants(adIn));
  auto const ad = copy ? CopyAndResizeIfNeeded(adIn)
                       : ResizeIfNeeded(adIn);
  if (UNLIKELY(!ad)) {
    auto const mixed = copy ? ToMixedCopy(adIn) : ToMixed(ad);
    return MixedArray::LvalNew(mixed, ret, copy);
  }

  if (ad->m_pos == ArrayData::invalid_index) {
    ad->m_pos = ad->m_size;
  }
  auto& tv = packedData(ad)[ad->m_size++];
  tv.m_type = KindOfNull;
  ret = &tvAsVariant(&tv);
  return ad;
}
Exemple #3
0
ArrayData* PackedArray::Append(ArrayData* adIn, const Variant& v, bool copy) {
  assert(checkInvariants(adIn));
  auto const ad = copy ? CopyAndResizeIfNeeded(adIn)
                       : ResizeIfNeeded(adIn);
  if (UNLIKELY(!ad)) {
    auto const mixed = copy ? ToMixedCopy(adIn) : ToMixed(adIn);
    return MixedArray::Append(mixed, v, copy);
  }

  if (ad->m_pos == ArrayData::invalid_index) {
    ad->m_pos = ad->m_size;
  }
  auto& dst = packedData(ad)[ad->m_size++];
  cellDup(*v.asCell(), dst);
  // TODO(#3888164): restructure this so we don't need KindOfUninit checks.
  if (dst.m_type == KindOfUninit) dst.m_type = KindOfNull;
  return ad;
}
Exemple #4
0
ArrayData* PackedArray::AppendWithRef(ArrayData* adIn,
                                      const Variant& v,
                                      bool copy) {
  assert(checkInvariants(adIn));
  auto const ad = copy ? CopyAndResizeIfNeeded(adIn)
                       : ResizeIfNeeded(adIn);
  if (UNLIKELY(!ad)) {
    auto const mixed = copy ? ToMixedCopy(adIn) : ToMixed(adIn);
    // XXX: constness
    return MixedArray::AppendRef(mixed, const_cast<Variant&>(v), copy);
  }

  if (ad->m_pos == ArrayData::invalid_index) {
    ad->m_pos = ad->m_size;
  }
  auto& dst = packedData(ad)[ad->m_size++];
  dst.m_type = KindOfNull;
  tvAsVariant(&dst).setWithRef(v);
  return ad;
}
Exemple #5
0
ArrayData* PackedArray::AppendRef(ArrayData* adIn,
                                  Variant& v,
                                  bool copy) {
  assert(checkInvariants(adIn));
  auto const ad = copy ? CopyAndResizeIfNeeded(adIn)
                       : ResizeIfNeeded(adIn);
  if (UNLIKELY(!ad)) {
    auto const mixed = copy ? ToMixedCopy(adIn) : ToMixed(adIn);
    return MixedArray::AppendRef(mixed, v, copy);
  }

  if (ad->m_pos == ArrayData::invalid_index) {
    ad->m_pos = ad->m_size;
  }
  auto& dst = packedData(ad)[ad->m_size++];
  dst.m_data.pref = v.asRef()->m_data.pref;
  dst.m_type = KindOfRef;
  dst.m_data.pref->incRefCount();
  return ad;
}
Exemple #6
0
ArrayData* StructArray::LvalStr(
  ArrayData* ad,
  StringData* property,
  Variant*& ret,
  bool copy
) {
  auto structArray = asStructArray(ad);
  auto shape = structArray->shape();
  auto offset = shape->offsetFor(property);
  if (offset != PropertyTable::kInvalidOffset) {
    auto const result = asStructArray(
      copy ? Copy(structArray) : structArray);
    ret = &tvAsVariant(&result->data()[offset]);
    return result;
  }

  auto convertToMixedAndAdd = [&]() {
    auto mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
    return mixed->addLvalImpl(property, ret);
  };

  // We don't support adding non-static strings yet.
  StringData* staticKey;
  if (property->isStatic()) {
    staticKey = property;
  } else {
    staticKey = lookupStaticString(property);
    if (!staticKey) return convertToMixedAndAdd();
  }

  auto newShape = shape->transition(staticKey);
  if (!newShape) return convertToMixedAndAdd();
  auto result = copy ? CopyAndResizeIfNeeded(structArray, newShape)
                     : ResizeIfNeeded(structArray, newShape);

  assert(newShape->hasOffsetFor(staticKey));
  offset = newShape->offsetFor(staticKey);
  tvWriteNull(&result->data()[offset]);
  ret = &tvAsVariant(&result->data()[offset]);
  return result;
}
Exemple #7
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;
}