aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-11-02 16:02:10 +0100
committerLars Knoll <lars.knoll@qt.io>2017-11-14 21:45:42 +0000
commit002fdc48d43e4fd67921e0cd46c28d28aee06848 (patch)
tree08fdc81dc91153649d8b6c6514ed3b49ad970064
parent010197a42150ee73a17cb53fbe397a6c55b2d342 (diff)
Bring back markObjects(), this time generated
Doing the marking of objects in a function instead of using the table seems to be somewhat faster. Change-Id: I9ec00cc0264f9a15c69b285db493bee31d99bf96 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h6
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp3
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h2
-rw-r--r--src/qml/jsruntime/qv4context_p.h6
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine_p.h29
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4managed.cpp1
-rw-r--r--src/qml/jsruntime/qv4managed_p.h12
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h2
-rw-r--r--src/qml/jsruntime/qv4object.cpp13
-rw-r--r--src/qml/jsruntime/qv4object_p.h13
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp4
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h4
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp6
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h4
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4string.cpp9
-rw-r--r--src/qml/jsruntime/qv4string_p.h2
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h2
-rw-r--r--src/qml/jsruntime/qv4value_p.h7
-rw-r--r--src/qml/memory/qv4heap_p.h23
-rw-r--r--src/qml/memory/qv4mm.cpp58
-rw-r--r--src/qml/memory/qv4mmdefs_p.h61
-rw-r--r--src/qml/memory/qv4writebarrier_p.h36
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp2
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp9
-rw-r--r--src/quick/items/qquickitem.cpp8
33 files changed, 151 insertions, 191 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index a7a85743fc..cc7eada4b9 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -63,7 +63,7 @@ namespace Heap {
Member(class, NoMark, uint, index)
DECLARE_HEAP_OBJECT(ArgumentsGetterFunction, FunctionObject) {
- DECLARE_MARK_TABLE(ArgumentsGetterFunction);
+ DECLARE_MARKOBJECTS(ArgumentsGetterFunction);
inline void init(QV4::ExecutionContext *scope, uint index);
};
@@ -71,7 +71,7 @@ DECLARE_HEAP_OBJECT(ArgumentsGetterFunction, FunctionObject) {
Member(class, NoMark, uint, index)
DECLARE_HEAP_OBJECT(ArgumentsSetterFunction, FunctionObject) {
- DECLARE_MARK_TABLE(ArgumentsSetterFunction);
+ DECLARE_MARKOBJECTS(ArgumentsSetterFunction);
inline void init(QV4::ExecutionContext *scope, uint index);
};
@@ -83,7 +83,7 @@ DECLARE_HEAP_OBJECT(ArgumentsSetterFunction, FunctionObject) {
Member(class, NoMark, int, nFormals)
DECLARE_HEAP_OBJECT(ArgumentsObject, Object) {
- DECLARE_MARK_TABLE(ArgumentsObject);
+ DECLARE_MARKOBJECTS(ArgumentsObject);
enum {
LengthPropertyIndex = 0,
CalleePropertyIndex = 1,
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index b77fab3305..0130dc0077 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -53,7 +53,6 @@ const QV4::VTable QV4::ArrayData::static_vtbl = {
0,
0,
0,
- 0,
QV4::ArrayData::IsExecutionContext,
QV4::ArrayData::IsString,
QV4::ArrayData::IsObject,
@@ -64,7 +63,7 @@ const QV4::VTable QV4::ArrayData::static_vtbl = {
QV4::ArrayData::MyType,
"ArrayData",
Q_VTABLE_FUNCTION(QV4::ArrayData, destroy),
- 0,
+ ArrayData::Data::markObjects,
isEqualTo
};
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 6e41c756a8..154fe5d150 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -99,7 +99,7 @@ namespace Heap {
Member(class, ValueArray, ValueArray, values)
DECLARE_HEAP_OBJECT(ArrayData, Base) {
- DECLARE_MARK_TABLE(ArrayData);
+ DECLARE_MARKOBJECTS(ArrayData);
enum Type { Simple = 0, Complex = 1, Sparse = 2, Custom = 3 };
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 34a406e8e0..a73e7118ea 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -120,7 +120,7 @@ struct QmlContext;
Member(class, Pointer, Object *, activation)
DECLARE_HEAP_OBJECT(ExecutionContext, Base) {
- DECLARE_MARK_TABLE(ExecutionContext);
+ DECLARE_MARKOBJECTS(ExecutionContext);
enum ContextType {
Type_GlobalContext = 0x1,
@@ -155,7 +155,7 @@ Q_STATIC_ASSERT(offsetof(ExecutionContextData, activation) == offsetof(Execution
Member(class, ValueArray, ValueArray, locals)
DECLARE_HEAP_OBJECT(CallContext, ExecutionContext) {
- DECLARE_MARK_TABLE(CallContext);
+ DECLARE_MARKOBJECTS(CallContext);
void init()
{
@@ -186,7 +186,7 @@ Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0);
Member(class, HeapValue, HeapValue, exceptionValue)
DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) {
- DECLARE_MARK_TABLE(CatchContext);
+ DECLARE_MARKOBJECTS(CatchContext);
void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
};
diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h
index c921a0ca45..1e07d85118 100644
--- a/src/qml/jsruntime/qv4dataview_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -69,7 +69,7 @@ struct DataViewCtor : FunctionObject {
Member(class, NoMark, uint, byteOffset)
DECLARE_HEAP_OBJECT(DataView, Object) {
- DECLARE_MARK_TABLE(DataView);
+ DECLARE_MARKOBJECTS(DataView);
void init() { Object::init(); }
};
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index db002035da..aaf69f6555 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -498,35 +498,6 @@ inline void ExecutionEngine::setCurrentContext(Heap::ExecutionContext *context)
currentStackFrame->jsFrame->context = context;
}
-inline
-void Heap::Base::mark(QV4::MarkStack *markStack)
-{
- Q_ASSERT(inUse());
- const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
- Chunk *c = h->chunk();
- size_t index = h - c->realBase();
- Q_ASSERT(!Chunk::testBit(c->extendsBitmap, index));
- quintptr *bitmap = c->blackBitmap + Chunk::bitmapIndex(index);
- quintptr bit = Chunk::bitForIndex(index);
- if (!(*bitmap & bit)) {
- *bitmap |= bit;
- markStack->push(this);
- }
-}
-
-inline void Value::mark(MarkStack *markStack)
-{
- Heap::Base *o = heapObject();
- if (o)
- o->mark(markStack);
-}
-
-inline void Managed::mark(MarkStack *markStack)
-{
- Q_ASSERT(m());
- m()->mark(markStack);
-}
-
#define CHECK_STACK_LIMITS(v4) if ((v4)->checkStackLimits()) return Encode::undefined(); \
ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index a2f00ff81e..a5ee0eb886 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -67,7 +67,7 @@ namespace Heap {
Member(class, Pointer, String *, stack)
DECLARE_HEAP_OBJECT(ErrorObject, Object) {
- DECLARE_MARK_TABLE(ErrorObject);
+ DECLARE_MARKOBJECTS(ErrorObject);
enum ErrorType {
Error,
EvalError,
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index e6073425d8..4293d43791 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -68,8 +68,6 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
-Q_STATIC_ASSERT((Heap::FunctionObject::markTable & Heap::Object::markTable) == Heap::Object::markTable);
-
void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name,
ReturnedValue (*code)(const QV4::FunctionObject *, const Value *thisObject, const Value *argv, int argc))
{
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 6f787b3e38..27024b3455 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -78,7 +78,7 @@ namespace Heap {
Member(class, NoMark, jsConstructFunction, jsConstruct)
DECLARE_HEAP_OBJECT(FunctionObject, Object) {
- DECLARE_MARK_TABLE(FunctionObject);
+ DECLARE_MARKOBJECTS(FunctionObject);
enum {
Index_Prototype = 0,
Index_ProtoConstructor = 0
@@ -131,7 +131,7 @@ struct ScriptFunction : FunctionObject {
Member(class, Pointer, MemberData *, boundArgs)
DECLARE_HEAP_OBJECT(BoundFunction, FunctionObject) {
- DECLARE_MARK_TABLE(BoundFunction);
+ DECLARE_MARKOBJECTS(BoundFunction);
void init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs);
};
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index e00eaa0d9b..200380eda0 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -49,7 +49,6 @@ const VTable Managed::static_vtbl =
0,
0,
0,
- 0,
Managed::IsExecutionContext,
Managed::IsString,
Managed::IsObject,
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 40dfc244ea..ea10f6f6d1 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -93,7 +93,6 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
dptr->_checkIsInitialized(); \
return dptr; \
} \
- static Q_CONSTEXPR quint64 markTable = QV4::Heap::DataClass::markTable; \
V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass)
#define V4_MANAGED(DataClass, superClass) \
@@ -132,7 +131,6 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
parentVTable, \
- markTable, \
(sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
(sizeof(classname::Data) + (std::is_same<classname, Object>::value ? 2*sizeof(QV4::Value) : 0) + QV4::Chunk::SlotSize - 1)/QV4::Chunk::SlotSize*QV4::Chunk::SlotSize/sizeof(QV4::Value) \
- (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
@@ -146,9 +144,9 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
classname::MyType, \
#classname, \
Q_VTABLE_FUNCTION(classname, destroy), \
- Q_VTABLE_FUNCTION(classname, markObjects), \
+ classname::Data::markObjects, \
isEqualTo \
-}
+} \
#define DEFINE_MANAGED_VTABLE(classname) \
QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \
@@ -221,7 +219,6 @@ public:
inline void mark(MarkStack *markStack);
static void destroy(Heap::Base *) {}
- static void markObjects(Heap::Base *, MarkStack *) {}
Q_ALWAYS_INLINE Heap::Base *heapObject() const {
return m();
@@ -240,6 +237,11 @@ private:
friend struct ObjectIterator;
};
+inline void Managed::mark(MarkStack *markStack)
+{
+ Q_ASSERT(m());
+ m()->mark(markStack);
+}
template<>
inline const Managed *Value::as() const {
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index bae524d088..3e231d693b 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -63,7 +63,7 @@ namespace Heap {
Member(class, ValueArray, ValueArray, values)
DECLARE_HEAP_OBJECT(MemberData, Base) {
- DECLARE_MARK_TABLE(MemberData);
+ DECLARE_MARKOBJECTS(MemberData);
};
V4_ASSERT_IS_TRIVIAL(MemberData)
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 8a178506aa..a9aa8f30a9 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -261,9 +261,18 @@ void Object::defineReadonlyConfigurableProperty(String *name, const Value &value
insertMember(name, value, Attr_ReadOnly_ButConfigurable);
}
-void Object::markObjects(Heap::Base *b, MarkStack *stack)
+void Object::markObjects(Heap::Base *base, MarkStack *stack)
{
- Heap::Object *o = static_cast<Heap::Object *>(b);
+ Heap::Object::markObjects(base, stack);
+}
+
+void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack)
+{
+ Object *o = static_cast<Object *>(b);
+ if (o->memberData)
+ o->memberData->mark(stack);
+ if (o->arrayData)
+ o->arrayData->mark(stack);
uint nInline = o->vtable()->nInlineProperties;
Value *v = reinterpret_cast<Value *>(o) + o->vtable()->inlinePropertyOffset;
const Value *end = v + nInline;
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index cfec387f44..6e7d002a1b 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -72,10 +72,9 @@ namespace Heap {
Member(class, Pointer, MemberData *, memberData) \
Member(class, Pointer, ArrayData *, arrayData)
-DECLARE_HEAP_OBJECT(Object, Base) {
- DECLARE_MARK_TABLE(Object);
+DECLARE_EXPORTED_HEAP_OBJECT(Object, Base) {
+ static void markObjects(Heap::Base *base, MarkStack *stack);
void init() { Base::init(); }
- void destroy() { Base::destroy(); }
const Value *inlinePropertyData(uint index) const {
Q_ASSERT(index < vtable()->nInlineProperties);
@@ -129,8 +128,6 @@ DECLARE_HEAP_OBJECT(Object, Base) {
Heap::Object *prototype() const { return internalClass->prototype; }
};
-Q_STATIC_ASSERT(Object::markTable == ((2 << 2) | (2 << 4)));
-
}
#define V4_OBJECT2(DataClass, superClass) \
@@ -150,8 +147,7 @@ Q_STATIC_ASSERT(Object::markTable == ((2 << 2) | (2 << 4)));
dptr->_checkIsInitialized(); \
return dptr; \
} \
- V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass); \
- static Q_CONSTEXPR quint64 markTable = QV4::Heap::DataClass::markTable;
+ V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass);
#define V4_PROTOTYPE(p) \
static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
@@ -308,6 +304,8 @@ struct Q_QML_EXPORT Object: Managed {
// Array handling
public:
+ static void markObjects(Heap::Base *base, MarkStack *stack);
+
void copyArrayData(Object *other);
bool setArrayLength(uint newLen);
@@ -436,7 +434,6 @@ protected:
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
- static void markObjects(Heap::Base *, MarkStack *);
private:
ReturnedValue internalGet(String *name, bool *hasProperty) const;
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 3427ee89fe..0394c704f9 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -177,9 +177,9 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
DEFINE_OBJECT_VTABLE(ForEachIteratorObject);
-void ForEachIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
+void Heap::ForEachIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
{
- ForEachIteratorObject::Data *o = static_cast<ForEachIteratorObject::Data *>(that);
+ ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
o->workArea[0].mark(markStack);
o->workArea[1].mark(markStack);
Object::markObjects(that, markStack);
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 6168d59914..30a6ad3025 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -116,6 +116,7 @@ struct ForEachIteratorObject : Object {
ObjectIterator &it() { return *reinterpret_cast<ObjectIterator*>(&itData); }
Value workArea[2];
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
private:
ObjectIteratorData itData;
};
@@ -127,9 +128,6 @@ struct ForEachIteratorObject: Object {
Q_MANAGED_TYPE(ForeachIteratorObject)
ReturnedValue nextPropertyName() { return d()->it().nextPropertyNameAsString(); }
-
-protected:
- static void markObjects(Heap::Base *that, MarkStack *markStack);
};
inline
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index f0782c7ee1..a1df5cb95f 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -79,7 +79,7 @@ struct QQmlContextWrapper : Object {
#define QmlContextMembers(class, Member)
DECLARE_HEAP_OBJECT(QmlContext, ExecutionContext) {
- DECLARE_MARK_TABLE(QmlContext);
+ DECLARE_MARKOBJECTS(QmlContext);
QQmlContextWrapper *qml() { return static_cast<QQmlContextWrapper *>(activation.get()); }
void init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 9746b82817..6d7d929b61 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1015,9 +1015,9 @@ static void markChildQObjectsRecursively(QObject *parent, QV4::MarkStack *markSt
}
}
-void QObjectWrapper::markObjects(Heap::Base *that, QV4::MarkStack *markStack)
+void Heap::QObjectWrapper::markObjects(Heap::Base *that, QV4::MarkStack *markStack)
{
- QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
+ QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
if (QObject *o = This->object()) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
@@ -1032,7 +1032,7 @@ void QObjectWrapper::markObjects(Heap::Base *that, QV4::MarkStack *markStack)
markChildQObjectsRecursively(o, markStack);
}
- QV4::Object::markObjects(that, markStack);
+ Object::markObjects(that, markStack);
}
void QObjectWrapper::destroyObject(bool lastCall)
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 7b31fcc1e5..c00e82e4fa 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -90,6 +90,7 @@ struct Q_QML_EXPORT QObjectWrapper : Object {
}
QObject *object() const { return qObj.data(); }
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
private:
QQmlQPointer<QObject> qObj;
@@ -102,7 +103,7 @@ private:
Member(class, NoMark, int, index)
DECLARE_HEAP_OBJECT(QObjectMethod, FunctionObject) {
- DECLARE_MARK_TABLE(QObjectMethod);
+ DECLARE_MARKOBJECTS(QObjectMethod);
void init(QV4::ExecutionContext *scope);
void destroy()
@@ -196,7 +197,6 @@ protected:
static bool put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
- static void markObjects(Heap::Base *that, QV4::MarkStack *markStack);
static ReturnedValue method_connect(const BuiltinFunction *, CallData *callData);
static ReturnedValue method_disconnect(const BuiltinFunction *, CallData *callData);
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 37e8994c23..7e4f186dc4 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -76,7 +76,7 @@ namespace Heap {
Member(class, Pointer, RegExp *, value)
DECLARE_HEAP_OBJECT(RegExpObject, Object) {
- DECLARE_MARK_TABLE(RegExpObject);
+ DECLARE_MARKOBJECTS(RegExpObject);
void init();
void init(QV4::RegExp *value);
@@ -90,7 +90,7 @@ DECLARE_HEAP_OBJECT(RegExpObject, Object) {
Member(class, NoMark, int, lastMatchEnd)
DECLARE_HEAP_OBJECT(RegExpCtor, FunctionObject) {
- DECLARE_MARK_TABLE(RegExpCtor);
+ DECLARE_MARKOBJECTS(RegExpCtor);
void init(QV4::ExecutionContext *scope);
void clearLastMatch();
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index c0183a46a7..b38b01c9f7 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -52,17 +52,18 @@ using namespace QV4;
#ifndef V4_BOOTSTRAP
-DEFINE_MANAGED_VTABLE(String);
-
-void String::markObjects(Heap::Base *that, MarkStack *markStack)
+void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack)
{
- String::Data *s = static_cast<String::Data *>(that);
+ String *s = static_cast<String *>(that);
if (s->largestSubLength) {
s->left->mark(markStack);
s->right->mark(markStack);
}
}
+DEFINE_MANAGED_VTABLE(String);
+
+
bool String::isEqualTo(Managed *t, Managed *o)
{
if (t == o)
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index d1b936bb4e..85345aca4d 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -65,6 +65,7 @@ struct Identifier;
namespace Heap {
struct Q_QML_PRIVATE_EXPORT String : Base {
+ static void markObjects(Heap::Base *that, MarkStack *markStack);
enum StringType {
StringType_Unknown,
StringType_Regular,
@@ -206,7 +207,6 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
Identifier *identifier() const { return d()->identifier; }
protected:
- static void markObjects(Heap::Base *that, MarkStack *markStack);
static bool isEqualTo(Managed *that, Managed *o);
static uint getLength(const Managed *m);
#endif
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 317da4ec1e..7d25678b61 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -64,7 +64,7 @@ namespace Heap {
Member(class, Pointer, String *, string)
DECLARE_HEAP_OBJECT(StringObject, Object) {
- DECLARE_MARK_TABLE(StringObject);
+ DECLARE_MARKOBJECTS(StringObject);
enum {
LengthPropertyIndex = 0
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 835858b474..129c662c97 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -80,7 +80,7 @@ namespace Heap {
Member(class, NoMark, uint, arrayType)
DECLARE_HEAP_OBJECT(TypedArray, Object) {
- DECLARE_MARK_TABLE(TypedArray);
+ DECLARE_MARKOBJECTS(TypedArray);
enum Type {
Int8Array,
UInt8Array,
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 8497d47800..944abbf4be 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -510,6 +510,13 @@ public:
};
V4_ASSERT_IS_TRIVIAL(Value)
+inline void Value::mark(MarkStack *markStack)
+{
+ Heap::Base *o = heapObject();
+ if (o)
+ o->mark(markStack);
+}
+
inline bool Value::isString() const
{
Heap::Base *b = heapObject();
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index f00ce4283c..363e891d5c 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -75,7 +75,6 @@ struct InternalClass;
struct VTable
{
const VTable * const parent;
- const quint64 markTable;
uint inlinePropertyOffset : 16;
uint nInlineProperties : 16;
uint isExecutionContext : 1;
@@ -97,7 +96,7 @@ namespace Heap {
struct Q_QML_EXPORT Base {
void *operator new(size_t) = delete;
- static Q_CONSTEXPR quint64 markTable = 0;
+ static void markObjects(Heap::Base *, MarkStack *) {}
InternalClass *internalClass;
@@ -131,7 +130,9 @@ struct Q_QML_EXPORT Base {
return Chunk::testBit(c->objectBitmap, h - c->realBase());
}
- inline void markChildren(MarkStack *markStack);
+ inline void markChildren(MarkStack *markStack) {
+ vtable()->markObjects(this, markStack);
+ }
void *operator new(size_t, Managed *m) { return m; }
void *operator new(size_t, Heap::Base *m) { return m; }
@@ -184,6 +185,22 @@ Q_STATIC_ASSERT(sizeof(Base) == QT_POINTER_SIZE);
}
+inline
+void Heap::Base::mark(QV4::MarkStack *markStack)
+{
+ Q_ASSERT(inUse());
+ const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
+ Chunk *c = h->chunk();
+ size_t index = h - c->realBase();
+ Q_ASSERT(!Chunk::testBit(c->extendsBitmap, index));
+ quintptr *bitmap = c->blackBitmap + Chunk::bitmapIndex(index);
+ quintptr bit = Chunk::bitForIndex(index);
+ if (!(*bitmap & bit)) {
+ *bitmap |= bit;
+ markStack->push(this);
+ }
+}
+
#ifdef QT_NO_QOBJECT
template <class T>
struct QQmlQPointer {
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 21c95bbe6e..3ea7908e9d 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -279,64 +279,6 @@ QString binary(quintptr) { return QString(); }
#define SDUMP if (1) ; else qDebug
#endif
-void Heap::Base::markChildren(MarkStack *markStack)
-{
- if (vtable()->markObjects)
- vtable()->markObjects(this, markStack);
- if (quint64 m = vtable()->markTable) {
-// qDebug() << "using mark table:" << hex << m << "for" << h;
- void **mem = reinterpret_cast<void **>(this);
- while (m) {
- MarkFlags mark = static_cast<MarkFlags>(m & 3);
- switch (mark) {
- case Mark_NoMark:
- break;
- case Mark_Value:
-// qDebug() << "marking value at " << mem;
- reinterpret_cast<Value *>(mem)->mark(markStack);
- break;
- case Mark_Pointer: {
-// qDebug() << "marking pointer at " << mem;
- Heap::Base *p = *reinterpret_cast<Heap::Base **>(mem);
- if (p)
- p->mark(markStack);
- break;
- }
- case Mark_ValueArray: {
- Q_ASSERT(m == Mark_ValueArray);
-// qDebug() << "marking Value Array at offset" << hex << (mem - reinterpret_cast<void **>(h));
- ValueArray<0> *a = reinterpret_cast<ValueArray<0> *>(mem);
- Value *v = a->values;
- const Value *end = v + a->alloc;
- if (a->alloc > 32*1024) {
- // drain from time to time to avoid overflows in the js stack
- Heap::Base **currentBase = markStack->top;
- while (v < end) {
- v->mark(markStack);
- ++v;
- if (markStack->top >= currentBase + 32*1024) {
- Heap::Base **oldBase = markStack->base;
- markStack->base = currentBase;
- markStack->drain();
- markStack->base = oldBase;
- }
- }
- } else {
- while (v < end) {
- v->mark(markStack);
- ++v;
- }
- }
- break;
- }
- }
-
- m >>= 2;
- ++mem;
- }
- }
-}
-
// Stores a classname -> freed count mapping.
typedef QHash<const char*, int> MMStatsHash;
Q_GLOBAL_STATIC(MMStatsHash, freedObjectStatsGlobal)
diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h
index 328797fb5e..6d911e69f6 100644
--- a/src/qml/memory/qv4mmdefs_p.h
+++ b/src/qml/memory/qv4mmdefs_p.h
@@ -287,32 +287,8 @@ struct MarkStack {
};
-// Some helper classes and macros to automate the generation of our
-// tables used for marking objects
-
-enum MarkFlags {
- Mark_NoMark = 0,
- Mark_Value = 1,
- Mark_Pointer = 2,
- Mark_ValueArray = 3
-};
-
-template <typename T>
-struct MarkFlagEvaluator {
- static Q_CONSTEXPR quint64 value = 0;
-};
-template <typename T, size_t o>
-struct MarkFlagEvaluator<Heap::Pointer<T, o>> {
- static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_Pointer) << (2*o / sizeof(quintptr));
-};
-template <size_t o>
-struct MarkFlagEvaluator<ValueArray<o>> {
- static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_ValueArray) << (2*o / sizeof(quintptr));
-};
-template <size_t o>
-struct MarkFlagEvaluator<HeapValue<o>> {
- static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_Value) << (2 *o / sizeof(quintptr));
-};
+// Some helper to automate the generation of our
+// functions used for marking objects
#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION(c, gcType, type, name) \
HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_##gcType(c, type, name)
@@ -334,25 +310,42 @@ struct MarkFlagEvaluator<HeapValue<o>> {
#define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) \
type<offsetof(c##OffsetStruct, name) + baseOffset> name;
-#define HEAP_OBJECT_MARK_EXPANSION(class, gcType, type, name) \
- MarkFlagEvaluator<decltype(class::name)>::value |
+#define HEAP_OBJECT_MARKOBJECTS_EXPANSION(c, gcType, type, name) \
+ HEAP_OBJECT_MARKOBJECTS_EXPANSION_##gcType(c, type, name)
+#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_Pointer(c, type, name) \
+ if (o->name) o->name.heapObject()->mark(stack);
+#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_NoMark(c, type, name)
+#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_HeapValue(c, type, name) \
+ o->name.mark(stack);
+#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_ValueArray(c, type, name) \
+ o->name.mark(stack);
-#define DECLARE_HEAP_OBJECT(name, base) \
+
+#define DECLARE_HEAP_OBJECT_BASE(name, base) \
struct name##OffsetStruct { \
name##Members(name, HEAP_OBJECT_OFFSET_MEMBER_EXPANSION) \
}; \
struct name##SizeStruct : base, name##OffsetStruct {}; \
struct name##Data { \
+ typedef base SuperClass; \
static Q_CONSTEXPR size_t baseOffset = sizeof(name##SizeStruct) - sizeof(name##OffsetStruct); \
name##Members(name, HEAP_OBJECT_MEMBER_EXPANSION) \
}; \
Q_STATIC_ASSERT(sizeof(name##SizeStruct) == sizeof(name##Data) + name##Data::baseOffset); \
-static Q_CONSTEXPR quint64 name##_markTable = \
- (name##Members(name##Data, HEAP_OBJECT_MARK_EXPANSION) 0) | QV4::Heap::base::markTable; \
- \
-struct name : base, name##Data
-#define DECLARE_MARK_TABLE(class) static Q_CONSTEXPR quint64 markTable = class##_markTable
+#define DECLARE_HEAP_OBJECT(name, base) \
+DECLARE_HEAP_OBJECT_BASE(name, base) \
+struct name : base, name##Data
+#define DECLARE_EXPORTED_HEAP_OBJECT(name, base) \
+DECLARE_HEAP_OBJECT_BASE(name, base) \
+struct Q_QML_EXPORT name : base, name##Data
+
+#define DECLARE_MARKOBJECTS(class) \
+ static void markObjects(Heap::Base *b, MarkStack *stack) { \
+ class *o = static_cast<class *>(b); \
+ class##Data::SuperClass::markObjects(o, stack); \
+ class##Members(class, HEAP_OBJECT_MARKOBJECTS_EXPANSION) \
+ }
}
diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h
index f55c724c12..4ec224cc36 100644
--- a/src/qml/memory/qv4writebarrier_p.h
+++ b/src/qml/memory/qv4writebarrier_p.h
@@ -114,8 +114,8 @@ namespace Heap {
template <typename T, size_t o>
struct Pointer {
static Q_CONSTEXPR size_t offset = o;
- T operator->() const { return ptr; }
- operator T () const { return ptr; }
+ T operator->() const { return get(); }
+ operator T () const { return get(); }
Heap::Base *base() {
Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base));
@@ -124,16 +124,18 @@ struct Pointer {
}
void set(EngineBase *e, T newVal) {
- WriteBarrier::write(e, base(), reinterpret_cast<Heap::Base **>(&ptr), reinterpret_cast<Heap::Base *>(newVal));
+ WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Heap::Base *>(newVal));
}
- T get() { return ptr; }
+ T get() const { return reinterpret_cast<T>(ptr); }
template <typename Type>
Type *cast() { return static_cast<Type *>(ptr); }
+ Heap::Base *heapObject() const { return ptr; }
+
private:
- T ptr;
+ Heap::Base *ptr;
};
typedef Pointer<char *, 0> V4PointerCheck;
V4_ASSERT_IS_TRIVIAL(V4PointerCheck)
@@ -194,6 +196,30 @@ struct ValueArray {
values[i] = values[i + n];
}
}
+
+ void mark(MarkStack *markStack) {
+ Value *v = values;
+ const Value *end = v + alloc;
+ if (alloc > 32*1024) {
+ // drain from time to time to avoid overflows in the js stack
+ Heap::Base **currentBase = markStack->top;
+ while (v < end) {
+ v->mark(markStack);
+ ++v;
+ if (markStack->top >= currentBase + 32*1024) {
+ Heap::Base **oldBase = markStack->base;
+ markStack->base = currentBase;
+ markStack->drain();
+ markStack->base = oldBase;
+ }
+ }
+ } else {
+ while (v < end) {
+ v->mark(markStack);
+ ++v;
+ }
+ }
+ }
};
// It's really important that the offset of values in this structure is
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 15ee1ac86f..5a03f2dd93 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1098,7 +1098,7 @@ namespace Heap {
Member(class, NoMark, QQmlQPointer<QObject>, parent)
DECLARE_HEAP_OBJECT(QmlIncubatorObject, Object) {
- DECLARE_MARK_TABLE(QmlIncubatorObject);
+ DECLARE_MARKOBJECTS(QmlIncubatorObject);
void init(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
inline void destroy();
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 323074e12f..08842e714c 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1619,7 +1619,7 @@ struct QQmlXMLHttpRequestWrapper : Object {
Member(class, Pointer, Object *, proto)
DECLARE_HEAP_OBJECT(QQmlXMLHttpRequestCtor, FunctionObject) {
- DECLARE_MARK_TABLE(QQmlXMLHttpRequestCtor);
+ DECLARE_MARKOBJECTS(QQmlXMLHttpRequestCtor);
void init(ExecutionEngine *engine);
};
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 3a5d8f7a13..49b2bf5838 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -529,6 +529,11 @@ struct QQuickJSContext2DPixelData : Object {
struct QQuickJSContext2DImageData : Object {
void init();
+ static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) {
+ static_cast<QQuickJSContext2DImageData *>(that)->pixelData.mark(markStack);
+ Object::markObjects(that, markStack);
+ }
+
QV4::Value pixelData;
};
@@ -928,10 +933,6 @@ struct QQuickJSContext2DImageData : public QV4::Object
static QV4::ReturnedValue method_get_height(const QV4::BuiltinFunction *b, QV4::CallData *callData);
static QV4::ReturnedValue method_get_data(const QV4::BuiltinFunction *b, QV4::CallData *callData);
- static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) {
- static_cast<QQuickJSContext2DImageData::Data *>(that)->pixelData.mark(markStack);
- QV4::Object::markObjects(that, markStack);
- }
};
void QV4::Heap::QQuickJSContext2DImageData::init()
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 6579175cc6..ec4adf1ccd 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -8541,25 +8541,25 @@ QAccessible::Role QQuickItemPrivate::accessibleRole() const
namespace QV4 {
namespace Heap {
struct QQuickItemWrapper : public QObjectWrapper {
+ static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack);
};
}
}
struct QQuickItemWrapper : public QV4::QObjectWrapper {
V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper)
- static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack);
};
DEFINE_OBJECT_VTABLE(QQuickItemWrapper);
-void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack)
+void QV4::Heap::QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack)
{
- QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
+ QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
for (QQuickItem *child : qAsConst(QQuickItemPrivate::get(item)->childItems))
QV4::QObjectWrapper::markWrapper(child, markStack);
}
- QV4::QObjectWrapper::markObjects(that, markStack);
+ QObjectWrapper::markObjects(that, markStack);
}
quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine)