Revert "clean up SharedMap"

Esse commit está contido em:
aravind
2013-07-22 12:34:43 -07:00
commit de Sara Golemon
commit 3606603fbd
8 arquivos alterados com 216 adições e 210 exclusões
+3 -3
Ver Arquivo
@@ -253,7 +253,7 @@ SharedVariant* ConcurrentTableSharedStore::unserialize(CStrRef key,
VariableUnserializer vu(sval->sAddr, sval->getSerializedSize(), sType);
Variant v;
v.unserialize(&vu);
sval->var = new SharedVariant(v, sval->isSerializedObj());
sval->var = SharedVariant::Create(v, sval->isSerializedObj());
stats_on_add(key.get(), sval, 0, true, true); // delayed prime
return sval->var;
} catch (Exception &e) {
@@ -520,7 +520,7 @@ bool ConcurrentTableSharedStore::constructPrime(CStrRef v, KeyValuePair& item,
return false;
}
}
item.value = new SharedVariant(v, serialized);
item.value = SharedVariant::Create(v, serialized);
return true;
}
@@ -538,7 +538,7 @@ bool ConcurrentTableSharedStore::constructPrime(CVarRef v,
return false;
}
}
item.value = new SharedVariant(v, false);
item.value = SharedVariant::Create(v, false);
return true;
}
+2 -2
Ver Arquivo
@@ -39,7 +39,7 @@ namespace HPHP {
class ConcurrentTableSharedStore : public SharedStore {
public:
explicit ConcurrentTableSharedStore(int id)
ConcurrentTableSharedStore(int id)
: SharedStore(id), m_lockingFlag(false), m_purgeCounter(0) {}
virtual int size() {
@@ -63,7 +63,7 @@ public:
protected:
virtual SharedVariant* construct(CVarRef v) {
return new SharedVariant(v, false);
return SharedVariant::Create(v, false);
}
struct charHashCompare {
+19 -40
Ver Arquivo
@@ -39,7 +39,11 @@ ImmutableMap* ImmutableMap::Create(ArrayData* arr,
try {
for (ArrayIter it(arr); !it.end(); it.next()) {
ret->add(ret->m.m_num, it.first(), it.secondRef(), unserializeObj);
SharedVariant* key = SharedVariant::Create(it.first(), false, true,
unserializeObj);
SharedVariant* val = SharedVariant::Create(it.secondRef(), false, true,
unserializeObj);
ret->add(ret->m.m_num, key, val);
++ret->m.m_num;
}
} catch (...) {
@@ -54,62 +58,36 @@ HOT_FUNC
void ImmutableMap::Destroy(ImmutableMap* map) {
Bucket* buckets = map->buckets();
for (int i = 0; i < map->m.m_num; i++) {
(*(SharedVariant*)&buckets[i].val).~SharedVariant();
delete buckets[i].key;
delete buckets[i].val;
}
free(map);
}
HOT_FUNC
void ImmutableMap::addVal(int pos, int hash_pos,
CVarRef val, bool unserializeObj) {
void ImmutableMap::add(int pos, SharedVariant *key, SharedVariant *val) {
// NOTE: no check on duplication because we assume the original array has no
// duplication
Bucket* bucket = buckets() + pos;
new (&bucket->val) SharedVariant(val, false, true, unserializeObj);
bucket->key = key;
bucket->val = val;
int hash_pos =
(key->is(KindOfInt64) ?
key->intData() : key->getStringData()->hash()) & m.m_capacity_mask;
int& hp = hash()[hash_pos];
bucket->next = hp;
hp = pos;
}
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);
}
#define STR_HASH(x) (int32_t(x) | 0x80000000)
HOT_FUNC
int ImmutableMap::indexOf(const StringData* key) {
strhash_t h = STR_HASH(key->hash());
strhash_t h = key->hash();
int bucket = hash()[h & m.m_capacity_mask];
Bucket* b = buckets();
while (bucket != -1) {
Bucket* cand = &b[bucket];
if (cand->hash() == h && (cand->skey == key || key->same(cand->skey))) {
if (!b[bucket].key->is(KindOfInt64) &&
key->same(b[bucket].key->getStringData())) {
return bucket;
}
bucket = b[bucket].next;
@@ -122,7 +100,8 @@ int ImmutableMap::indexOf(int64_t key) {
int bucket = hash()[key & m.m_capacity_mask];
Bucket* b = buckets();
while (bucket != -1) {
if (b[bucket].hasIntKey() && key == b[bucket].ikey) {
if (b[bucket].key->is(KindOfInt64) &&
key == b[bucket].key->intData()) {
return bucket;
}
bucket = b[bucket].next;
+12 -42
Ver Arquivo
@@ -19,7 +19,6 @@
#define incl_HPHP_IMMUTABLE_MAP_H_
#include "hphp/runtime/base/types.h"
#include "hphp/runtime/base/shared_variant.h"
#include "hphp/util/lock.h"
#include "hphp/util/hash.h"
#include "hphp/util/atomic.h"
@@ -27,6 +26,7 @@
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
class SharedVariant;
/**
* an immutable map is a php-style array that can take strings and
* ints as keys. the map also stores the order in which the elements
@@ -38,19 +38,14 @@ public:
int indexOf(const StringData* key);
int indexOf(int64_t key);
Variant getKey(int index) {
SharedVariant* getKeyIndex(int index) {
assert(index < size());
Bucket* b = &buckets()[index];
if (b->hasIntKey()) {
return b->ikey;
} else {
return b->skey;
}
return buckets()[index].key;
}
SharedVariant* getValue(int index) {
SharedVariant* getValIndex(int index) {
assert(index < size());
return (SharedVariant*)&buckets()[index].val;
return buckets()[index].val;
}
unsigned size() const {
@@ -71,43 +66,18 @@ public:
static ImmutableMap* Create(ArrayData* arr,
bool unserializeObj);
static void Destroy(ImmutableMap* im);
private:
ImmutableMap() {}
~ImmutableMap() {}
void add(int pos, SharedVariant *key, SharedVariant *val);
struct Bucket {
/** index of the next bucket, or -1 if the end of a chain */
int next;
/* similar to HphpArray::Elm */
union {
int64_t ikey;
StringData* skey;
};
// cannot declare SharedVariant here because of cyclic header
// includes
TypedValueAux val;
bool hasStrKey() const {
return val.hash() != 0;
}
bool hasIntKey() const {
return val.hash() == 0;
}
int32_t hash() const {
return val.hash();
}
void setStrKey(StringData* k, strhash_t h) {
skey = k;
val.hash() = int32_t(h) | 0x80000000;
}
void setIntKey(int64_t k) {
ikey = k;
val.hash() = 0;
}
/** the value of this bucket */
SharedVariant *key;
SharedVariant *val;
};
private:
ImmutableMap() {}
~ImmutableMap() {}
void addVal(int pos, int hash_pos, CVarRef val, bool unserializeObj);
void add(int pos, CVarRef key, CVarRef val, bool unserializeObj);
/** index of the beginning of each hash chain */
int *hash() const { return (int*)(this + 1); }
/** buckets, stored in index order */
+25 -59
Ver Arquivo
@@ -28,16 +28,17 @@ IMPLEMENT_SMART_ALLOCATION_HOT(SharedMap);
///////////////////////////////////////////////////////////////////////////////
HOT_FUNC
CVarRef SharedMap::getValueRef(ssize_t pos) const {
SharedVariant *sv = getValueImpl(pos);
SharedVariant *sv = m_arr->getValue(pos);
DataType t = sv->getType();
if (!IS_REFCOUNTED_TYPE(t)) return sv->asCVarRef();
if (LIKELY(m_localCache != nullptr)) {
assert(unsigned(pos) < size());
assert(unsigned(pos) < m_arr->arrCap());
TypedValue* tv = &m_localCache[pos];
if (tv->m_type != KindOfUninit) return tvAsCVarRef(tv);
} else {
static_assert(KindOfUninit == 0, "must be 0 since we use smart_calloc");
m_localCache = (TypedValue*) smart_calloc(size(), sizeof(TypedValue));
unsigned cap = m_arr->arrCap();
m_localCache = (TypedValue*) smart_calloc(cap, sizeof(TypedValue));
}
TypedValue* tv = &m_localCache[pos];
tvAsVariant(tv) = sv->toLocal();
@@ -52,7 +53,7 @@ CVarRef SharedMap::GetValueRef(const ArrayData* ad, ssize_t pos) {
HOT_FUNC
SharedMap::~SharedMap() {
if (m_localCache) {
for (TypedValue* tv = m_localCache, *end = tv + size();
for (TypedValue* tv = m_localCache, *end = tv + m_arr->arrCap();
tv < end; ++tv) {
tvRefcountedDecRef(tv);
}
@@ -75,39 +76,32 @@ inline const SharedMap* SharedMap::asSharedMap(const ArrayData* ad) {
return static_cast<const SharedMap*>(ad);
}
ssize_t SharedMap::getIndex(const StringData* k) const {
if (isVector()) return -1;
return m_map->indexOf(k);
}
ssize_t SharedMap::getIndex(int64_t k) const {
if (isVector()) {
if (k < 0 || (size_t)k >= m_vec->m_size) return -1;
return k;
}
return m_map->indexOf(k);
}
bool SharedMap::IsVectorData(const ArrayData* ad) {
auto a = asSharedMap(ad);
if (a->isVector()) return true;
const auto n = a->size();
for (ssize_t i = 0; i < n; i++) {
if (a->m_map->indexOf(i) != i) return false;
if (a->getIndex(i) != i) return false;
}
return true;
}
bool SharedMap::ExistsStr(const ArrayData* ad, const StringData* k) {
auto a = asSharedMap(ad);
if (a->isVector()) return false;
return a->m_map->indexOf(k) != -1;
return a->getIndex(k) != -1;
}
bool SharedMap::ExistsInt(const ArrayData* ad, int64_t k) {
return asSharedMap(ad)->getIndex(k) != -1;
}
ssize_t SharedMap::getIndex(int64_t k) const {
return m_arr->getIndex(k);
}
ssize_t SharedMap::getIndex(const StringData* k) const {
return m_arr->getIndex(k);
}
/* if a2 is modified copy of a1 (i.e. != a1), then release a1 and return a2 */
inline ArrayData* releaseIfCopied(ArrayData* a1, ArrayData* a2) {
if (a1 != a2) a1->release();
@@ -212,7 +206,8 @@ ArrayData *SharedMap::Prepend(ArrayData* ad, CVarRef v, bool copy) {
}
ArrayData *SharedMap::Escalate(const ArrayData* ad) {
auto ret = asSharedMap(ad)->loadElems();
auto smap = asSharedMap(ad);
auto ret = smap->m_arr->loadElems(*smap);
assert(!ret->isStatic());
return ret;
}
@@ -233,22 +228,17 @@ TypedValue* SharedMap::NvGetStr(const ArrayData* ad, const StringData* key) {
void SharedMap::NvGetKey(const ArrayData* ad, TypedValue* out, ssize_t pos) {
auto a = asSharedMap(ad);
if (a->isVector()) {
out->m_data.num = pos;
out->m_type = KindOfInt64;
} else {
Variant k = a->m_map->getKey(pos);
TypedValue* tv = k.asTypedValue();
// copy w/out clobbering out->_count.
out->m_type = tv->m_type;
out->m_data.num = tv->m_data.num;
if (tv->m_type != KindOfInt64) out->m_data.pstr->incRefCount();
}
Variant k = a->m_arr->getKey(pos);
TypedValue* tv = k.asTypedValue();
// copy w/out clobbering out->_count.
out->m_type = tv->m_type;
out->m_data.num = tv->m_data.num;
if (tv->m_type != KindOfInt64) out->m_data.pstr->incRefCount();
}
ArrayData* SharedMap::EscalateForSort(ArrayData* ad) {
auto a = asSharedMap(ad);
auto ret = a->loadElems(true /* mapInit */);
auto ret = a->m_arr->loadElems(*a, true /* mapInit */);
assert(!ret->isStatic());
return ret;
}
@@ -286,33 +276,9 @@ bool SharedMap::AdvanceFullPos(ArrayData* ad, FullPos& fp) {
return false;
}
ArrayData* SharedMap::loadElems(bool mapInit /* = false */) const {
uint count = size();
bool isVec = isVector();
auto ai =
mapInit ? ArrayInit(count, ArrayInit::mapInit) :
isVec ? ArrayInit(count, ArrayInit::vectorInit) :
ArrayInit(count);
if (isVec) {
for (uint i = 0; i < count; i++) {
ai.set(getValueRef(i));
}
} else {
for (uint i = 0; i < count; i++) {
ai.add(m_map->getKey(i), getValueRef(i),
true);
}
}
ArrayData* elems = ai.create();
if (elems->isStatic()) elems = elems->copy();
return elems;
}
void SharedMap::getChildren(std::vector<TypedValue *> &out) {
if (m_localCache) {
TypedValue *localCacheEnd = m_localCache + size();
TypedValue *localCacheEnd = m_localCache + m_size;
for (TypedValue *tv = m_localCache;
tv < localCacheEnd;
++tv) {
+8 -18
Ver Arquivo
@@ -33,11 +33,10 @@ namespace HPHP {
class SharedMap : public ArrayData {
public:
explicit SharedMap(SharedVariant* source)
: ArrayData(kSharedKind)
, m_localCache(nullptr) {
m_map = source->getMap();
m_isVector = source->getIsVector();
m_size = isVector() ? m_vec->m_size : m_map->size();
: ArrayData(kSharedKind)
, m_arr(source)
, m_localCache(nullptr) {
m_size = m_arr->arrSize();
}
~SharedMap();
@@ -54,8 +53,8 @@ public:
using ArrayData::addLval;
using ArrayData::remove;
SharedVariant* getValueImpl(ssize_t pos) const {
return isVector() ? m_vec->getValue(pos) : m_map->getValue(pos);
Variant getKey(ssize_t pos) const {
return m_arr->getKey(pos);
}
CVarRef getValueRef(ssize_t pos) const;
@@ -120,25 +119,16 @@ public:
static ArrayData* Escalate(const ArrayData*);
static ArrayData* EscalateForSort(ArrayData*);
ArrayData* loadElems(bool mapInit = false) const;
private:
ssize_t getIndex(int64_t k) const;
ssize_t getIndex(const StringData* k) const;
static SharedMap* asSharedMap(ArrayData* ad);
static const SharedMap* asSharedMap(const ArrayData* ad);
private:
bool m_isVector;
union {
ImmutableMap* m_map;
VectorData* m_vec;
};
mutable TypedValue* m_localCache;
bool isVector() const { return m_isVector; }
public:
void getChildren(std::vector<TypedValue *> &out);
SharedVariant *m_arr;
mutable TypedValue* m_localCache;
};
///////////////////////////////////////////////////////////////////////////////
+92 -8
Ver Arquivo
@@ -29,6 +29,7 @@ SharedVariant::SharedVariant(CVarRef source, bool serialized,
bool unserializeObj /* = false */)
: m_flags(0) {
assert(!serialized || source.isString());
m_count = 1;
m_type = source.getType();
switch (m_type) {
case KindOfBoolean:
@@ -91,7 +92,9 @@ StringCase:
setIsVector();
m_data.vec = new (arr->size()) VectorData();
for (ArrayIter it(arr); !it.end(); it.next()) {
m_data.vec->add(it.secondRef(), unserializeObj);
SharedVariant* val = Create(it.secondRef(), false, true,
unserializeObj);
m_data.vec->vals()[m_data.vec->m_size++] = val;
}
} else {
m_data.map = ImmutableMap::Create(arr, unserializeObj);
@@ -244,6 +247,88 @@ SharedVariant::~SharedVariant() {
///////////////////////////////////////////////////////////////////////////////
HOT_FUNC
int SharedVariant::getIndex(const StringData* key) {
assert(is(KindOfArray));
if (getIsVector()) return -1;
return m_data.map->indexOf(key);
}
int SharedVariant::getIndex(int64_t key) {
assert(is(KindOfArray));
if (getIsVector()) {
if (key < 0 || (size_t) key >= m_data.vec->m_size) return -1;
return key;
}
return m_data.map->indexOf(key);
}
Variant SharedVariant::getKey(ssize_t pos) const {
assert(is(KindOfArray));
if (getIsVector()) {
assert(pos < (ssize_t) m_data.vec->m_size);
return pos;
}
return m_data.map->getKeyIndex(pos)->toLocal();
}
HOT_FUNC
SharedVariant* SharedVariant::getValue(ssize_t pos) const {
assert(is(KindOfArray));
if (getIsVector()) {
assert(pos < (ssize_t) m_data.vec->m_size);
return m_data.vec->vals()[pos];
}
return m_data.map->getValIndex(pos);
}
ArrayData* SharedVariant::loadElems(const SharedMap &sharedMap,
bool mapInit /* = false */) {
assert(is(KindOfArray));
uint count = arrSize();
bool isVector = getIsVector();
auto ai =
mapInit ? ArrayInit(count, ArrayInit::mapInit) :
isVector ? ArrayInit(count, ArrayInit::vectorInit) :
ArrayInit(count);
if (isVector) {
for (uint i = 0; i < count; i++) {
ai.set(sharedMap.getValueRef(i));
}
} else {
for (uint i = 0; i < count; i++) {
ai.add(m_data.map->getKeyIndex(i)->toLocal(), sharedMap.getValueRef(i),
true);
}
}
ArrayData* elems = ai.create();
if (elems->isStatic()) elems = elems->copy();
return elems;
}
int SharedVariant::countReachable() const {
int count = 1;
if (getType() == KindOfArray) {
int size = arrSize();
if (!getIsVector()) {
count += size; // for keys
}
for (int i = 0; i < size; i++) {
SharedVariant* p = getValue(i);
count += p->countReachable(); // for values
}
}
return count;
}
SharedVariant *SharedVariant::Create
(CVarRef source, bool serialized, bool inner /* = false */,
bool unserializeObj /* = false*/) {
return new SharedVariant(source, serialized, inner, unserializeObj);
}
SharedVariant* SharedVariant::convertObj(CVarRef var) {
if (!var.is(KindOfObject) || getObjAttempted()) {
return nullptr;
@@ -283,14 +368,14 @@ int32_t SharedVariant::getSpaceUsage() const {
size += sizeof(VectorData) +
sizeof(SharedVariant*) * m_data.vec->m_size;
for (size_t i = 0; i < m_data.vec->m_size; i++) {
size += m_data.vec->getValue(i)->getSpaceUsage();
size += m_data.vec->vals()[i]->getSpaceUsage();
}
} else {
ImmutableMap *map = m_data.map;
size += map->getStructSize();
for (int i = 0; i < map->size(); i++) {
size += sizeof(int64_t);
size += map->getValue(i)->getSpaceUsage();
size += map->getKeyIndex(i)->getSpaceUsage();
size += map->getValIndex(i)->getSpaceUsage();
}
}
break;
@@ -337,7 +422,7 @@ void SharedVariant::getStats(SharedVariantStats *stats) const {
stats->dataTotalSize = sizeof(SharedVariant) + sizeof(VectorData);
stats->dataTotalSize += sizeof(SharedVariant*) * m_data.vec->m_size;
for (size_t i = 0; i < m_data.vec->m_size; i++) {
SharedVariant *v = m_data.vec->getValue(i);
SharedVariant *v = m_data.vec->vals()[i];
SharedVariantStats childStats;
v->getStats(&childStats);
stats->addChildStats(&childStats);
@@ -347,10 +432,9 @@ void SharedVariant::getStats(SharedVariantStats *stats) const {
stats->dataTotalSize = sizeof(SharedVariant) + map->getStructSize();
for (int i = 0; i < map->size(); i++) {
SharedVariantStats childStats;
// for key
childStats.dataSize = childStats.dataTotalSize = sizeof(int64_t);
map->getKeyIndex(i)->getStats(&childStats);
stats->addChildStats(&childStats);
map->getValue(i)->getStats(&childStats);
map->getValIndex(i)->getStats(&childStats);
stats->addChildStats(&childStats);
}
}
+55 -38
Ver Arquivo
@@ -52,6 +52,11 @@ public:
bool unserializeObj = false);
~SharedVariant();
// Create will do the wrapped check before creating a SharedVariant
static SharedVariant* Create(CVarRef source, bool serialized,
bool inner = false,
bool unserializeObj = false);
bool is(DataType d) const { return m_type == d; }
DataType getType() const { return (DataType)m_type; }
CVarRef asCVarRef() const {
@@ -83,6 +88,28 @@ public:
return m_data.str->hash();
}
size_t arrSize() const {
assert(is(KindOfArray));
if (getIsVector()) return m_data.vec->m_size;
return m_data.map->size();
}
size_t arrCap() const {
assert(is(KindOfArray));
if (getIsVector()) return m_data.vec->m_size;
return m_data.map->capacity();
}
int getIndex(int64_t key);
int getIndex(const StringData* key);
ArrayData* loadElems(const SharedMap &sharedMap,
bool mapInit = false);
Variant getKey(ssize_t pos) const;
SharedVariant* getValue(ssize_t pos) const;
// implementing LeakDetectable
void dump(std::string &out);
@@ -97,7 +124,34 @@ public:
SharedVariant *convertObj(CVarRef var);
bool isUnserializedObj() { return getIsObj(); }
int countReachable() const;
private:
class VectorData {
public:
union {
size_t m_size;
SharedVariant* m_align_dummy;
};
VectorData() : m_size(0) {}
~VectorData() {
SharedVariant** v = vals();
for (size_t i = 0; i < m_size; i++) {
delete v[i];
}
}
SharedVariant** vals() { return (SharedVariant**)(this + 1); }
void *operator new(size_t sz, int num) {
assert(sz == sizeof(VectorData));
return malloc(sizeof(VectorData) + num * sizeof(SharedVariant*));
}
void operator delete(void* ptr) { free(ptr); }
// just to keep the compiler happy; used if the constructor throws
void operator delete(void* ptr, int num) { free(ptr); }
};
/*
* Keep the object layout binary compatible with Variant for primitive types.
* We want to have compile time assertion to guard it but still want to have
@@ -159,6 +213,7 @@ private:
void setSerializedArray() { m_flags |= SerializedArray;}
void clearSerializedArray() { m_flags &= ~SerializedArray;}
bool getIsVector() const { return (bool)(m_flags & IsVector);}
void setIsVector() { m_flags |= IsVector;}
void clearIsVector() { m_flags &= ~IsVector;}
@@ -169,44 +224,6 @@ private:
bool getObjAttempted() const { return (bool)(m_flags & ObjAttempted);}
void setObjAttempted() { m_flags |= ObjAttempted;}
void clearObjAttempted() { m_flags &= ~ObjAttempted;}
public:
bool getIsVector() const { return (bool)(m_flags & IsVector);}
ImmutableMap* getMap() const { return m_data.map; }
};
/* VectorData is used when when all the keys are integers
* in the sequential range 0 to n-1. */
class VectorData {
public:
union {
size_t m_size;
SharedVariant* m_align_dummy;
};
VectorData() : m_size(0) {}
~VectorData() {
SharedVariant* v = vals();
for (size_t i = 0; i < m_size; i++) {
v[i].~SharedVariant();
}
}
SharedVariant* getValue(ssize_t pos) {
return &((SharedVariant *)(this + 1))[pos];
}
SharedVariant* vals() { return (SharedVariant*)(this + 1); }
void *operator new(size_t sz, int num) {
assert(sz == sizeof(VectorData));
return malloc(sizeof(VectorData) + num * sizeof(SharedVariant));
}
void add(CVarRef val, bool unserializeObj) {
/* placement new */
new (&vals()[m_size++]) SharedVariant(val, false, true, unserializeObj);
}
void operator delete(void* ptr) { free(ptr); }
// just to keep the compiler happy; used if the constructor throws
void operator delete(void* ptr, int num) { free(ptr); }
};
class SharedVariantStats {