From: Lars Knoll Date: Wed, 26 Jun 2013 13:03:11 +0000 (+0200) Subject: Introduce an Identifier class X-Git-Tag: upstream/5.2.1~669^2~109 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1b3e648a831ba87d9342ed6a08dc11f1bc1b1b3e;p=platform%2Fupstream%2Fqtdeclarative.git Introduce an Identifier class Identifier are now (opaque) pointers. They contain the string and it's hash value making conversion from Identifier back to it's string value a no-op. Change-Id: Ied7e845a981514890ff6a686e0e3e3057e6b6fbf Reviewed-by: Simon Hausmann --- diff --git a/src/qml/qml/v4/qv4engine.cpp b/src/qml/qml/v4/qv4engine.cpp index 608a94c..3d2f79f 100644 --- a/src/qml/qml/v4/qv4engine.cpp +++ b/src/qml/qml/v4/qv4engine.cpp @@ -114,7 +114,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory) memoryManager->setExecutionEngine(this); - identifierCache = new Identifiers(this); + identifierCache = new IdentifierHash(this); emptyClass = new (classPool.allocate(sizeof(InternalClass))) InternalClass(this); diff --git a/src/qml/qml/v4/qv4engine_p.h b/src/qml/qml/v4/qv4engine_p.h index 2109acf..b861994 100644 --- a/src/qml/qml/v4/qv4engine_p.h +++ b/src/qml/qml/v4/qv4engine_p.h @@ -100,7 +100,7 @@ struct URIErrorPrototype; struct VariantPrototype; struct SequencePrototype; struct EvalFunction; -struct Identifiers; +struct IdentifierHash; struct InternalClass; class MultiplyWrappedQObjectMap; class RegExp; @@ -119,7 +119,7 @@ struct Q_QML_EXPORT ExecutionEngine WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine. - Identifiers *identifierCache; + IdentifierHash *identifierCache; QQmlJS::Debugging::Debugger *debugger; diff --git a/src/qml/qml/v4/qv4identifier_p.h b/src/qml/qml/v4/qv4identifier_p.h index f79ee8f..c4ae825 100644 --- a/src/qml/qml/v4/qv4identifier_p.h +++ b/src/qml/qml/v4/qv4identifier_p.h @@ -49,14 +49,20 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct Identifiers +struct Identifier +{ + QString string; + uint hashValue; +}; + + +struct IdentifierHash { ExecutionEngine *engine; - uint currentIndex; QHash identifiers; public: - Identifiers(ExecutionEngine *engine) : engine(engine), currentIndex(0) {} + IdentifierHash(ExecutionEngine *engine) : engine(engine) {} String *insert(const QString &s) { @@ -69,31 +75,30 @@ public: if (str->subtype == String::StringType_ArrayIndex) return str; - str->identifier = currentIndex; - if (currentIndex <= USHRT_MAX) { - identifiers.insert(s, str); - ++currentIndex; - } + str->identifier = new Identifier; + str->identifier->string = str->toQString(); + str->identifier->hashValue = str->hashValue(); + identifiers.insert(s, str); + return str; } - void toIdentifier(String *s) { - if (s->identifier != UINT_MAX) + void toIdentifier(String *str) { + if (str->identifier) return; - if (s->subtype == String::StringType_Unknown) - s->createHashValue(); - if (s->subtype == String::StringType_ArrayIndex) + if (str->subtype == String::StringType_Unknown) + str->createHashValue(); + if (str->subtype == String::StringType_ArrayIndex) return; - QHash::const_iterator it = identifiers.find(s->toQString()); + QHash::const_iterator it = identifiers.find(str->toQString()); if (it != identifiers.constEnd()) { - s->identifier = (*it)->identifier; + str->identifier = (*it)->identifier; return; } - s->identifier = currentIndex; - if (currentIndex <= USHRT_MAX) { - identifiers.insert(s->toQString(), s); - ++currentIndex; - } + str->identifier = new Identifier; + str->identifier->string = str->toQString(); + str->identifier->hashValue = str->hashValue(); + identifiers.insert(str->toQString(), str); } void mark() { diff --git a/src/qml/qml/v4/qv4internalclass.cpp b/src/qml/qml/v4/qv4internalclass.cpp index 785808e..e590399 100644 --- a/src/qml/qml/v4/qv4internalclass.cpp +++ b/src/qml/qml/v4/qv4internalclass.cpp @@ -47,8 +47,28 @@ 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; +} + using namespace QV4; +static bool operator==(const InternalClassTransition &a, const InternalClassTransition &b) +{ + return a.id == b.id && a.flags == b.flags; +} + static const uchar prime_deltas[] = { 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 @@ -66,10 +86,7 @@ PropertyHashData::PropertyHashData(int numBits) { alloc = primeForNumBits(numBits); entries = (PropertyHash::Entry *)malloc(alloc*sizeof(PropertyHash::Entry)); - for (uint i = 0; i < alloc; ++i) { - entries[i].identifier = UINT_MAX; - entries[i].index = UINT_MAX; - } + memset(entries, 0, alloc*sizeof(PropertyHash::Entry)); } void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize) @@ -81,10 +98,10 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize) PropertyHashData *dd = new PropertyHashData(grow ? d->numBits + 1 : d->numBits); for (uint i = 0; i < d->alloc; ++i) { const Entry &e = d->entries[i]; - if (e.identifier == UINT_MAX || e.index >= classSize) + if (!e.identifier || e.index >= classSize) continue; - uint idx = e.identifier % dd->alloc; - while (dd->entries[idx].identifier != UINT_MAX) { + uint idx = hash(e.identifier) % dd->alloc; + while (dd->entries[idx].identifier) { ++idx; idx %= dd->alloc; } @@ -96,8 +113,8 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize) d = dd; } - uint idx = entry.identifier % d->alloc; - while (d->entries[idx].identifier != UINT_MAX) { + uint idx = hash(entry.identifier) % d->alloc; + while (d->entries[idx].identifier) { ++idx; idx %= d->alloc; } @@ -105,15 +122,15 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize) ++d->size; } -uint PropertyHash::lookup(uint identifier) const +uint PropertyHash::lookup(const Identifier *identifier) const { assert(d->entries); - uint idx = identifier % d->alloc; + uint idx = hash(identifier) % d->alloc; while (1) { if (d->entries[idx].identifier == identifier) return d->entries[idx].index; - if (d->entries[idx].identifier == UINT_MAX) + if (!d->entries[idx].identifier) return UINT_MAX; ++idx; idx %= d->alloc; @@ -147,9 +164,9 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da if (data == propertyData[idx]) return this; - uint tid = string->identifier | (data.flags() << 27); - QHash::const_iterator tit = transitions.constFind(tid); + Transition t = { string->identifier, data.flags() }; + QHash::const_iterator tit = transitions.constFind(t); if (tit != transitions.constEnd()) return tit.value(); @@ -169,8 +186,8 @@ InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, if (propertyTable.lookup(string->identifier) < size) return changeMember(string, data, index); - uint id = string->identifier | (data.flags() << 27); - QHash::const_iterator tit = transitions.constFind(id); + Transition t = { string->identifier, data.flags() }; + QHash::const_iterator tit = transitions.constFind(t); if (index) *index = size; @@ -190,17 +207,17 @@ InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, newClass->propertyData.append(data); ++newClass->size; - transitions.insert(id, newClass); + transitions.insert(t, newClass); return newClass; } -void InternalClass::removeMember(Object *object, uint id) +void InternalClass::removeMember(Object *object, Identifier *id) { int propIdx = propertyTable.lookup(id); assert(propIdx < size); - int toRemove = - (int)id; - QHash::const_iterator tit = transitions.constFind(toRemove); + Transition t = { id, -1 }; + QHash::const_iterator tit = transitions.constFind(t); if (tit != transitions.constEnd()) { object->internalClass = tit.value(); @@ -215,13 +232,13 @@ void InternalClass::removeMember(Object *object, uint id) object->internalClass = object->internalClass->addMember(nameMap.at(i), propertyData.at(i)); } - transitions.insert(toRemove, object->internalClass); + transitions.insert(t, object->internalClass); } uint InternalClass::find(String *string) { engine->identifierCache->toIdentifier(string); - uint id = string->identifier; + const Identifier *id = string->identifier; uint index = propertyTable.lookup(id); if (index < size) @@ -283,7 +300,7 @@ void InternalClass::destroy() if (m_frozen) m_frozen->destroy(); - for (QHash::ConstIterator it = transitions.begin(), end = transitions.end(); + for (QHash::ConstIterator it = transitions.begin(), end = transitions.end(); it != end; ++it) it.value()->destroy(); diff --git a/src/qml/qml/v4/qv4internalclass_p.h b/src/qml/qml/v4/qv4internalclass_p.h index 7543844..9bc95da 100644 --- a/src/qml/qml/v4/qv4internalclass_p.h +++ b/src/qml/qml/v4/qv4internalclass_p.h @@ -52,12 +52,13 @@ namespace QV4 { struct String; struct ExecutionEngine; struct Object; +struct Identifier; struct PropertyHashData; struct PropertyHash { struct Entry { - uint identifier; + const Identifier *identifier; uint index; }; @@ -68,7 +69,7 @@ struct PropertyHash inline ~PropertyHash(); void addEntry(const Entry &entry, int classSize); - uint lookup(uint identifier) const; + uint lookup(const Identifier *identifier) const; private: PropertyHash &operator=(const PropertyHash &other); @@ -105,6 +106,12 @@ inline PropertyHash::~PropertyHash() delete d; } +struct InternalClassTransition +{ + Identifier *id; + int flags; +}; +uint qHash(const QV4::InternalClassTransition &t, uint = 0); struct InternalClass { ExecutionEngine *engine; @@ -113,7 +120,8 @@ struct InternalClass { QVector propertyData; - QHash transitions; // id to next class, positive means add, negative delete + typedef InternalClassTransition Transition; + QHash transitions; // id to next class, positive means add, negative delete InternalClass *m_sealed; InternalClass *m_frozen; @@ -122,7 +130,7 @@ struct InternalClass { InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0); InternalClass *changeMember(String *string, PropertyAttributes data, uint *index = 0); - void removeMember(Object *object, uint id); + void removeMember(Object *object, Identifier *id); uint find(String *s); InternalClass *sealed(); @@ -136,7 +144,6 @@ private: InternalClass(const InternalClass &other); }; - } QT_END_NAMESPACE diff --git a/src/qml/qml/v4/qv4string.cpp b/src/qml/qml/v4/qv4string.cpp index 97c5401..966da14 100644 --- a/src/qml/qml/v4/qv4string.cpp +++ b/src/qml/qml/v4/qv4string.cpp @@ -183,7 +183,7 @@ bool String::deleteIndexedProperty(Managed *m, uint index) } String::String(ExecutionEngine *engine, const QString &text) - : Managed(engine ? engine->emptyClass : 0), _text(text), stringHash(UINT_MAX), identifier(UINT_MAX) + : Managed(engine ? engine->emptyClass : 0), _text(text), identifier(0), stringHash(UINT_MAX) { vtbl = &static_vtbl; type = Type_String; diff --git a/src/qml/qml/v4/qv4string_p.h b/src/qml/qml/v4/qv4string_p.h index 81108c6..84f2b23 100644 --- a/src/qml/qml/v4/qv4string_p.h +++ b/src/qml/qml/v4/qv4string_p.h @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct ExecutionEngine; +struct Identifier; struct Q_QML_EXPORT String : public Managed { enum StringType { @@ -58,7 +59,7 @@ struct Q_QML_EXPORT String : public Managed { StringType_ArrayIndex }; - String() : Managed(0), stringHash(UINT_MAX), identifier(UINT_MAX) + String() : Managed(0), identifier(0), stringHash(UINT_MAX) { vtbl = &static_vtbl; type = Type_String; subtype = StringType_Unknown; } String(ExecutionEngine *engine, const QString &text); ~String() { _data = 0; } @@ -68,7 +69,7 @@ struct Q_QML_EXPORT String : public Managed { return true; if (hashValue() != other->hashValue()) return false; - if (identifier != UINT_MAX && identifier == other->identifier) + if (identifier && identifier == other->identifier) return true; if (subtype >= StringType_UInt && subtype == other->subtype) return true; @@ -100,7 +101,7 @@ struct Q_QML_EXPORT String : public Managed { uint toUInt(bool *ok) const; void makeIdentifier() { - if (identifier != UINT_MAX) + if (identifier) return; makeIdentifierImpl(); } @@ -118,8 +119,8 @@ struct Q_QML_EXPORT String : public Managed { } QString _text; + mutable Identifier *identifier; mutable uint stringHash; - mutable uint identifier; protected: static void destroy(Managed *);