Exemple #1
0
void DataWalker::traverseData(ArrayData* data,
                              DataFeature& features,
                              PointerSet& visited) const {
  for (ArrayIter iter(data); iter; ++iter) {
    const Variant& var = iter.secondRef();

    if (var.isReferenced()) {
      Variant *pvar = var.getRefData();
      if (markVisited(pvar, features, visited)) {
        if (canStopWalk(features)) return;
        continue; // don't recurse forever; we already went down this path
      }
      // Right now consider it circular even if the referenced variant only
      // showed up in one spot.  This could be revisted later.
      features.isCircular = true;
      if (canStopWalk(features)) return;
    }

    auto const type = var.getType();
    // cheap enough, do it always
    features.hasRefCountReference = isRefcountedType(type);
    if (type == KindOfObject) {
      features.hasObjectOrResource = true;
      traverseData(var.getObjectData(), features, visited);
    } else if (isArrayType(type)) {
      traverseData(var.getArrayData(), features, visited);
    } else if (type == KindOfResource) {
      features.hasObjectOrResource = true;
    }
    if (canStopWalk(features)) return;
  }
}
Exemple #2
0
ALWAYS_INLINE
bool DataWalker::visitTypedValue(TypedValue rval,
                                 DataFeature& features,
                                 PointerSet& visited,
                                 PointerMap* seenArrs) const {
  if (isRefType(rval.m_type)) {
    if (rval.m_data.pref->isReferenced()) {
      if (markVisited(rval.m_data.pref, features, visited)) {
        // Don't recurse forever; we already went down this path, and
        // stop the walk if we've already got everything we need.
        return canStopWalk(features);
      }
      // Right now consider it circular even if the referenced variant
      // only showed up in one spot.  This could be revisted later.
      features.isCircular = true;
      if (canStopWalk(features)) return true;
    }
    rval = *rval.m_data.pref->cell();
  }

  if (rval.m_type == KindOfObject) {
    features.hasObjectOrResource = true;
    traverseData(rval.m_data.pobj, features, visited);
  } else if (isArrayLikeType(rval.m_type)) {
    traverseData(rval.m_data.parr, features, visited, seenArrs);
  } else if (rval.m_type == KindOfResource) {
    features.hasObjectOrResource = true;
  }
  return canStopWalk(features);
}
Exemple #3
0
void DataWalker::traverseData(
    ObjectData* data,
    DataFeature& features,
    PointerSet& visited) const {
  objectFeature(data, features);
  if (markVisited(data, features, visited)) {
    return; // avoid infinite recursion
  }
  if (canStopWalk(features)) return;

  if (data->isCollection()) {
    auto const arr = collections::asArray(data);
    if (arr) {
      traverseData(arr, features, visited);
      return;
    }
    assertx(data->collectionType() == CollectionType::Pair);
    auto const pair = static_cast<c_Pair*>(data);
    visitTypedValue(*pair->get(0), features, visited);
    visitTypedValue(*pair->get(1), features, visited);
    return;
  }

  IteratePropMemOrderNoInc(
    data,
    [&](Slot slot, const Class::Prop& prop, tv_rval val) {
      visitTypedValue(val.tv(), features, visited);
    },
    [&](Cell key_tv, TypedValue val) {
      visitTypedValue(val, features, visited);
    }
  );
}
Exemple #4
0
void DataWalker::traverseData(ArrayData* data,
                              DataFeature& features,
                              PointerSet& visited) const {
  // shared arrays by definition do not contain circular references or
  // collections
  if (data->isSharedArray()) {
    // If not looking for references to objects/resources OR
    // if one was already found we can bail out
    if (!(m_features & LookupFeature::HasObjectOrResource) ||
        features.hasObjectOrResource()) {
      features.m_hasRefCountReference = true; // just in case, cheap enough...
      return;
    }
  }

  for (ArrayIter iter(data); iter; ++iter) {
    const Variant& var = iter.secondRef();

    if (var.isReferenced()) {
      Variant *pvar = var.getRefData();
      if (markVisited(pvar, features, visited)) {
        // don't recurse forever
        if (canStopWalk(features)) {
          return;
        }
        continue;
      }
      markVisited(pvar, features, visited);
    }

    DataType type = var.getType();
    // cheap enough, do it always
    features.m_hasRefCountReference = IS_REFCOUNTED_TYPE(type);
    if (type == KindOfObject) {
      features.m_hasObjectOrResource = true;
      traverseData(var.getObjectData(), features, visited);
    } else if (type == KindOfArray) {
      traverseData(var.getArrayData(), features, visited);
    } else if (type == KindOfResource) {
      features.m_hasObjectOrResource = true;
    }
    if (canStopWalk(features)) return;
  }
}
Exemple #5
0
void DataWalker::traverseData(
    ObjectData* data,
    DataFeature& features,
    PointerSet& visited) const {
  objectFeature(data, features, visited);
  if (markVisited(data, features, visited)) {
    return; // avoid infinite recursion
  }
  if (!canStopWalk(features)) {
    traverseData(data->toArray().get(), features, visited);
  }
}