aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@theqtcompany.com>2015-08-26 16:40:11 +0200
committerLars Knoll <lars.knoll@theqtcompany.com>2015-09-22 08:19:53 +0000
commit833c99db20a6ccbf337d77855098141e008b04ee (patch)
treed6bfae879061b1de22740ce20960542025c7a4d5 /src/qml/jsruntime
parent884097f463b1ab8c3fed929c3586d6ceea612442 (diff)
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 <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp18
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp36
-rw-r--r--src/qml/jsruntime/qv4object.cpp18
-rw-r--r--src/qml/jsruntime/qv4object_p.h16
4 files changed, 62 insertions, 26 deletions
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<ObjectPrototype>(emptyClass, (QV4::Object *)0);
arrayClass = emptyClass->addMember(id_length(), Attr_NotConfigurable|Attr_NotEnumerable);
- jsObjects[ArrayProto] = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype());
+ jsObjects[ArrayProto] = memoryManager->allocObject<ArrayPrototype>(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<Object>(this));
- return object->d();
+ return memoryManager->allocObject<Object>(emptyClass, objectPrototype());
}
Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype)
{
- Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(internalClass, prototype));
- return object->d();
+ return memoryManager->allocObject<Object>(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<ArrayObject>(this));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(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<ArrayObject>(this, list));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(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<ArrayObject>(ic, prototype));
+ ScopedArrayObject object(scope, memoryManager->allocObject<ArrayObject>(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<Heap::Object *>(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<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; }
+ uint inlineMemberOffset;
+ uint inlineMemberSize;
InternalClass *internalClass;
Pointer<Object> prototype;
Pointer<MemberData> 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); }
};