From 833c99db20a6ccbf337d77855098141e008b04ee Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 26 Aug 2015 16:40:11 +0200 Subject: Inline property data into the object Append the part of the objects property data that is known ad instantiation time to the object itself and by that avoid creating a separate MemberData. Saves some memory and should speed up object creation. Currently implemented only for Object and ArrayObject. Change-Id: I7693bf2f3a28fb718522398ebb94ac115e021fa4 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 18 +++++++---------- src/qml/jsruntime/qv4internalclass.cpp | 36 ++++++++++++++++++++++++++++++++-- src/qml/jsruntime/qv4object.cpp | 18 ++++++++++++----- src/qml/jsruntime/qv4object_p.h | 16 +++++++-------- 4 files changed, 62 insertions(+), 26 deletions(-) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 58193fd68f..6c2705871a 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -301,7 +301,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) jsObjects[ObjectProto] = memoryManager->alloc(emptyClass, (QV4::Object *)0); arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable); - jsObjects[ArrayProto] = memoryManager->alloc(arrayClass, objectPrototype()); + jsObjects[ArrayProto] = memoryManager->allocObject(arrayClass, objectPrototype()); InternalClass *argsClass = emptyClass->addMember(id_length(), Attr_NotEnumerable); argumentsObjectClass = argsClass->addMember(id_callee(), Attr_Data|Attr_NotEnumerable); @@ -540,16 +540,12 @@ ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *context) cons Heap::Object *ExecutionEngine::newObject() { - Scope scope(this); - ScopedObject object(scope, memoryManager->alloc(this)); - return object->d(); + return memoryManager->allocObject(emptyClass, objectPrototype()); } Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype) { - Scope scope(this); - ScopedObject object(scope, memoryManager->alloc(internalClass, prototype)); - return object->d(); + return memoryManager->allocObject(internalClass, prototype); } Heap::String *ExecutionEngine::newString(const QString &s) @@ -587,7 +583,7 @@ Heap::Object *ExecutionEngine::newBooleanObject(bool b) Heap::ArrayObject *ExecutionEngine::newArrayObject(int count) { Scope scope(this); - ScopedArrayObject object(scope, memoryManager->alloc(this)); + ScopedArrayObject object(scope, memoryManager->allocObject(arrayClass, arrayPrototype())); if (count) { if (count < 0x1000) @@ -600,14 +596,14 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(int count) Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list) { Scope scope(this); - ScopedArrayObject object(scope, memoryManager->alloc(this, list)); + ScopedArrayObject object(scope, memoryManager->allocObject(arrayClass, arrayPrototype(), list)); return object->d(); } -Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *prototype) +Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *internalClass, Object *prototype) { Scope scope(this); - ScopedArrayObject object(scope, memoryManager->alloc(ic, prototype)); + ScopedArrayObject object(scope, memoryManager->allocObject(internalClass, prototype)); return object->d(); } diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index bb2670036d..87987f7d50 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -136,12 +136,44 @@ InternalClass::InternalClass(const QV4::InternalClass &other) static void insertHoleIntoPropertyData(Object *object, int idx) { - memmove(object->d()->memberData->data + idx + 1, object->d()->memberData->data + idx, (object->internalClass()->size - idx - 1)*sizeof(Value)); + int inlineSize = object->d()->inlineMemberSize; + int icSize = object->internalClass()->size; + int from = qMax(idx, inlineSize); + int to = from + 1; + if (from < icSize) + memmove(object->propertyData(to), object->propertyData(from), icSize - from - 1); + if (from == idx) + return; + if (inlineSize < icSize) + *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1); + from = idx; + to = from + 1; + if (from < inlineSize - 1) + memmove(object->propertyData(to), object->propertyData(from), inlineSize - from - 1); } static void removeFromPropertyData(Object *object, int idx, bool accessor = false) { - memmove(object->d()->memberData->data + idx, object->d()->memberData->data + idx + (accessor ? 2 : 1), (object->internalClass()->size - idx)*sizeof(Value)); + int inlineSize = object->d()->inlineMemberSize; + int icSize = object->internalClass()->size; + int delta = (accessor ? 2 : 1); + int to = idx; + int from = to + delta; + if (from < inlineSize) { + memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value)); + to = inlineSize - delta; + from = inlineSize; + } + if (to < inlineSize && from < icSize) { + Q_ASSERT(from >= inlineSize); + memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value)); + to = inlineSize; + from = inlineSize + delta; + } + if (from < icSize + delta) { + Q_ASSERT(to >= inlineSize && from > to); + memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value)); + } } void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index) diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 5f96e0d758..c8b703e198 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -213,6 +213,13 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e) { Heap::Object *o = static_cast(that); + if (o->inlineMemberSize) { + Value *v = o->propertyData(0); + Q_ASSERT(((char *)v) - ((char *)that) == sizeof(Heap::Object)); + for (uint i = 0; i < o->inlineMemberSize; ++i) + v[i].mark(e); + } + if (o->memberData) o->memberData->mark(e); if (o->arrayData) @@ -224,7 +231,8 @@ void Object::markObjects(Heap::Base *that, ExecutionEngine *e) void Object::ensureMemberData() { QV4::InternalClass *ic = internalClass(); - d()->memberData = MemberData::reallocate(ic->engine, d()->memberData, ic->size); + if (ic->size > d()->inlineMemberSize) + d()->memberData = MemberData::reallocate(ic->engine, d()->memberData, ic->size - d()->inlineMemberSize); } void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes) @@ -1156,11 +1164,11 @@ void Object::initSparseArray() DEFINE_OBJECT_VTABLE(ArrayObject); -Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) - : Heap::Object(engine->arrayClass, engine->arrayPrototype()) +Heap::ArrayObject::ArrayObject(const QStringList &list) + : Heap::Object() { init(); - Scope scope(engine); + Scope scope(internalClass->engine); ScopedObject a(scope, this); // Converts a QStringList to JS. @@ -1171,7 +1179,7 @@ Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) a->arrayReserve(len); ScopedValue v(scope); for (int ii = 0; ii < len; ++ii) - a->arrayPut(ii, (v = engine->newString(list.at(ii)))); + a->arrayPut(ii, (v = scope.engine->newString(list.at(ii)))); a->setArrayLengthUnchecked(len); } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 943325ef03..636755808b 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -47,12 +47,15 @@ namespace QV4 { namespace Heap { struct Object : Base { + inline Object() {} inline Object(ExecutionEngine *engine); Object(InternalClass *internal, QV4::Object *prototype); - const Value *propertyData(uint index) const { return memberData->data + index; } - Value *propertyData(uint index) { return memberData->data + index; } + const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } + Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } + uint inlineMemberOffset; + uint inlineMemberSize; InternalClass *internalClass; Pointer prototype; Pointer memberData; @@ -371,13 +374,10 @@ struct ArrayObject : Object { LengthPropertyIndex = 0 }; - ArrayObject(ExecutionEngine *engine) - : Heap::Object(engine->arrayClass, engine->arrayPrototype()) - { init(); } - ArrayObject(ExecutionEngine *engine, const QStringList &list); - ArrayObject(InternalClass *ic, QV4::Object *prototype) - : Heap::Object(ic, prototype) + ArrayObject() + : Heap::Object() { init(); } + ArrayObject(const QStringList &list); void init() { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); } }; -- cgit v1.2.3