diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-06-27 16:01:04 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-06-28 14:56:17 +0200 |
commit | f418bbb8836a648bdd08728e88323a4c8db9140c (patch) | |
tree | edacdfb55168c2e0a8c7c6b21e8242ca65446d13 /src/qml/qml/v4 | |
parent | d33025fe108fb35f6e5c40b94432f8850b86d16b (diff) |
Add a replacement for QQmlIntegerCache
Change-Id: Ie3e23e10644ce957a0029e83a43367a2339d5335
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/qml/v4')
-rw-r--r-- | src/qml/qml/v4/qv4identifier.cpp | 99 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4identifier_p.h | 91 | ||||
-rw-r--r-- | src/qml/qml/v4/qv4internalclass.cpp | 11 |
3 files changed, 190 insertions, 11 deletions
diff --git a/src/qml/qml/v4/qv4identifier.cpp b/src/qml/qml/v4/qv4identifier.cpp index e3c70ff398..af11d2db41 100644 --- a/src/qml/qml/v4/qv4identifier.cpp +++ b/src/qml/qml/v4/qv4identifier.cpp @@ -54,6 +54,105 @@ static inline int primeForNumBits(int numBits) 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) diff --git a/src/qml/qml/v4/qv4identifier_p.h b/src/qml/qml/v4/qv4identifier_p.h index b8a2e7c88f..40d5207d7b 100644 --- a/src/qml/qml/v4/qv4identifier_p.h +++ b/src/qml/qml/v4/qv4identifier_p.h @@ -49,12 +49,101 @@ QT_BEGIN_NAMESPACE 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 { @@ -79,7 +168,7 @@ public: 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(); } diff --git a/src/qml/qml/v4/qv4internalclass.cpp b/src/qml/qml/v4/qv4internalclass.cpp index a933637850..4e3e006a69 100644 --- a/src/qml/qml/v4/qv4internalclass.cpp +++ b/src/qml/qml/v4/qv4internalclass.cpp @@ -44,19 +44,10 @@ #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; |