diff options
-rw-r--r-- | src/qml/jsruntime/qv4lookup.cpp | 51 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup_p.h | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 46 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 1 |
4 files changed, 94 insertions, 9 deletions
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index b5ea877bd4..345611d46c 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -362,4 +362,55 @@ void Lookup::setter0(Lookup *l, const Value &object, const Value &value) setterGeneric(l, object, value); } +void Lookup::setterInsert0(Lookup *l, const Value &object, const Value &value) +{ + Object *o = object.asObject(); + if (o && o->internalClass == l->classList[0]) { + if (!o->prototype) { + o->memberData[l->index].value = value; + o->internalClass = l->classList[3]; + return; + } + } + + l->setter = setterGeneric; + setterGeneric(l, object, value); +} + +void Lookup::setterInsert1(Lookup *l, const Value &object, const Value &value) +{ + Object *o = object.asObject(); + if (o && o->internalClass == l->classList[0]) { + Object *p = o->prototype; + if (p && p->internalClass == l->classList[1]) { + o->memberData[l->index].value = value; + o->internalClass = l->classList[3]; + return; + } + } + + l->setter = setterGeneric; + setterGeneric(l, object, value); +} + +void Lookup::setterInsert2(Lookup *l, const Value &object, const Value &value) +{ + Object *o = object.asObject(); + if (o && o->internalClass == l->classList[0]) { + Object *p = o->prototype; + if (p && p->internalClass == l->classList[1]) { + p = p->prototype; + if (p && p->internalClass == l->classList[2]) { + o->ensureMemberIndex(l->index); + o->memberData[l->index].value = value; + o->internalClass = l->classList[3]; + return; + } + } + } + + l->setter = setterGeneric; + setterGeneric(l, object, value); +} + QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index e77552826a..3763182e84 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct Lookup { - enum { Size = 3 }; + enum { Size = 4 }; union { void (*getter)(Lookup *l, Value *result, const Value &object); void (*globalGetter)(Lookup *l, ExecutionContext *ctx, Value *result); @@ -82,6 +82,9 @@ struct Lookup { static void setterGeneric(Lookup *l, const Value &object, const Value &value); static void setter0(Lookup *l, const Value &object, const Value &value); + static void setterInsert0(Lookup *l, const Value &object, const Value &value); + static void setterInsert1(Lookup *l, const Value &object, const Value &value); + static void setterInsert2(Lookup *l, const Value &object, const Value &value); Property *lookup(Object *obj, PropertyAttributes *attrs); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 45a0a19e2f..01be2d7091 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -293,14 +293,8 @@ void Object::markObjects(Managed *that) o->markArrayObjects(); } -Property *Object::insertMember(String *s, PropertyAttributes attributes) +void Object::ensureMemberIndex(uint idx) { - uint idx; - internalClass = internalClass->addMember(s, attributes, &idx); - - if (attributes.isAccessor()) - hasAccessorProperty = 1; - if (idx >= memberDataAlloc) { memberDataAlloc = qMax((uint)8, 2*memberDataAlloc); Property *newMemberData = new Property[memberDataAlloc]; @@ -310,6 +304,18 @@ Property *Object::insertMember(String *s, PropertyAttributes attributes) delete [] memberData; memberData = newMemberData; } +} + +Property *Object::insertMember(String *s, PropertyAttributes attributes) +{ + uint idx; + internalClass = internalClass->addMember(s, attributes, &idx); + + if (attributes.isAccessor()) + hasAccessorProperty = 1; + + ensureMemberIndex(idx); + return memberData + idx; } @@ -540,7 +546,8 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value) { Object *o = static_cast<Object *>(m); - uint idx = o->internalClass->find(l->name); + InternalClass *c = o->internalClass; + uint idx = c->find(l->name); if (!o->isArrayObject() || idx != ArrayObject::LengthPropertyIndex) { if (idx != UINT_MAX && o->internalClass->propertyData[idx].isData() && o->internalClass->propertyData[idx].isWritable()) { l->classList[0] = o->internalClass; @@ -557,6 +564,29 @@ void Object::setLookup(Managed *m, Lookup *l, const Value &value) } o->put(l->name, value); + + if (o->internalClass == c) + return; + idx = o->internalClass->find(l->name); + if (idx == UINT_MAX) + return; + l->classList[0] = c; + l->classList[3] = o->internalClass; + l->index = idx; + if (!o->prototype) { + l->setter = Lookup::setterInsert0; + return; + } + o = o->prototype; + l->classList[1] = o->internalClass; + if (!o->prototype) { + l->setter = Lookup::setterInsert1; + return; + } + o = o->prototype; + l->classList[2] = o->internalClass; + if (!o->prototype) + l->setter = Lookup::setterInsert2; } Property *Object::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs) diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index e6b1e04286..ea8911124d 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -328,6 +328,7 @@ public: return false; } + void ensureMemberIndex(uint idx); inline Value get(String *name, bool *hasProperty = 0) { return vtbl->get(this, name, hasProperty); } |