int SharedVariant::getIndex(CVarRef key) {
  ASSERT(is(KindOfArray));
  switch (key.getType()) {
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64: {
    int64 num = key.getNumData();
    if (getIsVector()) {
      if (num < 0 || (size_t) num >= m_data.vec->size) return -1;
      return num;
    }
    return m_data.map->indexOf(num);
  }
  case KindOfStaticString:
  case KindOfString: {
    if (getIsVector()) return -1;
    StringData *sd = key.getStringData();
    return m_data.map->indexOf(sd);
  }
  default:
    // No other types are legitimate keys
    break;
  }
  return -1;
}
Exemple #2
0
int64 HphpMap::hash(CVarRef s) {
  int64 hash;
  switch (s.getType()) {
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    hash = hash_int64(s.toInt64());
    break;
  case LiteralString:
    {
      const char* d = s.getLiteralString();
      hash = hash_string(d, strlen(d));
    }
    break;
  case KindOfString:
    {
      StringData *st = s.getStringData();
      hash = hash_string(st->data(), st->size());
    }
    break;
  default:
    ASSERT(false);
    return 0;
  }
  return hash;
}
HOT_FUNC
void ImmutableMap::add(int pos, CVarRef key, CVarRef val, bool unserializeObj) {
  int64_t ikey;
  StringData* skey;
  int32_t hash;
  Bucket* b = buckets() + pos;

  switch (key.getType()) {
    case KindOfInt64: {
      hash = ikey = key.toInt64();
      b->setIntKey(ikey);
      break;
    }
    case KindOfString: {
      skey = StringData::GetStaticString(key.getStringData());
      goto static_case;
    }
    case KindOfStaticString: {
      skey = key.getStringData();
static_case:
      hash = skey->hash();
      b->setStrKey(skey, hash);
      break;
    }
    default: not_reached();
  }
  addVal(pos, hash & m.m_capacity_mask, val, unserializeObj);
}
Exemple #4
0
int64_t f_count(CVarRef var, bool recursive /* = false */) {
  switch (var.getType()) {
  case KindOfUninit:
  case KindOfNull:
    return 0;
  case KindOfObject:
    {
      Object obj = var.toObject();
      if (obj->isCollection()) {
        return obj->getCollectionSize();
      }
      if (obj.instanceof(SystemLib::s_CountableClass)) {
        return obj->o_invoke_few_args(s_count, 0).toInt64();
      }
    }
    break;
  case KindOfArray:
    if (recursive) {
      CArrRef arr_var = var.toCArrRef();
      return php_count_recursive(arr_var);
    }
    return var.getArrayData()->size();
  default:
    break;
  }
  return 1;
}
Exemple #5
0
bool Array::less(CVarRef v2) const {
  if (m_px == nullptr || v2.isNull()) {
    return HPHP::less(toBoolean(), v2.toBoolean());
  }
  if (v2.getType() == KindOfArray) {
    return m_px->compare(v2.toArray().get()) < 0;
  }
  return v2.more(*this);
}
Exemple #6
0
bool Array::more(CVarRef v2) const {
  if (m_px == NULL || v2.isNull()) {
    return HPHP::more(toBoolean(), v2.toBoolean());
  }
  if (v2.getType() == KindOfArray) {
    return v2.toArray().get()->compare(m_px) < 0;
  }
  return v2.less(*this);
}
Exemple #7
0
void Array::remove(CVarRef key) {
  switch(key.getType()) {
  case KindOfBoolean:
  case KindOfInt64:
    removeImpl(key.toInt64());
    return;
  default:
    break;
  }
  VarNR k(key.toKey());
  if (!k.isNull()) {
    removeImpl(k);
  }
}
void Parameter::bind(VariableEnvironment &env, CVarRef val,
                     bool ref /* = false */) const {
  if (m_kind != KindOfNull) {
    DataType otype = val.getType();
    if (!(m_nullDefault && otype == KindOfNull ||
          otype == m_kind &&
          (m_kind != KindOfObject ||
           m_kind == KindOfObject &&
           val.toObject().instanceof(m_type.c_str())))) {
      throw_unexpected_argument_type(m_argNum, m_fnName, m_type.c_str(), val);
    }
  }
  if (ref) val.setContagious();
  env.getIdx(m_idx) = val;
}
bool Array::exists(CVarRef key, bool isKey /* = false */) const {
    switch(key.getType()) {
    case KindOfBoolean:
    case KindOfInt64:
        return existsImpl(key.toInt64());
    default:
        break;
    }
    if (isKey) return existsImpl(key);
    VarNR k(key.toKey());
    if (!k.isNull()) {
        return existsImpl(k);
    }
    return false;
}
bool ConcurrentTableSharedStore::constructPrime(CVarRef v,
                                                KeyValuePair& item) {
  if (s_apc_file_storage.getState() != SharedStoreFileStorage::StateInvalid &&
      (IS_REFCOUNTED_TYPE(v.getType()))) {
    // Only do the storage for ref-counted type
    String s = apc_serialize(v);
    char *sAddr = s_apc_file_storage.put(s.data(), s.size());
    if (sAddr) {
      item.sAddr = sAddr;
      item.sSize = s.size();
      return false;
    }
  }
  item.value = SharedVariant::Create(v, false);
  return true;
}
Exemple #11
0
CVarRef Array::set(CVarRef key, CVarRef v, int64 prehash /* = -1 */) {
  switch(key.getType()) {
  case KindOfBoolean:
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    return setImpl(key.toInt64(), v, prehash);
  default:
    break;
  }
  Variant k = key.toKey();
  if (!k.isNull()) {
    return setImpl(k, v, prehash);
  }
  return null_variant;
}
Exemple #12
0
bool Array::exists(CVarRef key, int64 prehash /* = -1 */) const {
  switch(key.getType()) {
  case KindOfBoolean:
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    return existsImpl(key.toInt64(), prehash);
  default:
    break;
  }
  Variant k = key.toKey();
  if (!k.isNull()) {
    return existsImpl(k, prehash);
  }
  return false;
}
Exemple #13
0
void Array::remove(CVarRef key, int64 prehash /* = -1 */) {
  switch(key.getType()) {
  case KindOfBoolean:
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    removeImpl(key.toInt64(), prehash);
    return;
  default:
    break;
  }
  Variant k = key.toKey();
  if (!k.isNull()) {
    removeImpl(k, prehash);
  }
}
Exemple #14
0
String f_gettype(CVarRef v) {
  switch (v.getType()) {
  case KindOfUninit:
  case KindOfNull:    return "NULL";
  case KindOfBoolean: return "boolean";
  case KindOfInt64:   return "integer";
  case KindOfDouble:  return "double";
  case KindOfStaticString:
  case KindOfString:  return "string";
  case KindOfArray:   return "array";
  case KindOfObject:  return "object";
  default:
    assert(false);
    break;
  }
  return "";
}
Exemple #15
0
int hphp_ffi_exportVariant(CVarRef v, void** result) {
  switch (v.getType()) {
  case KindOfNull:    return 0;
  case KindOfBoolean: *result = (void*)v.toBoolean(); return 1;
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64: {
    *result = (void*)v.toInt64();
    return 2;
  }
  case KindOfDouble: {
    union {
      double d;
      void* p;
    } u;
    u.d = v.toDouble();
    *result = u.p;
    return 3;
  }
  case LiteralString: *result = (void*)v.getLiteralString(); return 4;
  case KindOfString: {
    StringData *sd = v.getStringData();
    sd->incRefCount();
    *result = (void*)sd;
    return 5;
  }
  case KindOfArray: {
    ArrayData *ad = v.getArrayData();
    ad->incRefCount();
    *result = (void*)ad;
    return 6;
  }
  case KindOfObject: {
    ObjectData *od = v.getObjectData();
    od->incRefCount();
    *result = (void*)od;
    return 7;
  }
  default:
    ASSERT(false);
    return 0;
  }
}
Exemple #16
0
Variant Array::rvalAt(CVarRef key, int64 prehash /* = -1 */) const {
  if (!m_px) return null;

  switch(key.getType()) {
  case KindOfBoolean:
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    return m_px->get(key.toInt64(), prehash);
  default:
    break;
  }
  Variant k = key.toKey();
  if (!k.isNull()) {
    return m_px->get(k, prehash);
  }
  return null;
}
String f_serialize(CVarRef value) {
  switch (value.getType()) {
  case KindOfUninit:
  case KindOfNull:
    return "N;";
  case KindOfBoolean:
    return value.getBoolean() ? "b:1;" : "b:0;";
  case KindOfInt64: {
    StringBuffer sb;
    sb.append("i:");
    sb.append(value.getInt64());
    sb.append(';');
    return sb.detach();
  }
  case KindOfStaticString:
  case KindOfString: {
    StringData *str = value.getStringData();
    StringBuffer sb;
    sb.append("s:");
    sb.append(str->size());
    sb.append(":\"");
    sb.append(str->data(), str->size());
    sb.append("\";");
    return sb.detach();
  }
  case KindOfArray: {
    ArrayData *arr = value.getArrayData();
    if (arr->empty()) return "a:0:{}";
    // fall-through
  }
  case KindOfObject:
  case KindOfResource:
  case KindOfDouble: {
    VariableSerializer vs(VariableSerializer::Type::Serialize);
    return vs.serialize(value, true);
  }
  default:
    assert(false);
    break;
  }
  return "";
}
int ThreadSharedVariant::getIndex(CVarRef key) {
  ASSERT(is(KindOfArray));
  switch (key.getType()) {
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64: {
    int64 num = key.getNumData();
    if (getIsVector()) {
      if (num < 0 || (size_t) num >= m_data.vec->size) return -1;
      return num;
    }
    if (RuntimeOption::ApcUseGnuMap) {
      Int64ToIntMap::const_iterator it = m_data.gnuMap->intMap->find(num);
      if (it == m_data.gnuMap->intMap->end()) return -1;
      return it->second;
    }
    return m_data.map->indexOf(num);
  }
  case KindOfStaticString:
  case KindOfString: {
    if (getIsVector()) return -1;
    StringData *sd = key.getStringData();
    if (RuntimeOption::ApcUseGnuMap) {
      StringDataToIntMap::const_iterator it = m_data.gnuMap->strMap->find(sd);
      if (it == m_data.gnuMap->strMap->end()) return -1;
      return it->second;
    }
    return m_data.map->indexOf(sd);
  }
  default:
    // No other types are legitimate keys
    break;
  }
  return -1;
}
Exemple #19
0
Array Array::operator+(CVarRef var) const {
  if (var.getType() != KindOfArray) {
    throw BadArrayMergeException();
  }
  return operator+(var.getArrayData());
}
ThreadSharedVariant::ThreadSharedVariant(CVarRef source, bool serialized,
                                         bool inner /* = false */) {
  ASSERT(!serialized || source.isString());

  setOwner();
  m_ref = 1;

  switch (source.getType()) {
  case KindOfBoolean:
    {
      m_type = KindOfBoolean;
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_type = KindOfDouble;
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      m_type = serialized ? KindOfObject : KindOfString;
      if (serialized) {
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      m_type = KindOfArray;

      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          setShouldCache();
          String s = apc_serialize(source);
          m_data.str = new StringData(s.data(), s.size(), CopyString);
          break;
        }
      }

      size_t size = arr->size();
      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new VectorData(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          ThreadSharedVariant* val = createAnother(it.second(), false, true);
          if (val->shouldCache()) setShouldCache();
          m_data.vec->vals[i] = val;
        }
      } else {
        m_data.map = new ImmutableMap(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          ThreadSharedVariant* key = createAnother(it.first(), false);
          ThreadSharedVariant* val = createAnother(it.second(), false, true);
          if (val->shouldCache()) setShouldCache();
          m_data.map->add(key, val);
        }
      }
      break;
    }
  default:
    {
      m_type = KindOfObject;
      setShouldCache();
      String s = apc_serialize(source);
      m_data.str = new StringData(s.data(), s.size(), CopyString);
      break;
    }
  }
}
String f_gettype(CVarRef v) {
  return getDataTypeString(v.getType());
}
ProcessSharedVariant::ProcessSharedVariant(CVarRef source,
                                           ProcessSharedVariantLock* lock)
  : m_lock(putPtr(lock)) {
  switch (source.getType()) {
  case KindOfBoolean:
    {
      m_type = KindOfBoolean;
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_type = KindOfDouble;
      m_data.dbl = source.toDouble();
      break;
    }
  case LiteralString:
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      m_type = KindOfString;
      if (lock) {
        m_data.str = putPtr(SharedMemoryManager::GetSegment()
                            ->construct<SharedMemoryString>
                            (boost::interprocess::anonymous_instance)
                            (s.data(), s.size()));
      } else {
        // Just need this string to live long enough for the key lookup so
        // don't store in shared memory.
        m_data.str = putPtr(new SharedMemoryString(s.data(), s.size()));
      }
      break;
    }
  case KindOfArray:
    {
      ASSERT(lock);
      m_type = KindOfArray;
      uint i = 0;
      ProcessSharedVariantMapData* mapData = SharedMemoryManager::GetSegment()
        ->construct<ProcessSharedVariantMapData>
        (boost::interprocess::anonymous_instance)();
      m_data.map = putPtr(mapData);
      ProcessSharedVariantToIntMap* map = SharedMemoryManager::GetSegment()
        ->construct<ProcessSharedVariantToIntMap>
        (boost::interprocess::anonymous_instance)();
      mapData->map = putPtr(map);
      SharedMemoryVector<SharedVariant*>* keys =
        SharedMemoryManager::GetSegment()
        ->construct<SharedMemoryVector<SharedVariant*> >
        (boost::interprocess::anonymous_instance)();
      mapData->keys = putPtr(keys);
      SharedMemoryVector<SharedVariant*>* vals =
        SharedMemoryManager::GetSegment()
        ->construct<SharedMemoryVector<SharedVariant*> >
        (boost::interprocess::anonymous_instance)();
      mapData->vals = putPtr(vals);
      for (ArrayIterPtr it = source.begin(); !it->end(); it->next()) {
        ProcessSharedVariant* key = SharedMemoryManager::GetSegment()
          ->construct<ProcessSharedVariant>
          (boost::interprocess::anonymous_instance)
          (it->first(), getLock());
        ProcessSharedVariant* val = SharedMemoryManager::GetSegment()
          ->construct<ProcessSharedVariant>
          (boost::interprocess::anonymous_instance)
          (it->second(), getLock());
        (*map)[key] = i++;
        keys->push_back(putPtr(key));
        vals->push_back(putPtr(val));
      }
      break;
    }
  default:
    {
      m_type = KindOfObject;
      String s = f_serialize(source);
      m_data.str = putPtr(SharedMemoryManager::GetSegment()
                          ->construct<SharedMemoryString>
                          (boost::interprocess::anonymous_instance)
                          (s.data(), s.size()));
      break;
    }
  }
}
Exemple #23
0
bool HphpMap::same(CVarRef s1, CVarRef s2) {
  DataType t1 = s1.getType();
  DataType t2 = s2.getType();
  switch (t1) {
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    switch (t2) {
    case KindOfInt16:
    case KindOfInt32:
    case KindOfInt64:
      break;
    default:
      return false;
    }
    break;
  case LiteralString:
  case KindOfString:
    switch (t2) {
    case LiteralString:
    case KindOfString:
      break;
    default:
      return false;
    }
    break;
  default:
    ASSERT(false);
    if (t1 != t2) return false;
    break;
  }

  switch (t1) {
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    return s1.toInt64() == s2.toInt64();
  default:
    const char* s1d;
    uint64 s1l;
    const char* s2d;
    uint64 s2l;
    if (t1 == LiteralString) {
      s1d = s1.getLiteralString();
      s1l = strlen(s1d);
    } else {
      StringData *s1data = s1.getStringData();
      s1d = s1data->data();
      s1l = s1data->size();
    }
    if (t2 == LiteralString) {
      s2d = s2.getLiteralString();
      s2l = strlen(s2d);
    } else {
      StringData *s2data = s2.getStringData();
      s2d = s2data->data();
      s2l = s2data->size();
    }
    return string_strcmp(s1d, s1l, s2d, s2l) == 0;
  }
}
Exemple #24
0
bool f_is_resource(CVarRef v) {
  return (v.getType() == KindOfResource && !v.getResourceData()->isInvalid());
}
Exemple #25
0
String f_gettype(CVarRef v) {
  if (v.getType() == KindOfResource && v.getResourceData()->isInvalid()) {
    return s_unknown_type;
  }
  return getDataTypeString(v.getType());
}
SharedVariant::SharedVariant(CVarRef source, bool serialized,
                             bool inner /* = false */,
                             bool unserializeObj /* = false */)
  : m_shouldCache(false), m_flags(0) {
  assert(!serialized || source.isString());
  m_count = 1;
  m_type = source.getType();
  switch (m_type) {
  case KindOfBoolean:
    {
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
    {
      if (serialized) goto StringCase;
      m_data.str = source.getStringData();
      break;
    }
StringCase:
  case KindOfString:
    {
      String s = source.toString();
      if (serialized) {
        m_type = KindOfObject;
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      StringData* st = StringData::LookupStaticString(s.get());
      if (st) {
        m_data.str = st;
        m_type = KindOfStaticString;
        break;
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          m_shouldCache = true;
          String s = apc_serialize(source);
          m_data.str = StringData::MakeMalloced(s.data(), s.size());
          break;
        }
      }

      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new (arr->size()) VectorData();
        for (ArrayIter it(arr); !it.end(); it.next()) {
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.vec->vals()[m_data.vec->m_size++] = val;
        }
      } else {
        m_data.map = ImmutableMap::Create(arr, unserializeObj, m_shouldCache);
      }
      break;
    }
  case KindOfUninit:
  case KindOfNull:
    {
      break;
    }
  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.
      m_type = KindOfArray;
      setIsVector();
      m_data.vec = new (0) VectorData();
      break;
    }
  default:
    {
      assert(source.isObject());
      m_shouldCache = true;
      if (unserializeObj) {
        // This assumes hasInternalReference(seen, true) is false
        ImmutableObj* obj = new ImmutableObj(source.getObjectData());
        m_data.obj = obj;
        setIsObj();
      } else {
        String s = apc_serialize(source);
        m_data.str = StringData::MakeMalloced(s.data(), s.size());
      }
      break;
    }
  }
  assert(m_type != KindOfResource);
}
SharedVariant::SharedVariant(CVarRef source, bool serialized,
                             bool inner /* = false */,
                             bool unserializeObj /* = false */)
  : m_count (1), m_shouldCache(false), m_flags(0){
  ASSERT(!serialized || source.isString());

  m_type = source.getType();

  switch (m_type) {
  case KindOfBoolean:
    {
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      if (serialized) {
        m_type = KindOfObject;
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          m_shouldCache = true;
          String s = apc_serialize(source);
          m_data.str = new StringData(s.data(), s.size(), CopyString);
          break;
        }
      }

      size_t size = arr->size();
      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new VectorData(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.vec->vals[i] = val;
        }
      } else {
        m_data.map = new ImmutableMap(size);
        for (ArrayIter it(arr); !it.end(); it.next()) {
          SharedVariant* key = Create(it.first(), false, true,
                                      unserializeObj);
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.map->add(key, val);
        }
      }
      break;
    }
  case KindOfNull:
    {
      m_data.num = 0;
      break;
    }
  default:
    {
      ASSERT(source.isObject());
      m_shouldCache = true;
      if (unserializeObj) {
        // This assumes hasInternalReference(seen, true) is false
        ImmutableObj* obj = new ImmutableObj(source.getObjectData());
        m_data.obj = obj;
        setIsObj();
      } else {
        String s = apc_serialize(source);
        m_data.str = new StringData(s.data(), s.size(), CopyString);
      }
      break;
    }
  }
}