Arquivos
hhvm/hphp/runtime/vm/fixed_string_map.cpp
T
mwilliams 1626223e97 Avoid allocations for empty maps
Empty FixedStringMaps would do a malloc of at least 9 bytes,
and IndexedStringMap would do a 1 byte malloc, and a malloc of at least 9
bytes.

We have a lot of typically empty maps in our data structures.
2013-06-15 23:32:08 -07:00

105 linhas
3.5 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/fixed_string_map.h"
#include "hphp/runtime/vm/core_types.h"
#include "hphp/runtime/base/macros.h"
namespace HPHP {
TRACE_SET_MOD(runtime);
///////////////////////////////////////////////////////////////////////////////
class Func;
static const StringData* null_key;
inline bool strEqual(bool case_sensitive,
const StringData* sd1, const StringData* sd2) {
if (sd1 == sd2) return true;
if (sd1->size() != sd2->size()) return false;
return case_sensitive ?
(0 == memcmp(sd1->data(), sd2->data(), sd1->size())) :
bstrcaseeq(sd1->data(), sd2->data(), sd1->size());
}
template <typename V, bool case_sensitive>
FixedStringMap<V, case_sensitive>::~FixedStringMap() {
if (m_table != (Elm*)&null_key) {
free(m_table);
}
}
template <typename V, bool case_sensitive>
void FixedStringMap<V, case_sensitive>::init(int num) {
if (!num) {
m_table = (Elm*)&null_key;
m_mask = 0;
return;
}
static const double kLoadFactor = 0.80;
int capac = 1;
while (num >= kLoadFactor * capac) {
capac *= 2;
}
TRACE(1, "FixedStringMap::init: %d -> %d\n", num, capac);
assert(!m_table);
m_table = (Elm*)calloc(capac * sizeof(Elm), 1);
assert(m_table);
m_mask = capac - 1;
}
template <typename V, bool case_sensitive>
void FixedStringMap<V, case_sensitive>::add(const StringData* sd, const V& v) {
assert(sd->isStatic());
Elm* elm = &m_table[sd->hash() & m_mask];
UNUSED unsigned numProbes = 0;
while (elm->sd) {
assert(numProbes++ < m_mask + 1);
// Semantics for multiple insertion: new value wins.
if (strEqual(case_sensitive, elm->sd, sd)) break;
if (UNLIKELY(++elm == &m_table[m_mask + 1])) elm = m_table;
}
elm->sd = sd;
elm->data = v;
}
template <typename V, bool case_sensitive>
V* FixedStringMap<V, case_sensitive>::find(const StringData* sd) const {
Elm* elm = &m_table[sd->hash() & m_mask];
UNUSED unsigned numProbes = 0;
for(;;) {
assert(numProbes++ < m_mask + 1);
if (UNLIKELY(nullptr == elm->sd)) return nullptr;
if (strEqual(case_sensitive, elm->sd, sd)) return &elm->data;
if (UNLIKELY(++elm == &m_table[m_mask + 1])) elm = m_table;
}
}
template class FixedStringMap<Slot, false>;
template class FixedStringMap<Slot, true>;
template class FixedStringMap<Id, false>;
template class FixedStringMap<Id, true>;
template class FixedStringMap<Func*, false>;
template class FixedStringMap<unsigned char* /* TCA */, true>;
///////////////////////////////////////////////////////////////////////////////
}