typename std::enable_if<
  std::is_base_of<BaseSet, TSet>::value, Object>::type
BaseSet::php_takeWhile(const Variant& fn) {
  CallCtx ctx;
  vm_decode_function(fn, nullptr, false, ctx);
  if (!ctx.func) {
    SystemLib::throwInvalidArgumentExceptionObject(
               "Parameter must be a valid callback");
  }
  auto set = req::make<TSet>();
  if (!m_size) return Object(std::move(set));
  set->mutate();
  int32_t version UNUSED;
  if (std::is_same<c_Set, TSet>::value) {
    version = m_version;
  }
  uint32_t used = posLimit();
  for (uint32_t i = 0; i < used; ++i) {
    if (isTombstone(i)) continue;
    Elm* e = &data()[i];
    bool b = invokeAndCastToBool(ctx, 1, &e->data);
    if (std::is_same<c_Set, TSet>::value) {
      if (UNLIKELY(version != m_version)) {
        throw_collection_modified();
      }
    }
    if (!b) break;
    e = &data()[i];
    if (e->hasIntKey()) {
      set->addRaw(e->data.m_data.num);
    } else {
      assert(e->hasStrKey());
      set->addRaw(e->data.m_data.pstr);
    }
  }
  return Object(std::move(set));
}
/**
 * postSort() runs after the sort has been performed. For HphpArray, postSort()
 * handles rebuilding the hash. Also, if resetKeys is true, postSort() will
 * renumber the keys 0 thru n-1.
 */
void HphpArray::postSort(bool resetKeys) {
  ASSERT(m_size > 0);
  size_t tableSize = computeTableSize(m_tableMask);
  initHash(m_hash, tableSize);
  m_hLoad = 0;
  if (resetKeys) {
    for (ElmInd pos = 0; pos <= m_lastE; ++pos) {
      Elm* e = &m_data[pos];
      if (e->hasStrKey() && e->key->decRefCount() == 0) {
        e->key->release();
      }
      e->setIntKey(pos);
      m_hash[pos] = pos;
    }
    m_nextKI = m_size;
  } else {
    for (ElmInd pos = 0; pos <= m_lastE; ++pos) {
      Elm* e = &m_data[pos];
      ElmInd* ei = findForNewInsert(e->hasIntKey() ? e->ikey : e->hash);
      *ei = pos;
    }
  }
  m_hLoad = m_size;
}
/**
 * postSort() runs after the sort has been performed. For HphpArray, postSort()
 * handles rebuilding the hash. Also, if resetKeys is true, postSort() will
 * renumber the keys 0 thru n-1.
 */
void HphpArray::postSort(bool resetKeys) {
  assert(m_size > 0);
  size_t tableSize = computeTableSize(m_tableMask);
  initHash(m_hash, tableSize);
  m_hLoad = 0;
  if (resetKeys) {
    for (uint32_t pos = 0; pos < m_used; ++pos) {
      Elm* e = &m_data[pos];
      if (e->hasStrKey()) decRefStr(e->key);
      e->setIntKey(pos);
      m_hash[pos] = pos;
    }
    m_nextKI = m_size;
  } else {
    for (uint32_t pos = 0; pos < m_used; ++pos) {
      Elm* e = &m_data[pos];
      ElmInd* ei = findForNewInsert(e->hasIntKey() ? e->ikey : e->hash());
      *ei = pos;
    }
  }
  m_hLoad = m_size;
}