aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--src/qml/memory/qv4mm_p.h61
-rw-r--r--tests/manual/v4/crypto.js1
-rw-r--r--tools/qmljs/qmljs.cpp2
7 files changed, 116 insertions, 36 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); }
};
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index c01866ff11..6b6b502b95 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -37,6 +37,7 @@
#include <private/qv4global_p.h>
#include <private/qv4value_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4object_p.h>
//#define DETAILED_MM_STATS
@@ -91,6 +92,57 @@ public:
return static_cast<typename ManagedType::Data *>(o);
}
+ template <typename ManagedType, typename Arg1>
+ typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
+ {
+ Scope scope(engine());
+ Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
+ (void)new (t->d()) typename ManagedType::Data(this, arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype)
+ {
+ Scope scope(engine());
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ Scoped<ObjectType> t(scope, allocManaged<ObjectType>(size + ic->size*sizeof(Value)));
+ t->d()->internalClass = ic;
+ t->d()->prototype = prototype->d();
+ t->d()->inlineMemberSize = ic->size;
+ t->d()->inlineMemberOffset = size/sizeof(Value);
+ (void)new (t->d()) typename ObjectType::Data();
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1)
+ {
+ Scope scope(engine());
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ Scoped<ObjectType> t(scope, allocManaged<ObjectType>(size + ic->size*sizeof(Value)));
+ t->d()->internalClass = ic;
+ t->d()->prototype = prototype->d();
+ t->d()->inlineMemberSize = ic->size;
+ t->d()->inlineMemberOffset = size/sizeof(Value);
+ (void)new (t->d()) typename ObjectType::Data(arg1);
+ return t->d();
+ }
+
+ template <typename ObjectType, typename Arg1, typename Arg2>
+ typename ObjectType::Data *allocObject(InternalClass *ic, Object *prototype, Arg1 arg1, Arg2 arg2)
+ {
+ Scope scope(engine());
+ const int size = (sizeof(typename ObjectType::Data) + (sizeof(Value) - 1)) & ~(sizeof(Value) - 1);
+ Scoped<ObjectType> t(scope, allocManaged<ObjectType>(size + ic->size*sizeof(Value)));
+ t->d()->internalClass = ic;
+ t->d()->prototype = prototype->d();
+ t->d()->inlineMemberSize = ic->size;
+ t->d()->inlineMemberOffset = size/sizeof(Value);
+ (void)new (t->d()) typename ObjectType::Data(arg1, arg2);
+ return t->d();
+ }
+
template <typename ManagedType>
typename ManagedType::Data *alloc()
{
@@ -109,15 +161,6 @@ public:
return t->d();
}
- template <typename ManagedType, typename Arg1>
- typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
- {
- Scope scope(engine());
- Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
- (void)new (t->d()) typename ManagedType::Data(this, arg1);
- return t->d();
- }
-
template <typename ManagedType, typename Arg1, typename Arg2>
typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
{
diff --git a/tests/manual/v4/crypto.js b/tests/manual/v4/crypto.js
index cd48bdb019..7c24b08439 100644
--- a/tests/manual/v4/crypto.js
+++ b/tests/manual/v4/crypto.js
@@ -1710,3 +1710,4 @@ if (typeof(print) === "undefined")
print = console.log;
print("done in", new Date - d1)
+gc()
diff --git a/tools/qmljs/qmljs.cpp b/tools/qmljs/qmljs.cpp
index 53e520cd1f..a882c5ef50 100644
--- a/tools/qmljs/qmljs.cpp
+++ b/tools/qmljs/qmljs.cpp
@@ -188,7 +188,7 @@ int main(int argc, char *argv[])
QV4::Scope scope(&vm);
QV4::ScopedContext ctx(scope, vm.rootContext());
- QV4::ScopedObject print(scope, vm.memoryManager->alloc<builtins::Print>(ctx));
+ QV4::ScopedObject print(scope, vm.memoryManager->alloc<builtins::Print>(vm.rootContext()));
vm.globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("print"))).getPointer(), print);
QV4::ScopedObject gc(scope, vm.memoryManager->alloc<builtins::GC>(ctx));
vm.globalObject->put(QV4::ScopedString(scope, vm.newIdentifier(QStringLiteral("gc"))).getPointer(), gc);