namespace QV4 {
-struct Identifiers
+struct Identifier
+{
+ QString string;
+ uint hashValue;
+};
+
+
+struct IdentifierHash
{
ExecutionEngine *engine;
- uint currentIndex;
QHash<QString, String *> identifiers;
public:
- Identifiers(ExecutionEngine *engine) : engine(engine), currentIndex(0) {}
+ IdentifierHash(ExecutionEngine *engine) : engine(engine) {}
String *insert(const QString &s)
{
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<QString, String*>::const_iterator it = identifiers.find(s->toQString());
+ QHash<QString, String*>::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() {
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
{
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)
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;
}
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;
}
++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;
if (data == propertyData[idx])
return this;
- uint tid = string->identifier | (data.flags() << 27);
- QHash<int, InternalClass *>::const_iterator tit = transitions.constFind(tid);
+ Transition t = { string->identifier, data.flags() };
+ QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
if (tit != transitions.constEnd())
return tit.value();
if (propertyTable.lookup(string->identifier) < size)
return changeMember(string, data, index);
- uint id = string->identifier | (data.flags() << 27);
- QHash<int, InternalClass *>::const_iterator tit = transitions.constFind(id);
+ Transition t = { string->identifier, data.flags() };
+ QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
if (index)
*index = size;
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<int, InternalClass *>::const_iterator tit = transitions.constFind(toRemove);
+ Transition t = { id, -1 };
+ QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
if (tit != transitions.constEnd()) {
object->internalClass = tit.value();
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)
if (m_frozen)
m_frozen->destroy();
- for (QHash<int, InternalClass *>::ConstIterator it = transitions.begin(), end = transitions.end();
+ for (QHash<Transition, InternalClass *>::ConstIterator it = transitions.begin(), end = transitions.end();
it != end; ++it)
it.value()->destroy();
struct String;
struct ExecutionEngine;
struct Object;
+struct Identifier;
struct PropertyHashData;
struct PropertyHash
{
struct Entry {
- uint identifier;
+ const Identifier *identifier;
uint index;
};
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);
delete d;
}
+struct InternalClassTransition
+{
+ Identifier *id;
+ int flags;
+};
+uint qHash(const QV4::InternalClassTransition &t, uint = 0);
struct InternalClass {
ExecutionEngine *engine;
QVector<PropertyAttributes> propertyData;
- QHash<int, InternalClass *> transitions; // id to next class, positive means add, negative delete
+ typedef InternalClassTransition Transition;
+ QHash<Transition, InternalClass *> transitions; // id to next class, positive means add, negative delete
InternalClass *m_sealed;
InternalClass *m_frozen;
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();
InternalClass(const InternalClass &other);
};
-
}
QT_END_NAMESPACE