return (1 << numBits) + prime_deltas[numBits];
}
+
+IdentifierIntHashData::IdentifierIntHashData(int numBits)
+ : refCount(Q_BASIC_ATOMIC_INITIALIZER(1))
+ , numBits(numBits)
+ , size(0)
+{
+ alloc = primeForNumBits(numBits);
+ entries = (IdentifierIntHash::Entry *)malloc(alloc*sizeof(IdentifierIntHash::Entry));
+ memset(entries, 0, alloc*sizeof(IdentifierIntHash::Entry));
+}
+
+IdentifierIntHash::IdentifierIntHash(ExecutionEngine *engine)
+{
+ d = new IdentifierIntHashData(3);
+ d->identifierTable = engine->identifierTable;
+}
+
+void IdentifierIntHash::add(const QString &str, int value)
+{
+ Identifier *i = d->identifierTable->identifier(str);
+ addEntry(i, value);
+}
+
+int IdentifierIntHash::value(const QString &str)
+{
+ return lookup(d->identifierTable->identifier(str));
+}
+
+int IdentifierIntHash::value(String *str)
+{
+ return lookup(d->identifierTable->identifier(str));
+}
+
+QString IdentifierIntHash::findId(int value) const
+{
+ Entry *e = d->entries;
+ Entry *end = e + d->alloc;
+ while (e < end) {
+ if (e->value == value)
+ return e->identifier->string;
+ }
+ return QString();
+}
+
+
+void IdentifierIntHash::addEntry(const Identifier *identifier, uint value)
+{
+ // fill up to max 50%
+ bool grow = (d->alloc <= d->size*2);
+
+ if (grow) {
+ ++d->numBits;
+ int newAlloc = primeForNumBits(d->numBits);
+ Entry *newEntries = (Entry *)malloc(newAlloc * sizeof(Entry));
+ memset(newEntries, 0, newAlloc*sizeof(Entry));
+ for (uint i = 0; i < d->alloc; ++i) {
+ const Entry &e = d->entries[i];
+ if (!e.identifier)
+ continue;
+ uint idx = hash(e.identifier) % newAlloc;
+ while (newEntries[idx].identifier) {
+ ++idx;
+ idx %= newAlloc;
+ }
+ newEntries[idx] = e;
+ }
+ free(d->entries);
+ d->entries = newEntries;
+ d->alloc = newAlloc;
+ }
+
+ uint idx = hash(identifier) % d->alloc;
+ while (d->entries[idx].identifier) {
+ Q_ASSERT(d->entries[idx].identifier != identifier);
+ ++idx;
+ idx %= d->alloc;
+ }
+ d->entries[idx].identifier = identifier;
+ d->entries[idx].value = value;
+ ++d->size;
+}
+
+int IdentifierIntHash::lookup(const Identifier *identifier) const
+{
+ assert(d->entries);
+
+ uint idx = hash(identifier) % d->alloc;
+ while (1) {
+ if (d->entries[idx].identifier == identifier)
+ return d->entries[idx].value;
+ if (!d->entries[idx].identifier)
+ return -1;
+ ++idx;
+ idx %= d->alloc;
+ }
+}
+
+
+
IdentifierTable::IdentifierTable(ExecutionEngine *engine)
: engine(engine)
, size(0)
namespace QV4 {
+struct IdentifierTable;
+
struct Identifier
{
QString string;
uint hashValue;
};
+inline uint hash(const QV4::Identifier *id)
+{
+ quintptr h = (quintptr)id;
+ if (sizeof(quintptr) == sizeof(uint))
+ return h ^ (h >> 8);
+ else
+ return (uint)(h ^ (h >> 8) ^ (h >> 32));
+}
+
+
+
+struct IdentifierIntHashData;
+struct IdentifierIntHash
+{
+ struct Entry {
+ const Identifier *identifier;
+ int value;
+ };
+
+ IdentifierIntHashData *d;
+
+ IdentifierIntHash() : d(0) {}
+ IdentifierIntHash(ExecutionEngine *engine);
+ inline IdentifierIntHash(const IdentifierIntHash &other);
+ inline ~IdentifierIntHash();
+ inline IdentifierIntHash &operator=(const IdentifierIntHash &other);
+
+ bool isEmpty() const { return !d; }
+ // ###
+ void reserve(int) {}
+
+ inline int count() const;
+ void add(const QString &str, int value);
+
+ int value(const QString &);
+ int value(String *str);
+
+ QString findId(int value) const;
+
+private:
+ void addEntry(const Identifier *i, uint value);
+ int lookup(const Identifier *identifier) const;
+};
+
+struct IdentifierIntHashData
+{
+ IdentifierIntHashData(int numBits);
+ ~IdentifierIntHashData() {
+ free(entries);
+ }
+
+ QBasicAtomicInt refCount;
+ int alloc;
+ int size;
+ int numBits;
+ IdentifierTable *identifierTable;
+ IdentifierIntHash::Entry *entries;
+};
+
+inline IdentifierIntHash::IdentifierIntHash(const IdentifierIntHash &other)
+{
+ d = other.d;
+ if (d)
+ d->refCount.ref();
+}
+
+inline IdentifierIntHash::~IdentifierIntHash()
+{
+ if (d && !d->refCount.deref())
+ delete d;
+}
+
+IdentifierIntHash &IdentifierIntHash::operator=(const IdentifierIntHash &other)
+{
+ if (other.d)
+ other.d->refCount.ref();
+ if (d && !d->refCount.deref())
+ delete d;
+ d = other.d;
+ return *this;
+}
+
+inline int IdentifierIntHash::count() const
+{
+ return d ? d->size : 0;
+}
+
struct IdentifierTable
{
Identifier *identifier(const char *s, int len);
void mark() {
- for (uint i = 0; i < alloc; ++i)
+ for (int i = 0; i < alloc; ++i)
if (entries[i])
entries[i]->mark();
}
#include <qv4engine_p.h>
#include <qv4identifier_p.h>
#include "qv4object_p.h"
+#include "qv4identifier_p.h"
QT_BEGIN_NAMESPACE
-uint hash(const QV4::Identifier *id, uint = 0)
-{
- quintptr h = (quintptr)id;
- if (sizeof(quintptr) == sizeof(uint))
- return h ^ (h >> 8);
- else
- return (uint)(h ^ (h >> 8) ^ (h >> 32));
-}
-
-
uint QV4::qHash(const QV4::InternalClassTransition &t, uint)
{
return hash(t.id) ^ t.flags;