a8e3321fbd
We'd like to start using ##mixed## instead of ##var## for attribute types to be consistent with Hack. As a followup to this (once released), we would codemod all ##var## to ##mixed##.
135 linhas
4.0 KiB
C++
135 linhas
4.0 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
|
| Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 2.00 of the Zend license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.zend.com/license/2_00.txt. |
|
|
| If you did not receive a copy of the Zend license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@zend.com so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include "hphp/runtime/base/immutable_map.h"
|
|
#include "hphp/runtime/base/shared_variant.h"
|
|
#include "hphp/runtime/base/array_iterator.h"
|
|
|
|
namespace HPHP {
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
HOT_FUNC
|
|
ImmutableMap* ImmutableMap::Create(ArrayData* arr,
|
|
bool unserializeObj) {
|
|
int num = arr->size();
|
|
int cap = num > 2 ? Util::roundUpToPowerOfTwo(num) : 2;
|
|
|
|
ImmutableMap* ret = (ImmutableMap*)malloc(sizeof(ImmutableMap) +
|
|
sizeof(int) * cap +
|
|
sizeof(Bucket) * num);
|
|
|
|
ret->m.m_capacity_mask = cap - 1;
|
|
ret->m.m_num = 0;
|
|
for (int i = 0; i < cap; i++) ret->hash()[i] = -1;
|
|
|
|
try {
|
|
for (ArrayIter it(arr); !it.end(); it.next()) {
|
|
ret->add(ret->m.m_num, it.first(), it.secondRef(), unserializeObj);
|
|
++ret->m.m_num;
|
|
}
|
|
} catch (...) {
|
|
Destroy(ret);
|
|
throw;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
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();
|
|
}
|
|
free(map);
|
|
}
|
|
|
|
HOT_FUNC
|
|
void ImmutableMap::addVal(int pos, int hash_pos,
|
|
CVarRef val, bool unserializeObj) {
|
|
// 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);
|
|
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());
|
|
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))) {
|
|
return bucket;
|
|
}
|
|
bucket = b[bucket].next;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
HOT_FUNC
|
|
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) {
|
|
return bucket;
|
|
}
|
|
bucket = b[bucket].next;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
}
|