Пример #1
0
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);
}
Пример #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;
}
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;
}
Пример #4
0
bool same(CVarRef v1, const StringData* v2) {
  bool null1 = v1.isNull();
  bool null2 = (v2 == nullptr);
  if (null1 && null2) return true;
  if (null1 || null2) return false;
  if (!v1.isString()) return false;
  auto const sdata = v1.getStringData();
  return sdata == v2 || v2->same(sdata);
}
Пример #5
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;
  }
}
Пример #6
0
Variant f_class_uses(CVarRef obj, bool autoload /* = true */) {
  Class* cls;
  if (obj.isString()) {
    cls = Unit::getClass(obj.getStringData(), autoload);
    if (!cls) {
      return false;
    }
  } else if (obj.isObject()) {
    cls = obj.getObjectData()->getVMClass();
  } else {
    return false;
  }
  Array ret(Array::Create());
  for (auto& elem : cls->usedTraits()) {
    auto& traitName = elem->nameRef();
    ret.set(traitName, traitName);
  }
  return ret;
}
Пример #7
0
Variant f_class_parents(CVarRef obj, bool autoload /* = true */) {
  Class* cls;
  if (obj.isString()) {
    cls = Unit::getClass(obj.getStringData(), autoload);
    if (!cls) {
      return false;
    }
  } else if (obj.isObject()) {
    cls = obj.getObjectData()->getVMClass();
  } else {
    return false;
  }
  Array ret(Array::Create());
  for (cls = cls->parent(); cls; cls = cls->parent()) {
    auto& clsName = cls->nameRef();
    ret.set(clsName, clsName);
  }
  return ret;
}
Пример #8
0
Variant f_class_implements(CVarRef obj, bool autoload /* = true */) {
  Class* cls;
  if (obj.isString()) {
    cls = Unit::getClass(obj.getStringData(), autoload);
    if (!cls) {
      return false;
    }
  } else if (obj.isObject()) {
    cls = obj.getObjectData()->getVMClass();
  } else {
    return false;
  }
  Array ret(Array::Create());
  const Class::InterfaceMap& ifaces = cls->allInterfaces();
  for (int i = 0, size = ifaces.size(); i < size; i++) {
    ret.set(ifaces[i]->nameRef(), ifaces[i]->nameRef());
  }
  return ret;
}
Пример #9
0
Variant f_class_uses(CVarRef obj, bool autoload /* = true */) {
    Class* cls;
    if (obj.isString()) {
        cls = Unit::getClass(obj.getStringData(), autoload);
        if (!cls) {
            return false;
        }
    } else if (obj.isObject()) {
        cls = obj.getObjectData()->getVMClass();
    } else {
        return false;
    }
    Array ret(Array::Create());
    for (auto const& traitName : cls->preClass()->usedTraits()) {
        const String& nameRef = *(String*)(&traitName);
        ret.set(nameRef, nameRef);
    }
    return ret;
}
Пример #10
0
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 "";
}
Пример #11
0
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;
}
Пример #12
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;
  }
}
Пример #13
0
bool ArrayData::IsValidKey(CVarRef k) {
  return k.isInteger() ||
         (k.isString() && IsValidKey(k.getStringData()));
}
Пример #14
0
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);
}