Esempio n. 1
0
StringData* StringData::Make(const APCString* shared) {
  // No need to check if len > MaxSize, because if it were we'd never
  // have made the StringData in the APCVariant without throwing.
  assert(size_t(shared->getStringData()->size()) <= size_t(MaxSize));

  auto const data = shared->getStringData();
  auto const len = data->size();
  if (UNLIKELY(len > SmallStringReserve)) {
    return MakeAPCSlowPath(shared);
  }

  // small-string path: make a flat copy.
  static_assert(SmallStringReserve + kCapOverhead <= CapCode::Threshold, "");
  static_assert(SmallStringReserve + kCapOverhead == 64, "");
  auto const sd = allocFlatSmallImpl(SmallStringReserve);
  sd->m_lenAndHash = data->m_lenAndHash;

  auto const psrc = data->data();
  auto const pdst = reinterpret_cast<char*>(sd + 1);
  auto const mcret = memcpy(pdst, psrc, len + 1); // also copy the tailing 0
  auto const ret = reinterpret_cast<StringData*>(mcret) - 1;
  // Recalculating ret from mcret avoids a spill.

  assert(ret == sd);
  assert(ret->m_len == len);
  assert(ret->hasExactlyOneRef());
  assert(ret->m_hash == data->m_hash);
  assert(ret->isFlat());
  assert(ret->checkSane());
  return ret;
}
Esempio n. 2
0
StringData* StringData::Make(const APCString* shared) {
  // No need to check if len > MaxSize, because if it were we'd never
  // have made the StringData in the APCVariant without throwing.
  assert(size_t(shared->getStringData()->size()) <= size_t(MaxSize));

  auto const data = shared->getStringData();
  auto const len = data->size();
  if (UNLIKELY(len > SmallStringReserve)) {
    return MakeAPCSlowPath(shared);
  }

  // small-string path
  auto const psrc = data->data();
  auto const hash = data->m_hash & STRHASH_MASK;
  assert(hash != 0);

  static_assert(SmallStringReserve + sizeof(StringData) + 1 <
                CapCode::Threshold, "");
  auto const need = sizeof(StringData) + len + 1;
  auto const cap = MemoryManager::smallSizeClass(need);
  auto const sd = static_cast<StringData*>(MM().mallocSmallSize(cap));
  auto const pdst = reinterpret_cast<char*>(sd + 1);
  auto const cc = CapCode::ceil(cap - kCapOverhead);
  assert(cc.code == cap - kCapOverhead);

  sd->m_data = pdst;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  sd->m_lenAndHash = len | int64_t{hash} << 32;

  // pdst[len] = 0;
  auto const mcret = memcpy(pdst, psrc, len + 1);
  auto const ret = reinterpret_cast<StringData*>(mcret) - 1;
  // Recalculating ret from mcret avoids a spill.

  // Note: this return value thing is doing a dead lea into %rsi in
  // the caller for some reason.

  assert(ret == sd);
  assert(ret->m_len == len);
  assert(ret->hasExactlyOneRef());
  assert(ret->m_hash == hash);
  assert(ret->isFlat());
  assert(ret->checkSane());
  return ret;
}