Esempio n. 1
0
APCHandle* APCArray::MakeUncountedArray(ArrayData* array) {
  assert(apcExtension::UseUncounted);
  APCTypedValue* value;
  if (array->isPacked()) {
    value = new APCTypedValue(MixedArray::MakeUncountedPacked(array));
  } else if (array->isStruct()) {
    value = new APCTypedValue(StructArray::MakeUncounted(array));
  } else {
    value = new APCTypedValue(MixedArray::MakeUncounted(array));
  }
  return value->getHandle();
}
Esempio n. 2
0
APCHandle* APCArray::MakeUncountedArray(ArrayData* array) {
  assert(apcExtension::UseUncounted);
  APCTypedValue* value;
  if (array->isPackedLayout()) {
    ArrayData* data = PackedArray::MakeUncounted(array, sizeof(APCTypedValue));
    auto mem = reinterpret_cast<APCTypedValue*>(data) - 1;
    value = new(mem) APCTypedValue(APCTypedValue::UncountedArr{}, data);
  } else {
    ArrayData* data = MixedArray::MakeUncounted(array, sizeof(APCTypedValue));
    auto mem = reinterpret_cast<APCTypedValue*>(data) - 1;
    value = new(mem) APCTypedValue(APCTypedValue::UncountedArr{}, data);
  }
  return value->getHandle();
}
Esempio n. 3
0
ssize_t APCArray::indexOf(const StringData* key) const {
  strhash_t h = key->hash();
  ssize_t bucket = hash()[h & m.m_capacity_mask];
  Bucket* b = buckets();
  while (bucket != -1) {
    if (!IS_REFCOUNTED_TYPE(b[bucket].key->getType())) {
      APCTypedValue *k = APCTypedValue::fromHandle(b[bucket].key);
      if (!b[bucket].key->is(KindOfInt64) &&
          key->same(k->getStringData())) {
        return bucket;
      }
    } else {
      assert(b[bucket].key->is(KindOfString));
      APCString *k = APCString::fromHandle(b[bucket].key);
      if (key->same(k->getStringData())) {
        return bucket;
      }
    }
    bucket = b[bucket].next;
  }
  return -1;
}
Esempio n. 4
0
void APCArray::add(APCHandle *key, APCHandle *val) {
  int pos = m.m_num;
  // NOTE: no check on duplication because we assume the original array has no
  // duplication
  Bucket* bucket = buckets() + pos;
  bucket->key = key;
  bucket->val = val;
  m.m_num++;
  int hash_pos;
  if (!IS_REFCOUNTED_TYPE(key->getType())) {
    APCTypedValue *k = APCTypedValue::fromHandle(key);
    hash_pos = (key->is(KindOfInt64) ?
        k->getInt64() : k->getStringData()->hash()) & m.m_capacity_mask;
  } else {
    assert(key->is(KindOfString));
    APCString *k = APCString::fromHandle(key);
    hash_pos = k->getStringData()->hash() & m.m_capacity_mask;
  }

  int& hp = hash()[hash_pos];
  bucket->next = hp;
  hp = pos;
}
Esempio n. 5
0
APCHandle* APCHandle::Create(const Variant& source,
                             size_t& size,
                             bool serialized,
                             bool inner /* = false */,
                             bool unserializeObj /* = false */) {
  auto type = source.getType(); // this gets rid of the ref, if it was one
  switch (type) {
    case KindOfBoolean: {
      auto value = new APCTypedValue(type,
          static_cast<int64_t>(source.getBoolean()));
      size = sizeof(APCTypedValue);
      return value->getHandle();
    }
    case KindOfInt64: {
      auto value = new APCTypedValue(type, source.getInt64());
      size = sizeof(APCTypedValue);
      return value->getHandle();
    }
    case KindOfDouble: {
      auto value = new APCTypedValue(type, source.getDouble());
      size = sizeof(APCTypedValue);
      return value->getHandle();
    }
    case KindOfUninit:
    case KindOfNull: {
      auto value = new APCTypedValue(type);
      size = sizeof(APCTypedValue);
      return value->getHandle();
    }

    case KindOfStaticString: {
      if (serialized) goto StringCase;

      auto value = new APCTypedValue(type, source.getStringData());
      size = sizeof(APCTypedValue);
      return value->getHandle();
    }
StringCase:
    case KindOfString: {
      StringData* s = source.getStringData();
      if (serialized) {
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        return APCObject::MakeShared(apc_reserialize(s), size);
      }

      auto const st = lookupStaticString(s);
      if (st) {
        APCTypedValue* value = new APCTypedValue(KindOfStaticString, st);
        size = sizeof(APCTypedValue);
        return value->getHandle();
      }

      assert(!s->isStatic()); // would've been handled above
      if (!inner && apcExtension::UseUncounted) {
        StringData* st = StringData::MakeUncounted(s->slice());
        APCTypedValue* value = new APCTypedValue(st);
        size = sizeof(APCTypedValue) + st->size();
        return value->getHandle();
      }
      return APCString::MakeShared(type, s, size);
    }

    case KindOfArray:
      return APCArray::MakeShared(source.getArrayData(),
                                  size,
                                  inner,
                                  unserializeObj);

    case KindOfResource:
      // TODO Task #2661075: Here and elsewhere in the runtime, we convert
      // Resources to the empty array during various serialization operations,
      // which does not match Zend behavior. We should fix this.
      size = sizeof(APCArray);
      return APCArray::MakeShared();

    case KindOfObject:
      return unserializeObj ?
          APCObject::Construct(source.getObjectData(), size) :
          APCObject::MakeShared(apc_serialize(source), size);

    default:
      return nullptr;
  }
}