795aa1309c
For PhpFiles, there was a mixed management system, where references from translated code were held until the code was made unreachable, while references from interpreted code were held for the duration of the current request. Under the new scheme, PhpFiles are always treadmilled. They are owned by the FileRepository, and so need to be ref-counted because the FileRepository can have the same PhpFile under multiple paths. But we don't ref-count the *uses* of PhpFiles anymore. Classes still need to be ref-counted, but as soon as their Unit goes away, most of their internals can be freed. We just need to hold onto them if derived classes are referencing them. Even in that case, the next time we try to instantiate the derived class, we can kill any that reference this Class. There were also lots of holes where references were not dropped, or owned data structures were not destroyed. eg a Class's methods were not destroyed when the Class was destroyed; there were several paths where an entry was erased from the file map, but the corresponding PhpFile was not decRef'd - or worse, a null entry was left in the map (something we had asserts to check for). This tries to make the handling more consistent.
105 linhas
3.5 KiB
C++
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/base/complex_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>
|
|
void FixedStringMap<V, case_sensitive>::clear() {
|
|
if (m_table != (Elm*)&null_key) free(m_table);
|
|
m_table = nullptr;
|
|
m_mask = 0;
|
|
}
|
|
|
|
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>;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
}
|