Add a replacement for QQmlIntegerCache
authorLars Knoll <lars.knoll@digia.com>
Thu, 27 Jun 2013 14:01:04 +0000 (16:01 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 28 Jun 2013 12:56:17 +0000 (14:56 +0200)
Change-Id: Ie3e23e10644ce957a0029e83a43367a2339d5335
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/qml/v4/qv4identifier.cpp
src/qml/qml/v4/qv4identifier_p.h
src/qml/qml/v4/qv4internalclass.cpp

index e3c70ff..af11d2d 100644 (file)
@@ -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)
index b8a2e7c..40d5207 100644 (file)
@@ -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();
     }
index a933637..4e3e006 100644 (file)
 #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;