コード例 #1
0
ファイル: hash-collection.cpp プロジェクト: DerPapst/hhvm
HashCollection::Elm& HashCollection::allocElmFront(MixedArray::Inserter ei) {
  assert(MixedArray::isValidIns(ei) && !MixedArray::isValidPos(*ei));
  assert(m_size <= posLimit() && posLimit() < cap());
  // Move the existing elements to make element slot 0 available.
  memmove(data() + 1, data(), posLimit() * sizeof(Elm));
  incPosLimit();
  // Update the hashtable to reflect the fact that everything was
  // moved over one position
  auto* hash = hashTab();
  auto* hashEnd = hash + hashSize();
  for (; hash != hashEnd; ++hash) {
    if (validPos(*hash)) {
      ++(*hash);
    }
  }
  // Set the hash entry we found to point to element slot 0.
  (*ei) = 0;
  // Adjust m_pos so that is points at this new first element.
  arrayData()->m_pos = 0;
  // Adjust size to reflect that we're adding a new element.
  incSize();
  // Store the value into element slot 0.
  return data()[0];
}
コード例 #2
0
ALWAYS_INLINE
typename std::enable_if<
  std::is_base_of<BaseMap, TMap>::value, Object>::type
BaseMap::php_map(const Variant& callback) const {
  VMRegGuard _;
  CallCtx ctx;
  vm_decode_function(callback, nullptr, false, ctx);
  if (!ctx.func) {
    SystemLib::throwInvalidArgumentExceptionObject(
               "Parameter must be a valid callback");
  }
  auto map = req::make<TMap>();
  if (!m_size) return Object{std::move(map)};
  assert(posLimit() != 0);
  assert(hashSize() > 0);
  assert(map->arrayData() == staticEmptyMixedArray());
  map->m_arr = MixedArray::asMixed(MixedArray::MakeReserveMixed(cap()));
  map->setIntLikeStrKeys(intLikeStrKeys());
  wordcpy(map->hashTab(), hashTab(), hashSize());
  {
    uint32_t used = posLimit();
    int32_t version = m_version;
    uint32_t i = 0;
    // When the loop below finishes or when an exception is thrown,
    // make sure that posLimit() get set to the correct value and
    // that m_pos gets set to point to the first element.
    SCOPE_EXIT {
      map->setPosLimit(i);
      map->arrayData()->m_pos = map->nthElmPos(0);
    };
    constexpr int64_t argc = useKey ? 2 : 1;
    TypedValue argv[argc];
    for (; i < used; ++i) {
      const Elm& e = data()[i];
      Elm& ne = map->data()[i];
      if (isTombstone(i)) {
        ne.data.m_type = e.data.m_type;
        continue;
      }
      TypedValue* tv = &ne.data;
      if (useKey) {
        if (e.hasIntKey()) {
          argv[0].m_type = KindOfInt64;
          argv[0].m_data.num = e.ikey;
        } else {
          argv[0].m_type = KindOfString;
          argv[0].m_data.pstr = e.skey;
        }
      }
      argv[argc-1] = e.data;
      g_context->invokeFuncFew(tv, ctx, argc, argv);
      if (UNLIKELY(version != m_version)) {
        tvRefcountedDecRef(tv);
        throw_collection_modified();
      }
      if (e.hasStrKey()) {
        e.skey->incRefCount();
      }
      ne.ikey = e.ikey;
      ne.data.hash() = e.data.hash();
      map->incSize();
      // Needed so that the new elements are accounted for when GC scanning.
      map->incPosLimit();
    }
  }
  return Object{std::move(map)};
}